carl  24.04
Computer ARithmetic Library
GBProcedure.h
Go to the documentation of this file.
1 /**
2  * @file GBProcedure.h
3  * @ingroup gb
4  * @author Sebastian Junges
5  *
6  */
7 
8 #pragma once
9 #include "Ideal.h"
10 #include "Reductor.h"
13 
14 namespace carl
15 {
16 
17 template<typename Polynomial>
19 {
20  public:
21  virtual ~AbstractGBProcedure() = default;
22  virtual void addPolynomial(const Polynomial& p) = 0;
23  virtual void reset()= 0;
24  virtual void calculate()= 0;
25 
26 
27  virtual std::list<std::pair<BitVector, BitVector> > reduceInput()= 0;
28  virtual const Ideal<Polynomial>& getIdeal() const = 0;
29 };
30 
31 /**
32  * A general class for Groebner Basis calculation.
33  * It is parameterized not only in the type of polynomial to be used,
34  * but also in the concrete procedure to be used,
35  * and the way polynomials should be added to this procedure.
36  *
37  * Please notice that this class is designed to support incremental calls.
38  * Therefore, it holds a queue with the polynomials which are added.
39  * Only upon calling the calculate method, these polynoimials are added to the actual groebner basis.
40  *
41  * Moreover, we can
42  * @ingroup gb
43  */
44 template<typename Polynomial, template<typename, template<typename> class > class Procedure, template<typename> class AddingPolynomialPolicy>
45 class GBProcedure : private Procedure<Polynomial, AddingPolynomialPolicy>, public AbstractGBProcedure<Polynomial>
46 {
47 private:
48  /// The ideal represented by the current elements of the Groebner basis.
49  std::shared_ptr<Ideal<Polynomial>> mGb;
50  /// The polynomials which are added during the next call for calculate.
51  std::list<Polynomial> mInputScheduled;
52  /// The input polynomials
53  std::vector<Polynomial> mOrigGenerators;
54  /// Indices of the input polynomials.
55  std::vector<size_t> mOrigGeneratorsIndices;
56 
57 public:
58 
60  Procedure<Polynomial, AddingPolynomialPolicy>(),
61  mGb(new Ideal<Polynomial>),
62  mInputScheduled(),
63  mOrigGenerators(),
64  mOrigGeneratorsIndices()
65  {
66  Procedure<Polynomial, AddingPolynomialPolicy>::setIdeal(mGb);
67  }
68 
69 
70  GBProcedure(const GBProcedure& old):
71  Procedure<Polynomial, AddingPolynomialPolicy>(old),
72  mGb(new Ideal<Polynomial>(*old.mGb)),
73  mInputScheduled(old.mInputScheduled),
74  mOrigGenerators(old.mOrigGenerators),
75  mOrigGeneratorsIndices(old.mOrigGeneratorsIndices)
76  {
77  Procedure<Polynomial, AddingPolynomialPolicy>::setIdeal(mGb);
78  }
79 
80  virtual ~GBProcedure() = default;
81 
83  {
84  if(this == &rhs) return *this;
85  mGb.reset(new Ideal<Polynomial>(*rhs.mGb));
86  mInputScheduled = rhs.mInputScheduled;
87  mOrigGenerators = rhs.mOrigGenerators;
88  mOrigGeneratorsIndices = rhs.mOrigGeneratorsIndices;
89  Procedure<Polynomial, AddingPolynomialPolicy>::setIdeal(mGb);
90  Procedure<Polynomial, AddingPolynomialPolicy>::setCriticalPairs(rhs.pCritPairs);
91  return *this;
92  }
93 
94  /**
95  * Check whether a polynomial is scheduled to be added to the Groebner basis.
96  * @return whether the input is empty.
97  */
98  bool inputEmpty() const
99  {
100  return mInputScheduled.empty();
101  }
102 
103  /**
104  * The number of polynomials which were originally added to the GB.
105  * @return number of polynomials added.
106  */
107  size_t nrOrigGenerators() const
108  {
109  return mOrigGenerators.size();
110  }
111 
112  /**
113  * Add a polynmomial which is added to the groebner basis during the next calculate call.
114  * @param p The polynomial to be added.
115  */
116  void addPolynomial(const Polynomial& p)
117  {
118  mInputScheduled.push_back(p);
119  mOrigGenerators.push_back(p);
120  }
121 
122  /**
123  * Checks whether the current representants of the GB contain a constant polynomial.
124  * @return
125  */
126  bool basisis_constant() const
127  {
128  return getIdeal().is_constant();
129  }
130 
131  /**
132  *
133  * @return
134  */
135  std::list<Polynomial> listBasisPolynomials() const
136  {
137  return std::list<Polynomial>(getBasisPolynomials().begin(), getBasisPolynomials().end());
138  }
139 
140  /**
141  *
142  * @return
143  */
144  const std::vector<Polynomial>& getBasisPolynomials() const
145  {
146  return getIdeal().getGenerators();
147  }
148 
149  void printScheduledPolynomials(bool breakLines = true, bool printReasons = true, std::ostream& os = std::cout) const
150  {
151  for(const Polynomial& p : mInputScheduled)
152  {
153  os << p;
154  if(printReasons)
155  {
156  os << "[";
157  p.getReasons().print(os);
158  os << "]";
159  }
160  if(breakLines)
161  {
162  os << std::endl;
163  }
164  else
165  {
166  os.flush();
167  }
168 
169  }
170  }
171 
172 
173  /**
174  * Remove all polynomials from the Groebner basis.
175  */
176  void reset()
177  {
178  mGb.reset(new Ideal<Polynomial>());
179  Procedure<Polynomial, AddingPolynomialPolicy>::setIdeal(mGb);
180  }
181 
182  /**
183  * Get the ideal which encodes the GB.
184  * @return
185  */
187  {
188  return *mGb;
189  }
190 
191  /**
192  * Calculate the Groebner basis of the current GB union the scheduled polynomials.
193  */
194  void calculate()
195  {
196  CARL_LOG_INFO("carl.gb.gbproc", "Calculate gb");
197  if(mGb->getGenerators().size() + mInputScheduled.size() == 0)
198  {
199  return;
200  }
201  // Use procedure
202  Procedure<Polynomial, AddingPolynomialPolicy>::calculate(mInputScheduled);
203  // remove the just added polynomials from the set of input polynomials
204  mInputScheduled.clear();
205  mGb->removeEliminated();
206  CARL_LOG_DEBUG("carl.gb.gbproc", "GB, before reduction: " << *mGb);
207  // We have to update our indices list. but we do this just before returning because in the next step
208  // we further shrink the size.
209  reduceGB();
210  }
211 
212  /**
213  * Reduce the input polynomials using the other input polynomials and the current Groebner basis.
214  * @return
215  */
216  std::list<std::pair<BitVector, BitVector> > reduceInput()
217  {
218  CARL_LOG_TRACE("carl.gb.gbproc", "Reduce input");
219  std::vector<Polynomial> toBeReduced;
220  //We only schedule "new" input for reduction
221  for(typename std::list<Polynomial>::const_iterator it = mInputScheduled.begin(); it != mInputScheduled.end(); ++it)
222  {
223  toBeReduced.push_back(*it);
224  }
225  std::sort(toBeReduced.begin(), toBeReduced.end(), Polynomial::compareByLeadingTerm);
226 
227  // We will continue to generate new scheduled polynomials, which make the scheduled polynomials from before superfluous.
228  mInputScheduled.clear();
229 
230  // We reduce with the whole ideal, that is,
231  // we also use polynomials to be added to reduce other polynomials which are about to be added.
232  Ideal<Polynomial> reduced(*mGb);
233 
234  // If we are going to trace the origns, we need to trace them here as well.
235  // Moreover, if we want to return deductions,
236  // that is done by return the bitvector together with the bitvector which represents the original.
237  std::list<std::pair<BitVector, BitVector> > result;
238 
239  for(typename std::vector<Polynomial>::const_iterator index = toBeReduced.begin(); index != toBeReduced.end(); ++index)
240  {
241  Reductor<Polynomial, Polynomial> reduct(reduced, *index);
242  Polynomial res = reduct.fullReduce();
243  if(is_zero(res))
244  {
245  result.push_back(std::pair<BitVector, BitVector>(index->getReasons(), res.getReasons()));
246  }
247  else // ( !is_zero(res) )
248  {
249  CARL_LOG_TRACE("carl.gb.gbproc", "Add input polynomial " << res.normalize());
250  // Use the polynomial to reduce other input polynomials.
251  reduced.addGenerator(res.normalize());
252  // And restore it as scheduled polynomial.
253  mInputScheduled.push_back(res.normalize());
254  }
255  }
256 
257  return result;
258  }
259 private:
260 
261  void reduceGB()
262  {
263  for(size_t i = 0; i < mGb->nrGenerators(); ++i)
264  {
265  bool divisible = false;
266 
267  CARL_LOG_TRACE("carl.gb.gbproc", "Check " << mGb->getGenerator(i));
268  for(size_t j = 0; !divisible && j != mGb->nrGenerators(); ++j)
269  {
270  if(j == i) continue;
271 
272  divisible = mGb->getGenerator(i).lmon()->divisible(mGb->getGenerator(j).lmon());
273  CARL_LOG_TRACE("carl.gb.gbproc", "" << (divisible ? "" : "not ") << "divisible by " << mGb->getGenerator(j));
274  }
275 
276  if(divisible)
277  {
278  CARL_LOG_TRACE("carl.gb.gbproc", "Eliminate " << mGb->getGenerator(i));
279  mGb->eliminateGenerator(i);
280  }
281  }
282  mGb->removeEliminated();
283  CARL_LOG_DEBUG("carl.gb.gbproc", "GB Reduction, minimal GB: " << *mGb);
284  // Calculate reduction
285  // The number of polynomials will not change anymore!
286  std::vector<size_t> toBeReduced(mGb->getOrderedIndices());
287 
288  std::shared_ptr<Ideal<Polynomial>> reduced(new Ideal<Polynomial>());
289  for(std::vector<size_t>::const_iterator index = toBeReduced.begin(); index != toBeReduced.end(); ++index)
290  {
291  Reductor<Polynomial, Polynomial> reduct(*reduced, mGb->getGenerator(*index));
292  Polynomial res = reduct.fullReduce();
293  if(!is_zero(res))
294  {
295  res.normalize();
296  CARL_LOG_DEBUG("carl.gb.gbproc", "GB Reduction, reduced " << mGb->getGenerator(*index) << " to " << res);
297  reduced->addGenerator(res);
298  }
299  }
300 
301  mGb = reduced;
302  Procedure<Polynomial, AddingPolynomialPolicy>::setIdeal(mGb);
303  }
304 };
305 }
A small wrapper that configures logging for carl.
#define CARL_LOG_TRACE(channel, msg)
Definition: carl-logging.h:44
#define CARL_LOG_DEBUG(channel, msg)
Definition: carl-logging.h:43
#define CARL_LOG_INFO(channel, msg)
Definition: carl-logging.h:42
carl is the main namespace for the library.
bool is_zero(const Interval< Number > &i)
Check if this interval is a point-interval containing 0.
Definition: Interval.h:1453
virtual void calculate()=0
virtual void addPolynomial(const Polynomial &p)=0
virtual const Ideal< Polynomial > & getIdeal() const =0
virtual void reset()=0
virtual ~AbstractGBProcedure()=default
virtual std::list< std::pair< BitVector, BitVector > > reduceInput()=0
A general class for Groebner Basis calculation.
Definition: GBProcedure.h:46
std::list< std::pair< BitVector, BitVector > > reduceInput()
Reduce the input polynomials using the other input polynomials and the current Groebner basis.
Definition: GBProcedure.h:216
std::shared_ptr< Ideal< Polynomial > > mGb
The ideal represented by the current elements of the Groebner basis.
Definition: GBProcedure.h:49
bool basisis_constant() const
Checks whether the current representants of the GB contain a constant polynomial.
Definition: GBProcedure.h:126
const std::vector< Polynomial > & getBasisPolynomials() const
Definition: GBProcedure.h:144
void calculate()
Calculate the Groebner basis of the current GB union the scheduled polynomials.
Definition: GBProcedure.h:194
size_t nrOrigGenerators() const
The number of polynomials which were originally added to the GB.
Definition: GBProcedure.h:107
GBProcedure(const GBProcedure &old)
Definition: GBProcedure.h:70
std::list< Polynomial > mInputScheduled
The polynomials which are added during the next call for calculate.
Definition: GBProcedure.h:51
virtual ~GBProcedure()=default
std::list< Polynomial > listBasisPolynomials() const
Definition: GBProcedure.h:135
std::vector< size_t > mOrigGeneratorsIndices
Indices of the input polynomials.
Definition: GBProcedure.h:55
void addPolynomial(const Polynomial &p)
Add a polynmomial which is added to the groebner basis during the next calculate call.
Definition: GBProcedure.h:116
bool inputEmpty() const
Check whether a polynomial is scheduled to be added to the Groebner basis.
Definition: GBProcedure.h:98
GBProcedure & operator=(const GBProcedure &rhs)
Definition: GBProcedure.h:82
const Ideal< Polynomial > & getIdeal() const
Get the ideal which encodes the GB.
Definition: GBProcedure.h:186
void reset()
Remove all polynomials from the Groebner basis.
Definition: GBProcedure.h:176
void printScheduledPolynomials(bool breakLines=true, bool printReasons=true, std::ostream &os=std::cout) const
Definition: GBProcedure.h:149
std::vector< Polynomial > mOrigGenerators
The input polynomials.
Definition: GBProcedure.h:53
size_t addGenerator(const Polynomial &f)
Definition: Ideal.h:67
A dedicated algorithm for calculating the remainder of a polynomial modulo a set of other polynomials...
Definition: Reductor.h:69
InputPolynomial fullReduce()
Uses the ideal to reduce a polynomial as far as possible.
Definition: Reductor.h:181