Macaulay2 Engine
Loading...
Searching...
No Matches
groebner.cpp
Go to the documentation of this file.
1// Copyright 2002 Michael E. Stillman
2
4
5#include <iostream>
6#include <limits>
7#include <sstream>
8
9#include "Eschreyer.hpp"
10#include "hilb.hpp"
11#include "comp-gb.hpp"
12#include "comp-res.hpp"
13#include "comp-gb-declared.hpp"
14#include "text-io.hpp"
15#include "sagbi.hpp"
16#include "exceptions.hpp"
17#include "gb-walk.hpp"
18#include "relem.hpp"
19#include "util.hpp"
20#include "matrix-ncbasis.hpp"
21
22#include "M2FreeAlgebra.hpp"
25#include "NCAlgebras/NCF4.hpp"
26
27#include "poly.hpp"
28#include "interrupted.hpp"
30
31class FreeModule;
32struct MonomialOrdering;
33struct MutableMatrix;
34struct RingMap;
35
37
39{
40 // const PolynomialRing *P = R->cast_to_PolynomialRing();
41 if (R->get_precision() > 0)
42 {
44 {
45 buffer o;
46 o << "-- warning: experimental computation over inexact field begun"
47 << newline;
48 o << "-- results not reliable (one warning given per "
49 "session)"
50 << newline;
51 emit(o.str());
53 }
54 }
55}
56
58const RingElement /* or null */ *IM2_Matrix_Hilbert(const Matrix *M)
59/* This routine computes the numerator of the Hilbert series
60 for coker leadterms(M), using the degrees of the rows of M.
61 nullptr is returned if the ring is not appropriate for
62 computing Hilbert series, or the computation was interrupted. */
63{
64 try
65 {
67 } catch (const exc::engine_error& e)
68 {
69 ERROR(e.what());
70 return nullptr;
71 }
72}
73
75/* Assuming that the columns of G form a GB, this routine computes
76 a Groebner basis of the kernel of these elements, using an
77 appropriate Schreyer order on the source of G. */
78{
79 GBMatrix *N = new GBMatrix(M);
81 G.calc();
82 GBMatrix *syz = G.get_syzygies();
83 return syz->to_matrix();
84}
85
90Computation /* or null */ *IM2_GB_make(
91 const Matrix *m,
92 M2_bool collect_syz,
93 int n_rows_to_keep,
94 M2_arrayint gb_weights,
95 M2_bool use_max_degree,
96 int max_degree,
97 int algorithm,
98 int strategy,
99 int max_reduction_count) /* drg: connected rawGB */
100{
101 // Choose the correct computation here.
102 try
103 {
106 int numThreads = M2_numTBBThreads; // settable from front end.
108 collect_syz,
109 n_rows_to_keep,
110 gb_weights,
111 use_max_degree,
112 max_degree,
113 algorithm,
114 strategy,
115 numThreads,
116 max_reduction_count);
117 } catch (const exc::engine_error& e)
118 {
119 ERROR(e.what());
120 return nullptr;
121 }
122}
123
124Computation /* or null */ *IM2_res_make(const Matrix *m,
125 M2_bool resolve_cokernel,
126 int max_level,
127 M2_bool use_max_slanted_degree,
128 int max_slanted_degree,
129 int algorithm,
130 int strategy,
131 M2_bool parallelizeByDegree)
132{
133 try
134 {
136 // Choose the correct computation here.
137
138 // XXX
139
140 // Grab max number of threads (settable from the front end).
141 int numThreads = M2_numTBBThreads; // settable from front end.
142 //std::cout << "Using numThreads = " << numThreads << std::endl;
143
146 resolve_cokernel,
147 max_level,
148 use_max_slanted_degree,
149 max_slanted_degree,
150 algorithm,
151 strategy,
152 numThreads,
153 parallelizeByDegree);
154 } catch (const exc::engine_error& e)
155 {
156 ERROR(e.what());
157 return nullptr;
158 }
159}
160
162 const RingElement *h)
163{
164 try
165 {
168 if (G->get_ring()->get_degree_ring() != h->get_ring())
169 {
170 ERROR("expected Hilbert function hint to be in correct degree ring");
171 return nullptr;
172 }
173 if (G != nullptr) return G->set_hilbert_function(h);
174 ERROR("computation type unknown or not implemented");
175 return nullptr;
176 } catch (const exc::engine_error& e)
177 {
178 ERROR(e.what());
179 return nullptr;
180 }
181}
182
184 const Matrix *m, /* trimmed or minimal gens, may be the same as gb */
185 const Matrix *gb,
186 const Matrix *change, /* same number of columns as 'gb', if not 0 */
187 const Matrix *syz) /* possibly 0 too, otherwise same rows as change */
188{
190 try
191 {
192 return GBDeclared::create(m, gb, change, syz);
193 } catch (const exc::engine_error& e)
194 {
195 ERROR(e.what());
196 return nullptr;
197 }
198}
199
201 const Matrix *leadterms,
202 const Matrix *m, /* trimmed or minimal gens, may be the same as gb */
203 const Matrix *gb,
204 const Matrix *change, /* same number of columns as 'gb', if not 0 */
205 const Matrix *syz) /* possibly 0 too, otherwise same rows as change */
206{
208 try
209 {
210 return GBDeclared::create(leadterms, m, gb, change, syz);
211 } catch (const exc::engine_error& e)
212 {
213 ERROR(e.what());
214 return nullptr;
215 }
216}
217
218Computation /* or null */ *rawGroebnerWalk(const Matrix *gb,
219 const MonomialOrdering *order1)
220{
221 try
222 {
223 return GBWalker::create(gb, order1);
224 } catch (const exc::engine_error& e)
225 {
226 ERROR(e.what());
227 return nullptr;
228 }
229}
230
232 Computation *G,
233 M2_bool always_stop,
234 M2_arrayint degree_limit,
235 int basis_element_limit,
236 int syzygy_limit,
237 int pair_limit,
238 int codim_limit,
239 int subring_limit,
240 M2_bool just_min_gens,
241 M2_arrayint length_limit) /* TODO */
242/* LongPolynomial, Sort, Primary, Inhomogeneous, Homogeneous */
243/* Res: SortStrategy, 0, 1, 2, 3 ?? */
244{
245 try
246 {
248 return G->set_stop_conditions(always_stop,
249 degree_limit,
250 basis_element_limit,
251 syzygy_limit,
252 pair_limit,
253 codim_limit,
254 subring_limit,
255 just_min_gens,
256 length_limit);
257 } catch (const exc::engine_error& e)
258 {
259 ERROR(e.what());
260 return nullptr;
261 }
262}
263
265/* start or continue the computation */
266{
267 try
268 {
271
272 if (M2_gbTrace == 15)
273 {
274 ComputationStatusCode ret = C->status();
275 switch (ret)
276 {
278 emit_line("computation stopped at degree limit");
279 break;
280 case COMP_DONE:
281 emit_line("computation of GB completed");
282 break;
284 emit_line("computation stopped at pair limit");
285 break;
286 case COMP_NEED_RESIZE:
287 case COMP_ERROR:
288 case COMP_INTERRUPTED:
289 case COMP_NOT_STARTED:
295 case COMP_DONE_CODIM:
297 case COMP_DONE_STEPS:
299 case COMP_COMPUTING:
300 case COMP_OVERFLOWED:
301 emit_line("computation stopped for some good reason");
302 break;
303 default:
304 emit_line("incorrect status code encountered");
305 break;
306 }
307 }
308
309 return error() ? nullptr : C;
310 } catch (const exc::engine_error& e)
311 {
312 ERROR(e.what());
313 return nullptr;
314 }
315}
316
319void rawShowComputation(const Computation *C) { C->show(); }
320const Matrix /* or null */ *rawGBGetMatrix(Computation *C)
321/* Get the minimal, auto-reduced GB of a GB computation.
322 Each call to this will produce a different raw matrix */
323{
324 try
325 {
328 if (G != nullptr) return G->get_gb();
329 ERROR("computation type unknown or not implemented");
330 return nullptr;
331 } catch (const exc::engine_error& e)
332 {
333 ERROR(e.what());
334 return nullptr;
335 }
336}
337
339/* Yields a matrix whose columns form a minimal generating set
340 for the ideal or submodule, as computed so far. In the
341 inhomogeneous case, this yields a generating set which is
342 sometimes smaller than the entire Groebner basis. */
343{
344 try
345 {
348 if (G != nullptr) return G->get_mingens();
349 ERROR("computation type unknown or not implemented");
350 return nullptr;
351 } catch (const exc::engine_error& e)
352 {
353 ERROR(e.what());
354 return nullptr;
355 }
356}
357
358const Matrix /* or null */ *rawGBChangeOfBasis(Computation *C)
359/* Yields the change of basis matrix from the Groebner basis to
360 the original generators, at least if n_rows_to_keep was set
361 when creating the GB computation. This matrix, after the
362 computation has run to completion, should satisfy:
363 (original matrix) = (GB matrix) * (change of basis matrix). */
364{
365 try
366 {
369 if (G != nullptr) return G->get_change();
370 ERROR("computation type unknown or not implemented");
371 return nullptr;
372 } catch (const exc::engine_error& e)
373 {
374 ERROR(e.what());
375 return nullptr;
376 }
377}
378
379const Matrix /* or null */ *rawGBGetLeadTerms(Computation *C, int nparts)
380{
381 try
382 {
385 if (G != nullptr) return G->get_initial(nparts);
386 ERROR("computation type unknown or not implemented");
387 return nullptr;
388 } catch (const exc::engine_error& e)
389 {
390 ERROR(e.what());
391 return nullptr;
392 }
393}
394
396 M2_arrayint w)
397{
398 try
399 {
402 if (G != nullptr) return G->get_parallel_lead_terms(w);
403 ERROR("computation type unknown or not implemented");
404 return nullptr;
405 } catch (const exc::engine_error& e)
406 {
407 ERROR(e.what());
408 return nullptr;
409 }
410}
411
412const Matrix /* or null */ *rawGBSyzygies(Computation *C)
413/* Yields a matrix containing the syzygies computed so far
414 via the GB computation C, assuming that 'collect_syz' was
415 set when the computation was created. If 'n_rows_to_keep' was
416 set to a non-negative integer, then only that many rows of each
417 syzygy are kept. */
418{
419 try
420 {
423 if (G != nullptr) return G->get_syzygies();
424 ERROR("computation type unknown or not implemented");
425 return nullptr;
426 } catch (const exc::engine_error& e)
427 {
428 ERROR(e.what());
429 return nullptr;
430 }
431}
432
434 const Matrix *m)
435{
436 try
437 {
440 if (G != nullptr) return G->matrix_remainder(m);
441 ERROR("computation type unknown or not implemented");
442 return nullptr;
443 } catch (const exc::engine_error& e)
444 {
445 ERROR(e.what());
446 return nullptr;
447 }
448}
449
451 const Matrix *m,
452 const Matrix /* or null */ **result_remainder,
453 const Matrix /* or null */ **result_quotient)
454{
455 try
456 {
459 if (G != nullptr)
460 return G->matrix_lift(m, result_remainder, result_quotient);
461 else
462 ERROR("computation type unknown or not implemented");
463 } catch (const exc::engine_error& e)
464 {
465 ERROR(e.what());
466 }
467 return false;
468}
469
471{
472 try
473 {
476 if (G != nullptr) return G->contains(m);
477 ERROR("computation type unknown or not implemented");
478 return -2;
479 } catch (const exc::engine_error& e)
480 {
481 ERROR(e.what());
482 return -2;
483 }
484}
485
486const Matrix /* or null */ *rawResolutionGetMatrix(Computation *C, int level)
487{
488 try
489 {
492 if (G != nullptr) return G->get_matrix(level);
493 ERROR("expected resolution computation type");
494 return nullptr;
495 } catch (const exc::engine_error& e)
496 {
497 ERROR(e.what());
498 return nullptr;
499 }
500}
501
503 int level,
504 int degree)
505{
506 try
507 {
510 if (G != nullptr) return G->get_matrix(level, degree);
511 ERROR("expected resolution computation type");
512 return nullptr;
513 } catch (const exc::engine_error& e)
514 {
515 ERROR(e.what());
516 return nullptr;
517 }
518}
519
521 const Ring *R,
522 int level)
523// Perhaps a HACK that might change.
524// First: C must be a nonminimal res computation, over QQ M.
525// Second: R must be a polynomial ring with the same monoid M as C's,
526// and the coefficient ring must be either RR, or ZZ/p, where p is the (a)
527// prime being used in the computation.
528{
529 try
530 {
532 F4ResComputation *G = dynamic_cast<F4ResComputation *>(C);
533 if (G != nullptr) return G->get_mutable_matrix(R, level);
534 ERROR("expected fast nonminimal resolution computation type");
535 return nullptr;
536 } catch (const exc::engine_error& e)
537 {
538 ERROR(e.what());
539 return nullptr;
540 }
541}
542
544 Computation *C,
545 const Ring *KK, // should be RR, or a finite field used in C.
546 int level,
547 int degree)
548{
549 try
550 {
552 F4ResComputation *G = dynamic_cast<F4ResComputation *>(C);
553 if (G != nullptr) return G->get_mutable_matrix(KK, level, degree);
554 ERROR("expected fast nonminimal resolution computation type");
555 return nullptr;
556 } catch (const exc::engine_error& e)
557 {
558 ERROR(e.what());
559 return nullptr;
560 }
561}
562
563const FreeModule /* or null */ *rawResolutionGetFree(Computation *C, int level)
564{
565 try
566 {
569 if (G != nullptr) return G->get_free(level);
570 ERROR("expected resolution computation type");
571 return nullptr;
572 } catch (const exc::engine_error& e)
573 {
574 ERROR(e.what());
575 return nullptr;
576 }
577}
578
580 int *complete_up_through_this_degree,
581 int *complete_up_through_this_level)
582{
583 (void) C;
584 (void) complete_up_through_this_degree;
585 (void) complete_up_through_this_level;
586#ifdef DEVELOPMENT
587#warning "IM2_Resolution_status to be written"
588#endif
589 ERROR("not re-implemented yet");
590 return -1;
591}
592
594 Computation *C,
595 int level,
596 M2_bool minimize,
597 int *complete_up_through_this_degree)
598{
599 (void) C;
600 (void) level;
601 (void) minimize;
602 (void) complete_up_through_this_degree;
603#ifdef DEVELOPMENT
604#warning "IM2_Resolution_status to be written"
605#endif
606 ERROR("not re-implemented yet");
607 return COMP_ERROR;
608#if 0
609// ResolutionComputation *G = C->cast_to_ResolutionComputation();
610// if (G != 0)
611// return G->status_level(level, complete_up_through_this_degree);
612// ERROR("expected resolution computation type");
613// return 0;
614#endif
615}
616
618/* see engine.h for description of what 'type' should be */
619{
620 try
621 {
623 if (G != nullptr) return G->get_betti(type);
624 ERROR("expected resolution computation type");
625 return nullptr;
626 } catch (const exc::engine_error& e)
627 {
628 ERROR(e.what());
629 return nullptr;
630 }
631}
632
634/* TODO */
635{
636 buffer o;
637 try
638 {
639 C->text_out(o);
640 return o.to_string();
641 } catch (const exc::engine_error& e)
642 {
643 o << "[unprintable gb]";
644 return o.to_string();
645 }
646}
647
648unsigned int rawComputationHash(const Computation *C) { return C->hash(); }
649Matrix /* or null */ *rawSubduction(int numparts, const Matrix *M,
650 const RingMap *F,
651 Computation *C)
652{
653 try
654 {
656 if (G == nullptr)
657 {
658 ERROR("expected a Groebner basis computation");
659 return nullptr;
660 }
661 return sagbi::subduct(numparts, M, F, G);
662 } catch (const exc::engine_error& e)
663 {
664 ERROR(e.what());
665 return nullptr;
666 }
667}
668
669Matrix /* or null */ *rawSubduction1(int numparts,
670 const Ring *rawT,
671 const Ring *rawS,
672 const Matrix *m,
673 const RingMap *inclusionAmbient,
674 const RingMap *fullSubstitution,
675 const RingMap *substitutionInclusion,
676 Computation *rawGBI,
677 Computation *rawGBReductionIdeal)
678{
679 try
680 {
681 GBComputation *gbReductionIdeal = rawGBReductionIdeal->cast_to_GBComputation();
682 GBComputation *gbI = rawGBI->cast_to_GBComputation();
683 if ((gbReductionIdeal == nullptr) || (gbI == nullptr))
684 {
685 ERROR("expected a Groebner basis computation");
686 return nullptr;
687 }
688 return sagbi::subduct1(numparts, rawT, rawS, m, inclusionAmbient, fullSubstitution, substitutionInclusion, gbI, gbReductionIdeal);
689 } catch (const exc::engine_error& e)
690 {
691 ERROR(e.what());
692 return nullptr;
693 }
694}
695
696#include "mathicgb.h"
697#include "matrix-stream.hpp"
698void rawDisplayMatrixStream(const Matrix *inputMatrix)
699{
700 const Ring *R = inputMatrix->get_ring();
701 const PolyRing *P = R->cast_to_PolyRing();
702 if (P == nullptr)
703 {
704 ERROR("expected a polynomial ring");
705 return;
706 }
707 if (P->characteristic() > std::numeric_limits<int>::max())
708 {
709 ERROR("characteristic is too large for mathic gb computation");
710 return;
711 }
712 int charac = static_cast<int>(P->characteristic());
713 int nvars = P->n_vars();
714
715 mgb::GroebnerConfiguration configuration(
716 charac, nvars, inputMatrix->n_rows());
717 mgb::GroebnerInputIdealStream input(configuration);
718
719 std::ostringstream computedStr;
720 mgb::IdealStreamLog<> computed(
721 computedStr, charac, nvars, inputMatrix->n_rows());
722 mgb::IdealStreamChecker<decltype(computed)> checked(computed);
723
724 matrixToStream(inputMatrix, checked);
725
726 std::cout << "result: " << std::endl;
727 std::cout << computedStr.str() << std::endl;
728}
729
743class MGBCallback : public mgb::GroebnerConfiguration::Callback
744{
745 public:
747 size_t callCount() const { return mCallCount; }
748 bool wasInterrupted() const { return mInterrupted; }
749 protected:
750 virtual Action call()
751 {
752 // printf("called callback\n");
753 mCallCount++;
754 if (system_interrupted())
755 {
756 mInterrupted = true;
757 return StopWithNoOutputAction;
758 }
759 return ContinueAction;
760 }
761
762 private:
765};
766
767// TODO: The following (in x-monoid.cpp) needs to be put into a header file.
768extern bool monomialOrderingToMatrix(
769 const struct MonomialOrdering &mo,
770 std::vector<int> &mat,
771 bool &base_is_revlex,
772 int &component_direction, // -1 is Down, +1 is Up, 0 is not present
773 int &component_is_before_row // -1 means: at the end. 0 means before the
774 // order.
775 // and r means considered before row 'r' of the matrix.
776 );
777
779 const Matrix *inputMatrix,
780 int reducer,
781 int spairGroupSize, // a value of 0 means let the algorithm choose
782 int nthreads,
783 M2_string logging)
784{
785 try
786 {
787 const Ring *R = inputMatrix->get_ring();
788 const PolyRing *P = R->cast_to_PolyRing();
789 if (P == nullptr)
790 {
791 ERROR("expected a polynomial ring");
792 return nullptr;
793 }
794 if (nthreads < 0)
795 {
796 ERROR("mgb: expected a non-negative number of threads");
797 return nullptr;
798 }
799 if (P->characteristic() > std::numeric_limits<int>::max())
800 {
801 ERROR("characteristic is too large for mathic gb computation");
802 return nullptr;
803 }
804 if (P->characteristic() == 0)
805 {
806 ERROR(
807 "characteristic for mathic gb computation must be a prime "
808 "number");
809 return nullptr;
810 }
812 {
813 ERROR("coefficients for mathic gb computation must be a prime field");
814 return nullptr;
815 }
816 int charac = static_cast<int>(P->characteristic());
817 int nvars = P->n_vars();
818 MGBCallback callback;
819 mgb::GroebnerConfiguration configuration(
820 charac, nvars, inputMatrix->n_rows());
821
822 const auto reducerType = reducer == 0
823 ? mgb::GroebnerConfiguration::ClassicReducer
824 : mgb::GroebnerConfiguration::MatrixReducer;
825 configuration.setReducer(reducerType);
826 configuration.setMaxSPairGroupSize(spairGroupSize);
827 configuration.setMaxThreadCount(nthreads);
828 std::string log((char *)logging->array, logging->len);
829 configuration.setLogging(log.c_str());
830 configuration.setCallback(&callback);
831
832 // Now set the monomial ordering info
833 std::vector<int> mat;
834 bool base_is_revlex = true;
835 int component_direction = 1;
836 int component_is_before_row = -1;
838 mat,
839 base_is_revlex,
840 component_direction,
841 component_is_before_row))
842 {
843 ERROR(
844 "monomial ordering is not appropriate for Groebner basis "
845 "computation");
846 return nullptr;
847 }
848 if (!configuration.setMonomialOrder(
849 (base_is_revlex
850 ?
851 // mgb::GroebnerConfiguration::BaseOrder::ReverseLexicographicBaseOrder
852 mgb::GroebnerConfiguration::BaseOrder::
853 RevLexDescendingBaseOrder
854 : mgb::GroebnerConfiguration::BaseOrder::
855 LexDescendingBaseOrder),
856 mat))
857 {
858 throw exc::engine_error("expected global monomial ordering");
859 }
860
861 if (component_is_before_row >= 0)
862 configuration.setComponentBefore(component_is_before_row);
863 configuration.setComponentsAscending(component_direction == 1); // BUG: what if descending??
864
865#if 0
866 // Debug information
867 printf("Setting monomial order:");
868 for (size_t i=0; i<mat.size(); i++) printf("%d ", mat[i]);
869 printf("\n");
870 printf(" Base=%d\n", base_is_revlex);
871 printf(" ComponentBefore=%d\n", component_is_before_row);
872 std::cout << "componentBefore: " << configuration.componentBefore() << std::endl;
873#endif
874
875 mgb::GroebnerInputIdealStream input(configuration);
876
877 std::ostringstream computedStr;
878 mgb::IdealStreamLog<> computed(
879 computedStr, charac, nvars, inputMatrix->n_rows());
880 mgb::IdealStreamChecker<decltype(computed)> checkedOut(computed);
881
882 matrixToStream(inputMatrix, input);
883 MatrixStream matStream(inputMatrix->rows());
884 // mgb::computeGroebnerBasis(input, checked);
885 mgb::computeGroebnerBasis(input, matStream);
886 if (callback.wasInterrupted())
887 {
888 ERROR("computation was interrupted");
889 return nullptr;
890 }
891 const Matrix *result = matStream.value();
892 // printf("number of callbacks = %lu result = %lu\n",
893 // callback.callCount(), result);
894 // rawDisplayMatrixStream(result);
895 return result;
896 } catch (const std::runtime_error& e)
897 {
898 ERROR(e.what());
899 return nullptr;
900 }
901}
902
904// Noncommutative Groebner bases (2-sided) //
906
908 const Matrix* input)
909{
911 (void) A;
912 result.reserve(input->n_cols() * input->n_rows());
913 for (int i=0; i < input->n_rows(); i++)
914 {
915 for (int j=0; j < input->n_cols(); ++j)
916 {
917 ring_elem a = input->elem(i,j);
918 auto f = reinterpret_cast<const Poly*>(a.get_Poly());
919 result.push_back(f);
920 }
921 }
922 return result;
923}
924
925// vectorToMatrix consumes 'elems': the same pointers are used for the resulting Matrix.
926template<typename PolyL>
928 const PolyL& elems,
929 int numrows,
930 int numcols)
931{
932 if (elems.size() != numrows*numcols)
933 ERROR("Number of elements in list does not match matrix size.");
934 MatrixConstructor mat(A->make_FreeModule(numrows), numcols);
935 for (auto i = 0; i < elems.size(); ++i)
936 {
937 int curCol = i % numcols;
938 int curRow = (i - curCol) / numcols;
939 ring_elem a = const_cast<Nterm*>(reinterpret_cast<const Nterm*>(elems[i]));
940 mat.set_entry(curRow, curCol, a);
941 }
943 return mat.to_matrix();
944}
945
946const Matrix* rawNCGroebnerBasisTwoSided(const Matrix* input, int maxdeg, int strategy)
947{
948 const Ring* R = input->get_ring();
949 const M2FreeAlgebra* A = R->cast_to_M2FreeAlgebra();
950 if (A != nullptr and input->n_rows() == 1)
951 {
952 auto elems = matrixToPolyList(A, input);
953 bool isF4 = strategy & 16;
954 bool isParallel = strategy & 32;
955 if (isF4)
956 {
957 int numthreads = M2_numTBBThreads; // settable from front end.
958 // std::cout << "Using numthreads = " << numthreads << std::endl;
959 NCF4 G(A->freeAlgebra(), elems, maxdeg, strategy, (isParallel ? numthreads : 1));
960 G.compute(maxdeg); // this argument is actually the soft degree limit
961 auto result = copyPolyVector(A, G.currentValue());
962 return polyListToMatrix(A, result, 1, result.size()); // consumes the Poly's in result
963 }
964 else
965 {
966 NCGroebner G(A->freeAlgebra(), elems, maxdeg, strategy);
967 G.compute(maxdeg); // this argument is actually the soft degree limit
968 auto result = copyPolyVector(A, G.currentValue());
969 return polyListToMatrix(A, result, 1, result.size()); // consumes the Poly's in result
970 }
971
972 }
973 ERROR("expected a one row matrix over a noncommutative algebra");
974 return nullptr;
975}
976
977const Matrix* rawNCReductionTwoSided(const Matrix* toBeReduced, const Matrix* reducerMatrix)
978{
979 const Ring* R = toBeReduced->get_ring();
980 if (R != reducerMatrix->get_ring())
981 {
982 ERROR("expected matrices to be over the same ring");
983 return nullptr;
984 }
985 const M2FreeAlgebra* A = R->cast_to_M2FreeAlgebra();
986 if (A != nullptr and reducerMatrix->n_rows() == 1)
987 {
988 auto outRows = toBeReduced->n_rows();
989 auto outCols = toBeReduced->n_cols();
990 auto reducees = matrixToPolyList(A, toBeReduced);
991 auto reducers = matrixToPolyList(A, reducerMatrix);
992 NCGroebner G(A->freeAlgebra(),reducers, 0, 0);
993 G.initReductionOnly();
994 auto result = G.twoSidedReduction(reducees);
995 return polyListToMatrix(A, result, outRows, outCols); // consumes the Poly's in result.
996 }
997 ERROR("expected a matrix over a noncommutative algebra");
998 return nullptr;
999}
1000
1001const Matrix* rawNCBasis(const Matrix* gb2SidedIdeal,
1002 M2_arrayint lo_degree,
1003 M2_arrayint hi_degree,
1004 int limit
1005 )
1006{
1007 const Ring* R = gb2SidedIdeal->get_ring();
1008 if (R == nullptr)
1009 {
1010 ERROR("internal error: expected non-null Ring!");
1011 return nullptr;
1012 }
1013 try {
1014 const M2FreeAlgebra* A = R->cast_to_M2FreeAlgebra();
1015 if (A != nullptr)
1016 {
1017 ConstPolyList G = matrixToPolyList(A, gb2SidedIdeal);
1018
1019 // WARNING: The following line creates new polynomials
1020 // which are used directly in vectorToMatrix (without copying)
1021 // but when result goes out of scope, the list is deleted,
1022 // but not the polynomials themselves, as they are pointers.
1024 bool worked = ncBasis(A->freeAlgebra(),
1025 G,
1028 limit,
1029 result);
1030 if (not worked) return nullptr;
1031 return polyListToMatrix(A, result, 1, result.size()); // consumes entries of result
1032 }
1033 ERROR("expected a free algebra");
1034 return nullptr;
1035 }
1036 catch (exc::engine_error& e) {
1037 ERROR(e.what());
1038 return nullptr;
1039 }
1040}
1041
1042
1043// Local Variables:
1044// compile-command: "make -C $M2BUILDDIR/Macaulay2/e "
1045// indent-tabs-mode: nil
1046// End:
Older Schreyer-style kernel computation, predecessor of schreyer-resolution/.
Free associative algebra k<x_1,...,x_n> over an arbitrary coefficient ring.
PolyList copyPolyVector(const M2FreeAlgebraOrQuotient *A, const PolyList &polys)
Ring-shaped wrapper that exposes a non-commutative FreeAlgebra to the rest of the engine.
NCF4 — non-commutative F4 Gröbner-basis driver building a per-degree Macaulay matrix.
NCGroebner — Buchberger-style two-sided Gröbner basis driver over a FreeAlgebra.
gc_vector< const Poly * > ConstPolyList
Polynomial< CoefficientRingType > Poly
gc_vector< Poly * > PolyList
enum ComputationStatusCode status() const
Definition comp.hpp:100
virtual void text_out(buffer &o) const
Definition comp.cpp:59
virtual ResolutionComputation * cast_to_ResolutionComputation()
Definition comp.hpp:112
virtual GBComputation * cast_to_GBComputation()
Definition comp.hpp:111
virtual void start_computation()=0
virtual int complete_thru_degree() const =0
virtual void show() const
Definition comp.cpp:61
Abstract base for long-running, resumable engine computations (GBComputation, ResolutionComputation,...
Definition comp.hpp:70
ResolutionComputation subclass that drives the F4 resolution engine (SchreyerFrame + F4Res) from the ...
Engine-side free module R^n over a Ring.
Definition freemod.hpp:66
static GBComputation * choose_gb(const Matrix *m, M2_bool collect_syz, int n_rows_to_keep, M2_arrayint gb_weights, M2_bool use_max_degree, int max_degree, int algorithm, int strategy, int numThreads, int max_reduction_count=10)
Definition comp-gb.cpp:39
base class for Groebner basis computations.
Definition comp-gb.hpp:69
static GBComputation * create(const Matrix *m, const Matrix *gb, const Matrix *change, const Matrix *syz)
Computes the kernel of a Schreyer-encoded GBMatrix and returns the syzygies in a Schreyer-compatible ...
Definition Eschreyer.hpp:82
static GBWalker * create(MarkedGB *G0, long **order1, long **order2)
const FreeAlgebra & freeAlgebra() const
Concrete Ring wrapper around an owned FreeAlgebra (no quotient).
Abstract Ring subclass that lifts either a FreeAlgebra or a FreeAlgebraQuotient into the engine's Rin...
size_t mCallCount
Definition groebner.cpp:763
bool mInterrupted
Definition groebner.cpp:764
bool wasInterrupted() const
Definition groebner.cpp:748
virtual Action call()
Definition groebner.cpp:750
size_t callCount() const
Definition groebner.cpp:747
mathicgb (mgb) callback that polls the engine's interrupt flag during a long-running GB computation.
Definition groebner.cpp:744
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
int n_rows() const
Definition matrix.hpp:146
const FreeModule * rows() const
Definition matrix.hpp:144
Matrix * to_matrix()
void compute_column_degrees()
void set_entry(int r, int c, ring_elem a)
Mutable builder used to assemble an immutable Matrix one column (or one term) at a time.
const Matrix * value() const
Streaming consumer that builds an engine Matrix from the mathicgb-style stream callbacks (idealBegin ...
const MonomialOrdering * getMonomialOrdering() const
Definition monoid.hpp:173
unsigned int hash() const
Definition hash.hpp:106
Abstract base class for mutable matrices over an arbitrary engine Ring, the in-place counterpart of t...
Definition mat.hpp:79
Non-commutative F4 Groebner-basis driver: builds a per-degree Macaulay matrix from overlaps and reduc...
Definition NCF4.hpp:104
One-overlap-at-a-time Groebner basis driver for the free associative algebra (the "Naive" companion t...
Concrete PolyRingFlat subclass implementing ordinary commutative polynomial rings K[x_1,...
Definition poly.hpp:64
const Ring * getCoefficientRing() const
Definition polyring.hpp:200
virtual const Monoid * getMonoid() const
Definition polyring.hpp:282
int n_vars() const
Definition polyring.hpp:196
static ResolutionComputation * choose_res(const Matrix *m, M2_bool resolve_cokernel, int max_level, M2_bool use_max_slanted_degree, int max_slanted_degree, int algorithm, int strategy, int numThreads, M2_bool parallelizeByDegree)
Definition comp-res.cpp:16
Base class for free resolution computation classes.
Definition comp-res.hpp:52
virtual FreeModule * make_FreeModule() const
Definition ring.cpp:53
virtual const PolyRing * cast_to_PolyRing() const
Definition ring.hpp:245
virtual unsigned long get_precision() const
Definition ring.cpp:438
long characteristic() const
Definition ring.hpp:159
virtual const M2FreeAlgebra * cast_to_M2FreeAlgebra() const
Definition ring.hpp:256
virtual bool isFinitePrimeField() const
Definition ring.hpp:169
const Ring * get_ring() const
Definition relem.hpp:81
Front-end-visible "ring element" value: an engine ring_elem paired with the Ring* that gives it meani...
Definition relem.hpp:67
xxx xxx xxx
Definition ring.hpp:102
const Monoid * M
Definition ringmap.hpp:93
const Ring * R
Definition ringmap.hpp:89
const PolynomialRing * P
Definition ringmap.hpp:91
int nvars
Definition ringmap.hpp:98
Engine-side ring homomorphism: stores, for each source-ring variable, the target-ring element it maps...
Definition ringmap.hpp:60
char * str()
Definition buffer.hpp:72
M2_string to_string()
Definition buffer.cpp:20
static RingElement * hilbertNumerator(const Matrix *M)
Definition hilb.cpp:665
static ring_elem subduct(int numslots, const PolyRing *R, ring_elem f, const RingMap *phi, GBComputation *J)
Definition sagbi.cpp:7
static ring_elem subduct1(int numslots, const PolyRing *T, const PolyRing *S, ring_elem a, const RingMap *inclusionAmbient, const RingMap *fullSubstitution, const RingMap *substitutionInclusion, GBComputation *gbI, GBComputation *gbReductionIdeal)
Definition sagbi.cpp:71
GBDeclared — a user-asserted Groebner basis the engine accepts without computing.
GBComputation — abstract base of every Groebner-basis algorithm in the engine.
ResolutionComputation — abstract base for every free-resolution algorithm in the engine.
ComputationStatusCode
Definition computation.h:53
@ COMP_DONE_MIN_GENS
Definition computation.h:68
@ COMP_NEED_RESIZE
Definition computation.h:55
@ COMP_DONE_PAIR_LIMIT
Definition computation.h:64
@ COMP_DONE_STEPS
Definition computation.h:69
@ COMP_DONE
Definition computation.h:60
@ COMP_OVERFLOWED
Definition computation.h:72
@ COMP_DONE_SUBRING_LIMIT
Definition computation.h:70
@ COMP_ERROR
Definition computation.h:56
@ COMP_INITIAL_STOP
Definition computation.h:59
@ COMP_DONE_LENGTH_LIMIT
Definition computation.h:62
@ COMP_DONE_GB_LIMIT
Definition computation.h:65
@ COMP_DONE_DEGREE_LIMIT
Definition computation.h:61
@ COMP_DONE_CODIM
Definition computation.h:67
@ COMP_DONE_SYZ_LIMIT
Definition computation.h:66
@ COMP_DONE_SYZYGY_LIMIT
Definition computation.h:63
@ COMP_COMPUTING
Definition computation.h:71
@ COMP_NOT_STARTED
Definition computation.h:58
@ COMP_INTERRUPTED
Definition computation.h:57
int error()
Definition error.c:48
namespace exc — internal C++ exception types and the TRY / CATCH macro pair.
#define Matrix
Definition factory.cpp:14
void gb(IntermediateBasis &F, int n)
GBWalker — generic Groebner-walk strategy that transports a basis between term orders.
const RingElement * IM2_Matrix_Hilbert(const Matrix *M)
Definition groebner.cpp:58
Matrix * rawSubduction(int numparts, const Matrix *M, const RingMap *F, Computation *C)
Definition groebner.cpp:649
ConstPolyList matrixToPolyList(const M2FreeAlgebraOrQuotient *A, const Matrix *input)
Definition groebner.cpp:907
const Matrix * rawGBMinimalGenerators(Computation *C)
Definition groebner.cpp:338
unsigned int rawComputationHash(const Computation *C)
Definition groebner.cpp:648
const Matrix * polyListToMatrix(const M2FreeAlgebraOrQuotient *A, const PolyL &elems, int numrows, int numcols)
Definition groebner.cpp:927
int IM2_GB_contains(Computation *C, const Matrix *m)
Definition groebner.cpp:470
const Matrix * rawGBMatrixRemainder(Computation *C, const Matrix *m)
Definition groebner.cpp:433
MutableMatrix * rawResolutionGetMatrix2(Computation *C, int level, int degree)
Definition groebner.cpp:502
Computation * IM2_res_make(const Matrix *m, M2_bool resolve_cokernel, int max_level, M2_bool use_max_slanted_degree, int max_slanted_degree, int algorithm, int strategy, M2_bool parallelizeByDegree)
Definition groebner.cpp:124
Computation * rawStartComputation(Computation *C)
Definition groebner.cpp:264
Computation * IM2_GB_set_hilbert_function(Computation *C, const RingElement *h)
Definition groebner.cpp:161
const Matrix * rawResolutionGetMatrix(Computation *C, int level)
Definition groebner.cpp:486
enum ComputationStatusCode IM2_Resolution_status_level(Computation *C, int level, M2_bool minimize, int *complete_up_through_this_degree)
Definition groebner.cpp:593
enum ComputationStatusCode rawStatus1(Computation *C)
Definition groebner.cpp:317
int rawStatus2(Computation *C)
Definition groebner.cpp:318
void rawShowComputation(const Computation *C)
Definition groebner.cpp:319
const Matrix * rawNCGroebnerBasisTwoSided(const Matrix *input, int maxdeg, int strategy)
Definition groebner.cpp:946
MutableMatrix * rawResolutionGetMutableMatrix2B(Computation *C, const Ring *KK, int level, int degree)
Definition groebner.cpp:543
MutableMatrix * rawResolutionGetMutableMatrixB(Computation *C, const Ring *R, int level)
Definition groebner.cpp:520
Computation * IM2_GB_make(const Matrix *m, M2_bool collect_syz, int n_rows_to_keep, M2_arrayint gb_weights, M2_bool use_max_degree, int max_degree, int algorithm, int strategy, int max_reduction_count)
Definition groebner.cpp:90
int IM2_Resolution_status(Computation *C, int *complete_up_through_this_degree, int *complete_up_through_this_level)
Definition groebner.cpp:579
const Matrix * rawKernelOfGB(const Matrix *M)
Definition groebner.cpp:74
const Matrix * rawGBGetLeadTerms(Computation *C, int nparts)
Definition groebner.cpp:379
const Matrix * rawGBGetMatrix(Computation *C)
Definition groebner.cpp:320
const FreeModule * rawResolutionGetFree(Computation *C, int level)
Definition groebner.cpp:563
void test_over_RR_or_CC(const Ring *R)
Definition groebner.cpp:38
Computation * rawMarkedGB(const Matrix *leadterms, const Matrix *m, const Matrix *gb, const Matrix *change, const Matrix *syz)
Definition groebner.cpp:200
const Matrix * rawGBSyzygies(Computation *C)
Definition groebner.cpp:412
Computation * rawGroebnerWalk(const Matrix *gb, const MonomialOrdering *order1)
Definition groebner.cpp:218
void rawDisplayMatrixStream(const Matrix *inputMatrix)
Definition groebner.cpp:698
const Matrix * rawGBChangeOfBasis(Computation *C)
Definition groebner.cpp:358
Computation * IM2_GB_force(const Matrix *m, const Matrix *gb, const Matrix *change, const Matrix *syz)
Definition groebner.cpp:183
bool monomialOrderingToMatrix(const struct MonomialOrdering &mo, std::vector< int > &mat, bool &base_is_revlex, int &component_direction, int &component_is_before_row)
M2_arrayintOrNull rawResolutionBetti(Computation *C, int type)
Definition groebner.cpp:617
M2_string IM2_GB_to_string(Computation *C)
Definition groebner.cpp:633
Matrix * rawSubduction1(int numparts, const Ring *rawT, const Ring *rawS, const Matrix *m, const RingMap *inclusionAmbient, const RingMap *fullSubstitution, const RingMap *substitutionInclusion, Computation *rawGBI, Computation *rawGBReductionIdeal)
Definition groebner.cpp:669
bool warning_given_for_gb_or_res_over_RR_or_CC
Definition groebner.cpp:36
M2_bool IM2_GB_matrix_lift(Computation *C, const Matrix *m, const Matrix **result_remainder, const Matrix **result_quotient)
Definition groebner.cpp:450
Computation * IM2_Computation_set_stop(Computation *G, M2_bool always_stop, M2_arrayint degree_limit, int basis_element_limit, int syzygy_limit, int pair_limit, int codim_limit, int subring_limit, M2_bool just_min_gens, M2_arrayint length_limit)
Definition groebner.cpp:231
const Matrix * rawNCBasis(const Matrix *gb2SidedIdeal, M2_arrayint lo_degree, M2_arrayint hi_degree, int limit)
const Matrix * rawMGB(const Matrix *inputMatrix, int reducer, int spairGroupSize, int nthreads, M2_string logging)
Definition groebner.cpp:778
const Matrix * rawGBGetParallelLeadTerms(Computation *C, M2_arrayint w)
Definition groebner.cpp:395
const Matrix * rawNCReductionTwoSided(const Matrix *toBeReduced, const Matrix *reducerMatrix)
Definition groebner.cpp:977
Engine-boundary C API for Gröbner basis, resolution, and Hilbert-series computations.
bool ncBasis(const FreeAlgebra &A, const ConstPolyList &gb, const std::vector< int > &lo_degree, const std::vector< int > &hi_degree, int limit, PolyList &result)
Hilbert-series numerator via the Bigatti-Caboara-Robbiano recursion.
bool system_interrupted()
system_interrupted() — thread-safe polling predicate for Ctrl+C handling.
const int ERROR
Definition m2-mem.cpp:55
VALGRIND_MAKE_MEM_DEFINED & result(result)
char newline[]
Definition m2-types.cpp:49
int M2_gbTrace
Definition m2-types.cpp:52
int M2_numTBBThreads
Definition m2-types.cpp:51
M2_arrayint M2_arrayintOrNull
Definition m2-types.h:99
char M2_bool
Definition m2-types.h:82
ncBasis — non-commutative analogue of basis(d, M) over NCAlgebras/FreeAlgebra.
void matrixToStream(const Matrix *M, T &stream)
MatrixStream — term-by-term streaming construction of a Matrix.
Concrete commutative PolyRing — standard polynomial ring inheriting from PolyRingFlat.
RingElement — tagged (Ring*, ring_elem) pair, the engine's universal element type.
F4ResComputation — top-level Schreyer-frame F4 free-resolution driver.
tbb::flow::graph G
sagbi — subduction helpers for canonical-subalgebra (SAGBI) bases.
Matrix * to_matrix()
Definition Eschreyer.cpp:55
gbvector-side matrix: a target FreeModule plus a list of gbvector* columns living in it.
Definition Eschreyer.hpp:54
Front-end-side description of a monomial ordering as a list of mon_part blocks.
Singly linked-list node carrying one term of a polynomial-ring element.
Definition ringelem.hpp:156
void emit_line(const char *s)
Definition text-io.cpp:47
void emit(const char *s)
Definition text-io.cpp:41
void clear_emit_size()
Definition text-io.cpp:26
Text-formatting helpers layered on buffer: bignum print, line wrapping, M2_gbTrace-gated emit.
const void * get_Poly() const
Definition ringelem.hpp:128
std::vector< T > M2_arrayint_to_stdvector(M2_arrayint arr)
Definition util.hpp:96
Conversion helpers between M2 boundary types and standard C++ containers.