/*******************************************************************\

Module:

Author: Georg Weissenbacher, georg.weissenbacher@inf.ethz.ch

\*******************************************************************/

#include <assert.h>

#include <i2string.h>

#include <Solver.h>

#include "sat_minimizer.h"

/*******************************************************************\

Function: satcheck_minimizert::prop_solve

  Inputs: a list of constraints (literals)

 Outputs:

 Purpose: Call Minisat solver with constraints

\*******************************************************************/

propt::resultt satcheck_minimizert::prop_solve(
  const std::list<literalt> &constraints)
{
  #ifdef SATCHECK_MINISAT
  {
    std::string msg=
      i2string(_no_literals)+" variables, "+
      i2string(solver->nClauses())+" clauses, "+
      i2string(constraints.size())+" constraints";
    messaget::status(msg);
  }
  
  if(solver->okay())
  {
    unsigned i=0;

    vec<Lit> c;
    c.growTo (constraints.size());

    for (std::list<literalt>::const_iterator it = constraints.begin();
         it != constraints.end (); it++)
    {
      const literalt &lit = *it;
      c[i]=Lit(lit.var_no(), lit.sign());
      i++;
    }

    solver->simplifyDB ();

    if (solver->solve(c))
      return propt::P_SATISFIABLE;
  }

  return propt::P_UNSATISFIABLE;
  #else
  return propt::P_ERROR;
  #endif
}

/*******************************************************************\

Function: satcheck_minimizert::minimize

  Inputs: 

 Outputs:

 Purpose: 

\*******************************************************************/

bool bv_minimizing_dect::minimize(const minimization_listt &symbols)
{
  #ifdef SATCHECK_MINISAT
  std::list<literalt> constraints;

  for(minimization_listt::const_iterator l_it=symbols.begin();
      l_it!=symbols.end();
      l_it++)
    {
      unsigned width;
      unsigned result = 0;

      const exprt &symbol = *l_it;

      status ("Minimizing... ");

      // FIXME: be more gener[ous|al] here!
      assert (symbol.type().id()=="unsignedbv");

      boolbv_get_width (symbol.type(), width);
      
      for (unsigned i = width; i > 0; i--)
        {
          literalt lit;
          #if 0
          std::cout << "SYMBOL: " << symbol << std::endl;
          #endif
          literal (symbol, i-1, lit);
          literalt nlit = satcheck.lnot (lit);
          constraints.push_back (nlit);

          if (satcheck.l_get(lit)==tvt(false))
            continue;

          // call Minisat with constraints
          if (satcheck.prop_solve (constraints) == propt::P_UNSATISFIABLE)
            {
              // change constraint to 1
              constraints.back().swap (lit);
              result |= 1 << (i-1);
              // make sure the model is reconstructed
              assert (satcheck.prop_solve (constraints) != 
                      propt::P_UNSATISFIABLE);
            }
        }
      status(symbol.get_string("identifier")+" = "+i2string(result));
    }
  return true;
  #else
  return false;
  #endif
}


