FreeModule *FreeModule::make_schreyer(const GBMatrix *m) { const FreeModule *F = m->get_free_module(); const PolynomialRing *R = F->get_ring()->cast_to_PolynomialRing(); if (R == 0) { ERROR("expected a polynomial ring"); return nullptr; } FreeModule *G = R->make_FreeModule(); int rk = INTSIZE(m->elems); if (rk == 0) return G; for (int i=0; i<rk; i++) { int *deg = R->degree_monoid()->make_one(); gbvector * v = m->elems[i]; if (v != 0) R->get_gb_ring()->gbvector_multidegree(F, v, deg); G->append(deg); } G->schreyer = SchreyerOrder::create(m); return G; }
FreeModule *FreeModule::exterior(int pp) const // p th exterior power { FreeModule *result; if (pp == 0) return get_ring()->make_FreeModule(1); else result = new_free(); int rk = rank(); if (pp > rk || pp < 0) return result; size_t p = static_cast<size_t>(pp); Subset a(p, 0); for (size_t i=0; i<p; i++) a[i] = i; int *deg = degree_monoid()->make_one(); do { degree_monoid()->one(deg); for (size_t r=0; r<p; r++) degree_monoid()->mult(deg, degree(static_cast<int>(a[r])), deg); result->append(deg); } while (Subsets::increment(rk, a)); degree_monoid()->remove(deg); if (schreyer != NULL) result->schreyer = schreyer->exterior(pp); return result; }
FreeModule *FreeModule::direct_sum(const FreeModule *G) const // direct sum { int i; if (get_ring() != G->get_ring()) { ERROR("expected free modules over the same ring"); return 0; } FreeModule *result = new_free(); for (i=0; i<rank(); i++) result->append(degree(i)); for (i=0; i<G->rank(); i++) result->append(G->degree(i)); // if (schreyer != NULL && G->schreyer != NULL) // result->schreyer = schreyer->direct_sum(G->schreyer); return result; }
FreeModule *FreeModule::transpose() const { FreeModule *result = new_free(); int *deg = degree_monoid()->make_one(); for (int i=0; i<rank(); i++) { degree_monoid()->power(degree(i), -1, deg); result->append(deg); } // result has no schreyer order degree_monoid()->remove(deg); return result; }
FreeModule *FreeModule::sub_space(int n) const { if (n < 0 || n > rank()) { ERROR("subfreemodule: index out of bounds"); return NULL; } FreeModule *result = new_free(); for (int i=0; i<n; i++) result->append(degree(i)); if (schreyer != NULL) result->schreyer = schreyer->sub_space(n); return result; }
FreeModule *FreeModule::make_schreyer(const Matrix *m) { int i; const Ring *R = m->get_ring(); FreeModule *F = R->make_FreeModule(); int rk = m->n_cols(); if (rk == 0) return F; for (i=0; i<rk; i++) F->append(m->cols()->degree(i)); F->schreyer = SchreyerOrder::create(m); return F; }
FreeModule *FreeModule::sub_space(M2_arrayint a) const { FreeModule *result = new_free(); for (unsigned int i=0; i<a->len; i++) if (a->array[i] >= 0 && a->array[i] < rank()) result->append(degree(a->array[i])); else { ERROR("subfreemodule: index out of bounds"); deleteitem(result); return NULL; } if (schreyer != NULL) result->schreyer = schreyer->sub_space(a); return result; }
FreeModule *FreeModule::shift(const int *d) const // Shift degree by d. { FreeModule *result = new_free(); int *deg = degree_monoid()->make_one(); for (int i=0; i<rank(); i++) { degree_monoid()->mult(degree(i), d, deg); result->append(deg); } if (schreyer != NULL) result->schreyer = schreyer->copy(); degree_monoid()->remove(deg); return result; }
void symm1(int lastn, // can use lastn..rank()-1 in product int pow) const // remaining power to take { if (pow == 0) symm1_result->append(symm1_deg); else { for (int i=lastn; i<F->rank(); i++) { // increase symm1_deg, with e_i D->mult(symm1_deg, F->degree(i), symm1_deg); symm1(i, pow-1); // decrease symm1_deg back D->divide(symm1_deg, F->degree(i), symm1_deg); } } }
FreeModule *FreeModule::make_schreyer(const Matrix *m) { int i; const PolynomialRing *R = m->get_ring()->cast_to_PolynomialRing(); if (R == 0) { ERROR("expected a polynomial ring"); return nullptr; } FreeModule *F = R->make_FreeModule(); int rk = m->n_cols(); if (rk == 0) return F; for (i=0; i<rk; i++) F->append(m->cols()->degree(i)); F->schreyer = SchreyerOrder::create(m); return F; }
FreeModule *FreeModule::tensor(const FreeModule *G) const // tensor product { if (get_ring() != G->get_ring()) { ERROR("expected free modules over the same ring"); return 0; } FreeModule *result = new_free(); int *deg = degree_monoid()->make_one(); for (int i=0; i<rank(); i++) for (int j=0; j<G->rank(); j++) { degree_monoid()->mult(degree(i), G->degree(j), deg); result->append(deg); } degree_monoid()->remove(deg); if (schreyer != NULL && G->schreyer != NULL) result->schreyer = schreyer->tensor(G->schreyer); return result; }
FreeModule *FreeModule::exterior(int p) const // p th exterior power { FreeModule *result; int rk = rank(); if (p == 0) return get_ring()->make_FreeModule(1); else result = new_free(); if (p > rk || p < 0) return result; int *a = newarray_atomic(int,p); for (int i=0; i<p; i++) a[i] = i; int *deg = degree_monoid()->make_one(); do { degree_monoid()->one(deg); for (int r=0; r<p; r++) degree_monoid()->mult(deg, degree(a[r]), deg); result->append(deg); } while (comb::increment(p, rk, a)); degree_monoid()->remove(deg); deletearray(a); if (schreyer != NULL) result->schreyer = schreyer->exterior(p); return result; }