| 
deba@2420
 | 
     1  | 
/* -*- C++ -*-
  | 
| 
deba@2420
 | 
     2  | 
 *
  | 
| 
deba@2420
 | 
     3  | 
 * This file is a part of LEMON, a generic C++ optimization library
  | 
| 
deba@2420
 | 
     4  | 
 *
  | 
| 
deba@2420
 | 
     5  | 
 * Copyright (C) 2003-2007
  | 
| 
deba@2420
 | 
     6  | 
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
  | 
| 
deba@2420
 | 
     7  | 
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
  | 
| 
deba@2420
 | 
     8  | 
 *
  | 
| 
deba@2420
 | 
     9  | 
 * Permission to use, modify and distribute this software is granted
  | 
| 
deba@2420
 | 
    10  | 
 * provided that this copyright notice appears in all copies. For
  | 
| 
deba@2420
 | 
    11  | 
 * precise terms see the accompanying LICENSE file.
  | 
| 
deba@2420
 | 
    12  | 
 *
  | 
| 
deba@2420
 | 
    13  | 
 * This software is provided "AS IS" with no warranty of any kind,
  | 
| 
deba@2420
 | 
    14  | 
 * express or implied, and with no claim as to its suitability for any
  | 
| 
deba@2420
 | 
    15  | 
 * purpose.
  | 
| 
deba@2420
 | 
    16  | 
 *
  | 
| 
deba@2420
 | 
    17  | 
 */
  | 
| 
deba@2420
 | 
    18  | 
  | 
| 
deba@2420
 | 
    19  | 
/// \ingroup demos
  | 
| 
deba@2420
 | 
    20  | 
/// \file
  | 
| 
deba@2420
 | 
    21  | 
/// \brief Solver for SAT-2 problems.
  | 
| 
deba@2420
 | 
    22  | 
///
  | 
| 
deba@2420
 | 
    23  | 
/// This demo progam solves the SAT-2 problem, i.e. the boolean
  | 
| 
deba@2420
 | 
    24  | 
/// satisfiability problem where each disjuction consists at most 2
  | 
| 
deba@2420
 | 
    25  | 
/// terms.
  | 
| 
deba@2420
 | 
    26  | 
///
  | 
| 
deba@2420
 | 
    27  | 
/// The program generates a graph from the boolean expression. Two
  | 
| 
deba@2420
 | 
    28  | 
/// nodes are assigned to each boolean variable, an <tt>x</tt> and a
  | 
| 
deba@2420
 | 
    29  | 
/// <tt>not x</tt> nodes. If there is an <tt>x or y</tt> disjunction
  | 
| 
deba@2420
 | 
    30  | 
/// in the formula, then the <tt>not x => y</tt> and the <tt>not y =>
  | 
| 
deba@2420
 | 
    31  | 
/// x</tt> edges are added to the graph. If there is a single
  | 
| 
deba@2420
 | 
    32  | 
/// <tt>x</tt> term disjunction in the formula then the <tt>not x
  | 
| 
deba@2420
 | 
    33  | 
/// =>x</tt> edge is added to the graph.
  | 
| 
deba@2420
 | 
    34  | 
///
  | 
| 
deba@2420
 | 
    35  | 
/// The boolean formula could be satified if and only if the
  | 
| 
deba@2420
 | 
    36  | 
/// <tt>x</tt> and <tt>not x</tt> nodes are in different strongly connected
  | 
| 
deba@2420
 | 
    37  | 
/// components. A feasible solution could be get from the current
  | 
| 
deba@2420
 | 
    38  | 
/// component numbering.
  | 
| 
deba@2420
 | 
    39  | 
///
  | 
| 
deba@2420
 | 
    40  | 
/// \include sat-2.cc
  | 
| 
deba@2420
 | 
    41  | 
  | 
| 
deba@2420
 | 
    42  | 
#include <iostream>
  | 
| 
deba@2420
 | 
    43  | 
#include <fstream>
  | 
| 
deba@2420
 | 
    44  | 
#include <sstream>
  | 
| 
deba@2420
 | 
    45  | 
#include <string>
  | 
| 
deba@2420
 | 
    46  | 
#include <map>
  | 
| 
deba@2420
 | 
    47  | 
  | 
| 
deba@2420
 | 
    48  | 
#include <lemon/smart_graph.h>
  | 
| 
deba@2420
 | 
    49  | 
#include <lemon/topology.h>
  | 
| 
deba@2420
 | 
    50  | 
  | 
| 
deba@2420
 | 
    51  | 
using namespace std;
  | 
| 
deba@2420
 | 
    52  | 
using namespace lemon;
  | 
| 
deba@2420
 | 
    53  | 
  | 
| 
deba@2420
 | 
    54  | 
  | 
