Frobby 0.9.6
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
34
43
44void MsmStrategy::run(const Ideal& ideal) {
45 ASSERT(_initialSubtract.get() == 0 ||
46 _initialSubtract->getVarCount() == ideal.getVarCount());
47
49 size_t varCount = ideal.getVarCount();
50 if (_initialSubtract.get() == 0)
52
54 for (size_t var = 0; var < varCount; ++var)
55 sliceMultiply[var] = 1;
56
58 (new MsmSlice(*this, ideal, *_initialSubtract, sliceMultiply, _consumer));
60
61 _initialSubtract.reset();
62 _tasks.addTask(slice.release());
65}
66
68 ASSERT(slice.get() != 0);
69
70 if (slice->baseCase(getUseSimplification())) {
71 freeSlice(std::move(slice));
72 return true;
73 }
74
76 independenceSplit(std::move(slice));
77 else if (_split->isLabelSplit())
78 labelSplit(std::move(slice));
79 else {
81 pivotSplit(std::move(slice));
82 }
83
84 return false;
85}
86
89 ASSERT(dynamic_cast<MsmSlice*>(slice.get()) != 0);
90 return unique_ptr<MsmSlice>(static_cast<MsmSlice*>(slice.release()));
91}
92
96
98 ASSERT(slice != 0);
99 ASSERT(dynamic_cast<MsmSlice*>(slice) != 0);
100 return true;
101}
102
104 ASSERT(sliceParam.get() != 0);
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();
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
149
150 if (label != stop) {
151 term = *label;
152 term[var] -= 1;
153
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) {
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
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
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
259 ASSERT(sliceParam.get() != 0);
262 (static_cast<MsmSlice*>(sliceParam.release()));
263
264 // Construct split object
266 autoSplit->reset(slice->getConsumer(), _indep);
268 _tasks.addTask(split); // Runs when we are done with all of this split.
269
270 // Construct left slice.
272 leftSlice->setToProjOf(*slice, split->getLeftProjection(), split);
273 _tasks.addTask(leftSlice.release());
274
275 // Construct right slice.
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
291
void nameFactoryRegister(NameFactory< AbstractProduct > &factory)
Registers the string returned by ConcreteProduct::getStaticName() to a function that default-construc...
Represents a monomial ideal with int exponents.
Definition Ideal.h:27
void clearAndSetVarCount(size_t varCount)
Definition Ideal.cpp:646
Cont::const_iterator const_iterator
Definition Ideal.h:43
void insert(const Exponent *term)
Definition Ideal.cpp:455
const_iterator end() const
Definition Ideal.h:49
const_iterator begin() const
Definition Ideal.h:48
size_t getVarCount() const
Definition Ideal.h:56
bool analyze(const Slice &slice)
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)
void inverseProject(Term &to, const Exponent *from) const
size_t getRangeVarCount() const
This class adds code to the SliceStrategy base class that is useful for derived classes.
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.
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.
virtual size_t getLabelSplitVariable(const Slice &slice) const =0
Returns the variable to perform a label split on.
virtual bool isPivotSplit() const =0
If returns true, only call getPivot.
virtual bool isLabelSplit() const =0
If returns true, only call getLabelSplitVariable.
virtual void getPivot(Term &pivot, Slice &slice) const =0
Sets pivot to the pivot of a pivot split on slice.
TaskEngine handles a list of tasks that are to be carried out.
Definition TaskEngine.h:40
void addTask(Task *task)
Add a task at the head of the list of pending tasks.
void runTasks()
Runs all pending tasks.
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,...
virtual void beginConsuming()=0
Tell the consumer to begin consuming an ideal.
virtual void doneConsuming()=0
Must be called once after each time beginConsuming has been called.
virtual void consume(const Term &term)=0
Consume a term.
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
void reset(size_t newVarCount)
Definition Term.h:551
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
#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.