Frobby 0.9.7
frobby.cpp
Go to the documentation of this file.
1/* Frobby: Software for monomial ideal computations.
2 Copyright (C) 2007 Bjarke Hammersholt Roune (www.broune.com)
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see http://www.gnu.org/licenses/.
16*/
17#include "stdinc.h"
18#include "frobby.h"
19
20#include "BigIdeal.h"
21#include "SliceFacade.h"
22#include "BigTermConsumer.h"
23#include "TermTranslator.h"
24#include "Term.h"
25#include "error.h"
26#include "CoefBigTermConsumer.h"
27#include "IdealFacade.h"
28#include "SliceParams.h"
29
30/* also increment the version number in:
31 - CMakeLists.txt
32 - doc/doxygen.conf
33 - doc/manual.tex
34 - test/messages/help-noparam.err
35 and update the library version as outlined in Makefile */
36const char* const frobby_version = "0.9.7";
37
39protected:
40 ConsumerWrapper(size_t varCount):
41 _varCount(varCount),
42 _term(new mpz_ptr[varCount]) {
43 }
44
45 virtual ~ConsumerWrapper() {
46 delete[] _term;
47 }
48
49 void setTerm(const Term& term, const TermTranslator& translator) {
50 ASSERT(term.getVarCount() == _varCount);
51 ASSERT(translator.getVarCount() == _varCount);
52
53 for (size_t var = 0; var < _varCount; ++var)
54 _term[var] = const_cast<mpz_ptr>
55 (translator.getExponent(var, term).get_mpz_t());
56 }
57
58 void setTerm(const vector<mpz_class>& term) {
59 ASSERT(term.size() == _varCount);
60
61 for (size_t var = 0; var < _varCount; ++var)
62 _term[var] = const_cast<mpz_ptr>(term[var].get_mpz_t());
63 }
64
65 size_t _varCount;
66 mpz_ptr* _term;
67};
68
70 public ConsumerWrapper {
71public:
73 size_t varCount):
74 ConsumerWrapper(varCount),
75 _consumer(consumer) {
76 ASSERT(_consumer != 0);
77 }
78
79 virtual void consumeRing(const VarNames& names) {
80 ASSERT(names.getVarCount() == _varCount);
81 }
82
83 virtual void beginConsuming() {
84 _consumer->idealBegin(_varCount);
85 }
86
87 virtual void consume(const Term& term, const TermTranslator& translator) {
88 ASSERT(term.getVarCount() == _varCount);
89 ASSERT(translator.getVarCount() == _varCount);
90
91 setTerm(term, translator);
92 _consumer->consume(_term);
93 }
94
95 virtual void consume(const vector<mpz_class>& term) {
96 ASSERT(term.size() == _varCount);
97
98 setTerm(term);
99 _consumer->consume(_term);
100 }
101
102 virtual void doneConsuming() {
103 _consumer->idealEnd();
104 }
105
106private:
108};
109
111 public ConsumerWrapper {
112public:
114 size_t varCount):
115 ConsumerWrapper(varCount),
116 _consumer(consumer),
117 _varCount(varCount) {
118 ASSERT(consumer != 0);
119 }
120
121 virtual void consumeRing(const VarNames& names) {
122 ASSERT(names.getVarCount() == _varCount);
123 }
124
125 virtual void beginConsuming() {
126 _consumer->polynomialBegin(_varCount);
127 }
128
129 virtual void consume(const mpz_class& coef,
130 const Term& term,
131 const TermTranslator& translator) {
132 ASSERT(term.getVarCount() == _varCount);
133 ASSERT(translator.getVarCount() == _varCount);
134
135 setTerm(term, translator);
136 _consumer->consume(coef.get_mpz_t(), _term);
137 }
138
139 virtual void consume(const mpz_class& coef,
140 const vector<mpz_class>& term) {
141 ASSERT(term.size() == _varCount);
142
143 for (size_t var = 0; var < _varCount; ++var)
144 _term[var] = const_cast<mpz_ptr>(term[var].get_mpz_t());
145 _consumer->consume(coef.get_mpz_t(), _term);
146 }
147
148 // TODO: make a note somewhere that in case of an exception,
149 // polynomialEnd might not get called, this being because it is too
150 // much of a burden to require it not to throw any
151 // exceptions. Hmm... maybe there is an alternative solution.
152 virtual void doneConsuming() {
153 _consumer->polynomialEnd();
154 }
155
156private:
158 size_t _varCount;
159};
160
163
165}
166
169
172
175
178
179namespace FrobbyImpl {
180 using ::BigIdeal;
181
183 public:
184 FrobbyIdealHelper(size_t variableCount):
185 _ideal(VarNames(variableCount)),
186 _atVariable(variableCount) {
187 }
188
189 static const BigIdeal& getIdeal(const Frobby::Ideal& ideal) {
190 return ideal._data->_ideal;
191 }
192
193 private:
194 friend class Frobby::Ideal;
195
198 };
199}
200
201Frobby::Ideal::Ideal(size_t variableCount) {
202 _data = new FrobbyImpl::FrobbyIdealHelper(variableCount);
203}
204
208
210 delete _data;
211}
212
214 // Allocate new object before deleting old object to leave *this
215 // in a valid state in case of new throwing an exception.
218
219 delete _data;
220 _data = newValue;
221
222 return *this;
223}
224
225void Frobby::Ideal::addExponent(const mpz_t exponent) {
226 ASSERT(_data->_atVariable <= _data->_ideal.getVarCount());
227
228 if (_data->_atVariable == _data->_ideal.getVarCount()) {
229 _data->_ideal.newLastTerm();
230 _data->_atVariable = 0;
231 if (_data->_ideal.getVarCount() == 0)
232 return;
233 }
234
235 mpz_class& ref = _data->_ideal.getLastTermExponentRef(_data->_atVariable);
236 mpz_set(ref.get_mpz_t(), exponent);
237 ++_data->_atVariable;
238}
239
240void Frobby::Ideal::addExponent(int exponent) {
241 mpz_class tmp(exponent);
242 addExponent(tmp.get_mpz_t());
243}
244
245void Frobby::Ideal::addExponent(unsigned int exponent) {
246 mpz_class tmp(exponent);
247 addExponent(tmp.get_mpz_t());
248}
249
250bool Frobby::alexanderDual(const Ideal& ideal,
251 const mpz_t* reflectionMonomial,
252 IdealConsumer& consumer) {
253 const BigIdeal& bigIdeal = FrobbyImpl::FrobbyIdealHelper::getIdeal(ideal);
254
255 ExternalIdealConsumerWrapper wrappedConsumer
256 (&consumer, bigIdeal.getVarCount());
257
258 SliceParams params;
259 SliceFacade facade(params, bigIdeal, wrappedConsumer);
260
261 if (reflectionMonomial == 0)
262 facade.computeAlexanderDual();
263 else {
264 vector<mpz_class> point;
265 point.resize(bigIdeal.getVarCount());
266 for (size_t var = 0; var < bigIdeal.getVarCount(); ++var)
267 mpz_set(point[var].get_mpz_t(), reflectionMonomial[var]);
268
269 // We guarantee not to retain a reference to reflectionMonomial
270 // when providing terms to the consumer.
271 reflectionMonomial = 0;
272
273 try {
274 facade.computeAlexanderDual(point);
275 } catch (const FrobbyException&) {
276 return false;
277 }
278 }
279
280 return true;
281}
282
283bool Frobby::alexanderDual(const Ideal& ideal,
284 const Ideal& reflectionMonomial,
285 IdealConsumer& consumer) {
286 const BigIdeal& bigIdeal = FrobbyImpl::FrobbyIdealHelper::getIdeal(ideal);
287 const BigIdeal& reflectionIdeal =
288 FrobbyImpl::FrobbyIdealHelper::getIdeal(reflectionMonomial);
289
290 if (reflectionIdeal.getGeneratorCount() != 1)
291 return false;
292 if (reflectionIdeal.getVarCount() != bigIdeal.getVarCount())
293 return false;
294
295 const vector<mpz_class>& monomial = reflectionIdeal.getTerm(0);
296 const mpz_t* monomialPtr = 0;
297 if (reflectionIdeal.getVarCount() > 0)
298 monomialPtr = (const mpz_t*)&(monomial[0]);
299
300 return alexanderDual(ideal, monomialPtr, consumer);
301}
302
304 PolynomialConsumer& consumer) {
305 const BigIdeal& bigIdeal = FrobbyImpl::FrobbyIdealHelper::getIdeal(ideal);
306
308 (&consumer, bigIdeal.getVarCount());
309 SliceParams params;
310 SliceFacade facade(params, bigIdeal, wrappedConsumer);
311
313}
314
316 PolynomialConsumer& consumer) {
317 const BigIdeal& bigIdeal = FrobbyImpl::FrobbyIdealHelper::getIdeal(ideal);
318
319 ExternalPolynomialConsumerWrapper wrappedConsumer(&consumer, 1);
320 SliceParams params;
321 SliceFacade facade(params, bigIdeal, wrappedConsumer);
322
324}
325
330public:
331 IrreducibleIdealDecoder(IdealConsumer* consumer):
332 _varCount(0),
333 _consumer(consumer),
334 _term(0) {
335 ASSERT(_consumer != 0);
336 }
337
340
341 virtual void idealBegin(size_t varCount) {
342 _varCount = varCount;
343 _term.resize(varCount);
344 for (size_t var = 0; var < _varCount; ++var)
345 _term[var] = _zero.get_mpz_t();
346 }
347
348 virtual void idealEnd() {
349 _term.clear();
350 }
351
352 virtual void consume(mpz_ptr* exponentVector) {
353 _consumer->idealBegin(_varCount);
354
355 bool isIdentity = true;
356 for (size_t var = 0; var < _varCount; ++var) {
357 if (mpz_cmp_ui(exponentVector[var], 0) != 0) {
358 isIdentity = false;
359 _term[var] = exponentVector[var];
360 _consumer->consume(&*(_term.begin()));
361 _term[var] = _zero.get_mpz_t();
362 }
363 }
364
365 _consumer->idealEnd();
366 }
367
368private:
369 size_t _varCount;
370 IdealConsumer* _consumer;
371 vector<mpz_ptr> _term;
372 mpz_class _zero;
373};
374
376 IdealConsumer& consumer) {
377 IrreducibleIdealDecoder wrappedConsumer(&consumer);
378 if (!irreducibleDecompositionAsMonomials(ideal, wrappedConsumer)) {
379 const BigIdeal& bigIdeal = FrobbyImpl::FrobbyIdealHelper::getIdeal(ideal);
380 consumer.idealBegin(bigIdeal.getVarCount());
381 consumer.idealEnd();
382 }
383}
384
386 IdealConsumer& consumer) {
387 const BigIdeal& bigIdeal = FrobbyImpl::FrobbyIdealHelper::getIdeal(ideal);
388 if (bigIdeal.getGeneratorCount() == 0)
389 return false;
390
391 ExternalIdealConsumerWrapper wrappedConsumer
392 (&consumer, bigIdeal.getVarCount());
393 SliceParams params;
394 SliceFacade facade(params, bigIdeal, wrappedConsumer);
395
397 return true;
398}
399
401 IdealConsumer& consumer) {
402 const BigIdeal& bigIdeal = FrobbyImpl::FrobbyIdealHelper::getIdeal(ideal);
403
404 ExternalIdealConsumerWrapper wrappedConsumer
405 (&consumer, bigIdeal.getVarCount());
406 SliceParams params;
407 SliceFacade facade(params, bigIdeal, wrappedConsumer);
408
410}
411
413 IdealConsumer& consumer) {
414 const BigIdeal& bigIdeal = FrobbyImpl::FrobbyIdealHelper::getIdeal(ideal);
415
416 ExternalIdealConsumerWrapper wrappedConsumer
417 (&consumer, bigIdeal.getVarCount());
418 SliceParams params;
419 SliceFacade facade(params, bigIdeal, wrappedConsumer);
420
422}
423
425 const mpz_t* l,
426 IdealConsumer& consumer) {
427 ASSERT(l != 0);
428
429 const BigIdeal& bigIdeal = FrobbyImpl::FrobbyIdealHelper::getIdeal(ideal);
430
431 vector<mpz_class> grading;
432 for (size_t var = 0; var < bigIdeal.getVarCount(); ++var)
433 grading.push_back(mpz_class(l[var]));
434
435 ExternalIdealConsumerWrapper wrappedConsumer
436 (&consumer, bigIdeal.getVarCount());
437 SliceParams params;
438 params.useIndependenceSplits(false); // not supported
439 SliceFacade facade(params, bigIdeal, wrappedConsumer);
440
441 mpz_class dummy;
442 return facade.solveStandardProgram(grading, dummy, false);
443}
444
445void Frobby::codimension(const Ideal& ideal, mpz_t codim) {
446 const BigIdeal& bigIdeal = FrobbyImpl::FrobbyIdealHelper::getIdeal(ideal);
447 dimension(ideal, codim);
448 mpz_ui_sub(codim, bigIdeal.getVarCount(), codim);
449}
450
451void Frobby::dimension(const Ideal& ideal, mpz_t dim) {
452 const BigIdeal& bigIdeal = FrobbyImpl::FrobbyIdealHelper::getIdeal(ideal);
453
454 IdealFacade facade(false);
455 mpz_class dimen = facade.computeDimension(bigIdeal, false);
456 mpz_set(dim, dimen.get_mpz_t());
457}
458
459void Frobby::associatedPrimes(const Ideal& ideal, IdealConsumer& consumer) {
460 const BigIdeal& bigIdeal = FrobbyImpl::FrobbyIdealHelper::getIdeal(ideal);
461 IrreducibleIdealDecoder decodingConsumer(&consumer);
462
463 ExternalIdealConsumerWrapper wrappedConsumer
464 (&decodingConsumer, bigIdeal.getVarCount());
465 SliceParams params;
466 SliceFacade facade(params, bigIdeal, wrappedConsumer);
467
469}
ConsumerWrapper(size_t varCount)
Definition frobby.cpp:40
void setTerm(const vector< mpz_class > &term)
Definition frobby.cpp:58
size_t _varCount
Definition frobby.cpp:65
void setTerm(const Term &term, const TermTranslator &translator)
Definition frobby.cpp:49
virtual ~ConsumerWrapper()
Definition frobby.cpp:45
mpz_ptr * _term
Definition frobby.cpp:66
virtual void doneConsuming()
Must be called once after each time beginConsuming has been called.
Definition frobby.cpp:102
ExternalIdealConsumerWrapper(Frobby::IdealConsumer *consumer, size_t varCount)
Definition frobby.cpp:72
Frobby::IdealConsumer * _consumer
Definition frobby.cpp:107
virtual void consumeRing(const VarNames &names)
Tell the consumer which ring is being used.
Definition frobby.cpp:79
virtual void consume(const Term &term, const TermTranslator &translator)
Definition frobby.cpp:87
virtual void consume(const vector< mpz_class > &term)
Definition frobby.cpp:95
virtual void beginConsuming()
Tell the consumer to begin consuming an ideal.
Definition frobby.cpp:83
virtual void consume(const mpz_class &coef, const Term &term, const TermTranslator &translator)
Definition frobby.cpp:129
virtual void consumeRing(const VarNames &names)
Definition frobby.cpp:121
ExternalPolynomialConsumerWrapper(Frobby::PolynomialConsumer *consumer, size_t varCount)
Definition frobby.cpp:113
Frobby::PolynomialConsumer * _consumer
Definition frobby.cpp:157
virtual void consume(const mpz_class &coef, const vector< mpz_class > &term)
Definition frobby.cpp:139
This is the base of the Frobby exception hierarchy for exceptions that can occur due to expected erro...
Definition error.h:27
const vector< mpz_class > & getTerm(size_t term) const
Definition BigIdeal.h:139
size_t getVarCount() const
Definition BigIdeal.h:148
size_t getGeneratorCount() const
Definition BigIdeal.h:144
FrobbyIdealHelper(size_t variableCount)
Definition frobby.cpp:184
static const BigIdeal & getIdeal(const Frobby::Ideal &ideal)
Definition frobby.cpp:189
This class provides a way to get monomial ideals as output from Frobby one generator at a time.
Definition frobby.h:75
virtual void idealBegin(size_t varCount)
Called before output of a monomial ideal.
Definition frobby.cpp:164
virtual ~IdealConsumer()
The provided implementation does nothing.
Definition frobby.cpp:161
virtual void idealEnd()
Called after output of a monomial ideal.
Definition frobby.cpp:167
Ideal & operator=(const Ideal &ideal)
Definition frobby.cpp:213
Ideal(size_t variableCount)
Definition frobby.cpp:201
FrobbyImpl::FrobbyIdealHelper * _data
Definition frobby.h:62
void addExponent(const mpz_t exponent)
Call addExponent once for each variable to add a term one exponent at a time.
Definition frobby.cpp:225
This class provides a way to get polynomials as output from Frobby one term at a time.
Definition frobby.h:112
virtual void polynomialBegin(size_t varCount)
Called before output of a polynomial.
Definition frobby.cpp:173
virtual ~PolynomialConsumer()
The provided implementation does nothing.
Definition frobby.cpp:170
virtual void polynomialEnd()
Called after output of a polynomial.
Definition frobby.cpp:176
A facade for performing operations on BigIdeal.
Definition IdealFacade.h:34
mpz_class computeDimension(const BigIdeal &ideal, bool codimension=false, bool squareFreeAndMinimal=false)
Compute the Krull dimension of ideal.
IdealConsumer * _consumer
Definition frobby.cpp:370
virtual void idealBegin(size_t varCount)
Called before output of a monomial ideal.
Definition frobby.cpp:341
virtual void idealEnd()
Called after output of a monomial ideal.
Definition frobby.cpp:348
vector< mpz_ptr > _term
Definition frobby.cpp:371
IrreducibleIdealDecoder(IdealConsumer *consumer)
Definition frobby.cpp:331
virtual void consume(mpz_ptr *exponentVector)
For output of a generator of the ideal.
Definition frobby.cpp:352
A facade for operations on monomial ideals using the Slice Algorithm.
Definition SliceFacade.h:44
void computeAlexanderDual(const vector< mpz_class > &point)
Compute the Alexander dual of the ideal.
void computeAssociatedPrimes()
Compute the associated primes of the ideal.
void computeMultigradedHilbertSeries()
Compute the numerator of the multigraded Hilbert-Poincare series.
bool solveStandardProgram(const vector< mpz_class > &grading, mpz_class &value, bool reportAllSolutions)
Solve an optimization program over maximal standard monomials.
void computeUnivariateHilbertSeries()
Compute the numerator of the univariate Hilbert-Poincare series.
void computePrimaryDecomposition()
Compute the unique "nicest" primary decomposition of the ideal.
void computeIrreducibleDecomposition(bool encode)
Compute the unique irredundant set of irreducible ideals whose intersection equals ideal.
void computeMaximalStandardMonomials()
Compute the maximal standard monomials of the ideal.
void useIndependenceSplits(bool value)
Definition SliceParams.h:34
TermTranslator handles translation between terms whose exponents are infinite precision integers and ...
const mpz_class & getExponent(size_t variable, Exponent exponent) const
This method translates from IDs to arbitrary precision integers.
size_t getVarCount() const
Term represents a product of variables which does not include a coefficient.
Definition Term.h:49
size_t getVarCount() const
Definition Term.h:85
Defines the variables of a polynomial ring and facilities IO involving them.
Definition VarNames.h:40
size_t getVarCount() const
Returns the current number of variables.
Definition VarNames.h:113
const char *const frobby_version
Definition frobby.cpp:36
The namespace FrobbyImpl is for internal use inside Frobby only.
Definition frobby.cpp:179
void dimension(const Ideal &ideal, mpz_t dim)
Compute the Krull dimension of a monomial ideal.
Definition frobby.cpp:451
bool alexanderDual(const Ideal &ideal, const mpz_t *reflectionMonomial, IdealConsumer &consumer)
Compute the Alexander dual of ideal using the point reflectionMonomial.
Definition frobby.cpp:250
void irreducibleDecompositionAsIdeals(const Ideal &ideal, IdealConsumer &consumer)
Compute the irreducible decomposition of ideal.
Definition frobby.cpp:375
void codimension(const Ideal &ideal, mpz_t codim)
Compute the codimension of a monomial ideal.
Definition frobby.cpp:445
void associatedPrimes(const Ideal &ideal, IdealConsumer &consumer)
Compute the associated primes of the ideal.
Definition frobby.cpp:459
void univariateHilbertPoincareSeries(const Ideal &ideal, PolynomialConsumer &consumer)
Compute the univariate Hilbert-Poincare series of ideal.
Definition frobby.cpp:315
bool solveStandardMonomialProgram(const Ideal &ideal, const mpz_t *l, IdealConsumer &consumer)
Solve the optimization program.
Definition frobby.cpp:424
bool irreducibleDecompositionAsMonomials(const Ideal &ideal, IdealConsumer &consumer)
Compute the irreducible decomposition of ideal, and encode each irreducible component as a monomial.
Definition frobby.cpp:385
void maximalStandardMonomials(const Ideal &ideal, IdealConsumer &consumer)
Compute the maximal standard monomials of ideal.
Definition frobby.cpp:412
void primaryDecomposition(const Ideal &ideal, IdealConsumer &consumer)
Compute the canonical primary decomposition of a monomial ideal.
Definition frobby.cpp:400
void multigradedHilbertPoincareSeries(const Ideal &ideal, PolynomialConsumer &consumer)
Compute the multigraded Hilbert-Poincare series of ideal.
Definition frobby.cpp:303
This header file includes common definitions and is included as the first line of code in every imple...
#define ASSERT(X)
Definition stdinc.h:86