Frobby 0.9.7
MsmStrategy.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 "MsmStrategy.h"
19
20#include "MsmSlice.h"
21#include "Term.h"
22#include "Ideal.h"
23#include "TermTranslator.h"
24#include <vector>
25#include "Projection.h"
26#include "TermGrader.h"
27
29 const SplitStrategy* splitStrategy):
30 SliceStrategyCommon(splitStrategy),
31 _consumer(consumer) {
32 ASSERT(consumer != 0);
33}
34
36 const SplitStrategy* splitStrategy,
37 const Ideal& initialSubtract):
38 SliceStrategyCommon(splitStrategy),
39 _consumer(consumer),
40 _initialSubtract(new Ideal(initialSubtract)) {
41 ASSERT(consumer != 0);
42}
43
44void MsmStrategy::run(const Ideal& ideal) {
45 ASSERT(_initialSubtract.get() == 0 ||
46 _initialSubtract->getVarCount() == ideal.getVarCount());
47
48 _consumer->beginConsuming();
49 size_t varCount = ideal.getVarCount();
50 if (_initialSubtract.get() == 0)
51 _initialSubtract = unique_ptr<Ideal>(new Ideal(varCount));
52
53 Term sliceMultiply(varCount);
54 for (size_t var = 0; var < varCount; ++var)
55 sliceMultiply[var] = 1;
56
57 unique_ptr<Slice> slice
58 (new MsmSlice(*this, ideal, *_initialSubtract, sliceMultiply, _consumer));
59 simplify(*slice);
60
61 _initialSubtract.reset();
62 _tasks.addTask(slice.release());
63 _tasks.runTasks();
64 _consumer->doneConsuming();
65}
66
67bool MsmStrategy::processSlice(TaskEngine& tasks, unique_ptr<Slice> slice) {
68 ASSERT(slice.get() != 0);
69
70 if (slice->baseCase(getUseSimplification())) {
71 freeSlice(std::move(slice));
72 return true;
73 }
74
75 if (getUseIndependence() && _indep.analyze(*slice))
76 independenceSplit(std::move(slice));
77 else if (_split->isLabelSplit())
78 labelSplit(std::move(slice));
79 else {
80 ASSERT(_split->isPivotSplit());
81 pivotSplit(std::move(slice));
82 }
83
84 return false;
85}
86
87unique_ptr<MsmSlice> MsmStrategy::newMsmSlice() {
88 unique_ptr<Slice> slice(newSlice());
89 ASSERT(dynamic_cast<MsmSlice*>(slice.get()) != 0);
90 return unique_ptr<MsmSlice>(static_cast<MsmSlice*>(slice.release()));
91}
92
93unique_ptr<Slice> MsmStrategy::allocateSlice() {
94 return unique_ptr<Slice>(new MsmSlice(*this));
95}
96
98 ASSERT(slice != 0);
99 ASSERT(dynamic_cast<MsmSlice*>(slice) != 0);
100 return true;
101}
102
103void MsmStrategy::labelSplit(unique_ptr<Slice> sliceParam) {
104 ASSERT(sliceParam.get() != 0);
105 ASSERT(debugIsValidSlice(sliceParam.get()));
106 unique_ptr<MsmSlice> slice
107 (static_cast<MsmSlice*>(sliceParam.release()));
108
109 ASSERT(!slice->adjustMultiply());
110 ASSERT(!slice->normalize());
111 ASSERT(_split != 0);
112 size_t var = _split->getLabelSplitVariable(*slice);
113
114 Term term(slice->getVarCount());
115
116 const Term& lcm = slice->getLcm();
117
118 Ideal::const_iterator stop = slice->getIdeal().end();
119 Ideal::const_iterator label = stop;
120 bool hasTwoLabels = false;
121 for (Ideal::const_iterator it = slice->getIdeal().begin();
122 it != stop; ++it) {
123 if ((*it)[var] == 1) {
124 term = *it;
125 term[var] -= 1;
126
127 bool couldBeLabel = !slice->getSubtract().contains(term);
128 if (couldBeLabel) {
129 for (size_t v = 0; v < slice->getVarCount(); ++v) {
130 if (term[v] == lcm[v]) {
131 couldBeLabel = false;
132 break;
133 }
134 }
135 }
136
137 if (couldBeLabel) {
138 if (label == stop)
139 label = it;
140 else {
141 hasTwoLabels = true;
142 break;
143 }
144 }
145 }
146 }
147
148 unique_ptr<Slice> hasLabelSlice;
149
150 if (label != stop) {
151 term = *label;
152 term[var] -= 1;
153
154 hasLabelSlice = newSlice();
155 *hasLabelSlice = *slice;
156 hasLabelSlice->innerSlice(term);
157
158 if (hasTwoLabels)
159 slice->outerSlice(term);
160 }
161
162 if (!hasTwoLabels) {
163 term.setToIdentity();
164 term[var] = 1;
165 slice->innerSlice(term);
166 }
167
168 if (hasLabelSlice.get() != 0) {
169 simplify(*hasLabelSlice);
170 _tasks.addTask(hasLabelSlice.release());
171 }
172
173 simplify(*slice);
174 _tasks.addTask(slice.release());
175}
176
177class MsmIndependenceSplit : public TermConsumer, public Task {
178public:
180 return this;
181 }
182
184 return this;
185 }
186
190
192 return _leftProjection;
193 }
194
196 return _rightProjection;
197 }
198
199 void reset(TermConsumer* consumer,
200 IndependenceSplitter& splitter) {
201 _consumer = consumer;
202 _tmpTerm.reset(splitter.getVarCount());
203
206
207 _rightConsumer._decom.clearAndSetVarCount
208 (_rightProjection.getRangeVarCount());
209 }
210
211private:
212 virtual void run(TaskEngine& engine) {
213 dispose();
214 }
215
216 virtual void dispose() {
217 delete this;
218 }
219
220 virtual void beginConsuming() {
221 }
222
223 virtual void doneConsuming() {
224 }
225
226 virtual void consume(const Term& term) {
227 _leftProjection.inverseProject(_tmpTerm, term);
228 Ideal::const_iterator stop = _rightConsumer._decom.end();
229 for (Ideal::const_iterator it = _rightConsumer._decom.begin();
230 it != stop; ++it) {
231 _rightProjection.inverseProject(_tmpTerm, *it);
232 _consumer->consume(_tmpTerm);
233 }
234 }
235
236 struct RightConsumer : public TermConsumer {
237 virtual void beginConsuming() {
238 }
239
240 virtual void doneConsuming() {
241 }
242
243 virtual void consume(const Term& term) {
244 _decom.insert(term);
245 }
246
249
251
254
256};
257
258void MsmStrategy::independenceSplit(unique_ptr<Slice> sliceParam) {
259 ASSERT(sliceParam.get() != 0);
260 ASSERT(debugIsValidSlice(sliceParam.get()));
261 unique_ptr<MsmSlice> slice
262 (static_cast<MsmSlice*>(sliceParam.release()));
263
264 // Construct split object
265 unique_ptr<MsmIndependenceSplit> autoSplit(new MsmIndependenceSplit());
266 autoSplit->reset(slice->getConsumer(), _indep);
267 MsmIndependenceSplit* split = autoSplit.release();
268 _tasks.addTask(split); // Runs when we are done with all of this split.
269
270 // Construct left slice.
271 unique_ptr<MsmSlice> leftSlice(new MsmSlice(*this));
272 leftSlice->setToProjOf(*slice, split->getLeftProjection(), split);
273 _tasks.addTask(leftSlice.release());
274
275 // Construct right slice.
276 unique_ptr<MsmSlice> rightSlice(new MsmSlice(*this));
277 rightSlice->setToProjOf(*slice, split->getRightProjection(),
278 split->getRightConsumer());
279 _tasks.addTask(rightSlice.release());
280
281 // Deal with slice.
282 freeSlice(std::move(slice));
283}
284
285void MsmStrategy::getPivot(Term& pivot, Slice& slice) {
286 ASSERT(_split != 0);
287 ASSERT(_split->isPivotSplit());
288
289 _split->getPivot(pivot, slice);
290}
291
292void MsmStrategy::getPivot(Term& pivot, Slice& slice, const TermGrader& grader) {
293 ASSERT(_split != 0);
294 ASSERT(_split->isPivotSplit());
295
296 _split->getPivot(pivot, slice, grader);
297}
Represents a monomial ideal with int exponents.
Definition Ideal.h:27
Cont::const_iterator const_iterator
Definition Ideal.h:43
size_t getVarCount() const
Definition Ideal.h:56
void getRestProjection(Projection &projection) const
void getBigProjection(Projection &projection) const
MsmIndependenceSplit::RightConsumer _rightConsumer
virtual void dispose()
Called when the task is no longer used but run has not and will not be called.
virtual void beginConsuming()
Tell the consumer to begin consuming an ideal.
Projection _rightProjection
TermConsumer * _consumer
virtual void doneConsuming()
Must be called once after each time beginConsuming has been called.
virtual void run(TaskEngine &engine)
Does whatever work this task represents.
const Projection & getRightProjection()
TermConsumer * getLeftConsumer()
void reset(TermConsumer *consumer, IndependenceSplitter &splitter)
const Projection & getLeftProjection()
TermConsumer * getRightConsumer()
virtual void consume(const Term &term)
Consume a term.
Invariant: either the slice is a trivial base case, or removeDoubleLcm returns false.
Definition MsmSlice.h:33
virtual unique_ptr< Slice > allocateSlice()
Directly allocate a slice of the correct type using new.
virtual bool debugIsValidSlice(Slice *slice)
Check that this slice is valid for use with this strategy.
virtual bool processSlice(TaskEngine &tasks, unique_ptr< Slice > slice)
Process the parameter slice.
IndependenceSplitter _indep
Definition MsmStrategy.h:62
void independenceSplit(unique_ptr< Slice > slice)
unique_ptr< MsmSlice > newMsmSlice()
TermConsumer * _consumer
Definition MsmStrategy.h:63
unique_ptr< Ideal > _initialSubtract
Definition MsmStrategy.h:65
virtual void getPivot(Term &pivot, Slice &slice)
Used by pivotSplit to obtain a pivot.
void labelSplit(unique_ptr< Slice > slice)
virtual void run(const Ideal &ideal)
Run the Slice algorithm.
MsmStrategy(TermConsumer *consumer, const SplitStrategy *splitStrategy)
bool getUseIndependence() const
Returns true if independence splits should be performed when possible.
bool getUseSimplification() const
Returns true if slices should be simplified.
const SplitStrategy * _split
virtual void freeSlice(unique_ptr< Slice > slice)
It is allowed to delete returned slices directly, but it is better to use freeSlice.
virtual bool simplify(Slice &slice)
Simplifies slice and returns true if it changed.
virtual void pivotSplit(unique_ptr< Slice > slice)
Takes over ownership of slice.
SliceStrategyCommon(const SplitStrategy *splitStrategy)
unique_ptr< Slice > newSlice()
Returns a slice from the cache that freeSlice adds to, or allocate a new one using allocateSlice.
TaskEngine _tasks
This keeps track of pending tasks to process.
This class represents a slice, which is the central data structure of the Slice Algorithm.
Definition Slice.h:77
A SplitStrategy is an implementation of a split selection strategy for the Slice Algorithm.
TaskEngine handles a list of tasks that are to be carried out.
Definition TaskEngine.h:40
A Task object represents a unit of work that is performed when the method run() is called.
Definition Task.h:27
This class is used to transfer terms one at a time from one part of the program to another,...
A TermGrader assigns a value, the degree, to each monomial.
Definition TermGrader.h:27
Term represents a product of variables which does not include a coefficient.
Definition Term.h:49
static void setToIdentity(Exponent *res, size_t varCount)
Set res equal to , i.e. set each entry of res equal to 0.
Definition Term.h:304
This header file includes common definitions and is included as the first line of code in every imple...
#define ASSERT(X)
Definition stdinc.h:86
virtual void doneConsuming()
Must be called once after each time beginConsuming has been called.
virtual void consume(const Term &term)
Consume a term.
virtual void beginConsuming()
Tell the consumer to begin consuming an ideal.