Frobby  0.9.5
Public Types | Public Member Functions | Private Member Functions | Private Attributes | List of all members
OptimizeStrategy Class Reference

OptimizeStrategy optimizes a function on the maximal standard monomials of a monomial ideal using branch-and-bound. More...

#include <OptimizeStrategy.h>

Inheritance diagram for OptimizeStrategy:
MsmStrategy TermConsumer SliceStrategyCommon SliceStrategy

Public Types

enum  BoundSetting { DoNotUseBound , UseBoundToEliminate , UseBoundToEliminateAndSimplify }
 The values of BoundSetting indicate how to use the bound. More...
 

Public Member Functions

 OptimizeStrategy (TermGrader &grader, const SplitStrategy *splitStrategy, bool reportAllSolutions, BoundSetting boundSetting)
 Construct an OptimizeStrategy. More...
 
const IdealgetMaximalSolutions ()
 Returns one of or all of the msm's with optimal value found so far, depending on the value of reportAllSolutions passed to the constructor. More...
 
const mpz_class & getMaximalValue ()
 The optimal value associated to all entries from getMaximalSolutions(). More...
 
virtual void setUseIndependence (bool use)
 Independence splits are not supported, so calling this method does nothing. More...
 
virtual void getPivot (Term &pivot, Slice &slice)
 Used by pivotSplit to obtain a pivot. More...
 
virtual bool simplify (Slice &slice)
 This method calls MsmStrategy::simplify to perform the usual simplification of slice, which then occurs if and only if the usual simplification has been turned on. More...
 
virtual void beginConsuming ()
 Tell the consumer to begin consuming an ideal. More...
 
virtual void consume (const Term &term)
 Consume a term. More...
 
virtual void doneConsuming ()
 Must be called once after each time beginConsuming has been called. More...
 
- Public Member Functions inherited from MsmStrategy
 MsmStrategy (TermConsumer *consumer, const SplitStrategy *splitStrategy)
 
 MsmStrategy (TermConsumer *consumer, const SplitStrategy *splitStrategy, const Ideal &initialSubtract)
 
virtual void run (const Ideal &ideal)
 Run the Slice algorithm. More...
 
virtual bool processSlice (TaskEngine &tasks, auto_ptr< Slice > slice)
 Process the parameter slice. More...
 
- Public Member Functions inherited from SliceStrategyCommon
 SliceStrategyCommon (const SplitStrategy *splitStrategy)
 
virtual ~SliceStrategyCommon ()
 
virtual void freeSlice (auto_ptr< Slice > slice)
 It is allowed to delete returned slices directly, but it is better to use freeSlice. More...
 
virtual void setUseSimplification (bool use)
 This method should only be called before calling run(). More...
 
- Public Member Functions inherited from SliceStrategy
virtual ~SliceStrategy ()
 
- Public Member Functions inherited from TermConsumer
virtual ~TermConsumer ()
 
virtual void consumeRing (const VarNames &names)
 Tell the consumer which ring is being used. More...
 
virtual void beginConsumingList ()
 Tell the consumer that the ideals that are consumed until the next call to doneConsumingList are to be considered as one list of ideals, rather than as a number of separate ideals. More...
 
virtual void doneConsumingList ()
 Must be called once after each time beginConsumingList has been called. More...
 
void consume (const Ideal &ideal)
 This is a non-virtual utility method that calls the other methods to achieve its effect of calling beginConsuming, then consuming all generators, and then calling doneConsuming. More...
 

Private Member Functions

bool changedInWayRelevantToBound (const Term &oldDivisor, const Term &oldDominator, const Term &newDivisor, const Term &newDominator) const
 Returns true if iterating bound-based simplification might do something. More...
 
bool boundSimplify (Slice &slice, const Term &dominator, const mpz_class &upperBound)
 This method simplifies a slice based on generating non-improving outer and inner slices. More...
 
bool getInnerSimplify (const Term &divisor, const Term &dominator, const mpz_class &upperBound, Term &pivot)
 Find an outer slice that is non-improving, allowing us to replace the current slice with the inner slice. More...
 