| 
deba@2420
 | 
    55  | 
int main(int argc, const char *argv[]) {
 | 
| 
deba@2420
 | 
    56  | 
  if (argc != 2) {
 | 
| 
deba@2420
 | 
    57  | 
    std::cerr << "The SAT-2 solver demo" << std::endl << std::endl;
  | 
| 
deba@2420
 | 
    58  | 
    std::cerr << "The  parameter should be a filename" << std::endl;
  | 
| 
deba@2420
 | 
    59  | 
    std::cerr << "Each line of the file should contain a bool expression:" 
  | 
| 
deba@2420
 | 
    60  | 
              << std::endl;
  | 
| 
deba@2420
 | 
    61  | 
    std::cerr << "  [not] <variable> [or [not] <variable>]" << std::endl;
  | 
| 
deba@2420
 | 
    62  | 
    std::cerr << "The program prints a feasible solution if it exists" 
  | 
| 
deba@2420
 | 
    63  | 
              << std::endl;
  | 
| 
deba@2420
 | 
    64  | 
    return -1;
  | 
| 
deba@2420
 | 
    65  | 
  }
  | 
| 
deba@2420
 | 
    66  | 
  ifstream is(argv[1]);
  | 
| 
deba@2420
 | 
    67  | 
  | 
| 
deba@2420
 | 
    68  | 
  SmartGraph graph;
  | 
| 
deba@2420
 | 
    69  | 
  map<string, pair<SmartGraph::Node, SmartGraph::Node> > var;
  | 
| 
deba@2420
 | 
    70  | 
  | 
| 
deba@2420
 | 
    71  | 
  string line;
  | 
| 
deba@2420
 | 
    72  | 
  while (getline(is, line)) {
 | 
| 
deba@2420
 | 
    73  | 
    istringstream ls(line);
  | 
| 
deba@2420
 | 
    74  | 
    string var1, var2, op;
  | 
| 
deba@2420
 | 
    75  | 
    bool neg1 = false, neg2 = false;
  | 
| 
deba@2420
 | 
    76  | 
  | 
| 
deba@2420
 | 
    77  | 
    ls >> var1;
  | 
| 
deba@2420
 | 
    78  | 
    if (var1 == "not") {
 | 
| 
deba@2420
 | 
    79  | 
      neg1 = true;
  | 
| 
deba@2420
 | 
    80  | 
      ls >> var1;
  | 
| 
deba@2420
 | 
    81  | 
    }
  | 
| 
deba@2420
 | 
    82  | 
    if (ls >> op) {
 | 
| 
deba@2420
 | 
    83  | 
      if (op != "or") {
 | 
| 
deba@2420
 | 
    84  | 
        cerr << "Wrong bool expression" << std::endl;
  | 
| 
deba@2420
 | 
    85  | 
        return -1;
  | 
| 
deba@2420
 | 
    86  | 
      } else {
 | 
| 
deba@2420
 | 
    87  | 
        ls >> var2;
  | 
| 
deba@2420
 | 
    88  | 
        if (var2 == "not") {
 | 
| 
deba@2420
 | 
    89  | 
          neg2 = true;
  | 
| 
deba@2420
 | 
    90  | 
          ls >> var2;
  | 
| 
deba@2420
 | 
    91  | 
        }
  | 
| 
deba@2420
 | 
    92  | 
      }
  | 
| 
deba@2420
 | 
    93  | 
      if (ls >> op) {
 | 
| 
deba@2420
 | 
    94  | 
        cerr << "Wrong bool expression" << std::endl;
  | 
| 
deba@2420
 | 
    95  | 
        return -1;
  | 
| 
deba@2420
 | 
    96  | 
      }
  | 
| 
deba@2420
 | 
    97  | 
  | 
| 
deba@2420
 | 
    98  | 
      map<string, pair<SmartGraph::Node, SmartGraph::Node> >::iterator it1;
  | 
| 
deba@2420
 | 
    99  | 
      map<string, pair<SmartGraph::Node, SmartGraph::Node> >::iterator it2;    
  | 
| 
deba@2420
 | 
   100  | 
      it1 = var.find(var1);
  | 
| 
deba@2420
 | 
   101  | 
      if (it1 == var.end()) {
 | 
| 
deba@2420
 | 
   102  | 
        SmartGraph::Node node = graph.addNode();
  | 
| 
deba@2420
 | 
   103  | 
        SmartGraph::Node negNode = graph.addNode();
  | 
| 
deba@2420
 | 
   104  | 
        it1 = var.insert(make_pair(var1, make_pair(node, negNode))).first;
  | 
| 
deba@2420
 | 
   105  | 
      }
  | 
| 
deba@2420
 | 
   106  | 
  | 
| 
deba@2420
 | 
   107  | 
      it2 = var.find(var2);
  | 
| 
deba@2420
 | 
   108  | 
      if (it2 == var.end()) {
 | 
| 
deba@2420
 | 
   109  | 
        SmartGraph::Node node = graph.addNode();
  | 
| 
deba@2420
 | 
   110  | 
        SmartGraph::Node negNode = graph.addNode();
  | 
| 
deba@2420
 | 
   111  | 
        it2 = var.insert(make_pair(var2, make_pair(node, negNode))).first;
  | 
| 
deba@2420
 | 
   112  | 
      }
  | 
| 
deba@2420
 | 
   113  | 
  | 
| 
deba@2420
 | 
   114  | 
      graph.addEdge(neg1 ? it1->second.first : it1->second.second, 
  | 
| 
deba@2420
 | 
   115  | 
                    neg2 ? it2->second.second : it2->second.first);
  | 
| 
deba@2420
 | 
   116  | 
  | 
| 
deba@2420
 | 
   117  | 
      graph.addEdge(neg2 ? it2->second.first : it2->second.second, 
  | 
| 
deba@2420
 | 
   118  | 
                    neg1 ? it1->second.second : it1->second.first);
  | 
| 
deba@2420
 | 
   119  | 
    } else {
 | 
| 
deba@2420
 | 
   120  | 
  | 
| 
deba@2420
 | 
   121  | 
      map<string, pair<SmartGraph::Node, SmartGraph::Node> >::iterator it1;
  | 
| 
deba@2420
 | 
   122  | 
      it1 = var.find(var1);
  | 
| 
deba@2420
 | 
   123  | 
      if (it1 == var.end()) {
 | 
| 
deba@2420
 | 
   124  | 
        SmartGraph::Node node = graph.addNode();
  | 
| 
deba@2420
 | 
   125  | 
        SmartGraph::Node negNode = graph.addNode();
  | 
| 
deba@2420
 | 
   126  | 
        it1 = var.insert(make_pair(var1, make_pair(node, negNode))).first;
  | 
| 
deba@2420
 | 
   127  | 
      }
  | 
| 
deba@2420
 | 
   128  | 
      graph.addEdge(neg1 ? it1->second.first : it1->second.second, 
  | 
| 
deba@2420
 | 
   129  | 
                    neg1 ? it1->second.second : it1->second.first);
  | 
| 
deba@2420
 | 
   130  | 
      
  | 
| 
deba@2420
 | 
   131  | 
    }
  | 
| 
deba@2420
 | 
   132  | 
    
  | 
| 
deba@2420
 | 
   133  | 
  }
  | 
| 
deba@2420
 | 
   134  | 
  
  | 
| 
deba@2420
 | 
   135  | 
  SmartGraph::NodeMap<int> comp(graph);
  | 
| 
deba@2420
 | 
   136  | 
  | 
| 
deba@2420
 | 
   137  | 
  stronglyConnectedComponents(graph, comp); 
  | 
| 
deba@2420
 | 
   138  | 
  | 
| 
deba@2420
 | 
   139  | 
  for (map<string, pair<SmartGraph::Node, SmartGraph::Node> >::iterator
  | 
| 
deba@2420
 | 
   140  | 
         it = var.begin(); it != var.end(); ++it) {
 | 
| 
deba@2420
 | 
   141  | 
    if (comp[it->second.first] == comp[it->second.second]) {
 | 
| 
deba@2420
 | 
   142  | 
      std::cout << "There is no feasible solution." << std::endl;
  | 
| 
deba@2420
 | 
   143  | 
      return 0;
  | 
| 
deba@2420
 | 
   144  | 
    }
  | 
| 
deba@2420
 | 
   145  | 
  }
  | 
| 
deba@2420
 | 
   146  | 
  | 
| 
deba@2420
 | 
   147  | 
  for (map<string, pair<SmartGraph::Node, SmartGraph::Node> >::iterator
  | 
| 
deba@2420
 | 
   148  | 
         it = var.begin(); it != var.end(); ++it) {
 | 
| 
deba@2420
 | 
   149  | 
    if (comp[it->second.first] < comp[it->second.second]) {
 | 
| 
deba@2420
 | 
   150  | 
      std::cout << it->first << " = false " << std::endl;
  | 
| 
deba@2420
 | 
   151  | 
    } else {
 | 
| 
deba@2420
 | 
   152  | 
      std::cout << it->first << " = true " << std::endl;
  | 
| 
deba@2420
 | 
   153  | 
    }
  | 
| 
deba@2420
 | 
   154  | 
  }
  | 
| 
deba@2420
 | 
   155  | 
  
  | 
| 
deba@2420
 | 
   156  | 
  return 0;
  | 
| 
deba@2420
 | 
   157  | 
}
  |