support failure in constraints propagation and demon executions

This commit is contained in:
lperron@google.com
2014-05-22 17:37:21 +00:00
parent 3c7b0ab7d3
commit f14c0361c6
4 changed files with 116 additions and 19 deletions

View File

@@ -64,7 +64,7 @@ def test_search_monitor():
solver.Solve(db, monitor)
class DemonTest(pywrapcp.Demon):
class DemonTest(pywrapcp.PyDemon):
def __init__(self, x):
pywrapcp.Demon.__init__(self)
self._x = x
@@ -74,7 +74,7 @@ class DemonTest(pywrapcp.Demon):
print 'in Run(), saw ' + str(self._x)
class ConstraintTest(pywrapcp.Constraint):
class ConstraintTest(pywrapcp.PyConstraint):
def __init__(self, solver, x):
pywrapcp.Constraint.__init__(self, solver)
self._x = x
@@ -92,6 +92,14 @@ class ConstraintTest(pywrapcp.Constraint):
print self._x
print 'out of InitialPropagate()'
class InitialPropagateDemon(pywrapcp.PyDemon):
def __init__(self, ct):
pywrapcp.Demon.__init__(self)
self._ct = ct
def Run(self, solver):
self._ct.InitialPropagate()
def test_demon():
solver = pywrapcp.Solver('test export')
@@ -109,6 +117,32 @@ def test_constraint():
solver.Solve(db)
class DumbGreaterOrEqualToFive(pywrapcp.PyConstraint):
def __init__(self, solver, x):
pywrapcp.Constraint.__init__(self, solver)
self._x = x
def Post(self):
self._demon = InitialPropagateDemon(self)
self._x.WhenBound(self._demon)
def InitialPropagate(self):
if self._x.Bound():
if self._x.Value() < 5:
print 'Reject %d' % self._x.Value()
self.solver().Fail()
else:
print 'Accept %d' % self._x.Value()
def test_failing_constraint():
solver = pywrapcp.Solver('test export')
x = solver.IntVar(1, 10, 'x')
myct = DumbGreaterOrEqualToFive(solver, x)
solver.Add(myct)
db = solver.Phase([x], solver.CHOOSE_FIRST_UNBOUND, solver.ASSIGN_MIN_VALUE)
solver.Solve(db)
def main():
test_member()
@@ -119,6 +153,7 @@ def main():
test_search_monitor()
test_demon()
test_constraint()
test_failing_constraint()
if __name__ == '__main__':

View File

