singrdk/base/Applications/Benchmarks/sharpSAT/main.cs

700 lines
26 KiB
C#

///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections;
using System.Text;
using System.IO;
using SharpSAT;
//using Microsoft.Zap;
namespace SharpSATTest
{
public class SATSolverTests : SATCommon
{
/* a helper function */
static private string getToken(string [] tokens, ref int index)
{
for (; index < tokens.Length; )
{
++index;
if (tokens[index - 1] != String.Empty)
return tokens[index -1];
}
return null;
}
/* this demonstrate the structure interface */
static void test_structure_solver (string[] args)
{
SATSolver solver = new SATSolver();
int a = solver.CreatePI();
int b = solver.CreatePI();
int c = solver.CreatePI();
//int d = solver.CreatePI();
int xor_a_b = solver.Xor(a, b);
int not_a = solver.Not(a);
int not_b = solver.Not(b);
int and_a_not_b = solver.And (a, not_b);
int and_b_not_a = solver.And (b, not_a);
int xor_a_b_p = solver.Or(and_a_not_b, and_b_not_a);
int miter = solver.Xor(xor_a_b, xor_a_b_p);
SATStatus r = solver.TestSAT(miter);
System.Console.WriteLine ("Test Right {0}", r.ToString());
int and_a_b = solver.And (a, b);
int xor_a_b_wrong = solver.Or (and_a_not_b, and_a_b);
int miter1 = solver.Xor(xor_a_b, xor_a_b_wrong);
r = solver.TestSAT(miter1);
System.Console.WriteLine ("Test Wrong {0}", r.ToString());
int and_a_b_c = solver.And (solver.And(a,b), c);
int flag = solver.AllocFlag ();
solver.MarkTransitiveFanins(and_a_b_c, flag);
for (int i=0, sz=solver.NumPI(); i< sz; ++i)
{
int node_id = solver.NthPI(i);
bool flagset = solver.IsNodeFlagSet (node_id, flag);
if (flagset)
System.Console.WriteLine ("PI {0} is in the transitive fanin", i);
else
System.Console.WriteLine ("PI {0} is NOT in the transitive fanin", i);
}
solver.ClearFlag(flag);
MyHashtable nameMap = new MyHashtable();
nameMap.Add(0, "PrimaryIn 0");
System.Console.WriteLine(solver.TreeToString(miter1, nameMap));
System.Console.WriteLine(solver.TreeToString(xor_a_b, nameMap));
System.Console.WriteLine ("Press Return...");
System.Console.ReadLine();
}
/* this demonstrate the clause interface, it reads in a CNF file and
* Solve it, just as a regular SAT solver should do */
static void test_clause_solver (string[] args)
{
SATSolver solver = new SATSolver();
// NB: on Singularity, args[0] is the exe image name
if (args.Length != 2)
{
System.Console.WriteLine ("Simple SAT Solver using the C# interface");
System.Console.WriteLine ("Usage: Solve CNF_file ");
return;
}
StreamReader input = null;
try
{
input = new StreamReader(args[1]);
}
catch(Exception e)
{
Console.WriteLine (e.ToString());
}
string line;
System.Console.WriteLine ("Solving {0}", args[1]);
while (true)
{
line = input.ReadLine();
if (line == null)
break;
string [] tokens = line.Split(new char[] {' ','\t'});
int index = 0;
string token = getToken (tokens, ref index);
if (token == "c")
continue;
if (token == "p")
{
token = getToken (tokens, ref index);
if (token != "cnf")
{
System.Console.WriteLine("Unrecognized Header");
return;
}
else
{
token = getToken (tokens, ref index);
solver.SetNumVariables (int.Parse(token));
continue;
}
}
else
{
ArrayList lits = new ArrayList();
while (token != null && int.Parse(token) != 0)
{
lits.Add (int.Parse(token));
token = getToken (tokens, ref index);
}
if (lits.Count> 0)
{
int [] clause = new int [lits.Count];
for (int k=0; k< lits.Count; ++k)
{
clause[k] = (int)lits[k];
if (clause[k] > 0)
clause[k] += clause[k];
else
clause[k] = 1 - clause[k] - clause[k];
}
solver.AddClause ( clause );
}
}
}
input.Close();
SATStatus result = solver.Solve();
if (result == SATStatus.SATISFIABLE)
{
System.Console.WriteLine ("SAT");
for (int i=1; i<= solver.GetNumVariables(); ++i)
{
if (solver.VariableValue(i)==1)
{
Console.Write ("{0} ", i);
}
else if (solver.VariableValue(i)==0)
{
Console.Write ("-{0} ", i);
}
else
{
Console.Write ("({0}) ", i);
}
if (i % 10 == 0)
{
Console.WriteLine ("");
}
}
}
else if (result == SATStatus.UNSATISFIABLE)
System.Console.WriteLine ("UNSAT");
System.Console.WriteLine ("Num Variables {0}", solver.num_variables() );
System.Console.WriteLine ("Num Orig. Clauses {0}", solver.stats.num_orig_clauses );
System.Console.WriteLine ("Num Learned Clauses {0}", solver.stats.num_learned_clauses);
System.Console.WriteLine ("Num Learned Literals {0}", solver.stats.num_learned_literals);
System.Console.WriteLine ("Num Garbage Collection {0}", solver.stats.num_garbage_collections);
System.Console.WriteLine ("Num Deleted Clauses {0}", solver.stats.num_deleted_clauses );
System.Console.WriteLine ("Num Deleted Literals {0}", solver.stats.num_deleted_literals );
System.Console.WriteLine ("Num Decisions {0}", solver.stats.num_decisions );
System.Console.WriteLine ("Num Backtracks {0}", solver.stats.num_backtracks );
System.Console.WriteLine ("Num Implications {0}", solver.stats.num_implications );
System.Console.WriteLine ("Total Runtime {0}", solver.stats.total_cpu_time );
System.Console.WriteLine ("Instance is {0}", SATCommon.StatusToString(result));
}
public static void log_execution(string [] args)
{
SATSolver solver = new SATSolver();
if (args.Length != 1)
{
System.Console.WriteLine ("Simple SAT Solver using the C# interface");
System.Console.WriteLine ("Usage: Solve CNF_file ");
return;
}
FileInfo file = new FileInfo (args[0]);
StreamReader input = file.OpenText();
string line;
IntVector nodes = new IntVector(4);
while (true)
{
line = input.ReadLine();
if (line == null)
break;
string [] tokens = line.Split(new char[] {' ','\t'});
int index = 0;
string token = getToken (tokens, ref index);
int k = int.Parse (token);
token = getToken (tokens, ref index);
sharp_assert (token == "=");
token = getToken (tokens, ref index);
if (token == "INIT_VARS")
{
solver.SetNumVariables(k);
solver.ConvertVarsToPI();
nodes.resize ( k + k + 2);
for (int i=0; i < k + k + 2; ++i)
nodes[i] = i;
}
else if (token == "CONSTRAINT")
{
solver.Constraint(nodes[k]);
SATStatus status = solver.Solve();
if (status == SATStatus.UNSATISFIABLE)
Console.WriteLine("UNSAT");
else
Console.WriteLine("SAT");
}
else if (token == "PI")
{
continue;
}
else if (token == "CL")
{
IntVector lits = new IntVector(4);
token = getToken(tokens, ref index);
while ( token != null )
{
lits.push_back (int.Parse(token));
token = getToken(tokens, ref index);
}
solver.AddClause(lits.ToArray());
}
else if (token == "AND")
{
token = getToken (tokens, ref index);
int i1 = int.Parse (token);
token = getToken (tokens, ref index);
int i2 = int.Parse (token);
int r = solver.And (nodes[i1], nodes[i2]);
if (nodes.size() < k + 2)
nodes.resize (k + 2);
nodes[k] = r;
nodes [k ^ 1] = (r^1);
}
else if (token == "XOR")
{
token = getToken (tokens, ref index);
int i1 = int.Parse (token);
token = getToken (tokens, ref index);
int i2 = int.Parse (token);
int r = solver.Xor (nodes[i1], nodes[i2]);
if (nodes.size() < k + 1)
nodes.resize (k + 1);
nodes[k] = r;
nodes [k ^ 1] = (r^1);
}
else
fatal ("Unrecognized Symbol");
}
}
static Random rand;
static int [] randclause (int begin, int end)
{
IntVector cls = new IntVector(4);
while (cls.empty())
{
double r = rand.NextDouble();
int a = (int) (r * (end - begin)) + begin;
r = rand.NextDouble();
if (r < 0.5)
a = a + a;
else
a = a + a + 1;
r = rand.NextDouble();
int b = (int) (r * (end - begin)) + begin;
r = rand.NextDouble();
if (r < 0.5)
b = b + b;
else
b = b + b + 1;
r = rand.NextDouble();
int c = (int) (r * (end - begin)) + begin;
r = rand.NextDouble();
if (r < 0.5)
c = c + c;
else
c = c + c + 1;
if ((a>>1) != (b>>1))
{
cls.push_back (a);
cls.push_back (b);
if ((a>>1) != (c>>1) && (b>>1) != (c>>1))
cls.push_back (c);
}
else
{
cls.push_back (b);
if ((b>>1) != (c>>1))
cls.push_back (c);
}
}
return cls.ToArray();
}
static bool test_interpolant_clauses (int n_vars, int n_cls, int span, int randseed)
{
rand = new Random(randseed);
int [] [] a_clauses;
int [] [] b_clauses;
a_clauses = new int [n_cls][];
b_clauses = new int [n_cls][];
for (int i=0; i< n_cls; ++i)
a_clauses[i] = randclause ( 1, n_vars/2 + span);
for (int i=0; i< n_cls; ++i)
b_clauses[i] = randclause ( n_vars/2 - span, n_vars + 1);
SATSolver solver = new SATSolver();
solver.SetNumVariables(n_vars);
int a_gid = solver.AllocGID();
int b_gid = solver.AllocGID();
//1. Test if A is satisfiable
for (int i=0; i< n_cls; ++i)
solver.AddClause (a_clauses[i], a_gid);
if (solver.Solve() != SATStatus.SATISFIABLE)
{
Console.Write ("A SAT");
return false;
}
solver.DeleteGroup(a_gid);
//1. Test if B is satisfiable
for (int i=0; i< n_cls; ++i)
solver.AddClause (b_clauses[i], b_gid);
if (solver.Solve() != SATStatus.SATISFIABLE)
{
Console.Write ("B SAT");
return false;
}
//3. Generate Interpolant
a_gid = solver.AllocGID();
for (int i=0; i< n_cls; ++i)
solver.AddClause (a_clauses[i], a_gid);
Console.Write("Interpolant ");
int interpolant = solver.GenInterpolantFromClauseGroups ( a_gid, b_gid);
if (interpolant == -1 )
{
Console.Write("AB SAT" );
return false;
}
solver.Reference(interpolant);
//now test IB Unsatisfiable
Console.Write("IB ");
solver.DeleteGroup (a_gid);
sharp_assert (solver.stats.num_orig_clauses == n_cls);
int c = solver.Constraint(interpolant);
SATStatus status = solver.Solve();
if (status != SATStatus.UNSATISFIABLE)
sharp_assert (false);
//4. test AI Satisfiable
Console.Write("AI ");
solver.DeleteGroup (b_gid);
a_gid = solver.AllocGID();
for (int i=0; i< n_cls; ++i)
solver.AddClause (a_clauses[i], a_gid);
status = solver.Solve();
if (status != SATStatus.SATISFIABLE)
assert(false);
//5. test AI' Unsat (i.e. A=>I)
Console.Write("AI' ");
solver.ReleaseConstraint (c);
c = solver.Constraint(solver.Not(interpolant));
status = solver.Solve();
if (status != SATStatus.UNSATISFIABLE)
sharp_assert (false);
solver.ReleaseConstraint (c);
return true;
}
static int build_struct (SATSolver solver, int [][] clauses)
{
int sig = solver.one();
for (int i=0; i< clauses.Length; ++i)
{
int s = solver.zero();
foreach (int lit in clauses[i])
s = solver.Or(s, lit);
sig = solver.And(sig, s);
}
return sig;
}
static bool test_interpolant_structure (int n_vars, int n_cls, int span, int randseed)
{
rand = new Random(randseed);
int [] [] a_clauses;
int [] [] b_clauses;
a_clauses = new int [n_cls][];
b_clauses = new int [n_cls][];
for (int i=0; i< n_cls; ++i)
a_clauses[i] = randclause ( 1, n_vars/2 + span);
for (int i=0; i< n_cls; ++i)
b_clauses[i] = randclause ( n_vars/2 - span, n_vars + 1);
SATSolver solver = new SATSolver();
solver.SetNumVariables(n_vars);
solver.ConvertVarsToPI();
int s_a = build_struct(solver, a_clauses);
int s_b = build_struct(solver, b_clauses);
solver.Reference(s_a);
solver.Reference(s_b);
//1. Test if A is satisfiable
int c_a = solver.Constraint(s_a);
if (solver.Solve() != SATStatus.SATISFIABLE)
{
Console.Write ("A SAT");
return false;
}
solver.ReleaseConstraint(c_a);
//2. Test if B is satisfiable
int c_b = solver.Constraint(s_b);
if (solver.Solve() != SATStatus.SATISFIABLE)
{
Console.Write ("B SAT");
return false;
}
solver.ReleaseConstraint(c_b);
//now get interpolant I
Console.Write("Interpolant ");
int interpolant = solver.GenInterpolantFromSignals ( s_a, s_b);
if (interpolant == -1)
{
Console.Write ("AB SAT");
return false;
}
solver.Reference (interpolant);
//3. test IB Unsatisfiable
Console.Write("IB ");
c_b = solver.Constraint(s_b);
int c_i = solver.Constraint(interpolant);
SATStatus status = solver.Solve();
if (status != SATStatus.UNSATISFIABLE)
sharp_assert (false);
solver.ReleaseConstraint (c_b);
//4. test AI Satisfiable
Console.Write("AI ");
c_a = solver.Constraint (s_a);
status = solver.Solve();
if (status != SATStatus.SATISFIABLE)
assert(false);
//5. test AI' Unsat (i.e. A=>I)
Console.Write("AI' ");
solver.ReleaseConstraint (c_i);
solver.Constraint(solver.Not(interpolant));
status = solver.Solve();
if (status != SATStatus.UNSATISFIABLE)
sharp_assert (false);
return true;
}
static int build_irregular_struct (SATSolver solver, int [][] clauses,int randseed)
{
Random rand = new Random(randseed);
int sig = solver.one();
for (int i=0; i< clauses.Length; ++i)
{
int s = solver.zero();
foreach (int lit in clauses[i])
{
if (rand.NextDouble() > 0.2)
s = solver.Or(s, lit);
else
s = solver.Xor(s, lit);
}
if (rand.NextDouble() > 0.15)
sig = solver.And(sig, s);
else
sig = solver.Xor(sig, s);
}
return sig;
}
static bool test_existential_quantification ( int n_cls, int n_vars, int n_qvar, int rseed)
{
rand = new Random(rseed);
int [] [] clauses = new int [n_cls][];
for (int i=0; i< n_cls; ++i)
clauses[i] = randclause ( 1, n_vars + 1);
int [] qvars = new int [n_qvar];
for (int i=1; i<= n_qvar; ++i)
qvars[i-1] = i + i;
SATSolver solver = new SATSolver();
solver.SetNumVariables(n_vars);
solver.ConvertVarsToPI();
int s = build_irregular_struct(solver, clauses, 1);
int q1 = solver.expand_exist_quantify(s, qvars);
//int q2 = solver.enum_exist_quantify(s, qvars);
int q2 = solver.enum_exist_quantify_smart(s, qvars);
SATStatus status = solver.solve();
sharp_assert (status == SATStatus.SATISFIABLE);
int notequ = solver.Xor(q1, q2);
solver.Constraint(notequ);
status = solver.Solve();
sharp_assert (status == SATStatus.UNSATISFIABLE);
return true;
}
public static bool UnitTest()
{
SATSolver solver = new SATSolver();
int ab = solver.NthPI(0);
int bc = solver.NthPI(1);
int ac = solver.NthPI(2);
int not_ab = solver.Not(ab);
int not_bc = solver.Not(bc);
solver.Not(ac);
int fafb = solver.NthPI(3);
int not_fafb = solver.Not(fafb);
int fbfc = solver.NthPI(4);
int not_fbfc = solver.Not(fbfc);
// ((a=b && b != c) || (a!=b && b=c) || (a!=b && a=c)) && f(a)!=f(b) && f(b)!=f(c)
int d1 = solver.And(ab, not_bc);
int d2 = solver.And(bc, not_ab);
int d3 = solver.And(ac, not_ab);
int c1 = solver.Or(d1,d2);
int c2 = solver.Or(c1,d3);
int c3 = solver.And(c2,not_fafb);
int c4 = solver.And(c3, not_fbfc);
int formula = c4;
int[] ret = solver.FindSatAssignment(formula);
if(ret == null) return false;
int[] clause = new int[2];
clause[0] = solver.Not(ab);
clause[1] = fafb;
solver.AddClause(clause);
ret = solver.FindSatAssignment(formula);
if(ret == null) return false;
return true;
}
public static void print_model(int [] m)
{
Console.WriteLine ("Model Is " );
foreach (int e in m)
{
if ( (e&1) == 1)
Console.Write ("-");
Console.Write( (e/2) + " ");
}
Console.WriteLine("");
}
public static bool test_small_model()
{
SATSolver solver = new SATSolver();
int a = solver.NthPI(0);
int b = solver.NthPI(1);
int c = solver.NthPI(2);
int d = solver.NthPI(3);
int ab = solver.And(a, b);
int cd = solver.And(c, d);
int abcd = solver.And(ab, cd);
int constraint = solver.Constraint(abcd);
solver.Solve();
int [] model = solver.FindSmallModel();
print_model (model);
solver.ReleaseConstraint(constraint);
int not_abcd = solver.Not(abcd);
constraint = solver.Constraint(not_abcd);
solver.Solve();
model = solver.FindSmallModel();
print_model (model);
solver.ReleaseConstraint(constraint);
int e = solver.CreatePI();
int f = solver.CreatePI();
int exf = solver.Xor (e, f);
int and_exf_abcd = solver.And(exf, abcd);
constraint = solver.Constraint(and_exf_abcd);
solver.Solve();
model = solver.FindSmallModel();
print_model (model);
solver.ReleaseConstraint(constraint);
int not_and_exf_abcd = solver.Not(and_exf_abcd);
constraint = solver.Constraint(not_and_exf_abcd);
solver.Solve();
model = solver.FindSmallModel();
print_model (model);
solver.ReleaseConstraint(constraint);
return true;
}
public static void test_quantification_edge_case ()
{
int n_cls = 100;
int n_vars = 50;
int n_qvar = 10;
rand = new Random(10);
int [] [] clauses = new int [n_cls][];
for (int i=0; i< n_cls; ++i)
clauses[i] = randclause ( 1, n_vars + 1);
int [] qvars = new int [n_qvar];
for (int i=1; i<= n_qvar; ++i)
qvars[i-1] = i + i;
SATSolver solver = new SATSolver();
solver.SetNumVariables(n_vars);
solver.ConvertVarsToPI();
build_irregular_struct(solver, clauses, 1);
int t = solver.GetOne();
int f = solver.GetZero();
int s1 = solver.And (t, 10);
int s2 = solver.And (f, 10);
int [] bounded = new int[2];
bounded[0] = 2;
bounded[1] = 3;
int result = solver.EnumExistQuantify (s1, bounded);
result = solver.EnumExistQuantify (s2, bounded);
Console.WriteLine(result);
}
public static void Main(string [] args)
{
// bool r = UnitTest();
// sharp_assert (r == true);
//
// NetList net = new NetList();
// net.read_blif(args[0]);
// net.write_blif(args[0] + ".out");
// test_clause_solver(args);
// return;
// Console.WriteLine("Test Clause and Structure Based Interpolant Generation");
// for (int i=0; i< 100; ++i)
// {
// Console.Write ("Test {0}\tCLAUSE: ", i);
// r = test_interpolant_clauses (100, 200, 45, i) ;
// if (r == false)
// Console.Write ("*");
// Console.Write("\t STURCT:");
// r = test_interpolant_structure (100, 200, 45, i) ;
// if (r == false)
// Console.Write ("*");
// Console.WriteLine("");
// }
// for (int i=0 ; i < 100; ++i)
// {
// Console.WriteLine ("Test {0} ", i);
// test_existential_quantification(50, 30, 20, i);
// }
// test_small_model();
// test_quantification_edge_case();
test_clause_solver (args);
}
}
}