bool getOuterSimplify (const Term &divisor, const Term &dominator, const mpz_class &upperBound, Term &pivot)
 Find an inner slice that is non-improving, allowing us to replace the current slice with the outer slice. More...
 
bool getDominator (Slice &slice, Term &dominator)
 Sets dominator to be a term dominating every element of the content of slice. More...
 
size_t getVarCount () const
 The number of varibles this object was initialized with. More...
 
 FRIEND_TEST (OptimizeStrategy, ChangedInWayRelevantToBound)
 
 FRIEND_TEST (OptimizeStrategy, SimplifyPositiveGrading)
 
 FRIEND_TEST (OptimizeStrategy, SimplifyNegativeGrading)
 

Private Attributes

const TermGrader_grader
 We use _grader to assign values to solutions. More...
 
mpz_class _maxValue
 The best value of any solution found so far. More...
 
mpz_class _maxValueToBeat
 Is equal to _maxValue minus _reportAllSolutions, except when no solution has been found so far, in which case the value is undefined. More...
 
Ideal _maxSolutions
 Stores the optimal solutions found so far, according to the best value found so far. More...
 
bool _reportAllSolutions
 Indicates whether to compute all optimal solutions, as opposed to computing just one (when there are any). More...
 
BoundSetting _boundSetting
 Indicates how to use the bound. More...
 
mpz_class _consume_tmpDegree
 Temporary variable used in consume. More...
 
mpz_class _simplify_tmpUpperBound
 Temporary variable used in simplify. More...
 
Term _simplify_tmpDominator
 Temporary variable used in simplify. More...
 
Term _simplify_tmpOldDominator
 Temporary variable used in simplify. More...
 
Term _simplify_tmpOldDivisor
 Temporary variable used in simplify. More...
 
mpz_class _tmpC
 Temporary variable used in getInnerSimplify and getOuterSimplify. More...
 
Term _boundSimplify_tmpPivot
 Temporary variable used in simplify. More...
 

Additional Inherited Members

- Protected Member Functions inherited from MsmStrategy
virtual void getPivot (Term &pivot, Slice &slice, const TermGrader &grader)
 
- Protected Member Functions inherited from SliceStrategyCommon
auto_ptr< SlicenewSlice ()
 Returns a slice from the cache that freeSlice adds to, or allocate a new one using allocateSlice. More...
 
virtual void pivotSplit (auto_ptr< Slice > slice)
 Takes over ownership of slice. More...
 
bool getUseIndependence () const
 Returns true if independence splits should be performed when possible. More...
 
bool getUseSimplification () const
 Returns true if slices should be simplified. More...
 
- Protected Attributes inherited from SliceStrategyCommon
const SplitStrategy_split
 
TaskEngine _tasks
 This keeps track of pending tasks to process. More...
 

Detailed Description

OptimizeStrategy optimizes a function on the maximal standard monomials of a monomial ideal using branch-and-bound.

Branch-and-bound is an algorithmic technique. In this case, it amounts to having a bound, which is a function that assigns a value to each slice. This value is an non-strict upper bound on the value of each maximal standard monomial in the content of that slice. If the value of the bound is worse than the best value of an msm found so far, then we do not have to consider that slice further. Such a slice is called non-improving.

Whenever a slice is non-improving, we avoid some computation by ignoring it. We exploit this further, by purposefully seeking to generate slices that are non-improving.

Definition at line 43 of file OptimizeStrategy.h.

Member Enumeration Documentation

◆ BoundSetting

The values of BoundSetting indicate how to use the bound.

Enumerator
DoNotUseBound 

Make no use of the bound.

UseBoundToEliminate 

Eliminate non-improving slices, achieving a branch-and-bound algorithm in place of the usual backtracking.

UseBoundToEliminateAndSimplify 

Eliminate non-improving slices and simplify slices by trying to generate non-improving slices that are then eliminated, allowing to move to the other slice.

Definition at line 46 of file OptimizeStrategy.h.

Constructor & Destructor Documentation

◆ OptimizeStrategy()

OptimizeStrategy::OptimizeStrategy ( TermGrader grader,
const SplitStrategy splitStrategy,
bool  reportAllSolutions,
BoundSetting  boundSetting 
)

