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"
28 #include "PolynomialConsolidator.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 
37 namespace 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);
48  void readIdeal(Scanner& in,
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:
62  Fourti2IdealWriter(FILE* out): IdealWriter(out) {
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 
96  class Fourti2PolyWriter : public PolyWriter {
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('-'))
320  in.expectIntegerNoSign();
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())
331  names.addVarSyntaxCheckUnique(in, in.readIdentifier());
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)
337  names.addVarSyntaxCheckUnique(in, in.readIdentifier());
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 
400  void F::readSatBinomIdeal(Scanner& in,
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.
void beginIdeal()
Start consuming an ideal.
const VarNames & getRing() const
Returns the current ring.
Definition: InputConsumer.h:91
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