Frobby 0.9.7
IdealOrderer.cpp
Go to the documentation of this file.
1/* Frobby: Software for monomial ideal computations.
2 Copyright (C) 2010 University of Aarhus
3 Contact Bjarke Hammersholt Roune for license information (www.broune.com)
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see http://www.gnu.org/licenses/.
17*/
18#include "stdinc.h"
19#include "IdealOrderer.h"
20
21#include "Ideal.h"
22#include "TermPredicate.h"
23#include "IdealOrderer.h"
24#include "NameFactory.h"
25#include "TermExtra.h"
26#include "ElementDeleter.h"
27
28#include <algorithm>
29#include <cstdlib>
30#include <iterator>
31#include <map>
32
35
36namespace {
37 template<class Pred>
38 class IdealSorter : public IdealOrderer {
39 public:
40 static const char* staticGetName() {
41 return Pred::staticGetName();
42 }
43
44 private:
45 virtual void doOrder(Ideal& ideal) const {
46 Pred pred;
47 pred.setVarCount(ideal.getVarCount());
48 stable_sort(ideal.begin(), ideal.end(), pred);
49 }
50 };
51
52 class RandomOrderer : public IdealOrderer {
53 public:
54 static const char* staticGetName() {return "random";}
55 private:
56 struct URBG {
57 using result_type = unsigned;
58 static constexpr unsigned min() { return 0; }
59 static constexpr unsigned max() { return RAND_MAX; }
60 unsigned operator()() const { return std::rand(); }
61 };
62 void doOrder(Ideal& ideal) const {
63 URBG g;
64 std::shuffle(ideal.begin(), ideal.end(), g);
65 }
66 };
67
68 class TotalDegreeComparator : public TermPredicate {
69 public:
70 static const char* staticGetName() {return "tdeg";}
71 private:
72 virtual bool doPredicate(const Exponent* a,
73 const Exponent* b) const {
74 totalDegree(_degA, a, getVarCount());
75 totalDegree(_degB, b, getVarCount());
76 return _degA < _degB;
77 }
78 mutable mpz_class _degA; // member to avoid repeated allocation
79 mutable mpz_class _degB;
80 };
81
82 class MedianComparator : public TermPredicate {
83 public:
84 static const char* staticGetName() {return "median";}
85 private:
86 virtual bool doPredicate(const Exponent* a,
87 const Exponent* b) const {
88 return median(a, getVarCount()) < median(b, getVarCount());
89 }
90 };
91
92 class MedianPositiveComparator : public TermPredicate {
93 public:
94 static const char* staticGetName() {return "posMedian";}
95 private:
96 virtual bool doPredicate(const Exponent* a,
97 const Exponent* b) const {
98 return medianPositive(a, getVarCount()) <
99 medianPositive(b, getVarCount());
100 }
101 };
102
103 class MinimumPositiveComparator : public TermPredicate {
104 public:
105 static const char* staticGetName() {return "minPos";}
106 private:
107 virtual bool doPredicate(const Exponent* a,
108 const Exponent* b) const {
109 return minimumPositive(a, getVarCount()) <
110 minimumPositive(b, getVarCount());
111 }
112 };
113
114 class MaximumComparator : public TermPredicate {
115 public:
116 static const char* staticGetName() {return "max";}
117 private:
118 virtual bool doPredicate(const Exponent* a,
119 const Exponent* b) const {
120 return maximum(a, getVarCount()) < maximum(b, getVarCount());
121 }
122 };
123
124 class SupportComparator : public TermPredicate {
125 public:
126 static const char* staticGetName() {return "support";}
127 private:
128 virtual bool doPredicate(const Exponent* a,
129 const Exponent* b) const {
130 return Term::getSizeOfSupport(a, getVarCount()) <
131 Term::getSizeOfSupport(b, getVarCount());
132 }
133 };
134
135 class StrongGenericityOrderer : public IdealOrderer {
136 public:
137 static const char* staticGetName() {return "strongGenericity";}
138
139 protected:
140 void orderGenericity(Ideal& ideal, bool strong) const {
141 // Using a map here is the prettier of several ugly
142 // alternaties. Only trade more ugly for efficiency if this
143 // method turns up as a significant consumer of time in a
144 // profiler.
145 UnGenMap degeneracy;
146
147 // Make degeneracy[gen] be the number of other generators that
148 // shares a positive exponent with gen.
149 Term tmp(ideal.getVarCount());
150 for (cit a = ideal.begin(); a != ideal.end(); ++a) {
151 for (cit b = a + 1; b != ideal.end(); ++b) {
152 if (Term::sharesNonZeroExponent(*a, *b, ideal.getVarCount())) {
153 if (!strong) {
154 tmp.lcm(*a, *b);
155 if (ideal.strictlyContains(tmp))
156 continue;
157 }
158 ++degeneracy[*a];
159 ++degeneracy[*b];
160 }
161 }
162 }
163
164 Pred pred(degeneracy);
165 stable_sort(ideal.begin(), ideal.end(), pred);
166 }
167
168 private:
169 typedef Ideal::const_iterator cit;
170 typedef map<const Exponent*, size_t> UnGenMap;
171
172 virtual void doOrder(Ideal& ideal) const {
173 orderGenericity(ideal, true);
174 }
175
176 class Pred {
177 public:
178 Pred(UnGenMap& degeneracy): _degeneracy(degeneracy) {}
179
180 bool operator()(const Exponent* a, const Exponent* b) const {
181 return _degeneracy[a] < _degeneracy[b];
182 }
183
184 private:
185 UnGenMap& _degeneracy;
186 };
187 };
188
189 class NullOrderer : public IdealOrderer {
190 public:
191 static const char* staticGetName() {return "null";}
192 private:
193 virtual void doOrder(Ideal& ideal) const {}
194 };
195
197 class WeakGenericityOrderer : public StrongGenericityOrderer {
198 public:
199 static const char* staticGetName() {return "weakGenericity";}
200 private:
201 virtual void doOrder(Ideal& ideal) const {
202 orderGenericity(ideal, false);
203 }
204 };
205
208 class ReverseOrderer : public IdealOrderer {
209 public:
210 ReverseOrderer(unique_ptr<IdealOrderer> orderer): _orderer(std::move(orderer)) {}
211
212 private:
213 virtual void doOrder(Ideal& ideal) const {
214 // Could probably be done more efficiently by trying to interact
215 // with the orderer, but that would be so much more trouble. The
216 // first reverse is necessary to ensure the ordering is stable.
217 reverse(ideal.begin(), ideal.end());
218 _orderer->order(ideal);
219 reverse(ideal.begin(), ideal.end());
220 }
221 unique_ptr<IdealOrderer> _orderer;
222 };
223
224 class CompositeOrderer : public IdealOrderer {
225 public:
226 CompositeOrderer(): _orderersDeleter(_orderers) {}
227
228 void refineOrderingWith(unique_ptr<IdealOrderer> orderer) {
229 exceptionSafePushBack(_orderers, std::move(orderer));
230 }
231
232 private:
233 typedef vector<IdealOrderer*> Container;
234 typedef Container::const_reverse_iterator rev_cit;
235
236 virtual void doOrder(Ideal& ideal) const {
237 // This works because orderes that define a non-total order
238 // (i.e. those that can be interestingly refined) use a stable
239 // sorting algorithm.
240 rev_cit rbegin(_orderers.end());
241 rev_cit rend(_orderers.begin());
242 for (rev_cit it = rbegin; it != rend; ++it)
243 (*it)->order(ideal);
244 }
245
246 Container _orderers;
247 ElementDeleter<Container> _orderersDeleter;
248 };
249
250 typedef NameFactory<IdealOrderer> OrdererFactory;
251 OrdererFactory getOrdererFactory() {
252 OrdererFactory factory("ordering of terms");
253
266
267 return factory;
268 }
269
270 unique_ptr<IdealOrderer> createNonCompositeOrderer(const string& prefix) {
271 if (prefix.substr(0, 3) == "rev") {
272 unique_ptr<IdealOrderer> orderer =
273 createWithPrefix(getOrdererFactory(), prefix.substr(3));
274 return unique_ptr<IdealOrderer>(new ReverseOrderer(std::move(orderer)));
275 } else
276 return createWithPrefix(getOrdererFactory(), prefix);
277 }
278}
279
280unique_ptr<IdealOrderer> createIdealOrderer(const string& prefix) {
281 if (prefix.find('_') == string::npos)
282 return createNonCompositeOrderer(prefix);
283
284 unique_ptr<CompositeOrderer> composite(new CompositeOrderer());
285 size_t pos = 0;
286 while (true) {
287 size_t nextUnderscore = prefix.find('_', pos);
288 string subPrefix = prefix.substr(pos, nextUnderscore - pos);
289 composite->refineOrderingWith(createNonCompositeOrderer(subPrefix));
290
291 if (nextUnderscore == string::npos)
292 break;
293 pos = nextUnderscore + 1;
294 }
295 return unique_ptr<IdealOrderer>(composite.release());
296}
void exceptionSafePushBack(Container &container, unique_ptr< Element > pointer)
unique_ptr< IdealOrderer > createIdealOrderer(const string &prefix)
void nameFactoryRegister(NameFactory< AbstractProduct > &factory)
Registers the string returned by ConcreteProduct::getStaticName() to a function that default-construc...
unique_ptr< AbstractProduct > createWithPrefix(const NameFactory< AbstractProduct > &factory, const string &prefix)
Creates the unique product that has the indicated prefix, or create the actual product that has name ...
Exponent median(const Exponent *a, size_t varCount)
Returns the lower median exponent of a.
Definition TermExtra.cpp:25
Exponent medianPositive(const Exponent *a, size_t varCount)
Returns the lower median of the positive exponents of a.
Definition TermExtra.cpp:35
void totalDegree(mpz_class &res, const Exponent *a, size_t varCount)
Puts the sum of the entries of a into res.
Definition TermExtra.cpp:49
Exponent minimumPositive(const Exponent *a, size_t varCount)
Returns the smallest positive exponent of a.
Definition TermExtra.cpp:55
Exponent maximum(const Exponent *a, size_t varCount)
Returns the largest exponent of a.
Definition TermExtra.cpp:68
virtual ~IdealOrderer()
Cont::const_iterator const_iterator
Definition Ideal.h:43
bool strictlyContains(const Exponent *term) const
Definition Ideal.cpp:73
const_iterator end() const
Definition Ideal.h:49
const_iterator begin() const
Definition Ideal.h:48
size_t getVarCount() const
Definition Ideal.h:56
A NameFactory takes a name and then creates an instance of a class that has been previously registere...
Definition NameFactory.h:33
size_t getSizeOfSupport() const
Definition Term.h:411
static bool sharesNonZeroExponent(const Exponent *a, const Exponent *b, size_t varCount)
Returns whether there is some such that .
Definition Term.h:416
This header file includes common definitions and is included as the first line of code in every imple...
unsigned int Exponent
Definition stdinc.h:89