Construct an OptimizeStrategy.

Parameters
graderThis object assigns values to monomials.
splitStrategyThe split selection strategy to use.
reportAllSolutionsCompute all msm's of optimal value if true. Otherwise compute a single msm of optimal value.
boundSettingIndicates how much to use the bound.

Definition at line 23 of file OptimizeStrategy.cpp.

Member Function Documentation

◆ beginConsuming()

void OptimizeStrategy::beginConsuming ( )
virtual

Tell the consumer to begin consuming an ideal.

It is required to call this method before calling consume().

Implements TermConsumer.

Definition at line 54 of file OptimizeStrategy.cpp.

◆ boundSimplify()

bool OptimizeStrategy::boundSimplify ( Slice slice,
const Term dominator,
const mpz_class &  upperBound 
)
private

This method simplifies a slice based on generating non-improving outer and inner slices.

The idea is conceptually simple, but it has been quite a challenge to get the code to be correct, efficient and as good as possible in terms of simplifying as much as possible. This is why there are so many tests related to this, and why the comments for this and related methods are so detailed.

To each slice we associate a divisor $x^a$ and a dominator $x^b$, which respectively divide and dominate each msm $m$ in the content of the slice. I.e. $x^a|m|x^b$. We summarize this as a pair $(a,b)$. Let $d(a,b)$ be the associated upper bound, i.e. the largest possible value that the grader associates to a monomial $x^v$ such that $a\leq v\leq b$. Thus $d(a,b)$ is an uppper bound on the value of any msm in the content of the slice to which $(a,b)$ is associated.

To be more exact, for a slice $(I,S,q)$, $q$ is the divisor, while $q\textrm{lcm}(\min(I)):x_1\cdots x_n$ is the dominator. Also, let $d_i(t)$ be the value of $x_i^t$ and let $\max$ be the highest value according to the grader of an msm found so far.

This allows us to discard slices that are non-improving, in that they do not improve on the best value found so far. Note that whether "improve" means "strictly improve" or "weakly improve" depends on whether we are reporting all optimal msm's or just one. In the following discussion we will assume that we are looking for just one msm, so that a slice is non-improving if it does not strictly improve.

This method is called when the slice itself cannot be seen to be non-improving from the divisor and dominator. However, if we consider pivot splits on pivots that are pure powers, i.e. of the form $x_i^t$, then we can compute a divisor and dominator for both the inner and outer slice just from the divisor and dominator of the current slice. Note that the divisor and dominator assigned in this way are not necessarily as tight as the ones we would get if we actually computed the inner and outer slice.

It may be that we can see that the inner or outer slice from above is non-improving. If the inner slice is non-improving, then we can discard it and replace the current slice with the outer slice, and vice versa if the outer slice is non-improving. This is bound-driven simplification of a slice, and it is efficient since we can perform these calculations looking only at the two monomials divisor and dominator.

Consider a pivot split on $x_i^t$. Then the outer slice has $(a, b^\prime)$, where $b^\prime$ is equal to $b$ except that $b_i^\prime:= a_i+t-1$. The inner slice will have $(a^\prime,b)$, where $a^\prime$ is equal to $a$ except that $a^\prime_i := a_i + t$. Note that the sensible $t$'s to consider are those for which $a_i<a_i+t\leq b_i$. We need to work in terms of $a_i+t$ rather than just $t$ since we work with a TermGrader that has no reasonable way of making sense of just t.

If possible, this method moves to an inner or outer slice of the parameter slice based on this reasoning.

See getInnerSimplify and getOuterSimplify for more details. Which one of those two is relevant for a given slice and variable depends on the sign of that variable in the grading, and on whether the ideal contains a pure power that maps to the same value as zero does. We call the latter phenomenon a "fake power".

Parameters
sliceThe slice to work on.
dominatorThe dominator of slice (passed as a parameter to avoid recomputation).
upperBoundThe upper bound $d(a,b)$ associated to slice (to avoid recomputation).
Returns
Returns true if and only if slice changed.

Definition at line 203 of file OptimizeStrategy.cpp.

◆ changedInWayRelevantToBound()

