/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* * Main authors: * Guido Tack */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #pragma once #include #include #include #include #include #include #include #include #include namespace MiniZinc { /// An abstract SI class SolverInstanceBase { protected: Env& _env; Solns2Out* _pS2Out = nullptr; std::ostream& _log; public: /// Options base class /// A sub-class will be provided by each concrete SolverInstance class Options { public: bool verbose = false; bool printStatistics = false; }; protected: std::unique_ptr _options; typedef SolverInstance::Status Status; typedef SolverInstance::StatusReason StatusReason; Status _status; StatusReason _statusReason; public: SolverInstanceBase(Env& env, std::ostream& log, Options* options) : _env(env), _log(log), _options(options), _status(SolverInstance::UNKNOWN), _statusReason(SolverInstance::SR_OK) {} virtual ~SolverInstanceBase() {} /// Set/get the environment: virtual Env* getEnv() const { assert(&_env); return &_env; } virtual Env& env() const { return *getEnv(); } Solns2Out* getSolns2Out() const { assert(_pS2Out); return _pS2Out; } void setSolns2Out(Solns2Out* s2o) { _pS2Out = s2o; } virtual void printSolution(); // virtual void printSolution(ostream& ); // deprecated /// print statistics in form of comments virtual void printStatistics() {} virtual void printStatisticsLine(bool fLegend = false) {} /// find the next solution virtual Status next() = 0; /// generate the solver-instance-representation from the flatzinc model virtual void processFlatZinc() = 0; /// clean up input model & flatzinc void cleanupForNonincrementalSolving() const { getEnv()->envi().cleanupExceptOutput(); } /// solve the problem instance (according to the solve specification in the flatzinc model) virtual Status solve(); /// return reason for status given by solve virtual StatusReason reason() { return _statusReason; } virtual Status status() { return _status; } void setStatus(Status s) { _status = s; } Options* options() { return _options.get(); } /// reset the model to its core (removing temporary cts) and the solver to the root node of the /// search static void reset(); /// reset the solver to the root node of the search TODO: difference between reset() and /// resetSolver()? virtual void resetSolver() = 0; /// reset the solver and add temporary constraints given by the iterator virtual void resetWithConstraints(Model::iterator begin, Model::iterator end); /// add permanent constraints given by the iterator to the solver instance virtual void processPermanentConstraints(Model::iterator begin, Model::iterator end); protected: /// flatten the search annotations, pushing them into the vector \a out void flattenSearchAnnotations(const Annotation& ann, std::vector& out); void flattenMultipleObjectives(const Annotation& ann, MultipleObjectives& mo) const; static void flattenMultObjComponent(const Annotation& ann, MultipleObjectives::Objective& obj); private: SolverInstanceBase(const SolverInstanceBase&); SolverInstanceBase& operator=(const SolverInstanceBase&); }; /// This implements a solver which is linked and returns its solution by assignSolutionToOutput() class SolverInstanceBase2 : public SolverInstanceBase { protected: virtual Expression* getSolutionValue(Id* id) = 0; public: /// Assign output for all vars: need public for callbacks // Default impl requires a Solns2Out object set up virtual void assignSolutionToOutput(); /// Print solution to setup dest void printSolution() override; protected: std::vector _varsWithOutput; // this is to extract fzn vars. Identical to output()? TODO public: SolverInstanceBase2(Env& env, std::ostream& log, SolverInstanceBase::Options* opt) : SolverInstanceBase(env, log, opt) {} }; typedef void (*poster)(SolverInstanceBase&, const Call* call); class Registry { protected: ManagedASTStringMap _registry; SolverInstanceBase& _base; public: Registry(SolverInstanceBase& base) : _base(base) {} void add(ASTString name, poster p); void add(const std::string& name, poster p); void post(Call* c); void cleanup() { _registry.clear(); } }; /// Finally, this class also stores a mapping VarDecl->SolverVar and a constraint transformer /// It is a template holding parameterized VarId and Statistics, so cannot have members defined in a /// .cpp template class SolverInstanceImpl : public SolverInstanceBase2 { public: typedef typename Solver::Variable VarId; protected: IdMap _variableMap; // this to find solver's variables given an Id Registry _constraintRegistry; public: SolverInstanceImpl(Env& env, std::ostream& log, SolverInstanceBase::Options* opt) : SolverInstanceBase2(env, log, opt), _constraintRegistry(*this) {} }; } // namespace MiniZinc