/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* * Main authors: * Christian Schulte * * Copyright: * Christian Schulte, 2004 * * Last modified: * $Date: 2011-06-16 18:27:32 +1000 (Thu, 16 Jun 2011) $ by $Author: tack $ * $Revision: 12052 $ * * This file is part of Gecode, the generic constraint * development environment: * http://www.gecode.org * * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include #include #ifndef GECODE_THREADS_WINDOWS #include #endif namespace Gecode { namespace Driver { /** * \brief Stop object based on nodes, failures, and time * */ class Cutoff : public Search::Stop { private: Search::NodeStop* ns; ///< Used node stop object Search::FailStop* fs; ///< Used fail stop object Search::TimeStop* ts; ///< Used time stop object GECODE_DRIVER_EXPORT static bool sigint; ///< Whether search was interrupted using Ctrl-C /// Initialize stop object Cutoff(unsigned int node, unsigned int fail, unsigned int time) : ns((node > 0) ? new Search::NodeStop(node) : NULL), fs((fail > 0) ? new Search::FailStop(fail) : NULL), ts((time > 0) ? new Search::TimeStop(time) : NULL) { sigint = false; } public: /// Reason why search has been stopped enum { SR_NODE = 1 << 0, ///< Node limit reached SR_FAIL = 1 << 1, ///< Fail limit reached SR_TIME = 1 << 2, ///< Time limit reached SR_INT = 1 << 3 ///< Interrupted by user }; /// Test whether search must be stopped virtual bool stop(const Search::Statistics& s, const Search::Options& o) { return sigint || ((ns != NULL) && ns->stop(s,o)) || ((fs != NULL) && fs->stop(s,o)) || ((ts != NULL) && ts->stop(s,o)); } /// Report reason why search has been stopped int reason(const Search::Statistics& s, const Search::Options& o) { return (((ns != NULL) && ns->stop(s,o)) ? SR_NODE : 0) | (((fs != NULL) && fs->stop(s,o)) ? SR_FAIL : 0) | (((ts != NULL) && ts->stop(s,o)) ? SR_TIME : 0) | (sigint ? SR_INT : 0); } /// Create appropriate stop-object static Search::Stop* create(unsigned int node, unsigned int fail, unsigned int time, bool intr) { if ( (!intr) && (node == 0) && (fail == 0) && (time == 0)) return NULL; else return new Cutoff(node,fail,time); } #ifdef GECODE_THREADS_WINDOWS /// Handler for catching Ctrl-C static BOOL interrupt(DWORD t) { if (t == CTRL_C_EVENT) { sigint = true; installCtrlHandler(false,true); return true; } return false; } #else /// Handler for catching Ctrl-C static void interrupt(int) { sigint = true; installCtrlHandler(false,true); } #endif /// Install handler for catching Ctrl-C static void installCtrlHandler(bool install, bool force=false) { if (force || !sigint) { #ifdef GECODE_THREADS_WINDOWS SetConsoleCtrlHandler( (PHANDLER_ROUTINE) interrupt, install); #else std::signal(SIGINT, install ? interrupt : SIG_DFL); #endif } } /// Destructor ~Cutoff(void) { delete ns; delete fs; delete ts; } }; /** * \brief Get time since start of timer and print user friendly time * information. */ GECODE_DRIVER_EXPORT void stop(Support::Timer& t, std::ostream& os); /** * \brief Compute arithmetic mean of \a n elements in \a t */ GECODE_DRIVER_EXPORT double am(double t[], int n); /** * \brief Compute deviation of \a n elements in \a t */ GECODE_DRIVER_EXPORT double dev(double t[], int n); #ifdef GECODE_HAS_GIST /** * \brief Traits class for search engines */ template class GistEngine { }; /// Specialization for DFS template class GistEngine > { public: static void explore(S* root, const Gist::Options& opt) { (void) Gist::dfs(root, opt); } }; /// Specialization for BAB template class GistEngine > { public: static void explore(S* root, const Gist::Options& opt) { (void) Gist::bab(root, opt); } }; /// Specialization for Restart template class GistEngine > { public: static void explore(S* root, const Gist::Options& opt) { (void) Gist::bab(root, opt); } }; #endif template template class Engine, class Options> void ScriptBase::run(const Options& o) { using namespace std; try { switch (o.mode()) { case SM_GIST: #ifdef GECODE_HAS_GIST { Gist::Print