bool OptimizeStrategy::changedInWayRelevantToBound ( const Term oldDivisor,
const Term oldDominator,
const Term newDivisor,
const Term newDominator 
) const
private

Returns true if iterating bound-based simplification might do something.

There are four cases where it makes sense to iterate the bound-based simplification after the slice has changed.

  • Case 1: The sign is negative, and the divisor has increased. This is relevant whether or not we are using a fake power, since if so there still is an effect on the bound for a split that gets rid of the pure power.
  • Case 2: The sign is negative, and we were using a fake power to get the value of zero, but now it is gone.
  • Case 3: The sign is positive, and the dominator has decreased, and it did not just remove a fake power exponent.
  • Case 4: The sign is positive, and the dominator has a fake power exponent, and the divisor has increased so that we are forced to use it.

Definition at line 159 of file OptimizeStrategy.cpp.

◆ consume()

void OptimizeStrategy::consume ( const Term term)
virtual

Consume a term.

Implements TermConsumer.

Definition at line 58 of file OptimizeStrategy.cpp.

◆ doneConsuming()

void OptimizeStrategy::doneConsuming ( )
virtual

Must be called once after each time beginConsuming has been called.

Implements TermConsumer.

Definition at line 74 of file OptimizeStrategy.cpp.

◆ FRIEND_TEST() [1/3]

OptimizeStrategy::FRIEND_TEST ( OptimizeStrategy  ,
ChangedInWayRelevantToBound   
)
private

◆ FRIEND_TEST() [2/3]

OptimizeStrategy::FRIEND_TEST ( OptimizeStrategy  ,
SimplifyNegativeGrading   
)
private

◆ FRIEND_TEST() [3/3]

OptimizeStrategy::FRIEND_TEST ( OptimizeStrategy  ,
SimplifyPositiveGrading   
)
private

◆ getDominator()

bool OptimizeStrategy::getDominator ( Slice slice,
Term dominator 
)
private

Sets dominator to be a term dominating every element of the content of slice.

Returns false (and clears slice) only if slice is a trivial base case slice, but may return true even if it is a base case slice.

Definition at line 329 of file OptimizeStrategy.cpp.

◆ getInnerSimplify()

bool OptimizeStrategy::getInnerSimplify ( const Term divisor,
const Term dominator,
const mpz_class &  upperBound,
Term pivot 
)
private

Find an outer slice that is non-improving, allowing us to replace the current slice with the inner slice.

We only need to know a divisor $a$ and dominator $b$ of the current slice to perform this analysis. If $a_i=b_i$ then there is nothing to be done for the $i$'th entry, so assume that $a_i<b_i$.

There are two ways to obtain a non-improving outer slice. The first is if the grading sign is positive, and $d(a,b^\prime)\leq \max$. Let $B:=b_i$ if $b_i$ is not a fake exponent, and let $B := b_i-1$ if $b_i$ is a fake exponent. Then we have that

\[ d(a,b^\prime) = d(a,b) - d_i(B) + d_i(a_i+t-1), \]

whereby $d(a,b^\prime)\leq \max$ is equivalent to

\[ d_i(a_i+t-1) \leq \max - d(a,b) + d_i(B) =: C. \]

Letting $t^\prime:=a_i+t-1$, we are thus looking for a $t^\prime$ with $a_i\leq t^\prime<B$ such that $d_i(t^\prime)\leq C$. To make the inner slice as much simpler as possible, we would like to find the largest such t, if any. TermGrader has a method that does this.

The other way of getting a non-improving outer slice is with a negative grading sign and a fake power. The fake power allows to set the value at the i'th entry down to the value of zero, which is better than any other exponent when the sign is negative.

A non-trivial outer slice will not have the fake power, and thus possibly decrease the upper bound of the outer slice relative to the current slice, which may make it non-improving. This is most likely to happen for the largest possible $t=b_i$, and we want $t$ to be large anyway in order to make the inner slice as simple as possible, so it only makes sense to check this for $t=b_i-a_i$. As the sign is negative, we get that

\[ d(a,b^\prime)=d(a,b)-d_i(b_i)+d_i(a_i)=:C, \]

where we are noting that $d_i(b_i)=d_i(0)$. The question is then whether $C\leq\max$.

