home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
tlx501.zip
/
SOLVE
/
CSP.H
< prev
next >
Wrap
C/C++ Source or Header
|
1996-01-05
|
23KB
|
679 lines
/****************************************************************************
$Id: csp.h 501.0 1995/03/07 12:26:54 RON Exp $
Copyright (c) 1991-95 Tarma Software Research. All rights reserved.
Project: Tarma Library for C++ V5.0
Author: Ron van der Wal
Declarations for the basic classes that are used in CSP programming. The
file combines these declarations since they are mutually dependent. The
following classes are declared:
TLConstraint - abstract base class that represents a constraint
in a CSP.
TLNodeCon - represents a unary constraint on a variable
TLBinCon - represents a binary constraint
TLDomain - base class for copies of variable domains
TLVariable - defines the behaviour of variables in a constraint
propagation framework.
TLDomainMonitor - stores domains of variables that are changed
TLPropagator - base class for propagation algorithms
TLPropagatorAC3 - implements AC-3 algorithm
TLPropagatorFC - implements forward-checking algorithm
$Log: csp.h $
Revision 501.0 1995/03/07 12:26:54 RON
Updated for TLX 5.01
Revision 1.8 1995/02/22 12:18:38 RON
Update for release 012
Added partial support for SunPro C++ compiler
Revision 1.7 1995/01/13 15:26:02 ron
Switched from Constraint activation flag to activation count
Added activation count to debug version of Variable
Revision 1.6 1995/01/12 13:34:01 ron
Small formatting change
Revision 1.5 1995/01/08 11:51:19 ron
Renamed TLCSProblem to TLCSSubProblem
Revision 1.4 1995/01/05 15:36:34 ron
Naming changes
Revision 1.3 1994/11/16 15:31:00 ron
Added Propagate() member function
Revision 1.2 1994/10/07 17:10:54 ron
Changed Unregister...() to Deregister...()
Revision 1.1 1994/10/06 17:52:42 ron
Initial revision
****************************************************************************/
#ifndef _TLX_CSP_H
#define _TLX_CSP_H
//----- System headers
#include <stdarg.h>
//----- Project headers
#ifndef _TLX_ARRAYS_H
#include <tlx\501\arrays.h>
#endif
#ifndef _TLX_ASSOC_H
#include <tlx\501\assoc.h>
#endif
#ifndef _TLX_PTRARRAY_H
#include <tlx\501\ptrarray.h>
#endif
//----- Auxiliary types and forward declarations
class _TLXCLASS TLProblemState; // In searcher.h
class _TLXCLASS TLConstraint;
class _TLXCLASS TLVariable;
class _TLXCLASS TLPropagator;
typedef TLPtrSeq<TLVariable> TLVarList; // List of variables
typedef TLPtrSeq<TLConstraint> TLConstraintList; // List of constraints
/*---------------------------------------------------------------------------
TLConstraint -
Abstract base class for all constraint types.
---------------------------------------------------------------------------*/
class _TLXCLASS TLConstraint
{
static int32 sCheckCount; // Number of constraint checks
int mDeactiveCount; // Number of deactivations
public:
virtual ~TLConstraint();
// Propagation function: PropagateCond() is called to propagate the
// effects of the constraint. It will call the implementation-dependent
// Propagate() function, but only if the constraint is active.
//
// The other functions change and check the activation status of the
// constraint. All constraints start out active.
bool PropagateCond(TLVariable *);
void Activate();
void Deactivate();
bool IsActive() const;
// Functions to interrogate and update the constraint check count
static int32 CheckCount();
static void ResetCount();
// Output operators
virtual ostream & PrintOn(ostream &aStream) const = 0;
friend ostream & _TLXFUNC operator <<(ostream &, const TLConstraint &);
protected:
TLConstraint();
// Derived classes should call the following function whenever they
// perform a constraint check.
static void CountCheck();
private:
// Propagate() is the constraint revision function that implements
// constraint-specific behavior. It must return nonzero if the revision
// succeeds, else zero (= constraint violated).
virtual bool Propagate(TLVariable *) = 0;
};
/*---------------------------------------------------------------------------
TLNodeCon -
Abstract base class for unary constraints.
---------------------------------------------------------------------------*/
class _TLXCLASS TLNodeCon: public TLConstraint
{
TLVariable & mVar;
public:
TLNodeCon(TLVariable &);
// Functions to notify the variable involved in the constraint of
// our presence.
void WatchVar();
void UnwatchVar();
// Functions to obtain references to the variable.
TLVariable & Var();
const TLVariable & Var() const;
};
/*---------------------------------------------------------------------------
TLBinCon -
Abstract base class for binary constraints.
---------------------------------------------------------------------------*/
class _TLXCLASS TLBinCon: public TLConstraint
{
TLVariable & mVar1;
TLVariable & mVar2;
public:
TLBinCon(TLVariable &, TLVariable &);
// Functions to notify the variables involved in the constraint of
// our presence.
void WatchVars();
void UnwatchVars();
// Functions to obtain references to the variables and their opposites.
TLVariable & Var1();
const TLVariable & Var1() const;
TLVariable & Var2();
const TLVariable & Var2() const;
TLVariable & OppositeOf(TLVariable &);
const TLVariable & OppositeOf(const TLVariable &) const;
};
/*---------------------------------------------------------------------------
TLDomain -
Helper class that represents the domain of a variable.
---------------------------------------------------------------------------*/
class TLDomain
{
public:
virtual ~TLDomain();
// Output-related functions
virtual ostream & PrintOn(ostream &) const = 0;
friend ostream & _TLXFUNC operator <<(ostream &, const TLDomain &);
};
/*---------------------------------------------------------------------------
TLVariable -
Abstract base class for all variables. Contains various notification
functions that help the TLPropagator in controlling the constraint
propagation process.
---------------------------------------------------------------------------*/
class _TLXCLASS TLVariable
{
friend class _TLXCLASS TLPropagator;
friend class _TLXCLASS TLDomainMonitor;
char * mName; // Descriptive name
TLProblemState * mProblem; // Subproblem in search tree
TLConstraintList mConstraints; // Constraints on this variable
#ifdef _TLXDBG
int mDeactiveCount; // Number of deactivations
#endif
// In case of a propagator-controlled propagation process, a pointer to
// the active propagator is stored. There can only be one active
// propagator at a time. If this pointer is 0 when a variable attempts
// to propagate, a stand-alone propagation process is performed.
static TLPropagator *sPropagator; // Current propagator (if any)
// Data member to keep track of the current state monitor. There can only
// be one state monitor at a time for all variables in existence. It may
// also be 0, in which case changes to the states of variables are not
// captured.
static TLDomainMonitor *sDomainMonitor;
// Data members to keep track of stand-alone constraint propagation.
// We are careful not to perform recursive propagation of changes, but
// rather to restart the pending propagation.
bool mIsPropagating; // True if currently propagating
index_t mConIndex; // Constraint index during propagation
public:
enum DomChanges //----- Constants that indicate domain changes
{
kDomChange = 0x0001, // General domain change
kDomLower = 0x0002, // Lower bound raised
kDomUpper = 0x0004, // Upper bound lowered
kDomSingle = 0x0008, // Domain reduced to a single value
kDomEmpty = 0x8000 // Domain has become empty
};
public:
TLVariable(const char *);
virtual ~TLVariable();
const char * GetName() const;
void SetName(const char *);
// Operations on the list of constraints. Clients are not allowed to
// modify the constraint list directly.
void AddConstraint(TLConstraint *);
void RemoveConstraint(TLConstraint *);
void ActivateConstraints();
void DeactivateConstraints();
#ifdef _TLXDBG
bool IsActive() const;
#endif
// Accessor function for the constraint list -- read-only access
const TLConstraintList &Constraints() const;
// The following functions can be used to determine which variable to
// select next. DomainSize() should be overridden by derived classes
// if they have a meaningful measure for their domain size.
virtual size_t DomainSize() const;
size_t ConstraintCount() const;
// Function to propagate the changes in the variable:
//
// - PropagateChanges() performs change propagation through all
// constraints, with guards against recursive calls to itself.
bool PropagateChanges();
// The following functions are call-backs.
//
// - SaveDomain() must be called before making any changes to the
// domain of the variable, in order to ensure that the current domain
// can be captured for restoration later on.
//
// - RegisterChanges() must be called after changes have been made to the
// variable, in order to allow further propagation of those changes. If
// there currently is a propagator, it is called to register the
// changes; else PropagateChanges() is invoked to handle the propagation.
void SaveDomain();
void RegisterChanges(DomChanges = kDomChange);
// To interface with various searching algorithms, a variable may
// optionally store a pointer to the subproblem in which it was
// instantiated. The standard class TLCSProblemState will do this
// automatically.
TLProblemState * GetProblem() const;
void SetProblem(TLProblemState *);
// Output-related functions
virtual ostream & PrintOn(ostream &) const = 0;
friend ostream & _TLXFUNC operator <<(ostream &, const TLVariable &);
private:
// The following functions must be implemented in such a way as to allow
// restoration of the variable's domain. They are called by instances
// of TLDomainMonitor.
//
// - CopyDomain() should return information to allow restoration of the
// current domain;
//
// - RestoreDomain() should use this information to restore the domain;
// it is assumed that a single copy can be restored more than once.
virtual TLDomain * CopyDomain() = 0;
virtual void RestoreDomain(const TLDomain *) = 0;
};
/*---------------------------------------------------------------------------
TLDomainMonitor -
Class that captures changes to variables. It will store the domains of
variables just before they are changed. In order to do this, it relies
on the cooperation of the variables, in particular on the
TLVariable::SaveDomain() member function, that should be called
prior to any changes to the variable.
A given instance of TLDomainMonitor will store only one copy of
the domain of a variable (in particular, the first one), on the
assumption that later changes can be restored by reverting to the
earliest captured domain.
TLDomainMonitor instances can be nested (i.e. a new one can be
created while older ones still exist); in that case, the most recently
created one will capture all changes.
---------------------------------------------------------------------------*/
class _TLXCLASS TLDomainMonitor
{
friend class _TLXCLASS TLVariable;
// To allow nesting of domain monitors, we store a pointer to the
// monitor that was active at the time the current instance was
// activated. In conjunction with TLVariable::sDomainMonitor, this
// implements a stack of domain monitors.
TLDomainMonitor * mPrevMonitor;
// The original domains of all variables that are changed during the
// execution of a propagation algorithm are stored here.
TLDictionary<TLVariable *, TLDomain *> mDomains;
public:
TLDomainMonitor();
virtual ~TLDomainMonitor();
// Functions to start and stop the capturing process. Of all
// TLDomainMonitor instances, the one with the most recently
// executed StartCapturing() without a corresponding StopCapturing()
// will be the one that actually captures changes to variables.
//
// - StartCapturing() starts the capturing process; this is only allowed
// if the monitor is not currently capturing;
//
// - StopCapturing() stops the capturing process; this is only allowed
// if the monitor is currently capturing;
//
// - IsCapturing() returns true iff the monitor has been started and
// not stopped yet;
//
// - IsActive() returns true iff the monitor is the topmost
// monitor, and hence the one that is currently capturing changes
// to the domains of variables.
//
// - DomainCount() returns the number of domains captured by the monitor
void StartCapturing();
void StopCapturing();
bool IsCapturing() const;
bool IsActive() const;
size_t DomainCount() const;
// Call-back function for variables. Calling this function will
// cause the monitor to store a copy of the variable's domain, if
// it is not stored yet.
void CaptureDomain(TLVariable *);
// Utility functions that operate on the domains captured so far:
//
// - RestoreDomains() will restore the domains of all variables
// that were captured;
//
// - DiscardDomains() will forget all captured information, without
// restoring any domains.
void RestoreDomains();
void DiscardDomains();
private:
// Helper function to unregister the monitor with the variables.
void DeregisterMonitor();
};
/*---------------------------------------------------------------------------
TLPropagator -
Base class for various constraint propagation classes.
---------------------------------------------------------------------------*/
class _TLXCLASS TLPropagator
{
friend class _TLXCLASS TLVariable;
TLPropagator * mPrevProp; // Previously active propagator
TLConstraint * mFailed; // First constraint that failed
public:
struct _TLXCLASS Stats
{
int32 mCheckCount; // Total number of value checks
int32 mMaxPending; // Maximum # pending constraints
};
protected:
Stats mStats; // Propagation statistics
public:
virtual ~TLPropagator();
// Functions to manipulate the statistics gathered so far.
void GetStats(Stats &) const;
void ClearStats();
// Standard propagation interface:
//
// - Propagate(TLVariable *) propagates the effects of the domain of the
// given variable to all reachable variables according to the
// propagation algorithm under consideration.
//
// - Propagate(TLPtrIter<TLVariable> &) propagates the effects of all
// variables accessible from the iterator in a similar manner.
virtual const char *Description() const = 0;
virtual bool Propagate(TLVariable *) = 0;
virtual bool Propagate(TLPtrIter<TLVariable> &) = 0;
protected:
TLPropagator();
// Functions to register the propagator as the active propagator for
// constraint propagation. There can only be one propagator active at
// any time; trying to activate another one is an error.
//
// - RegisterPropagator() must be called to register the current
// propagator as the active one, prior to the start of the propagation
// process.
//
// - DeregisterPropagator() must be called to reverse the previous action.
//
// - IsRegistered() returns true iff the current propagator is registered.
//
// - IsActive() returns true iff the current propagator is the active
// propagator.
void RegisterPropagator();
void DeregisterPropagator();
bool IsRegistered() const;
bool IsActive() const;
// The propagator will store a pointer to the first constraint that fails
// during constraint propagation. It can be retrieved by means of the
// following function. The second function is available to explicitly
// set that constraint pointer; it should not normally be used.
TLConstraint * GetFailedConstraint() const;
void SetFailedConstraint(TLConstraint *);
private:
// The following function is a call-back from Variables. It must be
// called after a variable's state has been changed, in order to allow
// propagation of those changes.
virtual void RegisterChanges(TLVariable *) {}
};
/*---------------------------------------------------------------------------
TLPropagatorAC3 -
Class that implements the AC-3 arc consistency algorithm.
---------------------------------------------------------------------------*/
class _TLXCLASS TLPropagatorAC3: public TLPropagator
{
TLPtrQueue<TLVariable> mChanges; // Keeps track of changes to variables
public:
TLPropagatorAC3();
// Consistency checking and constraint propagation algorithms:
//
// - CheckAC3() propagates the effects of all constraints that
// start with any of the variables in the given set. Propagation
// continues until an inconsistency is detected or no more changes
// occur.
//
// - CheckAC3Set() propagates the effects of the constraints within
// a given set of variables. Variables outside this set may be
// affected, but this will not lead to further constraint propagation.
//
// All functions return true if the system is still consistent,
// else (inconsistency detected) they return false.
bool CheckAC3(TLVariable &);
bool CheckAC3(TLPtrIter<TLVariable> &);
bool CheckAC3Set(TLPtrIter<TLVariable> &,
TLPtrIter<TLVariable> &);
// Implementation of generic propagation functions. For the AC-3
// algorithm, 'reachable' variables are all variables that can be
// reached (recursively) by following constraints from variables given
// or processed.
virtual const char *Description() const;
virtual bool Propagate(TLVariable *);
virtual bool Propagate(TLPtrIter<TLVariable> &);
private:
// Override of call-back function inherited from TLPropagator. It
// must be called after the state of a variable has been changed,
// in order to allow further propagation of those changes.
virtual void RegisterChanges(TLVariable *);
// Helper function that implements the actual AC-3 algorithm
bool PerformAC3(TLPtrIter<TLVariable> &,
TLPtrIter<TLVariable> &, bool);
};
/*---------------------------------------------------------------------------
TLPropagatorFC -
Class that implements a forward-checking propagation algorithm.
---------------------------------------------------------------------------*/
class _TLXCLASS TLPropagatorFC: public TLPropagator
{
public:
TLPropagatorFC();
// Consistency checking and constraint propagation algorithms:
//
// - CheckForward() propagates the effects of the constraints that
// originate with the given variable (only).
bool CheckForward(TLVariable &);
// Implementation of generic propagation functions. For the forward
// check algorithm, only the constraints connected immediately to the
// given (set of) variable(s) are considered.
virtual const char *Description() const;
virtual bool Propagate(TLVariable *);
virtual bool Propagate(TLPtrIter<TLVariable> &);
};
/*---------------------------------------------------------------------------
Inline functions
---------------------------------------------------------------------------*/
//----- TLConstraint
inline bool TLConstraint::IsActive() const
{ return mDeactiveCount == 0; }
inline int32 TLConstraint::CheckCount()
{ return sCheckCount; }
inline void TLConstraint::ResetCount()
{ sCheckCount = 0; }
inline void TLConstraint::CountCheck()
{ sCheckCount++; }
inline ostream & _TLXFUNC operator <<(ostream &os, const TLConstraint &c)
{ return c.PrintOn(os); }
//----- TLNodeCon
inline TLVariable &TLNodeCon::Var()
{ return mVar; }
inline const TLVariable &TLNodeCon::Var() const
{ return mVar; }
//----- TLBinCon
inline TLVariable &TLBinCon::Var1()
{ return mVar1; }
inline const TLVariable &TLBinCon::Var1() const
{ return mVar1; }
inline TLVariable &TLBinCon::Var2()
{ return mVar2; }
inline const TLVariable &TLBinCon::Var2() const
{ return mVar2; }
//----- TLDomain
inline ostream & _TLXFUNC operator <<(ostream &os, const TLDomain &dom)
{ return dom.PrintOn(os); }
//----- TLVariable
inline const char *TLVariable::GetName() const
{ return mName; }
inline const TLConstraintList &TLVariable::Constraints() const
{ return mConstraints; }
#ifdef _TLXDBG
inline bool TLVariable::IsActive() const
{ return mDeactiveCount == 0; }
#endif
inline size_t TLVariable::DomainSize() const
{ return 0; }
inline size_t TLVariable::ConstraintCount() const
{ return mConstraints.Count(); }
inline TLProblemState *TLVariable::GetProblem() const
{ return mProblem; }
inline void TLVariable::SetProblem(TLProblemState *aProblem)
{ mProblem = aProblem; }
inline ostream & _TLXFUNC operator <<(ostream &os, const TLVariable &v)
{ return v.PrintOn(os); }
//----- TLDomainMonitor
inline size_t TLDomainMonitor::DomainCount() const
{ return mDomains.Count(); }
//----- TLPropagator
inline void TLPropagator::GetStats(Stats &s) const
{ s = mStats; }
inline TLConstraint *TLPropagator::GetFailedConstraint() const
{ return mFailed; }
#endif // _TLX_CSP_H