Frobby 0.9.7
HilbertStrategy.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 "HilbertStrategy.h"
19
20#include "Term.h"
21#include "HilbertSlice.h"
22#include "Ideal.h"
23#include "CoefTermConsumer.h"
24#include "Projection.h"
27#include "ElementDeleter.h"
28
30 const SplitStrategy* splitStrategy):
31 SliceStrategyCommon(splitStrategy),
34 _consumer(consumer) {
35}
36
37void HilbertStrategy::run(const Ideal& ideal) {
38 ASSERT(_consumer != 0);
39
40 size_t varCount = ideal.getVarCount();
41 Ideal sliceIdeal(varCount);
42
43 if (!ideal.contains(Term(varCount))) {
44 _consumer->consume(1, Term(varCount));
45
46 if (ideal.getGeneratorCount() > 0) {
47 Term allOnes(varCount);
48 for (size_t var = 0; var < varCount; ++var)
49 allOnes[var] = 1;
50
51 sliceIdeal = ideal;
52 sliceIdeal.product(allOnes);
53 }
54 }
55
56 unique_ptr<Slice> slice
57 (new HilbertSlice(*this, sliceIdeal, Ideal(varCount),
58 Term(varCount), _consumer));
59
60 simplify(*slice);
61 _tasks.addTask(slice.release());
62 _tasks.runTasks();
63 _consumerCacheDeleter.deleteElements();
64}
65
67(TaskEngine& tasks, unique_ptr<Slice> slice) {
68 ASSERT(slice.get() != 0);
69 ASSERT(debugIsValidSlice(slice.get()));
70
71 if (slice->baseCase(getUseSimplification())) {
72 freeSlice(std::move(slice));
73 return true;
74 }
75
76 if (getUseIndependence() && _indepSplitter.analyze(*slice)) {
77 independenceSplit(std::move(slice));
78 } else {
79 ASSERT(_split->isPivotSplit());
80 pivotSplit(std::move(slice));
81 }
82
83 return false;
84}
85
86unique_ptr<HilbertSlice> HilbertStrategy::newHilbertSlice() {
87 unique_ptr<Slice> slice(newSlice());
88 ASSERT(debugIsValidSlice(slice.get()));
89 return unique_ptr<HilbertSlice>(static_cast<HilbertSlice*>(slice.release()));
90}
91
92unique_ptr<Slice> HilbertStrategy::allocateSlice() {
93 return unique_ptr<Slice>(new HilbertSlice(*this));
94}
95
97 ASSERT(slice != 0);
98 ASSERT(dynamic_cast<HilbertSlice*>(slice) != 0);
99 return true;
100}
101
103 ASSERT(term.getVarCount() == slice.getVarCount());
104
105 _split->getPivot(term, slice);
106}
107
108void HilbertStrategy::freeConsumer(unique_ptr<HilbertIndependenceConsumer>
109 consumer) {
110 ASSERT(consumer.get() != 0);
111 ASSERT(std::find(_consumerCache.begin(),
112 _consumerCache.end(), consumer.get()) ==
113 _consumerCache.end());
114
115 consumer->clear();
116 noThrowPushBack(_consumerCache, std::move(consumer));
117}
118
119void HilbertStrategy::independenceSplit(unique_ptr<Slice> sliceParam) {
120 ASSERT(sliceParam.get() != 0);
121 ASSERT(debugIsValidSlice(sliceParam.get()));
122 unique_ptr<HilbertSlice> slice
123 (static_cast<HilbertSlice*>(sliceParam.release()));
124
125 // Construct split object.
126 unique_ptr<HilbertIndependenceConsumer> autoSplit = newConsumer();
127 autoSplit->reset(slice->getConsumer(), _indepSplitter, slice->getVarCount());
128 HilbertIndependenceConsumer* split = autoSplit.release();
129 _tasks.addTask(split); // Runs when we are done with all of this split.
130
131 // Construct left slice.
132 unique_ptr<HilbertSlice> leftSlice(newHilbertSlice());
133 leftSlice->setToProjOf(*slice, split->getLeftProjection(),
134 split->getLeftConsumer());
135 _tasks.addTask(leftSlice.release());
136
137 // Construct right slice.
138 unique_ptr<HilbertSlice> rightSlice(newHilbertSlice());
139 rightSlice->setToProjOf(*slice, split->getRightProjection(),
140 split->getRightConsumer());
141 _tasks.addTask(rightSlice.release());
142
143 // Deal with slice.
144 freeSlice(std::move(slice));
145}
146
147unique_ptr<HilbertIndependenceConsumer> HilbertStrategy::newConsumer() {
148 if (_consumerCache.empty())
149 return unique_ptr<HilbertIndependenceConsumer>
150 (new HilbertIndependenceConsumer(this));
151
152 unique_ptr<HilbertIndependenceConsumer> consumer(_consumerCache.back());
153 _consumerCache.pop_back();
154 return consumer;
155}
void noThrowPushBack(Container &container, unique_ptr< Element > pointer)
const Projection & getRightProjection() const
const Projection & getLeftProjection() const
virtual bool processSlice(TaskEngine &tasks, unique_ptr< Slice > slice)
Process the parameter slice.
unique_ptr< HilbertIndependenceConsumer > newConsumer()
virtual void getPivot(Term &term, Slice &slice)
Used by pivotSplit to obtain a pivot.
ElementDeleter< vector< HilbertIndependenceConsumer * > > _consumerCacheDeleter
HilbertStrategy(CoefTermConsumer *consumer, const SplitStrategy *splitStrategy)
virtual bool debugIsValidSlice(Slice *slice)
Check that this slice is valid for use with this strategy.
IndependenceSplitter _indepSplitter
vector< HilbertIndependenceConsumer * > _consumerCache
CoefTermConsumer * _consumer
virtual void run(const Ideal &ideal)
Run the Slice algorithm.
void freeConsumer(unique_ptr< HilbertIndependenceConsumer > consumer)
virtual unique_ptr< Slice > allocateSlice()
Directly allocate a slice of the correct type using new.
unique_ptr< HilbertSlice > newHilbertSlice()
void independenceSplit(unique_ptr< Slice > slice)
Represents a monomial ideal with int exponents.
Definition Ideal.h:27
void product(const Exponent *term)
Definition Ideal.cpp:525
size_t getGeneratorCount() const
Definition Ideal.h:57
bool contains(const Exponent *term) const
Definition Ideal.cpp:57
size_t getVarCount() const
Definition Ideal.h:56
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
size_t getVarCount() const
Returns the number of variables in the ambient ring.
Definition Slice.h:96
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
Term represents a product of variables which does not include a coefficient.
Definition Term.h:49
size_t getVarCount() const
Definition Term.h:85
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