@@ -242,12 +242,14 @@ class Queue {
solver_->TopPeriodicCheck();
}
demon->Run(solver_);
solver_->CheckFail();
} else {
solver_->GetPropagationMonitor()->BeginDemonRun(demon);
if (++solver_->demon_runs_[demon->priority()] % kTestPeriod == 0) {
solver_->TopPeriodicCheck();
}
demon->Run(solver_);
solver_->CheckFail();
solver_->GetPropagationMonitor()->EndDemonRun(demon);
}
}
@@ -257,6 +259,7 @@ class Queue {
solver_->TopPeriodicCheck();
}
demon->Run(solver_);
solver_->CheckFail();
}
void ProcessInstrumentedNormalDemon(Demon* const demon) {
@@ -265,6 +268,7 @@ class Queue {
solver_->TopPeriodicCheck();
}
demon->Run(solver_);
solver_->CheckFail();
solver_->GetPropagationMonitor()->EndDemonRun(demon);
}
@@ -307,6 +311,7 @@ class Queue {
solver_->TopPeriodicCheck();
}
demon->Run(solver_);
solver_->CheckFail();
}
}
} else {
@@ -1420,7 +1425,8 @@ Solver::Solver(const std::string& name, const SolverParameters& parameters)
additional_constraint_index_(0),
propagation_monitor_(BuildTrace(this)),
print_trace_(nullptr),
anonymous_variable_index_(0) {
anonymous_variable_index_(0) ,
should_fail_(false) {
Init();
}
@@ -1453,7 +1459,8 @@ Solver::Solver(const std::string& name)
additional_constraint_index_(0),
propagation_monitor_(BuildTrace(this)),
print_trace_(nullptr),
anonymous_variable_index_(0) {
anonymous_variable_index_(0),
should_fail_(false) {
Init();
}
@@ -2460,6 +2467,17 @@ void Solver::Fail() {
searches_.back()->JumpBack();
}
void Solver::ShouldFail() {
should_fail_ = true;
}
void Solver::CheckFail() {
if (should_fail_) {
should_fail_ = false;
Fail();
}
}
// ----- Cast Expression -----
IntExpr* Solver::CastExpression(const IntVar* const var) const {
@@ -3214,6 +3232,7 @@ void Constraint::PostAndPropagate() {
FreezeQueue();
Post();
InitialPropagate();
solver()->CheckFail();
UnfreezeQueue();
}

View File

@@ -2883,6 +2883,10 @@ class Solver {
// method returns expr, nullptr otherwise.
IntExpr* CastExpression(const IntVar* const var) const;
// Support for swig.
void ShouldFail();
void CheckFail();
private:
void Init(); // Initialization. To be called by the constructors only.
void PushState(MarkerType t, const StateInfo& info);
@@ -3021,6 +3025,7 @@ class Solver {
std::unique_ptr<PropagationMonitor> propagation_monitor_;
PropagationMonitor* print_trace_;
int anonymous_variable_index_;
bool should_fail_;
DISALLOW_COPY_AND_ASSIGN(Solver);
};

View File

@@ -260,22 +260,14 @@ gflags.DEFINE_boolean('cp_no_solve', False,
gflags.DEFINE_string('cp_profile_file', '',
'exports profiling overview to file.')
}
%pythoncode {
class PyDecisionBuilder(object):
def NextWrapper(self, solver):
result = None
try:
result = self.Next(solver)
except Exception:
return solver.FailDecision()
return result
def DebugString(self):
return "PyDecisionBuilder"
}
} // namespace operations_research
// Rename rules for directors
%rename (InitialPropagateWrapper)
operations_research::Constraint::InitialPropagate;
%rename (RunWrapper) operations_research::Demon::Run;
// Rename rules on SolutionCollector.
%rename (Branches) operations_research::SolutionCollector::branches;
%rename (Failures) operations_research::SolutionCollector::failures;
@@ -1260,7 +1252,7 @@ struct FailureProtect {
// Generic rename rule.
%rename("%(camelcase)s", %$isfunction) "";
// Rename rule on DecisionBuilder;
// Rename rule on directors;
%rename (NextWrap) operations_research::DecisionBuilder::Next;
// Rename rule on SearchLimit
@@ -2098,3 +2090,49 @@ namespace operations_research {
typedef Assignment::AssignmentContainer AssignmentContainer;
%template(AssignmentIntContainer) AssignmentContainer<IntVar, IntVarElement>;
}
#if defined(SWIGPYTHON)
%pythoncode {
class PyDecisionBuilder(object):
def NextWrapper(self, solver):
result = None
try:
result = self.Next(solver)
except Exception:
return solver.FailDecision()
return result
def DebugString(self):
return "PyDecisionBuilder"
class PyConstraint(Constraint):
def __init__(self, solver):
pywrapcp.Constraint.__init__(self, solver)
def InitialPropagateWrapper(self):
try:
self.InitialPropagate()
except:
self.solver().ShouldFail()
def DebugString(self):
return "PyConstraint"
class PyDemon(Demon):
def __init__(self):
pywrapcp.Demon.__init__(self)
def RunWrapper(self, solver):
try:
self.Run(solver)
except:
solver.ShouldFail()
def DebugString(self):
return "PyDemon"
}
#endif // SWIGPYTHON