home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tlx501.zip / SRC / SEARCHER.CPP < prev    next >
C/C++ Source or Header  |  1996-09-27  |  21KB  |  628 lines

  1. /****************************************************************************
  2.     $Id: searcher.cpp 501.0 1995/03/07 12:26:20 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 class TLSearcher. This class is the abstract base
  10.     class for all searcher algorithms.
  11.  
  12.     $Log: searcher.cpp $
  13.     Revision 501.0  1995/03/07 12:26:20  RON
  14.     Updated for TLX 5.01
  15.     Revision 1.15  1995/02/28 15:13:24  RON
  16.     Update for release 012
  17.     Added partial support for SunPro C++ compiler
  18.     Revision 1.14  1995/01/18  10:39:01  ron
  19.     Added subproblem parameter to search monitor events
  20.  
  21.     Revision 1.13  1995/01/17  17:02:21  ron
  22.     Added number of solutions to progress message
  23.  
  24.     Revision 1.12  1995/01/13  16:02:54  ron
  25.     Added parameter to CreateSolution call
  26.  
  27.     Revision 1.11  1995/01/13  15:34:13  ron
  28.     Changed CreateSolution() to only create new solutions if
  29.     the required number has not been reached yet
  30.  
  31.     Revision 1.10  1995/01/12  13:41:03  ron
  32.     Adapted to previous Searcher/ProblemRep model
  33.  
  34.     Revision 1.9  1995/01/10  16:33:13  ron
  35.     Added progress message every 100 processed problems
  36.     Added check for initial problem instead of assertion
  37.  
  38.     Revision 1.8  1995/01/08  11:47:15  ron
  39.     Changed type of depth from int32 to int
  40.     Changed first level of depth counting from 1 to 0
  41.  
  42.     Revision 1.7  1995/01/06  15:56:54  ron
  43.     Adapted to new Searcher/Problem model
  44.  
  45.     Revision 1.6  1995/01/05  15:28:07  ron
  46.     Naming changes
  47.  
  48.     Revision 1.5  1994/11/16  15:42:38  ron
  49.     Adapted to group-style tracing
  50.     Added module info; rearranged #include directives
  51.  
  52.     Revision 1.4  1994/10/11  19:04:40  ron
  53.     Replaced DeadEnd() + SolveProblem() by ProcessProblem()
  54.  
  55.     Revision 1.3  1994/10/10  16:54:46  ron
  56.     Moved definition of searcher events to TLSearcher
  57.  
  58.     Revision 1.2  1994/10/07  17:05:05  ron
  59.     Added support for search monitors
  60.  
  61.     Revision 1.1  1994/10/06  17:44:55  ron
  62.     Initial revision
  63.  
  64. ****************************************************************************/
  65.  
  66. #include <tlx\501\_build.h>
  67.  
  68. TLX_MODULE_INFO("$Revision: 501.0 $");
  69.  
  70. #include <iostream.h>
  71. #include <stdio.h>
  72. #include <time.h>
  73. #include <tlx\501\log.h>
  74. #include <tlx\501\solve\searcher.h>
  75.  
  76. /*---------------------------------------------------------------------------
  77.     Template instantiations
  78. ---------------------------------------------------------------------------*/
  79.  
  80. #if defined(THINK_CPLUS)
  81.     #include "ptrseq.cpp"
  82.     #include "seq.cpp"
  83.     #pragma template TLPtrSeq<TLSolution>;
  84.     #pragma template TLPtrSeqIter<TLSolution>;
  85.     #pragma template TLSeq<TLSearcher::MonitorEntry>;
  86. #elif defined(__BORLANDC__) || defined(_MSC_VER) || defined(__SC__) || defined(__WATCOMC__)
  87.     #include <tlx\501\template\ptrseq.cpp>
  88.     #include <tlx\501\template\seq.cpp>
  89. #elif defined(__SUNPRO_CC)
  90.     #include <tlx\501\template\ptrseq.cpp>
  91.     #include <tlx\501\template\seq.cpp>
  92. #elif defined(__IBMCPP__)
  93.   #if __IBMCPP__ < 300
  94.     #pragma implementation("tlx\\template\\ptrseq.cpp")
  95.     #pragma implementation("tlx\\template\\seq.cpp")
  96.   #else
  97.     #include <tlx\501\template\ptrseq.cpp>
  98.     #include <tlx\501\template\seq.cpp>
  99.   #endif
  100. #else
  101.     #error Unsupported compiler; contact Tarma Software Research
  102. #endif
  103.  
  104. /*-------------------------------------------------------------------------*/
  105.     TLSearcher::TLSearcher()
  106.  
  107. /*  Default constructor; resets contents of searcher.
  108. ---------------------------------------------------------------------------*/
  109. : mSolutions(100, 100), mMonitors(10, 10)
  110. {
  111.     mSolutions.BecomeOwner(true);       // Will delete contents
  112.  
  113.     mPrevSearcher = 0;
  114.     mProblemRep   = 0;
  115.  
  116.     mStats.mMaxSol       = 0;
  117.     mStats.mBTCount      =
  118.     mStats.mProblemCount = 0;
  119.     mStats.mDepth        = 0;
  120.  
  121.     mStats.mStart    =
  122.     mStats.mPrevious =
  123.     mStats.mFinish   = 0;
  124.  
  125.     mGlobalMask = seNone;
  126.     mMonEnabled = false;
  127. }
  128.  
  129. /*-------------------------------------------------------------------------*/
  130.     TLSearcher::~TLSearcher()
  131.  
  132. /*  Destructor. Discards the solutions (if any).
  133. ---------------------------------------------------------------------------*/
  134. {
  135.     // Solutions are automatically discarded
  136.     TLX_ASSERT(mSolutions.IsOwner());
  137.  
  138.     if (mProblemRep)
  139.     {
  140.         TLX_TRACE_ERROR(TLX, ("Searcher linked to ProblemRep on destruction"));
  141.         if (mProblemRep->mSearcher == this)
  142.             DeregisterProblemRep();
  143.         TLX_ASSERT_NULL(mProblemRep);
  144.     }
  145. }
  146.  
  147. /*-------------------------------------------------------------------------*/
  148.     void TLSearcher::AddSolution(TLSolution *aSolution)
  149.  
  150. /*  Adds the given solution and updates the relevant statistics.
  151. ---------------------------------------------------------------------------*/
  152. {
  153.     TLX_ASSERT_PTR(aSolution);
  154.     mSolutions.Append(aSolution);
  155.  
  156.     mStats.mPrevious = mStats.mFinishSearch;
  157.     time(&mStats.mFinishSearch);
  158.  
  159.     TLX_LOG_ENTRY("Solution #%u (%ld nodes processed)", mSolutions.Count(),
  160.                   mStats.mProblemCount);
  161. }
  162.  
  163. /*-------------------------------------------------------------------------*/
  164.     void TLSearcher::ClearSolutions()
  165.  
  166. /*  Discards all current solutions and resets the related statistics.
  167. ---------------------------------------------------------------------------*/
  168. {
  169.     mSolutions.RemoveAll();
  170. }
  171.  
  172. /*-------------------------------------------------------------------------*/
  173.     size_t TLSearcher::CreateInitialProblem(TLProblemList &aList)
  174.  
  175. /*  Forwards the initial expansion message to the problem representation.
  176. ---------------------------------------------------------------------------*/
  177. {
  178.     TLX_TRACE(TLX, (50, "Searcher: CreateInitialProblem"));
  179.  
  180.     TLX_ASSERT_PTR(mProblemRep);
  181.     TLX_ASSERT(aList.IsEmpty());
  182.  
  183.     size_t count = mProblemRep->CreateInitialProblem(aList);
  184.  
  185.     if (MustSend(seInitial))
  186.         SendEvent(TLSearchMonitor::Event(seInitial, (uint32)count));
  187.     return count;
  188. }
  189.  
  190. /*-------------------------------------------------------------------------*/
  191.     void TLSearcher::CreateSolution(TLProblemState *aProblem)
  192.  
  193. /*  Asks the problem representation to create a solution based on the given
  194.     subproblem, and calls AddSolution() to store the resulting object.
  195. ---------------------------------------------------------------------------*/
  196. {
  197.     TLX_TRACE(TLX, (50, "Searcher: CreateSolution"));
  198.  
  199.     // We only create a solution if the desired number of solutions has not
  200.     // yet been reached.
  201.  
  202.     if (mSolutions.Count() >= mStats.mMaxSol)
  203.         return;
  204.  
  205.   #ifdef _TLXDBG
  206.     TLX_ASSERT_PTR(aProblem);
  207.     TLX_ASSERT_PTR(mProblemRep);
  208.  
  209.     TLSolution *sol = mProblemRep->CreateSolution(aProblem);
  210.     TLX_ASSERT_PTR(sol);
  211.  
  212.     AddSolution(sol);
  213.   #else
  214.     AddSolution(mProblemRep->CreateSolution(aProblem));
  215.   #endif
  216.  
  217.     if (MustSend(seSolution))
  218.         SendEvent(TLSearchMonitor::Event(seSolution,
  219.                   (uint32)mSolutions.Count(), aProblem));
  220. }
  221.  
  222. /*-------------------------------------------------------------------------*/
  223.     void TLSearcher::DeregisterProblemRep()
  224.  
  225. /*  Deregisters the searcher with the problem representation, and vice versa.
  226. ---------------------------------------------------------------------------*/
  227. {
  228.     TLX_ASSERT_PTR(mProblemRep);
  229.     TLX_ASSERT(mProblemRep->mSearcher == this);
  230.  
  231.     mProblemRep->mSearcher = mPrevSearcher;
  232.     mPrevSearcher          = 0;
  233.     mProblemRep            = 0;
  234. }
  235.  
  236. /*-------------------------------------------------------------------------*/
  237.     void TLSearcher::DeregisterMonitor(TLSearchMonitor *aMon)
  238.  
  239. /*  Removes the given monitor from the list of search monitors.
  240. ---------------------------------------------------------------------------*/
  241. {
  242.     TLX_ASSERT_PTR(aMon);
  243.     for (index_t i = mMonitors.Mini(); i <= mMonitors.Maxi(); i++)
  244.     {
  245.         if (mMonitors.PeekAt(i).mMonitor == aMon)
  246.         {
  247.             mMonitors.RemoveAt(i);
  248.             UpdateEventMask();
  249.             return;
  250.         }
  251.     }
  252.     TLX_TRACE_WARN(TLX, ("Requested monitor not found"));
  253. }
  254.  
  255. /*-------------------------------------------------------------------------*/
  256.     bool TLSearcher::EnableMonitors(bool aFlag)
  257.  
  258. /*  Enables or disables the sending of events to the search monitors. If
  259.     the monitors are disabled, no events will besent, regardless of the
  260.     individual event settings.
  261.  
  262.     The function returns the previous setting of the flag.
  263. ---------------------------------------------------------------------------*/
  264. {
  265.     bool oldflag = mMonEnabled;
  266.     mMonEnabled  = aFlag;
  267.     return oldflag;
  268. }
  269.  
  270. /*-------------------------------------------------------------------------*/
  271.     void TLSearcher::EnterState(TLProblemState *aProblem)
  272.  
  273. /*  Signals the start of the processing of a given subproblem.
  274. ---------------------------------------------------------------------------*/
  275. {
  276.     TLX_TRACE(TLX, (50, "Searcher: EnterState"));
  277.  
  278.     TLX_ASSERT_PTR(aProblem);
  279.     TLX_ASSERT_PTR(mProblemRep);
  280.     TLX_ASSERT(!aProblem->mIsProcessed);
  281.  
  282.     mStats.mProblemCount++;
  283.     mStats.mDepth++;
  284.  
  285.     if ((mStats.mProblemCount % 1000) == 0)
  286.         cerr << "\rProcessed " << mStats.mProblemCount << " problems (" <<
  287.              mSolutions.Count() << ")...";
  288.  
  289.     mProblemRep->EnterState(aProblem);
  290.  
  291.     if (MustSend(seEnter))
  292.         SendEvent(TLSearchMonitor::Event(seEnter, (int32)mStats.mDepth,
  293.                   aProblem));
  294. }
  295.  
  296. /*-------------------------------------------------------------------------*/
  297.     size_t TLSearcher::GenerateBranches(
  298.         TLProblemState *        aProblem,
  299.         TLProblemList &         aList)
  300.  
  301. /*  Forwards the decompose message to the problem representation.
  302. ---------------------------------------------------------------------------*/
  303. {
  304.     TLX_TRACE(TLX, (50, "Searcher: GenerateBranches"));
  305.  
  306.     TLX_ASSERT_PTR(aProblem);
  307.     TLX_ASSERT_PTR(mProblemRep);
  308.  
  309.     size_t count = mProblemRep->GenerateBranches(aProblem, aList);
  310.  
  311.     if (MustSend(seBranch))
  312.         SendEvent(TLSearchMonitor::Event(seBranch, (uint32)count, aProblem));
  313.  
  314.     return count;
  315. }
  316.  
  317. /*-------------------------------------------------------------------------*/
  318.     void TLSearcher::LeaveState(TLProblemState *aProblem, bool aUndo)
  319.  
  320. /*  Signals the end of the processing of a given subproblem. If 'aUndo' is
  321.     true, the problem representation is informed; else it is not.
  322.  
  323.     In any case, a few searcher statistics are updated.
  324. ---------------------------------------------------------------------------*/
  325. {
  326.     TLX_TRACE(TLX, (50, "Searcher: LeaveState"));
  327.  
  328.     TLX_ASSERT_PTR(aProblem);
  329.     TLX_ASSERT_PTR(mProblemRep);
  330.     TLX_ASSERT(aProblem->mIsProcessed);
  331.  
  332.     if (aUndo) mProblemRep->LeaveState(aProblem);
  333.  
  334.     mStats.mBTCount++;
  335.     mStats.mDepth--;
  336.  
  337.     if (MustSend(seLeave))
  338.         SendEvent(TLSearchMonitor::Event(seLeave,
  339.                   (int32)mStats.mDepth, aProblem));
  340. }
  341.  
  342. /*-------------------------------------------------------------------------*/
  343.     void TLSearcher::PostProcess()
  344.  
  345. /*  Performs whatever postprocessing is necessary after the search process
  346.     has finished. The default implementation registers the stop time of the
  347.     search, reports the search statistics, and gives the problem representation an
  348.     opportunity to do its own postprocessing.
  349.  
  350.     If you override this function, you should call it in the overridden
  351.     version, probably after doing your own postprocessing.
  352. ---------------------------------------------------------------------------*/
  353. {
  354.     TLX_TRACE(TLX, (50, "Searcher: PostProcess"));
  355.  
  356.     TLX_ASSERT_PTR(mProblemRep);
  357.  
  358.     // Register end of search time, and announce completion.
  359.  
  360.     time(&mStats.mFinishSearch);
  361.     TLX_LOG_ENTRY("Search process finished");
  362.  
  363.     // Give the problem representation a chance to do postprocessing.
  364.  
  365.     mProblemRep->PostProcess();
  366.     time(&mStats.mFinish);
  367.     TLX_LOG_ENTRY("Postprocesssing finished");
  368.  
  369.     if (MustSend(sePostProcess))
  370.         SendEvent(TLSearchMonitor::Event(sePostProcess));
  371.  
  372.     ReportStats();              // Print statistics
  373.     ReportSolutions();          // Print solutions
  374. }
  375.  
  376. /*-------------------------------------------------------------------------*/
  377.     bool TLSearcher::PreProcess()
  378.  
  379. /*  Performs whatever preprocessing is necessary before the search process
  380.     is started. The default implementation resets all statistics, records
  381.     the start time, and gives the problem representation an opportunity to perform its
  382.     own preprocessing.
  383.  
  384.     If you override this function, you should call it in the overridden
  385.     version, probably before doing your own preprocessing.
  386. ---------------------------------------------------------------------------*/
  387. {
  388.     TLX_TRACE(TLX, (50, "Searcher: PreProcess"));
  389.  
  390.     TLX_ASSERT_PTR(mProblemRep);
  391.  
  392.     // Discard previous solutions (if any)
  393.  
  394.     ClearSolutions();
  395.  
  396.     // Reset statistics
  397.  
  398.     mStats.mBTCount      =
  399.     mStats.mProblemCount = 0;
  400.     mStats.mDepth        = 0;
  401.  
  402.     // Give the problem representation a chance to do preprocessing.
  403.  
  404.     TLX_LOG_ENTRY("Preprocessing started");
  405.  
  406.     time(&mStats.mStart);
  407.     if (!mProblemRep->PreProcess())
  408.     {
  409.         TLX_TRACE_INFO(TLX, ("Preprocessing failed; search aborted"));
  410.         return false;
  411.     }
  412.  
  413.     if (MustSend(sePreProcess))
  414.       #ifdef _NOBOOL
  415.         SendEvent(TLSearchMonitor::Event(sePreProcess, (int32)true));
  416.       #else
  417.         SendEvent(TLSearchMonitor::Event(sePreProcess, true));
  418.       #endif
  419.  
  420.     // Register the start time for the search, then announce start.
  421.  
  422.     time(&mStats.mStartSearch);
  423.     mStats.mPrevious     =
  424.     mStats.mFinishSearch = mStats.mStartSearch;
  425.  
  426.     TLX_LOG_ENTRY("Search process started");
  427.     return true;
  428. }
  429.  
  430. /*-------------------------------------------------------------------------*/
  431.     bool TLSearcher::Process(TLProblemState *aProblem)
  432.  
  433. /*  Forwards the processing message to the problem representation.
  434. ---------------------------------------------------------------------------*/
  435. {
  436.     TLX_TRACE(TLX, (50, "Searcher: Process"));
  437.  
  438.     TLX_ASSERT_PTR(aProblem);
  439.     TLX_ASSERT_PTR(mProblemRep);
  440.     TLX_ASSERT(!aProblem->mIsProcessed);
  441.  
  442.     bool result = mProblemRep->Process(aProblem);
  443.   #ifdef _TLXDBG
  444.     aProblem->mIsProcessed = true;
  445.   #endif
  446.  
  447.     if (MustSend(seProcess))
  448.       #ifdef _NOBOOL
  449.         SendEvent(TLSearchMonitor::Event(seProcess, (int32)result, aProblem));
  450.       #else
  451.         SendEvent(TLSearchMonitor::Event(seProcess, result, aProblem));
  452.       #endif
  453.     return result;
  454. }
  455.  
  456. /*-------------------------------------------------------------------------*/
  457.     void TLSearcher::RegisterMonitor(TLSearchMonitor *aMon)
  458.  
  459. /*  Registers a new search monitor with the given event mask.
  460. ---------------------------------------------------------------------------*/
  461. {
  462.     TLX_ASSERT_PTR(aMon);
  463.  
  464.     mMonitors.Append(MonitorEntry(aMon, aMon->DefaultEvents()));
  465.     mGlobalMask |= aMon->DefaultEvents();
  466. }
  467.  
  468. /*-------------------------------------------------------------------------*/
  469.     void TLSearcher::RegisterProblemRep(TLProblemRep *aRep)
  470.  
  471. /*  Registers the searcher with the problem representation, and vice versa.
  472. ---------------------------------------------------------------------------*/
  473. {
  474.     TLX_ASSERT_PTR(aRep);
  475.     TLX_ASSERT_NULL(mProblemRep);
  476.     TLX_ASSERT_NULL(mPrevSearcher);
  477.  
  478.     mProblemRep            = aRep;
  479.     mPrevSearcher          = mProblemRep->mSearcher;
  480.     mProblemRep->mSearcher = this;
  481. }
  482.  
  483. /*-------------------------------------------------------------------------*/
  484.     void TLSearcher::ReportProgress()
  485.  
  486. /*  Prints search progress statistics on stderr.
  487. ---------------------------------------------------------------------------*/
  488. {
  489.     fprintf(stderr, "Depth %4ld, %6lu problems, %6lu backtracks\r",
  490.             mStats.mDepth, mStats.mProblemCount, mStats.mBTCount);
  491. }
  492.  
  493. /*-------------------------------------------------------------------------*/
  494.     void TLSearcher::ReportSolutions()
  495.  
  496. /*  Prints all solution to the log stream.
  497. ---------------------------------------------------------------------------*/
  498. {
  499.     TLX_LOG_BEGIN << mSolutions.Count() << " solutions found";
  500.  
  501.     TLPtrSeqIter<TLSolution> iter(mSolutions);
  502.     for (int cnt = 0; iter.Next(); )
  503.     {
  504.         TLSolution *sol = iter.Peek();
  505.         TLX_ASSERT_PTR(sol);
  506.         TLX_LOG << "\n  Solution " << ++cnt << ": " << *sol;
  507.     }
  508.     TLX_LOG << TLX_LOG_END;
  509. }
  510.  
  511. /*-------------------------------------------------------------------------*/
  512.     void TLSearcher::ReportStats()
  513.  
  514. /*  Prints search statistics on stderr and the log output.
  515. ---------------------------------------------------------------------------*/
  516. {
  517.     fprintf(stderr, "Search process completed, %u solution(s)       \n",
  518.             mSolutions.Count());
  519.  
  520.     TLX_LOG_ENTRY("%lu problems tested, %lu backtracks, elapsed time %ld sec",
  521.                   mStats.mProblemCount, mStats.mBTCount,
  522.                   (mStats.mFinish - mStats.mStart));
  523.  
  524.     // ProblemRep statistics
  525.  
  526.     TLX_ASSERT_PTR(mProblemRep);
  527.     TLX_LOG_BEGIN << "ProblemRep: ";
  528.     mProblemRep->ReportStats(TLX_LOG);
  529.     TLX_LOG << TLX_LOG_END;
  530.  
  531.     // Search monitor information
  532.  
  533.     if (mMonEnabled && mMonitors.Count() > 0)
  534.     {
  535.         TLX_LOG_BEGIN << "Monitors: ";
  536.         for (index_t i = mMonitors.Mini(); i <= mMonitors.Maxi(); i++)
  537.         {
  538.             TLX_ASSERT_PTR(mMonitors.PeekAt(i).mMonitor);
  539.             mMonitors.PeekAt(i).mMonitor->PrintOn(TLX_LOG);
  540.         }
  541.         TLX_LOG << TLX_LOG_END;
  542.     }
  543. }
  544.  
  545. /*-------------------------------------------------------------------------*/
  546.     void TLSearcher::SendEvent(const TLSearchMonitor::Event &aEvent)
  547.  
  548. /*  Sends the event to all monitors that have the corresponding event in
  549.     their event mask.
  550. ---------------------------------------------------------------------------*/
  551. {
  552.     TLX_ASSERT(MustSend(aEvent.mCode));
  553.  
  554.     for (index_t i = mMonitors.Mini(); i <= mMonitors.Maxi(); i++)
  555.         if (mMonitors.PeekAt(i).mEventMask & aEvent.mCode)
  556.         {
  557.             TLX_ASSERT_PTR(mMonitors.PeekAt(i).mMonitor);
  558.             mMonitors.PeekAt(i).mMonitor->OnSearchEvent(this, aEvent);
  559.         }
  560. }
  561.  
  562. /*-------------------------------------------------------------------------*/
  563.     void TLSearcher::SetMonitorEvents(TLSearchMonitor *aMon, int aMask)
  564.  
  565. /*  Changes the event mask associated with the search monitor.
  566. ---------------------------------------------------------------------------*/
  567. {
  568.     TLX_ASSERT_PTR(aMon);
  569.  
  570.     for (index_t i = mMonitors.Mini(); i <= mMonitors.Maxi(); i++)
  571.     {
  572.         if (mMonitors.PeekAt(i).mMonitor == aMon)
  573.         {
  574.             mMonitors.PeekAt(i).mEventMask = aMask;
  575.             UpdateEventMask();
  576.             return;
  577.         }
  578.     }
  579.     TLX_TRACE_WARN(TLX, ("Requested monitor not found"));
  580. }
  581.  
  582. /*-------------------------------------------------------------------------*/
  583.     size_t TLSearcher::Solve(
  584.         TLProblemRep *  aRep,   // ProblemRep to be searched
  585.         size_t          maxsol  // Maximum # solutions to find
  586.     )
  587.  
  588. /*  Orchestrates the search process by performing the preprocessing, the
  589.     actual search, and the post processing. Returns number of solutions
  590.     found (up to the given maximum).
  591. ---------------------------------------------------------------------------*/
  592. {
  593.     TLX_ASSERT_PTR(aRep);
  594.  
  595.     mStats.mMaxSol = maxsol;
  596.     RegisterProblemRep(aRep);
  597.  
  598.     clock_t total_time = clock();
  599.     clock_t search_time = 0;
  600.     if (PreProcess())
  601.     {
  602.         search_time = clock();
  603.     Search();
  604.     search_time = clock() - search_time;
  605.         PostProcess();
  606.     }
  607.     total_time = clock() - total_time;
  608.     TLX_LOG_ENTRY("Total time = %.0f ms; search time = %.0f ms", 
  609.     (1000.0 * total_time) / CLOCKS_PER_SEC,
  610.     (1000.0 * search_time) / CLOCKS_PER_SEC);
  611.  
  612.     DeregisterProblemRep();
  613.     return mSolutions.Count();
  614. }
  615.  
  616. /*-------------------------------------------------------------------------*/
  617.     void TLSearcher::UpdateEventMask()
  618.  
  619. /*  Updates the global event mask by searching through all registered
  620.     monitors and combining their individual event masks.
  621. ---------------------------------------------------------------------------*/
  622. {
  623.     mGlobalMask = seNone;
  624.     for (index_t i = mMonitors.Mini(); i <= mMonitors.Maxi(); i++)
  625.         mGlobalMask |= mMonitors.PeekAt(i).mEventMask;
  626. }
  627.  
  628.