Parameters
divisorThe divisor $a$ associated to the slice.
dominatorThe dominator $b$ associated to the slice.
upperBoundThe upper bound $d(a,b)$ associated to the slice (passed as a parameter to avoid recomputation).
pivotIs set to a pivot that generates a non-improving outer slice if one is found.
Returns
Returns true if and only if a non-improving outer slice was found.

Definition at line 220 of file OptimizeStrategy.cpp.

◆ getMaximalSolutions()

const Ideal & OptimizeStrategy::getMaximalSolutions ( )

Returns one of or all of the msm's with optimal value found so far, depending on the value of reportAllSolutions passed to the constructor.

Definition at line 41 of file OptimizeStrategy.cpp.

◆ getMaximalValue()

const mpz_class & OptimizeStrategy::getMaximalValue ( )

The optimal value associated to all entries from getMaximalSolutions().

This method can only be called if getMaximalSolutions() is not the zero ideal.

Definition at line 45 of file OptimizeStrategy.cpp.

◆ getOuterSimplify()

bool OptimizeStrategy::getOuterSimplify ( const Term divisor,
const Term dominator,
const mpz_class &  upperBound,
Term pivot 
)
private

Find an inner slice that is non-improving, allowing us to replace the current slice with the outer slice.

We only need to know a divisor $a$ and dominator $b$ of the current slice to perform this analysis. If $a_i=b_i$ then there is nothing to be done for the $i$'th entry, so assume that $a_i<b_i$.

There are two ways to obtain a non-improving inner slice. The first is if the grading sign is negative, there is no fake power of $x_i$, and $d(a^\prime,b)\leq \max$. Since the sign is negative and there is no fake power, we have that

\[ d(a^\prime,b) = d(a,b) - d_i(a_i) + d_i(a_i+t), \]

, whereby $d(a^\prime,b)\leq \max$ is equivalent to

\[ d_i(a_i+t) \leq \max - d(a,b) + d_i(a_i) =: C. \]

Letting $t^\prime:=a_i+t$, we are thus looking for a $t^\prime$ with $a_i< t^\prime\leq b_i^\prime$ such that $d_i(t^\prime)\leq C$. To make the outer slice as much simpler as possible, we would like to find the smallest such t, if any. TermGrader has a method that does this.

Note that the assumption above that there is no fake power of $x_i$ does not rule out any useful simplification, as in that case the inner slice will never be non-improving, since it would also have the fake power (in our analysis of just looking at $a$ and $b$), so that the upper bound of the inner slice would be equal to the upper bound of the current slice.

The other way of getting a non-improving inner slice is with a positive grading sign and a fake power. If $t$ is as large as possible, i.e. $t=b_i-a_i$, then the outer slice is forced to use the fake power, which decreases the $i$'th entry down to the value for zero, which is the worst possible when the sign is positive, and this might make the inner slice non-improving.

As the sign is positive, and $b_i$ is a fake exponent, we get that

\[ d(a^\prime,b)=d(a,b)-d_i(b_i-1)+d_i(b_i):=C, \]

and it is then a question of whether $C\leq\max$.

Parameters
divisorThe divisor $a$ associated to the slice.
dominatorThe dominator $b$ associated to the slice.
upperBoundThe upper bound $d(a,b)$ associated to the slice (passed as a parameter to avoid recomputation).
pivotIs set to a pivot that generates a non-improving inner slice if one is found.
Returns
Returns true if and only if a non-improving inner slice was found.

Definition at line 277 of file OptimizeStrategy.cpp.

◆ getPivot()

void OptimizeStrategy::getPivot ( Term pivot,
Slice slice 
)
virtual

Used by pivotSplit to obtain a pivot.

Reimplemented from MsmStrategy.

Definition at line 77 of file OptimizeStrategy.cpp.

◆ getVarCount()

size_t OptimizeStrategy::getVarCount ( ) const
private

The number of varibles this object was initialized with.

Definition at line 350 of file OptimizeStrategy.cpp.

◆ setUseIndependence()

void OptimizeStrategy::setUseIndependence ( bool  use)
virtual

Independence splits are not supported, so calling this method does nothing.

