// -*- coding: utf-8 -*- // Copyright (C) 2013 Laboratoire de Recherche et Développement // de l'Epita. // // This file is part of Spot, a model checking library. // // Spot is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 3 of the License, or // (at your option) any later version. // // Spot is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public // License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #pragma once #include #include #include #include #include #include struct PicoSAT; // forward namespace spot { class printable; /// \brief Interface with a given sat solver. /// /// When created, it checks if SPOT_SATSOLVER env var is set. If so, /// its value is parsed and saved internally. The env variable musb be set /// like this: " [its_options] %I > %O" /// where %I and %O are replaced by input and output files. /// /// The run method permits of course to run the given sat solver. class satsolver_command: formater { private: const char* satsolver; public: satsolver_command(); /// \brief Return true if a satsolver is given, false otherwise. bool command_given(); /// \brief Run the given satsolver. int run(printable* in, printable* out); }; /// \brief Interface with a SAT solver. /// /// This class provides the necessary functions to add clauses, comments. /// Depending on SPOT_SATSOLVER, it will use either picosat solver (default) /// or the given satsolver. /// /// Now that spot is distributed with a satsolver (PicoSAT), it is used by /// default. But another satsolver can be configured via the /// SPOT_SATSOLVER environment variable. It must be set following /// this: "satsolver [options] %I > %O" /// where %I and %O are replaced by input and output files. class SPOT_API satsolver { public: /// \brief Construct the sat solver and itinialize variables. /// If no satsolver is provided through SPOT_SATSOLVER env var, a /// distributed version of PicoSAT will be used. satsolver(); ~satsolver(); /// \brief Adjust the number of variables used in the cnf formula. void adjust_nvars(int nvars); /// \brief Declare the number of vars reserved for assumptions. void set_nassumptions_vars(int nassumptions_vars); /// \brief Add a list of lit. to the current clause. void add(std::initializer_list values); /// \brief Add a single lit. to the current clause. void add(int v); /// \breif Get the current number of clauses. int get_nb_clauses() const; /// \brief Get the current number of variables. int get_nb_vars() const; /// \brief Returns std::pair; std::pair stats(); /// \brief Add a comment. /// It should be used only in debug mode after providing a satsolver. template void comment_rec(T single); /// \brief Add comments. /// It should be used only in debug mode after providing a satsolver. template void comment_rec(T first, Args... args); /// \brief Add a comment. It will start with "c ". /// It should be used only in debug mode after providing a satsolver. template void comment(T single); /// \brief Add comments. It will start with "c ". /// It should be used only in debug mode after providing a satsolver. template void comment(T first, Args... args); /// \brief Assume a litteral value. /// Must only be used with distributed picolib. void assume(int lit); typedef std::vector solution; typedef std::pair solution_pair; /// \brief Return std::vector. solution_pair get_solution(); private: // methods /// \brief Initialize cnf streams attributes. void start(); /// \brief End the current clause and increment the counter. void end_clause(); /// \brief Extract the solution of Picosat output. /// Must be called only if SPOT_SATSOLVER env variable is not set. satsolver::solution picosat_get_sol(int res); /// \brief Extract the solution of a SAT solver output. satsolver::solution satsolver_get_sol(const char* filename); /// \brief Check if SPOT_XCNF env var is set. bool xcnf_mode(); private: // variables /// \brief A satsolver_command. Check if SPOT_SATSOLVER is given. satsolver_command cmd_; // cnf streams and associated clause counter. // The next 2 pointers will be != nullptr if SPOT_SATSOLVER is given. temporary_file* cnf_tmp_; std::ostream* cnf_stream_; int nclauses_; int nvars_; int nassumptions_vars_; // Surplus of vars (for 'assume' algorithm). /// \brief Number of solutions to obtain from the satsolver /// (without assuming litterals). int nsols_; /// \brief Picosat satsolver instance. PicoSAT* psat_; // The next 2 pointers will be initialized if SPOT_XCNF env var // is set. This recquires SPOT_SATSOLVER to be set as well. std::ofstream* xcnf_tmp_; std::ofstream* xcnf_stream_; std::string path_; }; /// \brief Extract the solution of a SAT solver output. SPOT_API std::vector satsolver_get_solution(const char* filename); } namespace spot { template void satsolver::comment_rec(T single) { if (!psat_) *cnf_stream_ << ' ' << single; } template void satsolver::comment_rec(T first, Args... args) { if (!psat_) { *cnf_stream_ << ' ' << first; comment_rec(args...); } } template void satsolver::comment(T single) { if (!psat_) *cnf_stream_ << "c " << single; } template void satsolver::comment(T first, Args... args) { if (!psat_) { *cnf_stream_ << "c " << first; comment_rec(args...); } } }