Frobby 0.9.5
Fourti2IOHandler.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 "Fourti2IOHandler.h"
19
20#include "Scanner.h"
21#include "BigIdeal.h"
22#include "Term.h"
23#include "TermTranslator.h"
24#include "BigPolynomial.h"
25#include "BigTermConsumer.h"
26#include "DataType.h"
27#include "IdealConsolidator.h"
29#include "SatBinomIdeal.h"
30#include "SatBinomConsumer.h"
31#include "IdealWriter.h"
32#include "PolyWriter.h"
33#include "error.h"
34#include "display.h"
35#include "InputConsumer.h"
36
37namespace IO {
38 namespace Fourti2 {
39 void writeRing(const VarNames& names, FILE* out);
40 void writeRingWithoutHeader(const VarNames& names, FILE* out);
41 void readTerm(Scanner& in, InputConsumer& consumer);
42 void readRing(Scanner& in, VarNames& names);
43 void readRing(Scanner& in, VarNames& names, size_t varCount);
44 void writeTerm(const vector<mpz_class>& term, FILE* out);
45 void writeTerm(const Term& term,
46 const TermTranslator& translator,
47 FILE* out);
49 InputConsumer& consumer,
50 size_t generatorCount,
51 size_t varCount);
53 SatBinomConsumer& consumer,
54 size_t generatorCount,
55 size_t varCount);
57 }
58 namespace F = Fourti2;
59
61 public:
63 }
64
65 private:
66 virtual void doWriteHeader(bool first) {
68 }
69
70 virtual void doWriteHeader(bool first, size_t generatorCount) {
71 fprintf(getFile(), "%lu %lu\n",
72 (unsigned long)generatorCount,
73 (unsigned long)getNames().getVarCount());
74 }
75
76 virtual void doWriteTerm(const Term& term,
77 const TermTranslator& translator,
78 bool first) {
79 F::writeTerm(term, translator, getFile());
80 }
81
82 virtual void doWriteTerm(const vector<mpz_class>& term, bool first) {
83 F::writeTerm(term, getFile());
84 }
85
86 virtual void doWriteFooter(bool wasZeroIdeal) {
87 if (!getNames().namesAreDefault())
89 }
90
91 virtual void doWriteEmptyList() {
93 }
94 };
95
97 public:
98 Fourti2PolyWriter(FILE* out): PolyWriter(out) {
99 }
100
101 private:
102 virtual void doWriteHeader() {
104 }
105
106 virtual void doWriteHeader(size_t termCount) {
107 fprintf(getFile(), "%lu %lu\n",
108 (unsigned long)termCount,
109 (unsigned long)getNames().getVarCount() + 1);
110 }
111
112 virtual void doWriteTerm(const mpz_class& coef,
113 const Term& term,
114 const TermTranslator& translator,
115 bool firstGenerator) {
116 ASSERT(term.getVarCount() == translator.getVarCount());
117
118 mpz_out_str(getFile(), 10, coef.get_mpz_t());
119
120 if (term.getVarCount() > 0) {
121 fputc(' ', getFile());
122 F::writeTerm(term, translator, getFile());
123 } else
124 fputc('\n', getFile());
125 }
126
127 virtual void doWriteTerm(const mpz_class& coef,
128 const vector<mpz_class>& term,
129 bool firstGenerator) {
130 ASSERT(term.size() == getNames().getVarCount());
131
132 mpz_out_str(getFile(), 10, coef.get_mpz_t());
133
134 if (!term.empty()) {
135 fputc(' ', getFile());
136 F::writeTerm(term, getFile());
137 } else
138 fputc('\n', getFile());
139 }
140
141 virtual void doWriteFooter(bool wasZero) {
142 fputs("(coefficient)", getFile());
143 if (!getNames().namesAreDefault())
145 else
146 fputc('\n', getFile());
147 };
148 };
149
151 IOHandlerImpl(staticGetName(),
152 "Format used by the software package 4ti2.") {
160 }
161
163 return "4ti2";
164 }
165
168 auto_ptr<BigTermConsumer> writer(new Fourti2IdealWriter(out));
169 return new IdealConsolidator(writer);
170 }
171
174 auto_ptr<CoefBigTermConsumer> writer(new Fourti2PolyWriter(out));
175 return new PolynomialConsolidator(writer);
176 }
177
178 void Fourti2IOHandler::doWriteTerm(const vector<mpz_class>& term,
179 const VarNames& names,
180 FILE* out) {
181 if (term.empty()) {
182 // Otherwise we will print nothing, which would be OK inside an
183 // ideal since then it is possible to see what happened from the
184 // number of generators and variables. We do not have that
185 // information here, so we have to print something.
186 fputs("_fourtitwo_identity", out);
187 }
188 F::writeTerm(term, out);
189 }
190
192 F::readTerm(in, consumer);
193 }
194
196 size_t generatorCount;
197 in.readSizeT(generatorCount);
198
199 size_t varCount;
200 in.readSizeT(varCount);
201
202 F::readIdeal(in, consumer, generatorCount, varCount);
203 }
204
206 // An empty list is just a ring by itself, and this has a special
207 // syntax. So we first decipher whether we are looking at a ring or
208 // an ideal. At the point where we can tell that it is an ideal, we
209 // have already read part of the ideal, so we have to do something
210 // to pass the read information on to the code for reading the rest
211 // of the ideal.
212
213 size_t generatorCount;
214 in.readSizeT(generatorCount);
215
216 if (generatorCount == 42 && in.peekIdentifier()) {
217 in.expect("ring");
218 VarNames names;
219 F::readRing(in, names);
220 consumer.consumeRing(names);
221 in.expectEOF();
222 return;
223 }
224
225 size_t varCount;
226 in.readSizeT(varCount);
227
228 F::readIdeal(in, consumer, generatorCount, varCount);
229
230 while (hasMoreInput(in))
231 doReadIdeal(in, consumer);
232 }
233
235 CoefBigTermConsumer& consumer) {
236 size_t generatorCount;
237 size_t varCount;
238
239 in.readSizeT(generatorCount);
240 in.readSizeT(varCount);
241
242 if (varCount == 0)
244 ("A polynomial has at least one column in the matrix,"
245 "but this matrix has no columns.");
246
247 // The first column is the coefficient and so does not represent a
248 // variable.
249 --varCount;
250
251 BigPolynomial polynomial((VarNames(varCount)));
252
253 for (size_t t = 0; t < generatorCount; ++t) {
254 // Read a term
255 polynomial.newLastTerm();
256 in.readInteger(polynomial.getLastCoef());
257
258 vector<mpz_class>& term = polynomial.getLastTerm();
259 for (size_t var = 0; var < varCount; ++var) {
260 ASSERT(var < term.size());
261 in.readIntegerAndNegativeAsZero(term[var]);
262 }
263 }
264
265 if (!in.match('(')) {
266 // This expect will fail which improves the error message compared
267 // to just expect('(').
268 in.expect("(coefficient)");
269 }
270 in.expect("coefficient");
271 in.expect(')');
272
273 if (in.peekIdentifier()) {
274 VarNames names;
275 for (size_t var = 0; var < varCount; ++var)
276 names.addVar(in.readIdentifier());
277 polynomial.renameVars(names);
278 }
279
280 consumer.consume(polynomial);
281 }
282
284 SatBinomConsumer& consumer) {
285 size_t generatorCount;
286 in.readSizeT(generatorCount);
287
288 size_t varCount;
289 in.readSizeT(varCount);
290
291 F::readSatBinomIdeal(in, consumer, generatorCount, varCount);
292 }
293
294 void F::writeRing(const VarNames& names, FILE* out) {
295 fputs("42 ring\n", out);
296 writeRingWithoutHeader(names, out);
297 }
298
299 void F::writeRingWithoutHeader(const VarNames& names, FILE* out) {
300 if (names.getVarCount() == 0)
301 return;
302
303 fputc(' ', out);
304 for (size_t var = 0; var < names.getVarCount(); ++var) {
305 if (var > 0)
306 fputc(' ', out);
307 fputs(names.getName(var).c_str(), out);
308 }
309 fputc('\n', out);
310 }
311
312 void F::readTerm(Scanner& in, InputConsumer& consumer) {
313 consumer.beginTerm();
314 const size_t varCount = consumer.getRing().getVarCount();
315 if (varCount == 0)
316 in.expect("_fourtitwo_identity");
317 else {
318 for (size_t var = 0; var < varCount; ++var) {
319 if (in.match('-'))
321 else
322 consumer.consumeVarExponent(var, in);
323 }
324 }
325 consumer.endTerm();
326 }
327
328 void F::readRing(Scanner& in, VarNames& names) {
329 names.clear();
330 while (in.peekIdentifier())
332 }
333
334 void F::readRing(Scanner& in, VarNames& names, size_t varCount) {
335 names.clear();
336 for (size_t var = 0; var < varCount; ++var)
338 }
339
340 void F::writeTerm(const vector<mpz_class>& term, FILE* out) {
341 size_t varCount = term.size();
342 for (size_t var = 0; var < varCount; ++var) {
343 fputc(' ', out);
344 mpz_out_str(out, 10, term[var].get_mpz_t());
345 }
346
347 if (varCount != 0)
348 fputc('\n', out);
349 }
350
351 void F::writeTerm(const Term& term,
352 const TermTranslator& translator,
353 FILE* out) {
354 ASSERT(term.getVarCount() == translator.getVarCount());
355
356 size_t varCount = term.getVarCount();
357 for (size_t var = 0; var < varCount; ++var) {
358 fputc(' ', out);
359 const char* exp = translator.getExponentString(var, term[var]);
360 if (exp == 0)
361 exp = "0";
362 fputs(exp, out);
363 }
364
365 if (varCount != 0)
366 fputc('\n', out);
367 }
368
375 void F::readIdeal(Scanner& in,
376 InputConsumer& consumer,
377 size_t generatorCount,
378 size_t varCount) {
379 consumer.consumeRing(VarNames(varCount));
380 consumer.beginIdeal();
381
382 if (varCount == 0) {
383 for (size_t t = 0; t < generatorCount; ++t) {
384 consumer.beginTerm();
385 consumer.endTerm();
386 }
387 } else {
388 for (size_t t = 0; t < generatorCount; ++t)
389 F::readTerm(in, consumer);
390 }
391
392 if (in.peekIdentifier()) {
393 VarNames names;
394 F::readRing(in, names, varCount);
395 consumer.consumeRing(names);
396 }
397 consumer.endIdeal();
398 }
399
401 SatBinomConsumer& consumer,
402 size_t generatorCount,
403 size_t varCount) {
404 // We have to read the entire ideal before we can tell whether there is
405 // a ring associated to it, so we have to store the ideal here until
406 // that time.
407
408 SatBinomIdeal ideal((VarNames(varCount)));
409 ideal.reserve(generatorCount);
410 for (size_t t = 0; t < generatorCount; ++t) {
411 // Read a term
412 ideal.newLastTerm();
413 vector<mpz_class>& binom = ideal.getLastBinomRef();
414 for (size_t var = 0; var < varCount; ++var)
415 in.readInteger(binom[var]);
416 }
417
418 if (in.peekIdentifier()) {
419 VarNames names;
420 F::readRing(in, names, varCount);
421 ideal.renameVars(names);
422 }
423
424 consumer.consume(ideal);
425 }
426
427 void F::display4ti2Warning() {
428 string msg = "Using the format ";
430 msg += " makes it necessary to store all of the output in "
431 "memory before writing it out. This increases "
432 "memory consumption and decreases performance.";
433 displayNote(msg);
434 }
435}
mpz_class & getLastCoef()
void renameVars(const VarNames &names)
vector< mpz_class > & getLastTerm()
virtual void consume(const mpz_class &coef, const Term &term)
static const DataType & getSatBinomIdealType()
Returns the one and only instance for saturated binomial ideals.
Definition: DataType.cpp:59
static const DataType & getMonomialIdealListType()
Returns the one and only instance for monomial ideal lists.
Definition: DataType.cpp:54
static const DataType & getMonomialIdealType()
Returns the one and only instance for monomial ideals.
Definition: DataType.cpp:45
static const DataType & getPolynomialType()
Returns the one and only instance for polynomials.
Definition: DataType.cpp:50
bool hasMoreInput(Scanner &in) const
Definition: IOHandler.cpp:77
virtual BigTermConsumer * doCreateIdealWriter(FILE *out)
virtual void doReadIdeal(Scanner &in, InputConsumer &consumer)
virtual void doWriteTerm(const vector< mpz_class > &term, const VarNames &names, FILE *out)
virtual void doReadSatBinomIdeal(Scanner &in, SatBinomConsumer &consumer)
virtual void doReadPolynomial(Scanner &in, CoefBigTermConsumer &consumer)
static const char * staticGetName()
virtual CoefBigTermConsumer * doCreatePolynomialWriter(FILE *out)
virtual void doReadIdeals(Scanner &in, InputConsumer &consumer)
virtual void doReadTerm(Scanner &in, InputConsumer &consumer)
virtual void doWriteTerm(const vector< mpz_class > &term, bool first)
virtual void doWriteTerm(const Term &term, const TermTranslator &translator, bool first)
virtual void doWriteEmptyList()
virtual void doWriteHeader(bool first, size_t generatorCount)
virtual void doWriteFooter(bool wasZeroIdeal)
virtual void doWriteHeader(bool first)
virtual void doWriteFooter(bool wasZero)
virtual void doWriteTerm(const mpz_class &coef, const Term &term, const TermTranslator &translator, bool firstGenerator)
virtual void doWriteHeader(size_t termCount)
virtual void doWriteTerm(const mpz_class &coef, const vector< mpz_class > &term, bool firstGenerator)
virtual void doWriteHeader()
This class contains a minimum level of functionality that makes it more convenient to derive from tha...
Definition: IOHandlerImpl.h:37
void registerInput(const DataType &type)
Specify that input of the argument type is supported.
void registerOutput(const DataType &type)
Specify that output of the argument type is supported.
FILE * getFile()
Definition: IdealWriter.h:43
const VarNames & getNames()
Definition: IdealWriter.h:44
FILE * getFile()
Definition: PolyWriter.h:40
const VarNames & getNames() const
Definition: PolyWriter.h:41
void beginTerm()
Start consuming a term.
const VarNames & getRing() const
Returns the current ring.
Definition: InputConsumer.h:91
void beginIdeal()
Start consuming an ideal.
void consumeRing(const VarNames &names)
void consumeVarExponent(size_t var, Scanner &in)
Consumes var raised to an exponent read from in.
void endIdeal()
Done reading an ideal.
void endTerm()
Done reading a term.
virtual void consume(const vector< mpz_class > &term)=0
Represents a saturated binomial ideal.
Definition: SatBinomIdeal.h:28
This class offers an input interface which is more convenient and for some purposes more efficient th...
Definition: Scanner.h:50
void expectEOF()
Require that there is no more input.
Definition: Scanner.cpp:77
void readIntegerAndNegativeAsZero(mpz_class &integer)
Read an integer and set it to zero if it is negative.
Definition: Scanner.cpp:171
void expectIntegerNoSign()
Read an arbitrary-precision integer.
Definition: Scanner.h:243
void expect(char expected)
Require the next character to be equal to expected.
Definition: Scanner.h:231
const char * readIdentifier()
The returned string is only valid until the next method on this object gets called.
Definition: Scanner.cpp:255
bool peekIdentifier()
Skips whitespace and returns true if the next token is an identifier.
Definition: Scanner.h:257
void readSizeT(size_t &size)
Reads a size_t, where the representable range of that type determines when the number is too big.
Definition: Scanner.cpp:205
void readInteger(mpz_class &integer)
Read an arbitrary-precision integer.
Definition: Scanner.h:238
bool match(char c)
Return true if the next character is c, and in that case skip past it.
Definition: Scanner.h:215
TermTranslator handles translation between terms whose exponents are infinite precision integers and ...
size_t getVarCount() const
const char * getExponentString(size_t variable, Exponent exponent) const
as getExponent, except the string "e" is returned, where e is the exponent.
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
bool addVar(const string &name)
Adds the variable and returns true if name is not already a variable.
Definition: VarNames.cpp:44
size_t getVarCount() const
Returns the current number of variables.
Definition: VarNames.h:113
const string & getName(size_t index) const
The returned reference can become invalid next time addVar is called.
Definition: VarNames.cpp:100
void clear()
Resets the number of variables to zero.
Definition: VarNames.cpp:106
void addVarSyntaxCheckUnique(const Scanner &in, const string &name)
As addvar, except it reports a syntax error if name is already a variable.
Definition: VarNames.cpp:68
void displayNote(const string &msg)
Display msg to standard error in a way that indicates that this is something that the user should tak...
Definition: display.cpp:135
This file contains functions for printing strings to standard error.
void reportError(const string &errorMsg)
Definition: error.cpp:23
#define INTERNAL_ERROR_UNIMPLEMENTED()
Definition: error.h:47
void writeTerm(const vector< mpz_class > &term, FILE *out)
void writeTerm(const Term &term, const TermTranslator &translator, FILE *out)
void writeRing(const VarNames &names, FILE *out)
void writeRingWithoutHeader(const VarNames &names, FILE *out)
void readRing(Scanner &in, VarNames &names)
void readIdeal(Scanner &in, InputConsumer &consumer, size_t generatorCount, size_t varCount)
void readSatBinomIdeal(Scanner &in, SatBinomConsumer &consumer, size_t generatorCount, size_t varCount)
void display4ti2Warning()
void readRing(Scanner &in, VarNames &names, size_t varCount)
void readTerm(Scanner &in, InputConsumer &consumer)
#define ASSERT(X)
Definition: stdinc.h:86