home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tlx501.zip / SRC / VARIABLE.CPP < prev    next >
C/C++ Source or Header  |  1996-07-08  |  9KB  |  271 lines

  1. /****************************************************************************
  2.     $Id: variable.cpp 501.0 1995/03/07 12:26:26 RON Exp $
  3.  
  4.     Copyright (c) 1991-95 Tarma Software Research. All rights reserved.
  5.  
  6.     Project:    Tarma Library for C++ V5.0
  7.     Author:    Ron van der Wal
  8.  
  9.     Implementation of the TLVariable class. This class is the abstract base
  10.     class for all variables in the CSP framework.
  11.  
  12.     $Log: variable.cpp $
  13.     Revision 501.0  1995/03/07 12:26:26  RON
  14.     Updated for TLX 5.01
  15.     Revision 1.16  1995/01/31 16:30:32  RON
  16.     Update for release 012
  17.     Added partial support for SunPro C++ compiler
  18.     Revision 1.15  1995/01/13  15:35:31  ron
  19.     Added activation/deactivation count for debugging purposes
  20.  
  21.     Revision 1.14  1995/01/06  15:58:41  ron
  22.     Corrected Revision keyword
  23.  
  24.     Revision 1.13  1995/01/05  15:31:25  ron
  25.     Naming changes
  26.  
  27.     Revision 1.12  1994/11/16  15:45:42  ron
  28.     Added module info; rearranged #include directives
  29.  
  30.     Revision 1.11  1994/10/10  16:57:12  ron
  31.     Changed to <tlx\solve\csp.h>
  32.  
  33.     Revision 1.10  1994/10/05  18:45:39  ron
  34.     Implemented support for constraint activation/deactivation
  35.  
  36.     Revision 1.9  1994/09/28  14:47:19  ron
  37.     Removed Macintosh-style #include references
  38.  
  39.     Revision 1.8  1994/09/28  14:23:36  ron
  40.     Adapted to change from TLVarDomainMonitor to TLDomainMonitor
  41.  
  42.     Revision 1.7  1994/09/27  20:23:24  ron
  43.     Changed path separator from / to \
  44.  
  45.     Revision 1.6  1994/09/26  15:50:36  ron
  46.     Adapted to changes in constraint check counting
  47.  
  48.     Revision 1.5  1994/09/13  10:16:07  ron
  49.     Added code to remember the first constraint that fails during
  50.     propagation of changes.
  51.  
  52.     Revision 1.4  1994/09/07  15:45:02  ron
  53.     Small formatting changes
  54.  
  55.     Revision 1.3  1994/09/06  20:25:59  ron
  56.     Renamed RegisterDomain() to SaveDomain()
  57.  
  58.     Revision 1.2  1994/09/06  14:08:16  ron
  59.     Implemented new functions due to changes in the algorithms
  60.  
  61.     Revision 1.1  1994/08/16  18:13:21  ron
  62.     Initial revision
  63.  
  64. ****************************************************************************/
  65.  
  66. #include <tlx\501\_build.h>
  67.  
  68. TLX_MODULE_INFO("$Revision: 501.0 $");
  69.  
  70. #include <tlx\501\solve\csp.h>
  71.  
  72. /*---------------------------------------------------------------------------
  73.     Template instantiations
  74. ---------------------------------------------------------------------------*/
  75.  
  76. #ifdef THINK_CPLUS
  77.     #include "ptrseq.cpp"
  78.     #pragma template TLPtrSeq<TLConstraint>
  79. #else
  80.     #include <tlx\501\template\ptrseq.cpp>
  81. #endif
  82.  
  83. /*---------------------------------------------------------------------------
  84.     Static class variables
  85. ---------------------------------------------------------------------------*/
  86.  
  87. TLPropagator *        TLVariable::sPropagator = 0;
  88. TLDomainMonitor *    TLVariable::sDomainMonitor = 0;
  89.  
  90. /*-------------------------------------------------------------------------*/
  91.     TLVariable::TLVariable(const char *nm)
  92.  
  93. /*  Constructor. Stores a duplicate of the variable's name.
  94. ---------------------------------------------------------------------------*/
  95. : mName(0), mConstraints(10, 10)
  96. {
  97.     mIsPropagating = false;
  98.     mConIndex        = 0;
  99.     mProblem       = 0;
  100.   #ifdef _TLXDBG
  101.     mDeactiveCount = 0;
  102.   #endif
  103.  
  104.     SetName(nm);
  105. }
  106.  
  107. /*-------------------------------------------------------------------------*/
  108.     TLVariable::~TLVariable()
  109.  
  110. /*  Destructor. Discards name storage.
  111. ---------------------------------------------------------------------------*/
  112. {
  113.     delete [] mName;
  114. }
  115.  
  116. /*-------------------------------------------------------------------------*/
  117.     void TLVariable::ActivateConstraints()
  118.  
  119. /*  Activates all constraints attached to the variable.
  120. ---------------------------------------------------------------------------*/
  121. {
  122.   #ifdef _TLXDBG
  123.     if (--mDeactiveCount < 0)
  124.     {
  125.     TLX_TRACE_WARN(TLX, ("%s: Too many constraint activations",
  126.                GetName()));
  127.     mDeactiveCount = 0;
  128.     }
  129.   #endif
  130.     for (index_t i = mConstraints.Mini(); i <= mConstraints.Maxi(); i++)
  131.     mConstraints.PeekAt(i)->Activate();
  132. }
  133.  
  134. /*-------------------------------------------------------------------------*/
  135.     void TLVariable::AddConstraint(TLConstraint *con)
  136.  
  137. /*  Adds a constraint to the list of constraints whose revision depends on
  138.     changes in the current variable. The constraint will only be added
  139.     if it does not yet appear in the list.
  140. ---------------------------------------------------------------------------*/
  141. {
  142.     TLX_ASSERT_PTR(con);
  143.  
  144.     if (!mConstraints.Contains(con))
  145.     mConstraints.Append(con);
  146. }
  147.  
  148. /*-------------------------------------------------------------------------*/
  149.     void TLVariable::DeactivateConstraints()
  150.  
  151. /*  Deactivates all constraints attached to the variable.
  152. ---------------------------------------------------------------------------*/
  153. {
  154.   #ifdef _TLXDBG
  155.     if (mDeactiveCount < INT_MAX)
  156.     ++mDeactiveCount;
  157.     else
  158.     TLX_TRACE_WARN(TLX, ("%s: Maximum number of deactivations exceeded",
  159.                GetName()));
  160.   #endif
  161.     for (index_t i = mConstraints.Mini(); i <= mConstraints.Maxi(); i++)
  162.     mConstraints.PeekAt(i)->Deactivate();
  163. }
  164.  
  165. /*-------------------------------------------------------------------------*/
  166.     bool TLVariable::PropagateChanges()
  167.  
  168. /*  Propagates changes made to the current variable by calling the Propagate()
  169.     procedure for all constraints attached to the variable. To prevent
  170.     recursive calls from eating up runtime stack space and performing
  171.     unnecessary work, we check for recursive calls. If we find one, we
  172.     reset the current constraint iterator rather than starting a new
  173.     propagation.
  174. ---------------------------------------------------------------------------*/
  175. {
  176.     if (mIsPropagating)
  177.     {
  178.     // Already propagating. Do not restart propagating right now; just
  179.     // reset the constraint iteration index and drop out. When the
  180.     // recursion unwinds back to the original call to this function,
  181.     // it will simply re-evaluate the constraints involved.
  182.     //
  183.     // We set the index to Mini() - 1, because the constraint evaluation
  184.     // loop below will increment the index before doing anything else.
  185.  
  186.     mConIndex = mConstraints.Mini() - 1;
  187.     }
  188.     else
  189.     {
  190.     // Propagate changes through all constraints
  191.     //
  192.     // TODO: make the following a lock. In the current version,
  193.     // the mIsPropagating flag is never reset if the routine is left
  194.     // as the result of stack unwinding during exception handling.
  195.  
  196.     mIsPropagating = true;
  197.  
  198.     for (mConIndex = mConstraints.Mini();
  199.          mConIndex <= mConstraints.Maxi(); mConIndex++)
  200.     {
  201.         // The following PropagateCond() call may lead (eventually) to
  202.         // a recursive call to this function.
  203.  
  204.         if (!mConstraints.PeekAt(mConIndex)->PropagateCond(this))
  205.         {
  206.         // Dead end: stop propagation and return false. The
  207.         // constraint that failed is registered with the
  208.         // propagator (if any).
  209.  
  210.         if (sPropagator)
  211.             sPropagator->SetFailedConstraint(mConstraints.PeekAt(
  212.                                 mConIndex));
  213.         mIsPropagating = false;
  214.         return false;
  215.         }
  216.     }
  217.  
  218.     // If we get here, all constraints were revised without problems.
  219.     mIsPropagating = false;
  220.     }
  221.     return true;
  222. }
  223.  
  224. /*-------------------------------------------------------------------------*/
  225.     void TLVariable::RegisterChanges(DomChanges)
  226.  
  227. /*  Called to register changes to the variable. If there is currently
  228.     an active propagator, it will be informed of the changes; else our
  229.     own PropagateChanges() will be invoked (which will guard against
  230.     uncontrolled recursion).
  231. ---------------------------------------------------------------------------*/
  232. {
  233.     if (sPropagator)
  234.     sPropagator->RegisterChanges(this);
  235.     else
  236.     PropagateChanges();
  237. }
  238.  
  239. /*-------------------------------------------------------------------------*/
  240.     void TLVariable::RemoveConstraint(TLConstraint *con)
  241.  
  242. /*  Removes a constraint from the list of dependent constraints.
  243. ---------------------------------------------------------------------------*/
  244. {
  245.     TLX_ASSERT_PTR(con);
  246.     mConstraints.Remove(con);
  247. }
  248.  
  249. /*-------------------------------------------------------------------------*/
  250.     void TLVariable::SaveDomain()
  251.  
  252. /*  Called to register the current domain of the variable, presumably
  253.     because it will be modified shortly. If there is an active domain
  254.     monitor, it will inform that monitor of the request; this may cause
  255.     the monitor to call back to our CopyDomain() function.
  256. ---------------------------------------------------------------------------*/
  257. {
  258.     if (sDomainMonitor)
  259.     sDomainMonitor->CaptureDomain(this);
  260. }
  261.  
  262. /*-------------------------------------------------------------------------*/
  263.     void TLVariable::SetName(const char *aName)
  264.  
  265. /*  Changes the name of the variable, discarding the previous one.
  266. ---------------------------------------------------------------------------*/
  267. {
  268.     delete [] mName;
  269.     mName = aName ? tlStrDup(aName) : 0;
  270. }
  271.