Macaulay2 Engine
Loading...
Searching...
No Matches
res-f4-computation.cpp
Go to the documentation of this file.
1/* Copyright 2014, Michael E. Stillman */
2
3#include <iostream>
4
9
10#include "matrix.hpp"
11#include "exceptions.hpp"
12
13#include <iostream>
14
16class MutableMatrix;
17
18long nres = 0;
20
27ResolutionComputation* createF4Res(const Matrix* groebnerBasisMatrix,
28 int max_level,
29 int strategy,
30 int numThreads,
31 bool parallelizeByDegree)
32{
33 // We expect the following to hold:
34 // the ring of groebnerBasisMatrix is a PolynomialRing, but not:
35 // quotient ring
36 // Weyl algebra
37 // We assume also that the matrix is homogeneous.
38 // If any of these are incorrect, an error message is provided, and
39 // null is returned.
40 (void) strategy;
41 const PolynomialRing* origR =
42 groebnerBasisMatrix->get_ring()->cast_to_PolynomialRing();
43 if (origR == nullptr)
44 {
45 ERROR("expected polynomial ring");
46 return nullptr;
47 }
48 if (origR->is_quotient_ring())
49 {
50 ERROR("cannot use res(...,FastNonminimal=>true) for quotient rings");
51 return nullptr;
52 }
53 if (origR->is_weyl_algebra())
54 {
55 ERROR("cannot use res(...,FastNonminimal=>true) over Weyl algebras");
56 return nullptr;
57 }
58 if (origR->is_solvable_algebra())
59 {
60 ERROR(
61 "cannot use res(...,FastNonminimal=>true) over non-commutative "
62 "algebras");
63 return nullptr;
64 }
65 // if (!groebnerBasisMatrix->is_homogeneous())
66 // {
67 // ERROR(
68 // "cannot use res(...,FastNonminimal=>true) with inhomogeneous input");
69 // return nullptr;
70 // }
71 // if (origR->getMonoid()->get_degree_ring()->n_vars() != 1)
72 // {
73 // ERROR("expected singly graded with positive degrees for the variables");
74 // return nullptr;
75 // }
77 {
78 ERROR("expected the degree of each variable to be positive");
79 return nullptr;
80 }
81 // Still to check:
82 // (a) coefficients are ZZ/p, for p in range.
83
84 const Ring* K = origR->getCoefficients();
85 auto mo = origR->getMonoid()->getMonomialOrdering(); // mon ordering
87 if (moIsLex(mo))
89 else if (moIsGRevLex(mo))
91
92 auto MI = new ResMonoid(origR->n_vars(),
95 motype);
96 ResPolyRing* R;
97 if (origR->is_skew_commutative())
98 {
99 R = new ResPolyRing(K, MI, origR->getMonoid(), &(origR->getSkewInfo()));
100 }
101 else
102 {
103 R = new ResPolyRing(K, MI, origR->getMonoid());
104 }
105 auto result = new F4ResComputation(origR, R, groebnerBasisMatrix, max_level, numThreads, parallelizeByDegree);
106
107 // Set level 0
108 // take the columns of the matrix, and insert them into mComp
109 const FreeModule* F = groebnerBasisMatrix->rows();
110 int maxdeg = 0;
111 if (F->rank() > 0)
112 {
113 maxdeg = F->primary_degree(0);
114 for (int j = 1; j < F->rank(); j++)
115 if (maxdeg < F->primary_degree(j)) maxdeg = F->primary_degree(j);
116 }
117
118 // Set level 0
119 // take the info from F, place it into mComp
120 SchreyerFrame& frame = result->frame();
121 for (int i = 0; i < F->rank(); i++)
122 {
124 frame.monomialBlock().allocate(MI->max_monomial_size());
125 MI->one(i, elem);
126 frame.insertLevelZero(elem, F->primary_degree(i), maxdeg);
127 }
128 frame.endLevel();
129
130 // At this point, we want to sort the columns of groebnerBasisMatrix.
131 Matrix* leadterms = groebnerBasisMatrix->lead_term();
132 M2_arrayint pos = leadterms->sort(1 /* ascending degree */,
133 -1 /* descending monomial order */);
134
135 std::vector<ResPolynomial> input_polys;
136 for (int i = 0; i < groebnerBasisMatrix->n_cols(); i++)
137 {
139 ResF4toM2Interface::from_M2_vec(*R, F, groebnerBasisMatrix->elem(i), f);
140 input_polys.emplace_back(std::move(f));
141 }
142
143 // Set level 1.
144 for (int j = 0; j < F->rank(); j++)
145 {
146 // Only insert the ones whose lead monomials are in component j:
147 for (int i = 0; i < pos->len; i++)
148 {
149 int loc = pos->array[i];
150 ResPolynomial& f = input_polys[loc];
151 if (f.len == 0) continue;
152 if (MI->get_component(f.monoms.data()) != j) continue;
154 frame.monomialBlock().allocate(MI->max_monomial_size());
155 MI->copy(f.monoms.data(), elem);
156 // the following line grabs f.
157 if (!frame.insertLevelOne(
158 elem, groebnerBasisMatrix->cols()->primary_degree(loc), f))
159 {
160 ERROR(
161 "input polynomials/vectors were computed in a non-compatible "
162 "monomial order");
163 // TODO: clean up.
164 return nullptr;
165 }
166 }
167 }
168 frame.endLevel();
169 // frame.show(0);
170 // Remove matrix:
171 delete leadterms;
172
173 return result;
174}
175
177 ResPolyRing* R,
178 const Matrix* gbmatrix,
179 int max_level,
180 int numThreads,
181 bool parallelizeByDegree)
182
183 : mOriginalRing(*origR),
184 mInputGroebnerBasis(*gbmatrix),
185 mRing(R),
186 mComp(new SchreyerFrame(*mRing, max_level, numThreads, parallelizeByDegree))
187{
188 // mComp.reset(new SchreyerFrame(*mRing, max_level)); // might need
189 // gbmatrix->rows() too
190 nres++;
191}
192
194{
195 // The following lines should not be required.
196 // mComp.reset(); mComp = nullptr;
198}
199
200void F4ResComputation::start_computation() { mComp->start_computation(stop_); }
201
203// The computation is complete up through this degree.
204{
205 throw exc::engine_error("complete_thru_degree not implemented");
206}
207
209// type is documented under rawResolutionBetti, in engine.h
210{
211 return mComp->getBetti(type);
212}
213
215 M2_arrayint length_limit)
216{
217 bool stop_after_degree = (slanted_degree_limit->len == 1);
218 int top_slanted_degree = slanted_degree_limit->array[0];
219 int new_length_limit = (length_limit->len == 1 ? length_limit->array[0]
220 : frame().maxLevel() - 1);
221
222 // std::cout << "---- show mComp ------------------------" << std::endl;
223 // mComp->show(0);
224 // std::cout << "stop, topdeg, newlength: " << stop_after_degree << " "
225 // << top_slanted_degree << " " << new_length_limit << std::endl;
226 // std::cout << "---- end show mComp ------------------------" << std::endl;
227
229 stop_after_degree, top_slanted_degree, new_length_limit);
230 return B.getBetti();
231}
232
234{
235 o << "F4 resolution computation" << newline;
236}
237
238const Matrix /* or null */* F4ResComputation::get_matrix(int level)
239{
240 if (mOriginalRing.getCoefficientRing()->is_QQ())
241 {
242 std::cout << "setting error message, returning null" << std::endl;
243 ERROR("cannot create differential over this ring");
244 return nullptr;
245 }
246 const FreeModule* tar = get_free(level - 1);
247 const FreeModule* src = get_free(level);
248 return ResF4toM2Interface::to_M2_matrix(*mComp, level, tar, src);
249}
250
251MutableMatrix /* or null */* F4ResComputation::get_matrix(int level, int degree)
252{
253 if (mOriginalRing.getCoefficientRing()->is_QQ())
254 {
255 ERROR("cannot create differential over this ring");
256 return nullptr;
257 }
259 *mComp, mOriginalRing.getCoefficientRing(), level, degree);
260}
261
262const FreeModule /* or null */* F4ResComputation::get_free(int lev)
263{
264 if (lev < 0 or lev > mComp->maxLevel())
265 return mOriginalRing.make_FreeModule(0);
266 if (lev == 0) return mInputGroebnerBasis.rows();
268}
269
271 int level)
272{
274}
275
277 const Ring* KK,
278 int slanted_degree,
279 int level)
280{
282 frame(), KK, level, slanted_degree);
283}
284
285// Local Variables:
286// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
287// indent-tabs-mode: nil
288// End:
M2_arrayint getBetti() const
Definition betti.cpp:82
Engine-side Betti table: a (degree, homological level) rectangle of integers.
Definition betti.hpp:60
StopConditions stop_
Definition comp.hpp:75
M2_arrayint get_betti(int type) const
int complete_thru_degree() const
F4ResComputation(const PolynomialRing *origR, ResPolyRing *R, const Matrix *gbmatrix, int max_level, int numThreads, bool parallelizeByDegree)
const Matrix * get_matrix(int level)
std::unique_ptr< SchreyerFrame > mComp
const FreeModule * get_free(int level)
M2_arrayint minimal_betti(M2_arrayint slanted_degree_limit, M2_arrayint length_limit)
void text_out(buffer &o) const
std::unique_ptr< ResPolyRing > mRing
SchreyerFrame & frame()
const PolynomialRing & mOriginalRing
MutableMatrix * get_mutable_matrix(const Ring *R, int level)
const Matrix & mInputGroebnerBasis
ResolutionComputation subclass that drives the F4 resolution engine (SchreyerFrame + F4Res) from the ...
int primary_degree(int i) const
Definition freemod.cpp:440
int rank() const
Definition freemod.hpp:105
Engine-side free module R^n over a Ring.
Definition freemod.hpp:66
const Ring * get_ring() const
Definition matrix.hpp:134
ring_elem elem(int i, int j) const
Definition matrix.cpp:307
int n_cols() const
Definition matrix.hpp:147
const FreeModule * rows() const
Definition matrix.hpp:144
Matrix * lead_term(int n=-1) const
Definition matrix.cpp:840
M2_arrayint sort(int degorder, int monorder) const
const FreeModule * cols() const
Definition matrix.hpp:145
bool primary_degrees_of_vars_positive() const
Definition monoid.cpp:298
std::vector< int > getPrimaryDegreeVector() const
Definition monoid.cpp:237
const MonomialOrdering * getMonomialOrdering() const
Definition monoid.hpp:173
std::vector< int > getFirstWeightVector() const
Definition monoid.cpp:220
Abstract base class for mutable matrices over an arbitrary engine Ring, the in-place counterpart of t...
Definition mat.hpp:79
virtual bool is_solvable_algebra() const
Definition polyring.hpp:258
virtual const Monoid * getMonoid() const
Definition polyring.hpp:282
bool is_quotient_ring() const
Definition polyring.hpp:235
virtual const Ring * getCoefficients() const
Definition polyring.hpp:277
virtual bool is_weyl_algebra() const
Definition polyring.hpp:248
const SkewMultiplication & getSkewInfo() const
Definition polyring.hpp:241
int n_vars() const
Definition polyring.hpp:196
bool is_skew_commutative() const
Definition polyring.hpp:237
Abstract base for the engine's polynomial-ring hierarchy.
Definition polyring.hpp:96
static FreeModule * to_M2_freemodule(const PolynomialRing *R, SchreyerFrame &C, int lev)
static MutableMatrix * to_M2_MutableMatrix(SchreyerFrame &C, const Ring *R, int lev)
static void from_M2_vec(const ResPolyRing &R, const FreeModule *F, vec v, ResPolynomial &result)
static Matrix * to_M2_matrix(SchreyerFrame &C, int lev, const FreeModule *tar, const FreeModule *src)
T * allocate(int len=1)
The polynomial-ring view the F4 resolution engine reduces against: coefficient arithmetic plus the en...
std::vector< res_monomial_word > monoms
Polynomial type used by the F4 resolution engine: parallel coefficient vector and concatenated monomi...
Base class for free resolution computation classes.
Definition comp-res.hpp:52
virtual const PolynomialRing * cast_to_PolynomialRing() const
Definition ring.hpp:243
xxx xxx xxx
Definition ring.hpp:102
BettiDisplay minimalBettiNumbers(bool stop_after_degree, int top_slanted_degree, int length_limit)
void insertLevelZero(res_packed_monomial monom, int degree, int maxdeglevel0)
ResMemoryBlock< res_monomial_word > & monomialBlock()
bool insertLevelOne(res_packed_monomial monom, int degree, ResPolynomial &syzygy)
State container for the in-progress free resolution built by the F4 resolution engine.
namespace exc — internal C++ exception types and the TRY / CATCH macro pair.
#define Matrix
Definition factory.cpp:14
long nres_destruct
long nres
const int ERROR
Definition m2-mem.cpp:55
VALGRIND_MAKE_MEM_DEFINED & result(result)
char newline[]
Definition m2-types.cpp:49
Matrix — the engine's immutable homomorphism F -> G between free modules.
int moIsLex(const MonomialOrdering *mo)
int moIsGRevLex(const MonomialOrdering *mo)
Engine-boundary C API for assembling block-level MonomialOrderings from declarative pieces.
ResolutionComputation * createF4Res(const Matrix *groebnerBasisMatrix, int max_level, int strategy, int numThreads, bool parallelizeByDegree)
F4ResComputation — top-level Schreyer-frame F4 free-resolution driver.
Conversion layer between engine Matrix / vec types and the F4-resolution internal types.
ResMonoidDense ResMonoid
res_monomial_word * res_packed_monomial
SchreyerFrame — in-progress representation of a free resolution organised by (level,...