deba@2420: /* -*- C++ -*-
deba@2420: *
deba@2420: * This file is a part of LEMON, a generic C++ optimization library
deba@2420: *
alpar@2553: * Copyright (C) 2003-2008
deba@2420: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@2420: * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@2420: *
deba@2420: * Permission to use, modify and distribute this software is granted
deba@2420: * provided that this copyright notice appears in all copies. For
deba@2420: * precise terms see the accompanying LICENSE file.
deba@2420: *
deba@2420: * This software is provided "AS IS" with no warranty of any kind,
deba@2420: * express or implied, and with no claim as to its suitability for any
deba@2420: * purpose.
deba@2420: *
deba@2420: */
deba@2420:
deba@2420: /// \ingroup demos
deba@2420: /// \file
deba@2420: /// \brief Solver for SAT problems.
deba@2420: ///
deba@2420: /// This demo progam solves the SAT problem, i.e. the boolean
deba@2420: /// satisfiability problem. The problem in general case is
deba@2420: /// NP-complete.
deba@2420: ///
deba@2420: /// The program uses an integer linear program solver. A {0,
deba@2420: /// 1} variable is assigned to each boolean variable. The
deba@2420: /// disjunctions are converted to linear inequalities as each negation
deba@2420: /// is replaced with a substraction from one and each disjunction is
deba@2420: /// converted to addition. The generated linear expression should be
deba@2420: /// at least one.
deba@2420: ///
deba@2420: /// \include sat.cc
deba@2420:
deba@2420: #include
deba@2420: #include
deba@2420: #include
deba@2420: #include
deba@2420:
deba@2420: #include
deba@2420:
deba@2420: using namespace std;
deba@2420: using namespace lemon;
deba@2420:
deba@2420:
deba@2420: int main(int argc, const char *argv[]) {
deba@2420: if (argc != 2) {
deba@2420: std::cerr << "The SAT solver demo" << std::endl << std::endl;
deba@2420: std::cerr << "The parameter should be a filename" << std::endl;
deba@2420: std::cerr << "Each line of the file should contain a bool expression:"
deba@2420: << std::endl;
deba@2420: std::cerr << " [not] [or [not] ]..." << std::endl;
deba@2420: std::cerr << "The program prints a feasible solution if it exists"
deba@2420: << std::endl;
deba@2420: return -1;
deba@2420: }
deba@2420: ifstream is(argv[1]);
deba@2420:
deba@2420: Mip mip;
deba@2420: mip.max();
deba@2420: mip.obj(0);
deba@2420:
deba@2420: string line;
deba@2420: while (getline(is, line)) {
deba@2420: istringstream ls(line);
deba@2420:
deba@2420: Mip::Expr expr;
deba@2420:
deba@2420:
deba@2420: string op;
deba@2420: do {
deba@2420: string var;
deba@2420: bool neg = false;
deba@2420:
deba@2420: ls >> var;
deba@2420: if (var == "not") {
deba@2420: neg = true;
deba@2420: ls >> var;
deba@2420: }
deba@2420:
deba@2420: Mip::Col col = mip.colByName(var);
deba@2420:
deba@2420: if (col == INVALID) {
deba@2420: col = mip.addCol();
deba@2420: mip.colName(col, var);
deba@2420: mip.colLowerBound(col, 0);
deba@2420: mip.colUpperBound(col, 1);
deba@2420: mip.integer(col, true);
deba@2420: }
deba@2420:
deba@2420: expr += (neg ? 1 - col : col);
deba@2420:
deba@2420: } while (ls >> op && op == "or");
deba@2420: if (ls) {
deba@2420: std::cerr << "Wrong bool expression" << std::endl;
deba@2420: return -1;
deba@2420: }
deba@2420: mip.addRow(expr >= 1);
deba@2420: }
deba@2420:
deba@2420: mip.solve();
deba@2420:
deba@2420: if (mip.mipStatus() == Mip::OPTIMAL) {
deba@2420: for (Mip::ColIt it(mip); it != INVALID; ++it) {
deba@2420: std::cout << mip.colName(it) << " = "
deba@2420: << (mip.primal(it) == 1 ? "true" : "false")
deba@2420: << std::endl;
deba@2420: }
deba@2420: } else {
deba@2420: std::cout << "There is no feasible solution." << std::endl;
deba@2420: }
deba@2420:
deba@2420: return 0;
deba@2420: }