Changeset a1ef3a2 in git for kernel/combinatorics
- Timestamp:
- Mar 27, 2021, 7:21:22 PM (3 years ago)
- Branches:
- (u'fieker-DuVal', '117eb8c30fc9e991c4decca4832b1d19036c4c65')(u'spielwiese', 'c5facdfddea2addfd91babd8b9019161dea4b695')
- Children:
- 80dee2b8505d045ce3d5bf4fa6bee7b4383af86c
- Parents:
- 2daaaec2c36328eb8638fe3a6b61d9971c661dc4
- git-author:
- Karim Abou Zeid <karim23697@gmail.com>2021-03-27 19:21:22+01:00
- git-committer:
- Hans Schoenemann <hannes@mathematik.uni-kl.de>2021-03-30 00:45:51+02:00
- Location:
- kernel/combinatorics
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/combinatorics/hdegree.cc
r2daaae ra1ef3a2 19 19 #include "kernel/combinatorics/stairc.h" 20 20 #include "reporter/reporter.h" 21 22 #ifdef HAVE_SHIFTBBA 23 #include <vector> 24 #include "Singular/libsingular.h" 25 #endif 21 26 22 27 VAR int hCo, hMu, hMu2; … … 1668 1673 } 1669 1674 1670 static void _lp_computeStandardWords(ideal words, int n, ideal M, int& last) 1671 { 1672 // assume <M> != <1> 1673 if (n <= 0){ 1674 words->m[0] = pOne(); 1675 last = 0; 1675 // ATTENTION: 1676 // - `words` contains the words normal modulo M of length n 1677 // - `numberOfNormalWords` contains the number of words normal modulo M of length 0 ... n 1678 static void _lp_computeNormalWords(ideal words, int& numberOfNormalWords, int length, ideal M, int minDeg, int& last) 1679 { 1680 if (length <= 0){ 1681 poly one = pOne(); 1682 if (p_LPDivisibleBy(M, one, currRing)) // 1 \in M => no normal words at all 1683 { 1684 pDelete(&one); 1685 last = -1; 1686 numberOfNormalWords = 0; 1687 } 1688 else 1689 { 1690 words->m[0] = one; 1691 last = 0; 1692 numberOfNormalWords = 1; 1693 } 1676 1694 return; 1677 1695 } 1678 1696 1679 _lp_compute StandardWords(words, n - 1, M, last);1697 _lp_computeNormalWords(words, numberOfNormalWords, length - 1, M, minDeg, last); 1680 1698 1681 1699 int nVars = currRing->isLPring - currRing->LPncGenCount; 1700 int numberOfNewNormalWords = 0; 1682 1701 1683 1702 for (int j = nVars - 1; j >= 0; j--) … … 1693 1712 } 1694 1713 1695 int varOffset = (( n- 1) * currRing->isLPring) + 1;1714 int varOffset = ((length - 1) * currRing->isLPring) + 1; 1696 1715 pSetExp(words->m[index], varOffset + j, 1); 1697 1716 pSetm(words->m[index]); 1698 1717 pTest(words->m[index]); 1699 1718 1700 if ( p_LPDivisibleBy(M, words->m[index], currRing))1719 if (length >= minDeg && p_LPDivisibleBy(M, words->m[index], currRing)) 1701 1720 { 1702 1721 pDelete(&words->m[index]); 1703 1722 words->m[index] = NULL; 1704 1723 } 1724 else 1725 { 1726 numberOfNewNormalWords++; 1727 } 1705 1728 } 1706 1729 } … … 1708 1731 1709 1732 last = nVars * last + nVars - 1; 1710 } 1711 1712 static ideal lp_computeStandardWords(int n, ideal M) 1713 { 1733 1734 numberOfNormalWords += numberOfNewNormalWords; 1735 } 1736 1737 static ideal lp_computeNormalWords(int length, ideal M) 1738 { 1739 long minDeg = IDELEMS(M) > 0 ? pTotaldegree(M->m[0]) : 0; 1740 for (int i = 1; i < IDELEMS(M); i++) 1741 { 1742 minDeg = si_min(minDeg, pTotaldegree(M->m[i])); 1743 } 1744 1714 1745 int nVars = currRing->isLPring - currRing->LPncGenCount; 1715 1746 1716 1747 int maxElems = 1; 1717 for (int i = 0; i < n; i++) // maxElems = nVars^n1748 for (int i = 0; i < length; i++) // maxElems = nVars^n 1718 1749 maxElems *= nVars; 1719 1750 ideal words = idInit(maxElems); 1720 int last ;1721 _lp_compute StandardWords(words, n, M, last);1751 int last, numberOfNormalWords; 1752 _lp_computeNormalWords(words, numberOfNormalWords, length, M, minDeg, last); 1722 1753 idSkipZeroes(words); 1723 1754 return words; 1755 } 1756 1757 static int lp_countNormalWords(int upToLength, ideal M) 1758 { 1759 long minDeg = IDELEMS(M) > 0 ? pTotaldegree(M->m[0]) : 0; 1760 for (int i = 1; i < IDELEMS(M); i++) 1761 { 1762 minDeg = si_min(minDeg, pTotaldegree(M->m[i])); 1763 } 1764 1765 int nVars = currRing->isLPring - currRing->LPncGenCount; 1766 1767 int maxElems = 1; 1768 for (int i = 0; i < upToLength; i++) // maxElems = nVars^n 1769 maxElems *= nVars; 1770 ideal words = idInit(maxElems); 1771 int last, numberOfNormalWords; 1772 _lp_computeNormalWords(words, numberOfNormalWords, upToLength, M, minDeg, last); 1773 idDelete(&words); 1774 return numberOfNormalWords; 1724 1775 } 1725 1776 … … 1738 1789 int lV = currRing->isLPring; 1739 1790 1740 standardWords = lp_compute StandardWords(l, G);1791 standardWords = lp_computeNormalWords(l, G); 1741 1792 1742 1793 int n = IDELEMS(standardWords); … … 1823 1874 int ncGenCount = currRing->LPncGenCount; 1824 1875 if (lV - ncGenCount == 0) 1876 { 1877 idDelete(&G); 1825 1878 return 0; 1879 } 1826 1880 if (lV - ncGenCount == 1) 1881 { 1882 idDelete(&G); 1827 1883 return 1; 1884 } 1828 1885 if (lV - ncGenCount >= 2) 1886 { 1887 idDelete(&G); 1829 1888 return -1; 1889 } 1830 1890 } 1831 1891 … … 1840 1900 { 1841 1901 WerrorS("GK-Dim not defined for 0-ring"); 1902 idDelete(&G); 1842 1903 return -2; 1843 1904 } … … 1850 1911 int ncGenCount = currRing->LPncGenCount; 1851 1912 if (IDELEMS(G) == lV - ncGenCount) // V = {1} no edges 1913 { 1914 idDelete(&G); 1852 1915 return 0; 1916 } 1853 1917 if (IDELEMS(G) == lV - ncGenCount - 1) // V = {1} with loop 1918 { 1919 idDelete(&G); 1854 1920 return 1; 1921 } 1855 1922 if (IDELEMS(G) <= lV - ncGenCount - 2) // V = {1} with more than one loop 1923 { 1924 idDelete(&G); 1856 1925 return -1; 1926 } 1857 1927 } 1858 1928 1859 1929 ideal standardWords; 1860 1930 intvec* UG = lp_ufnarovskiGraph(G, standardWords); 1861 if (errorreported || UG == NULL) return -2; 1862 return graphGrowth(UG); 1931 if (UG == NULL) 1932 { 1933 idDelete(&G); 1934 return -2; 1935 } 1936 if (errorreported) 1937 { 1938 delete UG; 1939 idDelete(&G); 1940 return -2; 1941 } 1942 int gkDim = graphGrowth(UG); 1943 delete UG; 1944 idDelete(&G); 1945 return gkDim; 1946 } 1947 1948 // converts an intvec matrix to a vector<vector<int> > 1949 static std::vector<std::vector<int> > iv2vv(intvec* M) 1950 { 1951 int rows = M->rows(); 1952 int cols = M->cols(); 1953 1954 std::vector<std::vector<int> > mat(rows, std::vector<int>(cols)); 1955 1956 for (int i = 0; i < rows; i++) 1957 { 1958 for (int j = 0; j < cols; j++) 1959 { 1960 mat[i][j] = IMATELEM(*M, i + 1, j + 1); 1961 } 1962 } 1963 1964 return mat; 1965 } 1966 1967 static void vvPrint(const std::vector<std::vector<int> >& mat) 1968 { 1969 for (int i = 0; i < mat.size(); i++) 1970 { 1971 for (int j = 0; j < mat[i].size(); j++) 1972 { 1973 Print("%d ", mat[i][j]); 1974 } 1975 PrintLn(); 1976 } 1977 } 1978 1979 static void vvTest(const std::vector<std::vector<int> >& mat) 1980 { 1981 if (mat.size() > 0) 1982 { 1983 int cols = mat[0].size(); 1984 for (int i = 1; i < mat.size(); i++) 1985 { 1986 if (cols != mat[i].size()) 1987 WerrorS("number of cols in matrix inconsistent"); 1988 } 1989 } 1990 } 1991 1992 static void vvDeleteRow(std::vector<std::vector<int> >& mat, int row) 1993 { 1994 mat.erase(mat.begin() + row); 1995 } 1996 1997 static void vvDeleteColumn(std::vector<std::vector<int> >& mat, int col) 1998 { 1999 for (int i = 0; i < mat.size(); i++) 2000 { 2001 mat[i].erase(mat[i].begin() + col); 2002 } 2003 } 2004 2005 static BOOLEAN vvIsRowZero(const std::vector<std::vector<int> >& mat, int row) 2006 { 2007 for (int i = 0; i < mat[row].size(); i++) 2008 { 2009 if (mat[row][i] != 0) 2010 return FALSE; 2011 } 2012 return TRUE; 2013 } 2014 2015 static BOOLEAN vvIsColumnZero(const std::vector<std::vector<int> >& mat, int col) 2016 { 2017 for (int i = 0; i < mat.size(); i++) 2018 { 2019 if (mat[i][col] != 0) 2020 return FALSE; 2021 } 2022 return TRUE; 2023 } 2024 2025 static BOOLEAN vvIsZero(const std::vector<std::vector<int> >& mat) 2026 { 2027 for (int i = 0; i < mat.size(); i++) 2028 { 2029 if (!vvIsRowZero(mat, i)) 2030 return FALSE; 2031 } 2032 return TRUE; 2033 } 2034 2035 static std::vector<std::vector<int> > vvMult(const std::vector<std::vector<int> >& a, const std::vector<std::vector<int> >& b) 2036 { 2037 int ra = a.size(); 2038 int rb = b.size(); 2039 int ca = a.size() > 0 ? a[0].size() : 0; 2040 int cb = b.size() > 0 ? b[0].size() : 0; 2041 2042 if (ca != rb) 2043 { 2044 WerrorS("matrix dimensions do not match"); 2045 return std::vector<std::vector<int> >(); 2046 } 2047 2048 std::vector<std::vector<int> > res(ra, std::vector<int>(cb)); 2049 for (int i = 0; i < ra; i++) 2050 { 2051 for (int j = 0; j < cb; j++) 2052 { 2053 int sum = 0; 2054 for (int k = 0; k < ca; k++) 2055 sum += a[i][k] * b[k][j]; 2056 res[i][j] = sum; 2057 } 2058 } 2059 return res; 2060 } 2061 2062 static BOOLEAN isAcyclic(const intvec* G) 2063 { 2064 // init 2065 int n = G->cols(); 2066 std::vector<int> path; 2067 std::vector<BOOLEAN> visited; 2068 std::vector<BOOLEAN> cyclic; 2069 std::vector<int> cache; 2070 visited.resize(n, FALSE); 2071 cyclic.resize(n, FALSE); 2072 cache.resize(n, -2); 2073 2074 for (int v = 0; v < n; v++) 2075 { 2076 cache = countCycles(G, v, path, visited, cyclic, cache); 2077 // check that there are 0 cycles from v 2078 if (cache[v] != 0) 2079 return FALSE; 2080 } 2081 return TRUE; 2082 } 2083 2084 /* 2085 * Computation of the K-Dimension 2086 */ 2087 2088 // -1 is infinity, -2 is error 2089 int lp_kDim(const ideal _G) 2090 { 2091 if (rField_is_Ring(currRing)) { 2092 WerrorS("K-Dim not implemented for rings"); 2093 return -2; 2094 } 2095 2096 for (int i=IDELEMS(_G)-1;i>=0; i--) 2097 { 2098 if (_G->m[i] != NULL) 2099 { 2100 if (pGetComp(_G->m[i]) != 0) 2101 { 2102 WerrorS("K-Dim not implemented for modules"); 2103 return -2; 2104 } 2105 if (pGetNCGen(_G->m[i]) != 0) 2106 { 2107 WerrorS("K-Dim not implemented for bi-modules"); 2108 return -2; 2109 } 2110 } 2111 } 2112 2113 ideal G = id_Head(_G, currRing); // G = LM(G) (and copy) 2114 if (TEST_OPT_PROT) 2115 Print("%d original generators\n", IDELEMS(G)); 2116 idSkipZeroes(G); // remove zeros 2117 id_DelLmEquals(G, currRing); // remove duplicates 2118 if (TEST_OPT_PROT) 2119 Print("%d non-zero unique generators\n", IDELEMS(G)); 2120 2121 // check if G is the zero ideal 2122 if (IDELEMS(G) == 1 && G->m[0] == NULL) 2123 { 2124 // NOTE: this is needed because if the ideal is <0>, then idSkipZeroes keeps this element, and IDELEMS is still 1! 2125 int lV = currRing->isLPring; 2126 int ncGenCount = currRing->LPncGenCount; 2127 if (lV - ncGenCount == 0) 2128 { 2129 idDelete(&G); 2130 return 1; 2131 } 2132 if (lV - ncGenCount == 1) 2133 { 2134 idDelete(&G); 2135 return -1; 2136 } 2137 if (lV - ncGenCount >= 2) 2138 { 2139 idDelete(&G); 2140 return -1; 2141 } 2142 } 2143 2144 // get the max deg 2145 long maxDeg = 0; 2146 for (int i = 0; i < IDELEMS(G); i++) 2147 { 2148 maxDeg = si_max(maxDeg, pTotaldegree(G->m[i])); 2149 2150 // also check whether G = <1> 2151 if (pIsConstantComp(G->m[i])) 2152 { 2153 WerrorS("K-Dim not defined for 0-ring"); // TODO is it minus infinity ? 2154 idDelete(&G); 2155 return -2; 2156 } 2157 } 2158 if (TEST_OPT_PROT) 2159 Print("max deg: %ld\n", maxDeg); 2160 2161 2162 // for normal words of length minDeg ... maxDeg-1 2163 // brute-force the normal words 2164 if (TEST_OPT_PROT) 2165 PrintS("Computing normal words normally...\n"); 2166 long numberOfNormalWords = lp_countNormalWords(maxDeg - 1, G); 2167 2168 if (TEST_OPT_PROT) 2169 Print("%ld normal words up to length %ld\n", numberOfNormalWords, maxDeg - 1); 2170 2171 // early termination if G \subset X 2172 if (maxDeg <= 1) 2173 { 2174 int lV = currRing->isLPring; 2175 int ncGenCount = currRing->LPncGenCount; 2176 if (IDELEMS(G) == lV - ncGenCount) // V = {1} no edges 2177 { 2178 idDelete(&G); 2179 return numberOfNormalWords; 2180 } 2181 if (IDELEMS(G) == lV - ncGenCount - 1) // V = {1} with loop 2182 { 2183 idDelete(&G); 2184 return -1; 2185 } 2186 if (IDELEMS(G) <= lV - ncGenCount - 2) // V = {1} with more than one loop 2187 { 2188 idDelete(&G); 2189 return -1; 2190 } 2191 } 2192 2193 if (TEST_OPT_PROT) 2194 PrintS("Computing Ufnarovski graph...\n"); 2195 2196 ideal standardWords; 2197 intvec* UG = lp_ufnarovskiGraph(G, standardWords); 2198 if (UG == NULL) 2199 { 2200 idDelete(&G); 2201 return -2; 2202 } 2203 if (errorreported) 2204 { 2205 delete UG; 2206 idDelete(&G); 2207 return -2; 2208 } 2209 2210 if (TEST_OPT_PROT) 2211 Print("Ufnarovski graph is %dx%d.\n", UG->rows(), UG->cols()); 2212 2213 if (TEST_OPT_PROT) 2214 PrintS("Checking whether Ufnarovski graph is acyclic...\n"); 2215 2216 if (!isAcyclic(UG)) 2217 { 2218 // in this case we have infinitely many normal words 2219 return -1; 2220 } 2221 2222 std::vector<std::vector<int> > vvUG = iv2vv(UG); 2223 for (int i = 0; i < vvUG.size(); i++) 2224 { 2225 if (vvIsRowZero(vvUG, i) && vvIsColumnZero(vvUG, i)) // i is isolated vertex 2226 { 2227 vvDeleteRow(vvUG, i); 2228 vvDeleteColumn(vvUG, i); 2229 i--; 2230 } 2231 } 2232 if (TEST_OPT_PROT) 2233 Print("Simplified Ufnarovski graph to %ldx%ld.\n", vvUG.size(), vvUG.size()); 2234 2235 // for normal words of length >= maxDeg 2236 // use Ufnarovski graph 2237 if (TEST_OPT_PROT) 2238 PrintS("Computing normal words via Ufnarovski graph...\n"); 2239 std::vector<std::vector<int> > UGpower = vvUG; 2240 long nUGpower = 1; 2241 while (!vvIsZero(UGpower)) 2242 { 2243 if (TEST_OPT_PROT) 2244 PrintS("Start count graph entries.\n"); 2245 for (int i = 0; i < UGpower.size(); i++) 2246 { 2247 for (int j = 0; j < UGpower[i].size(); j++) 2248 { 2249 numberOfNormalWords += UGpower[i][j]; 2250 } 2251 } 2252 2253 if (TEST_OPT_PROT) 2254 { 2255 PrintS("Done count graph entries.\n"); 2256 Print("%ld normal words up to length %ld\n", numberOfNormalWords, maxDeg - 1 + nUGpower); 2257 } 2258 2259 if (TEST_OPT_PROT) 2260 PrintS("Start mat mult.\n"); 2261 UGpower = vvMult(UGpower, vvUG); // TODO: avoid creation of new intvec 2262 if (TEST_OPT_PROT) 2263 PrintS("Done mat mult.\n"); 2264 nUGpower++; 2265 } 2266 2267 delete UG; 2268 idDelete(&G); 2269 return numberOfNormalWords; 1863 2270 } 1864 2271 #endif -
kernel/combinatorics/stairc.h
r2daaae ra1ef3a2 34 34 #if HAVE_SHIFTBBA 35 35 int lp_gkDim(const ideal G); 36 int lp_kDim(const ideal G); 36 37 intvec * lp_ufnarovskiGraph(ideal G, ideal &standardWords); 37 38 #endif
Note: See TracChangeset
for help on using the changeset viewer.