Frobby  0.9.5
Macaulay2IOHandler.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 "Macaulay2IOHandler.h"
19 
20 #include "Scanner.h"
21 #include "VarNames.h"
22 #include "TermTranslator.h"
23 #include "DataType.h"
24 #include "Term.h"
25 #include "IdealWriter.h"
26 #include "PolyWriter.h"
27 #include "error.h"
28 #include "display.h"
29 #include "InputConsumer.h"
30 #include <cstdio>
31 
32 namespace IO {
33  namespace {
34  string m2GetRingName(const VarNames& names);
35  void m2WriteRing(const VarNames& names, FILE* out);
36  }
37 
38  class M2IdealWriter : public IdealWriter {
39  public:
40  M2IdealWriter(FILE* out): IdealWriter(out) {
41  }
42 
43  private:
44  virtual void doWriteHeader(bool first) {
45  if (first)
46  m2WriteRing(getNames(), getFile());
47  fputs("I = monomialIdeal(", getFile());
48  }
49 
50  virtual void doWriteTerm(const Term& term,
51  const TermTranslator& translator,
52  bool first) {
53  fputs(first ? "\n " : ",\n ", getFile());
54  writeTermProduct(term, translator, getFile());
55 
56  const size_t varCount = translator.getVarCount();
57  for (size_t var = 0; var < varCount; ++var)
58  if (translator.getExponent(var, term) != 0)
59  return;
60 
61  fputc('_', getFile());
62  fputs(m2GetRingName(translator.getNames()).c_str(), getFile());
63  }
64 
65  virtual void doWriteTerm(const vector<mpz_class>& term,
66  bool first) {
67  fputs(first ? "\n " : ",\n ", getFile());
68  writeTermProduct(term, getNames(), getFile());
69 
70  const size_t varCount = term.size();
71  for (size_t var = 0; var < varCount; ++var)
72  if (term[var] != 0)
73  return;
74 
75  fputc('_', getFile());
76  fputs(m2GetRingName(getNames()).c_str(), getFile());
77  }
78 
79  virtual void doWriteFooter(bool wasZeroIdeal) {
80  if (wasZeroIdeal) {
81  // Macaulay 2's monomialIdeal reports an error if we give it an
82  // empty list, so to get the zero ideal we have to explicitly
83  // specify zero as a generator.
84  fprintf(getFile(), "0_%s);\n", m2GetRingName(getNames()).c_str());
85  } else
86  fputs("\n);\n", getFile());
87  }
88 
89  virtual void doWriteEmptyList() {
90  m2WriteRing(getNames(), getFile());
91  }
92  };
93 
94  class M2PolyWriter : public PolyWriter {
95  public:
96  M2PolyWriter(FILE* out): PolyWriter(out) {
97  }
98 
99  virtual void doWriteHeader() {
100  m2WriteRing(getNames(), getFile());
101  fputs("p =", getFile());
102  }
103 
104  virtual void doWriteTerm(const mpz_class& coef,
105  const Term& term,
106  const TermTranslator& translator,
107  bool firstGenerator) {
108  if (firstGenerator)
109  fputs("\n ", getFile());
110  else
111  fputs(" +\n ", getFile());
112 
113  writeCoefTermProduct(coef, term, translator, true, getFile());
114  }
115 
116  virtual void doWriteTerm(const mpz_class& coef,
117  const vector<mpz_class>& term,
118  bool firstGenerator) {
119  if (firstGenerator)
120  fputs("\n ", getFile());
121  else
122  fputs(" +\n ", getFile());
123 
124  writeCoefTermProduct(coef, term, getNames(), true, getFile());
125  }
126 
127  virtual void doWriteFooter(bool wasZero) {
128  if (wasZero)
129  fputs("\n 0", getFile());
130  fputs(";\n", getFile());
131  }
132  };
133 
135  IOHandlerCommon(staticGetName(),
136  "Format understandable by the program Macaulay 2.") {
143  }
144 
146  return "m2";
147  }
148 
150  return new M2IdealWriter(out);
151  }
152 
154  return new M2PolyWriter(out);
155  }
156 
157  void Macaulay2IOHandler::doWriteTerm(const vector<mpz_class>& term,
158  const VarNames& names,
159  FILE* out) {
160  writeTermProduct(term, names, out);
161  }
162 
164  consumer.consumeTermProductNotation(in);
165  if (in.match('_'))
166  in.readIdentifier();
167  }
168 
170  names.clear();
171  const char* ringName = in.readIdentifier();
172  ASSERT(ringName != 0 && string(ringName) != "");
173  if (ringName[0] != 'R') {
175  (in, "Expected name of ring to start with an upper case R.");
176  ASSERT(false); // shouldn't reach here.
177  }
178 
179  in.expect('=');
180 
181  in.eatWhite();
182  if (in.peek() == 'Z') {
183  displayNote("In the Macaulay 2 format, writing ZZ as the ground field "
184  "instead of QQ is deprecated and may not work in future "
185  "releases of Frobby.");
186  in.expect("ZZ");
187  } else
188  in.expect("QQ");
189  in.expect('[');
190 
191  // The enclosing braces are optional, but if the start brace is
192  // there, then the end brace should be there too.
193  bool readBrace = in.match('{');
194  if (readBrace) {
195  displayNote("In the Macaulay 2 format, putting braces { } around the "
196  "variables is deprecated and may not work in future "
197  "releases of Frobby.");
198  }
199 
200  if (in.peekIdentifier()) {
201  do {
202  names.addVarSyntaxCheckUnique(in, in.readIdentifier());
203  } while (in.match(','));
204  }
205 
206  if (readBrace)
207  in.expect('}');
208  in.expect(']');
209  in.expect(';');
210  }
211 
213  return in.peek('R') || in.peek('r');
214  }
215 
217  (Scanner& in, InputConsumer& consumer) {
218  consumer.beginIdeal();
219 
220  in.expect('I');
221  in.expect('=');
222  in.expect("monomialIdeal");
223  in.expect('(');
224 
225  if (in.match('0')) {
226  if (in.match('_'))
227  in.readIdentifier();
228  } else {
229  do {
230  consumer.consumeTermProductNotation(in);
231  if (in.match('_'))
232  in.readIdentifier();
233  } while (in.match(','));
234  }
235  in.expect(')');
236  in.expect(';');
237  consumer.endIdeal();
238  }
239 
241  const VarNames& names,
242  CoefBigTermConsumer& consumer) {
243  consumer.consumeRing(names);
244  vector<mpz_class> term(names.getVarCount());
245  mpz_class coef;
246 
247  in.expect('p');
248  in.expect('=');
249 
250  consumer.beginConsuming();
251  bool first = true;
252  do {
253  readCoefTerm(coef, term, names, first, in);
254  consumer.consume(coef, term);
255  first = false;
256  } while (!in.match(';'));
257  consumer.doneConsuming();
258  }
259 
260  namespace {
261  string m2GetRingName(const VarNames& names) {
262  string name = "R";
263  if (!names.contains(name))
264  return name;
265 
266  for (mpz_class i = 1; true; ++i) {
267  name = "R" + i.get_str();
268  if (!names.contains(name))
269  return name;
270  }
271  }
272 
273  void m2WriteRing(const VarNames& names, FILE* out) {
274  fputs(m2GetRingName(names).c_str(), out);
275  fputs(" = QQ[", out);
276 
277  const char* pre = "";
278  for (unsigned int i = 0; i < names.getVarCount(); ++i) {
279  fputs(pre, out);
280  if (names.getName(i) == "R") {
281  string msg =
282  "The name of the ring in Macaulay 2 format is usually named R,\n"
283  "but in this case there is already a variable named R. Thus,\n"
284  "the ring has been renamed to " + m2GetRingName(names) + '.';
285  displayNote(msg);
286  }
287  fputs(names.getName(i).c_str(), out);
288  pre = ", ";
289  }
290  fputs("];\n", out);
291  }
292  }
293 }
virtual void beginConsuming()=0
virtual void consume(const mpz_class &coef, const Term &term)
virtual void doneConsuming()=0
virtual void consumeRing(const VarNames &names)=0
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
This class contains further functionality that makes it more convenient to derive from than IOHandler...
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
virtual void doWriteTerm(const vector< mpz_class > &term, bool first)
virtual void doWriteFooter(bool wasZeroIdeal)
virtual void doWriteTerm(const Term &term, const TermTranslator &translator, bool first)
virtual void doWriteHeader(bool first)
virtual void doWriteEmptyList()
virtual void doWriteFooter(bool wasZero)
virtual void doWriteTerm(const mpz_class &coef, const vector< mpz_class > &term, bool firstGenerator)
virtual void doWriteHeader()
virtual void doWriteTerm(const mpz_class &coef, const Term &term, const TermTranslator &translator, bool firstGenerator)
virtual bool doPeekRing(Scanner &in)
virtual void doReadBareIdeal(Scanner &in, InputConsumer &consumer)
virtual CoefBigTermConsumer * doCreatePolynomialWriter(FILE *out)
static const char * staticGetName()
virtual void doWriteTerm(const vector< mpz_class > &term, const VarNames &names, FILE *out)
virtual void doReadRing(Scanner &in, VarNames &names)
virtual BigTermConsumer * doCreateIdealWriter(FILE *out)
virtual void doReadTerm(Scanner &in, InputConsumer &consumer)
virtual void doReadBarePolynomial(Scanner &in, const VarNames &names, CoefBigTermConsumer &consumer)
FILE * getFile()
Definition: PolyWriter.h:40
const VarNames & getNames() const
Definition: PolyWriter.h:41
void beginIdeal()
Start consuming an ideal.
void consumeTermProductNotation(Scanner &in)
Reads a term in a format like "a^4*b*c^2".
void endIdeal()
Done reading an ideal.
This class offers an input interface which is more convenient and for some purposes more efficient th...
Definition: Scanner.h:50
bool peek(char character)
Skips whitespace and returns true if the next character is equal to the parameter(s).
Definition: Scanner.h:262
void eatWhite()
Reads past any whitespace, where whitespace is defined by the standard function isspace().
Definition: Scanner.h:267
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
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 ...
const mpz_class & getExponent(size_t variable, Exponent exponent) const
This method translates from IDs to arbitrary precision integers.
size_t getVarCount() const
const VarNames & getNames() const
Term represents a product of variables which does not include a coefficient.
Definition: Term.h:49
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 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
bool contains(const string &name) const
Returns true if name is the name of a variable.
Definition: VarNames.cpp:91
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 reportSyntaxError(const Scanner &scanner, const string &errorMsg)
Definition: error.cpp:44
void writeCoefTermProduct(const mpz_class &coef, const Term &term, const TermTranslator &translator, bool hidePlus, FILE *out)
void readCoefTerm(BigPolynomial &polynomial, bool firstTerm, Scanner &in)
void writeTermProduct(const Term &term, const TermTranslator &translator, FILE *out)
#define ASSERT(X)
Definition: stdinc.h:86