Will assert in debug mode if use is true.

Reimplemented from SliceStrategyCommon.

Definition at line 50 of file OptimizeStrategy.cpp.

◆ simplify()

bool OptimizeStrategy::simplify ( Slice slice)
virtual

This method calls MsmStrategy::simplify to perform the usual simplification of slice, which then occurs if and only if the usual simplification has been turned on.

Independent of whether usual simplification has been turned on, this method also eliminates non-improving slices, and uses bound-driven simplification, depending on the value of BoundSetting passed to the constructor.

Reimplemented from SliceStrategyCommon.

Definition at line 81 of file OptimizeStrategy.cpp.

Member Data Documentation

◆ _boundSetting

BoundSetting OptimizeStrategy::_boundSetting
private

Indicates how to use the bound.

Definition at line 374 of file OptimizeStrategy.h.

◆ _boundSimplify_tmpPivot

Term OptimizeStrategy::_boundSimplify_tmpPivot
private

Temporary variable used in simplify.

Is a member variable in order to avoid the cost of initializing a Term every time.

Definition at line 410 of file OptimizeStrategy.h.

◆ _consume_tmpDegree

mpz_class OptimizeStrategy::_consume_tmpDegree
private

Temporary variable used in consume.

Is a member variable in order to avoid the cost of initializing an mpz_class every time.

Definition at line 379 of file OptimizeStrategy.h.

◆ _grader

const TermGrader& OptimizeStrategy::_grader
private

We use _grader to assign values to solutions.

Definition at line 342 of file OptimizeStrategy.h.

◆ _maxSolutions

Ideal OptimizeStrategy::_maxSolutions
private

Stores the optimal solutions found so far, according to the best value found so far.

Definition at line 366 of file OptimizeStrategy.h.

◆ _maxValue

mpz_class OptimizeStrategy::_maxValue
private

The best value of any solution found so far.

The value is undefined if no solution has been found so far.

Definition at line 347 of file OptimizeStrategy.h.

◆ _maxValueToBeat

mpz_class OptimizeStrategy::_maxValueToBeat
private

Is equal to _maxValue minus _reportAllSolutions, except when no solution has been found so far, in which case the value is undefined.

We use _maxValueToBeat in place of _maxValue as a way to handle both values of _reportAllSolutions without having a lot of code of the type

if (_reportAllSolutions ? a < _maxValue : a <= _maxValue) ...

The point is that we can replace this by

if (a <= _maxValueToBeat) ...

Definition at line 361 of file OptimizeStrategy.h.

◆ _reportAllSolutions

bool OptimizeStrategy::_reportAllSolutions
private

Indicates whether to compute all optimal solutions, as opposed to computing just one (when there are any).

Definition at line 371 of file OptimizeStrategy.h.

◆ _simplify_tmpDominator

Term OptimizeStrategy::_simplify_tmpDominator
private

Temporary variable used in simplify.

Is a member variable in order to avoid the cost of initializing a Term every time.

Definition at line 389 of file OptimizeStrategy.h.

◆ _simplify_tmpOldDivisor

Term OptimizeStrategy::_simplify_tmpOldDivisor
private

Temporary variable used in simplify.

Is a member variable in order to avoid the cost of initializing a Term every time.

Definition at line 399 of file OptimizeStrategy.h.

◆ _simplify_tmpOldDominator

Term OptimizeStrategy::_simplify_tmpOldDominator
private

Temporary variable used in simplify.

Is a member variable in order to avoid the cost of initializing a Term every time.

Definition at line 394 of file OptimizeStrategy.h.

◆ _simplify_tmpUpperBound

mpz_class OptimizeStrategy::_simplify_tmpUpperBound
private

Temporary variable used in simplify.

Is a member variable in order to avoid the cost of initializing an mpz_class every time.

Definition at line 384 of file OptimizeStrategy.h.

◆ _tmpC

mpz_class OptimizeStrategy::_tmpC
private

Temporary variable used in getInnerSimplify and getOuterSimplify.

Is a member variable in order to avoid the cost of initializing an mpz_class every time.

Definition at line 405 of file OptimizeStrategy.h.


The documentation for this class was generated from the following files: