Changeset d906dc in git for Singular/dyn_modules/freealgebra/freealgebra.cc
- Timestamp:
- Jun 4, 2019, 2:33:32 PM (5 years ago)
- Branches:
- (u'spielwiese', 'fe61d9c35bf7c61f2b6cbf1b56e25e2f08d536cc')
- Children:
- d4cec6ab781a81162945ff680935242fcccc952a
- Parents:
- 56ff8efc45f5392a6e465782a66a5df5a54180f01708fac9cfbd392cceea00167eaa2746d291cd98
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
Singular/dyn_modules/freealgebra/freealgebra.cc
r1708fa rd906dc 1 1 #include "Singular/libsingular.h" 2 #include <vector> 2 3 3 4 #ifdef HAVE_SHIFTBBA … … 80 81 } 81 82 83 static BOOLEAN p_LPDivisibleBy(ideal I, poly p, ring r) 84 { 85 for(int i = 0; i < IDELEMS(I); i++) 86 { 87 if (p_LPDivisibleBy(I->m[i], p, r)) 88 { 89 return TRUE; 90 } 91 } 92 return FALSE; 93 } 94 82 95 static BOOLEAN lpLmDivides(leftv res, leftv h) 83 96 { … … 97 110 poly q=(poly)h->next->Data(); 98 111 res->rtyp = INT_CMD; 99 for(int i=0;i<IDELEMS(I);i++) 100 { 101 if (p_LPDivisibleBy(I->m[i],q, currRing)) 102 { 103 res->data=(void*)(long)1; 104 return FALSE; 105 } 106 } 107 res->data=(void*)(long)0; 112 res->data=(void*)(long) p_LPDivisibleBy(I, q, currRing); 108 113 return FALSE; 109 114 } … … 124 129 else return TRUE; 125 130 } 131 132 static void _computeStandardWords(ideal words, int n, ideal M, int& last) 133 { 134 if (n <= 0){ 135 words->m[0] = pOne(); 136 last = 0; 137 return; 138 } 139 140 _computeStandardWords(words, n - 1, M, last); 141 142 int nVars = currRing->isLPring; 143 144 for (int j = nVars - 1; j >= 0; j--) 145 { 146 for (int i = last; i >= 0; i--) 147 { 148 int index = (j * (last + 1)) + i; 149 150 if (words->m[i] != NULL) 151 { 152 if (j > 0) { 153 words->m[index] = pCopy(words->m[i]); 154 } 155 156 int varOffset = ((n - 1) * nVars) + 1; 157 pSetExp(words->m[index], varOffset + j, 1); 158 pSetm(words->m[index]); 159 pTest(words->m[index]); 160 161 if (p_LPDivisibleBy(M, words->m[index], currRing)) 162 { 163 pDelete(&words->m[index]); 164 words->m[index] = NULL; 165 } 166 } 167 } 168 } 169 170 last = nVars * last + nVars - 1; 171 } 172 173 static ideal computeStandardWords(int n, ideal M) 174 { 175 int nVars = currRing->isLPring; 176 177 int maxElems = 1; 178 for (int i = 0; i < n; i++) // maxElems = nVars^n 179 maxElems *= nVars; 180 ideal words = idInit(maxElems); 181 int last; 182 _computeStandardWords(words, n, M, last); 183 idSkipZeroes(words); 184 return words; 185 } 186 187 // NULL if graph is undefined 188 static intvec* ufnarovskiGraph(ideal G) 189 { 190 long l = 0; 191 for (int i = 0; i < IDELEMS(G); i++) 192 l = si_max(pTotaldegree(G->m[i]), l); 193 l--; 194 if (l <= 0) 195 { 196 WerrorS("Ufnarovski graph not implemented for l <= 0"); 197 return NULL; 198 } 199 int lV = currRing->isLPring; 200 201 ideal standardWords = computeStandardWords(l, G); 202 203 int n = IDELEMS(standardWords); 204 intvec* UG = new intvec(n, n, 0); 205 for (int i = 0; i < n; i++) 206 { 207 for (int j = 0; j < n; j++) 208 { 209 poly v = standardWords->m[i]; 210 poly w = standardWords->m[j]; 211 212 // check whether v*x1 = x2*w (overlap) 213 bool overlap = true; 214 for (int k = 1; k <= (l - 1) * lV; k++) 215 { 216 if (pGetExp(v, k + lV) != pGetExp(w, k)) { 217 overlap = false; 218 break; 219 } 220 } 221 222 if (overlap) 223 { 224 // create the overlap 225 poly p = pMult(pCopy(v), p_LPVarAt(w, l, currRing)); 226 227 // check whether the overlap is normal 228 bool normal = true; 229 for (int k = 0; k < IDELEMS(G); k++) 230 { 231 if (p_LPDivisibleBy(G->m[k], p, currRing)) 232 { 233 normal = false; 234 break; 235 } 236 } 237 238 if (normal) 239 { 240 IMATELEM(*UG, i + 1, j + 1) = 1; 241 } 242 } 243 } 244 } 245 return UG; 246 } 247 248 static std::vector<int> countCycles(const intvec* _G, int v, std::vector<int> path, std::vector<BOOLEAN> visited, std::vector<BOOLEAN> cyclic, std::vector<int> cache) 249 { 250 intvec* G = ivCopy(_G); // modifications must be local 251 252 if (cache[v] != -2) return cache; // value is already cached 253 254 visited[v] = TRUE; 255 path.push_back(v); 256 257 int cycles = 0; 258 for (int w = 0; w < G->cols(); w++) 259 { 260 if (IMATELEM(*G, v + 1, w + 1)) // edge v -> w exists in G 261 { 262 if (!visited[w]) 263 { // continue with w 264 cache = countCycles(G, w, path, visited, cyclic, cache); 265 if (cache[w] == -1) 266 { 267 cache[v] = -1; 268 return cache; 269 } 270 cycles = si_max(cycles, cache[w]); 271 } 272 else 273 { // found new cycle 274 int pathIndexOfW = -1; 275 for (int i = path.size() - 1; i >= 0; i--) { 276 if (cyclic[path[i]] == 1) { // found an already cyclic vertex 277 cache[v] = -1; 278 return cache; 279 } 280 cyclic[path[i]] = TRUE; 281 282 if (path[i] == w) { // end of the cycle 283 assume(IMATELEM(*G, v + 1, w + 1) != 0); 284 IMATELEM(*G, v + 1, w + 1) = 0; // remove edge v -> w 285 pathIndexOfW = i; 286 break; 287 } else { 288 assume(IMATELEM(*G, path[i - 1] + 1, path[i] + 1) != 0); 289 IMATELEM(*G, path[i - 1] + 1, path[i] + 1) = 0; // remove edge vi-1 -> vi 290 } 291 } 292 assume(pathIndexOfW != -1); // should never happen 293 for (int i = path.size() - 1; i >= pathIndexOfW; i--) { 294 cache = countCycles(G, path[i], path, visited, cyclic, cache); 295 if (cache[path[i]] == -1) 296 { 297 cache[v] = -1; 298 return cache; 299 } 300 cycles = si_max(cycles, cache[path[i]] + 1); 301 } 302 } 303 } 304 } 305 cache[v] = cycles; 306 307 delete G; 308 return cache; 309 } 310 311 // -1 is infinity 312 static int graphGrowth(const intvec* G) 313 { 314 // init 315 int n = G->cols(); 316 std::vector<int> path; 317 std::vector<BOOLEAN> visited; 318 std::vector<BOOLEAN> cyclic; 319 std::vector<int> cache; 320 visited.resize(n, FALSE); 321 cyclic.resize(n, FALSE); 322 cache.resize(n, -2); 323 324 // get max number of cycles 325 int cycles = 0; 326 for (int v = 0; v < n; v++) 327 { 328 cache = countCycles(G, v, path, visited, cyclic, cache); 329 if (cache[v] == -1) 330 return -1; 331 cycles = si_max(cycles, cache[v]); 332 } 333 return cycles; 334 } 335 336 // -1 is infinity, -2 is error 337 static int gkDim(const ideal _G) 338 { 339 if (rField_is_Ring(currRing)) { 340 WerrorS("GK-Dim not implemented for rings"); 341 return -2; 342 } 343 344 for (int i=IDELEMS(_G)-1;i>=0; i--) 345 { 346 if (pGetComp(_G->m[i]) != 0) 347 { 348 WerrorS("GK-Dim not implemented for modules"); 349 return -2; 350 } 351 } 352 353 ideal G = id_Head(_G, currRing); // G = LM(G) (and copy) 354 idSkipZeroes(G); // remove zeros 355 id_DelLmEquals(G, currRing); // remove duplicates 356 357 // get the max deg 358 long maxDeg = 0; 359 for (int i = 0; i < IDELEMS(G); i++) 360 { 361 maxDeg = si_max(maxDeg, pTotaldegree(G->m[i])); 362 363 // also check whether G = <1> 364 if (pIsConstantComp(G->m[i])) 365 { 366 WerrorS("GK-Dim not defined for 0-ring"); 367 return -2; 368 } 369 } 370 371 // early termination if G \subset X 372 if (maxDeg <= 1) 373 { 374 int lV = currRing->isLPring; 375 if (IDELEMS(G) == lV) // V = {1} no edges 376 return 0; 377 if (IDELEMS(G) == lV - 1) // V = {1} with loop 378 return 1; 379 if (IDELEMS(G) <= lV - 2) // V = {1} with more than one loop 380 return -1; 381 } 382 383 intvec* UG = ufnarovskiGraph(G); 384 if (errorreported || UG == NULL) return -2; 385 return graphGrowth(UG); 386 } 387 388 389 static BOOLEAN lpGkDim(leftv res, leftv h) 390 { 391 const short t[]={1,IDEAL_CMD}; 392 if (iiCheckTypes(h,t,1)) 393 { 394 assumeStdFlag(h); 395 ideal G = (ideal) h->Data(); 396 res->rtyp = INT_CMD; 397 res->data = (void*)(long) gkDim(G); 398 if (errorreported) return TRUE; 399 return FALSE; 400 } 401 else return TRUE; 402 } 126 403 #endif 127 404 … … 134 411 p->iiAddCproc("freealgebra.so","lpLmDivides",FALSE,lpLmDivides); 135 412 p->iiAddCproc("freealgebra.so","lpVarAt",FALSE,lpVarAt); 413 p->iiAddCproc("freealgebra.so","lpGkDim",FALSE,lpGkDim); 414 136 415 p->iiAddCproc("freealgebra.so","stest",TRUE,stest); 137 416 p->iiAddCproc("freealgebra.so","btest",TRUE,btest);
Note: See TracChangeset
for help on using the changeset viewer.