928 lines
33 KiB
C#
928 lines
33 KiB
C#
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Microsoft Research Singularity
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
using System;
|
||
|
using System.IO;
|
||
|
using System.Collections;
|
||
|
using System.Diagnostics;
|
||
|
//using Microsoft.Zap;
|
||
|
namespace SharpSAT
|
||
|
{
|
||
|
sealed class ResolveNode : SATCommon
|
||
|
{
|
||
|
public int uid;
|
||
|
public int [] reasons;
|
||
|
|
||
|
public ResolveNode () {}
|
||
|
public ResolveNode (int r, int [] antes)
|
||
|
{
|
||
|
uid = r;
|
||
|
reasons = antes;
|
||
|
}
|
||
|
|
||
|
public int footprint()
|
||
|
{
|
||
|
return (3 + reasons.Length) * 4;
|
||
|
}
|
||
|
|
||
|
public void Serialize (Stream stream)
|
||
|
{
|
||
|
stream.Seek (0, SeekOrigin.End);
|
||
|
BinaryWriter bw = new BinaryWriter ( stream );
|
||
|
bw.Write (uid);
|
||
|
bw.Write (reasons.Length);
|
||
|
for (int i=0; i< reasons.Length; ++i)
|
||
|
bw.Write (reasons[i]);
|
||
|
bw.Write ( - reasons.Length);
|
||
|
bw.Flush();
|
||
|
}
|
||
|
|
||
|
static public ResolveNode DeSerializeForward (Stream stream)
|
||
|
{
|
||
|
BinaryReader br = new BinaryReader ( stream );
|
||
|
ResolveNode r = new ResolveNode();
|
||
|
r.uid = br.ReadInt32();
|
||
|
int len = br.ReadInt32();
|
||
|
r.reasons = new int [len];
|
||
|
for (int i=0; i< r.reasons.Length; ++i)
|
||
|
r.reasons[i] = br.ReadInt32();
|
||
|
int mlen = br.ReadInt32();
|
||
|
sharp_assert (mlen == - len);
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
static public ResolveNode DeSerializeBackward (Stream stream)
|
||
|
{
|
||
|
BinaryReader br = new BinaryReader ( stream );
|
||
|
ResolveNode r = new ResolveNode();
|
||
|
stream.Seek( -4, SeekOrigin.Current );
|
||
|
int l = br.ReadInt32();
|
||
|
sharp_assert (l < 0);
|
||
|
stream.Seek( - (-l + 3) * 4, SeekOrigin.Current );
|
||
|
|
||
|
r.uid = br.ReadInt32();
|
||
|
int len = br.ReadInt32();
|
||
|
r.reasons = new int [len];
|
||
|
for (int i=0; i< r.reasons.Length; ++i)
|
||
|
r.reasons[i] = br.ReadInt32();
|
||
|
int mlen = br.ReadInt32();
|
||
|
sharp_assert (mlen == - len);
|
||
|
stream.Seek( - (-l + 3) * 4, SeekOrigin.Current );
|
||
|
return r;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class ResolutionTrace : SATCommon
|
||
|
{
|
||
|
const int A_LOCAL = 1;
|
||
|
const int B_LOCAL = 2;
|
||
|
const int GLOBAL = (A_LOCAL | B_LOCAL);
|
||
|
|
||
|
private SharpSATSolver solver = null;
|
||
|
private bool enable = false;
|
||
|
private int cache_limit = 1024 * 1024 * 4; // 4 meg
|
||
|
private ResolveNode empty = null;
|
||
|
private Stream storage = new MemoryStream();
|
||
|
private string filename = "resolution.trace";
|
||
|
private IntVector reasons = new IntVector(4);
|
||
|
|
||
|
public ResolutionTrace (SharpSATSolver s )
|
||
|
{
|
||
|
solver = s;
|
||
|
}
|
||
|
public void enable_trace (bool e)
|
||
|
{
|
||
|
enable = e;
|
||
|
}
|
||
|
|
||
|
public void reset()
|
||
|
{
|
||
|
empty = null;
|
||
|
if (storage != null)
|
||
|
storage.Close();
|
||
|
storage = new MemoryStream();
|
||
|
reasons = new IntVector(4);
|
||
|
}
|
||
|
|
||
|
public void set_cache_limit (int sz)
|
||
|
{
|
||
|
cache_limit = sz;
|
||
|
}
|
||
|
public void set_temp_file (string fname)
|
||
|
{
|
||
|
filename = fname;
|
||
|
}
|
||
|
public void add_reason (int uid)
|
||
|
{
|
||
|
reasons.push_back(uid);
|
||
|
}
|
||
|
public void set_resolvent (int uid)
|
||
|
{
|
||
|
if (enable)
|
||
|
{
|
||
|
ResolveNode nd = new ResolveNode (uid, reasons.ToArray());
|
||
|
|
||
|
if (storage is MemoryStream &&
|
||
|
storage.Length + nd.footprint() > cache_limit) //out of cache, so use file
|
||
|
{
|
||
|
Stream newstream = new FileStream (filename, FileMode.Create);
|
||
|
MemoryStream memstream = storage as MemoryStream;
|
||
|
byte [] buffer = memstream.ToArray();
|
||
|
newstream.Write (buffer, 0, buffer.Length);
|
||
|
storage = newstream;
|
||
|
}
|
||
|
nd.Serialize(storage);
|
||
|
}
|
||
|
reasons.clear();
|
||
|
}
|
||
|
public void set_empty_resolvents()
|
||
|
{
|
||
|
empty = new ResolveNode(-1, reasons.ToArray());
|
||
|
}
|
||
|
|
||
|
Clause clause(int cl_id) {
|
||
|
return solver.clause(cl_id);
|
||
|
}
|
||
|
|
||
|
public void dump_trace (string fname)
|
||
|
{
|
||
|
StreamWriter output = new StreamWriter (fname, false);
|
||
|
long oldpos = storage.Position;
|
||
|
storage.Seek(0, SeekOrigin.Begin);
|
||
|
while (storage.Position < storage.Length)
|
||
|
{
|
||
|
ResolveNode nd = ResolveNode.DeSerializeForward (storage);
|
||
|
output.Write ("{0} <== ", nd.uid);
|
||
|
foreach (int r in nd.reasons)
|
||
|
{
|
||
|
if (is_node(r))
|
||
|
output.Write(" {0}({1)}", node_uid(r), cls_idx(r));
|
||
|
else
|
||
|
output.Write (" {0}", r);
|
||
|
}
|
||
|
output.Write("\n");
|
||
|
}
|
||
|
output.Close();
|
||
|
storage.Seek (oldpos, SeekOrigin.Begin);
|
||
|
}
|
||
|
|
||
|
public MyHashtable generate_unsat_core()
|
||
|
{
|
||
|
if (empty == null)
|
||
|
fatal ("Not UNSAT, Cannot Generate Core");
|
||
|
|
||
|
MyHashtable hash = new MyHashtable();
|
||
|
foreach (int uid in empty.reasons)
|
||
|
hash.Add (uid, null);
|
||
|
|
||
|
long oldpos = storage.Position;
|
||
|
storage.Seek(0, SeekOrigin.End);
|
||
|
while (storage.Position > 0)
|
||
|
{
|
||
|
ResolveNode nd = ResolveNode.DeSerializeBackward (storage);
|
||
|
sharp_assert (!is_node(nd.uid));
|
||
|
if (hash.Contains (nd.uid))
|
||
|
{
|
||
|
foreach (int id in nd.reasons)
|
||
|
{
|
||
|
int uid = id;
|
||
|
if (is_node(id))
|
||
|
uid = node_uid(id);
|
||
|
if (!hash.Contains(uid))
|
||
|
hash.Add (uid, null);
|
||
|
}
|
||
|
hash.Remove (nd.uid);
|
||
|
}
|
||
|
}
|
||
|
storage.Seek (oldpos, SeekOrigin.Begin);
|
||
|
return hash;
|
||
|
}
|
||
|
|
||
|
int find_pivot (int [] cl1, int [] cl2)
|
||
|
{
|
||
|
int [] combined = new int [ cl1.Length + cl2.Length ];
|
||
|
Array.Copy (cl1, 0, combined, 0, cl1.Length);
|
||
|
Array.Copy (cl2, 0, combined, cl1.Length, cl2.Length);
|
||
|
Array.Sort (combined);
|
||
|
for (int i=1; i< combined.Length; ++ i)
|
||
|
if (combined[i] == (combined[i-1]^1))
|
||
|
return VID(combined[i]);
|
||
|
fatal ("No pivot variable? ");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int [] resolve (int [] cl1, int [] cl2)
|
||
|
{
|
||
|
IntVector result = new IntVector(4);
|
||
|
int [] combined = new int [ cl1.Length + cl2.Length ];
|
||
|
Array.Copy (cl1, 0, combined, 0, cl1.Length);
|
||
|
Array.Copy (cl2, 0, combined, cl1.Length, cl2.Length);
|
||
|
Array.Sort (combined);
|
||
|
|
||
|
for (int i=0; i< combined.Length; ++ i)
|
||
|
{
|
||
|
if (result.empty())
|
||
|
result.push_back (combined[i]);
|
||
|
else if (result.back == combined[i])
|
||
|
continue;
|
||
|
else if (result.back == (combined[i] ^ 1))
|
||
|
result.pop_back();
|
||
|
else
|
||
|
result.push_back (combined[i]);
|
||
|
}
|
||
|
return result.ToArray();
|
||
|
}
|
||
|
|
||
|
int distance (int [] cl1, int [] cl2)
|
||
|
{
|
||
|
int [] combined = new int [ cl1.Length + cl2.Length ];
|
||
|
Array.Copy (cl1, 0, combined, 0, cl1.Length);
|
||
|
Array.Copy (cl2, 0, combined, cl1.Length, cl2.Length);
|
||
|
Array.Sort (combined);
|
||
|
int distance = 0;
|
||
|
for (int i=1; i< combined.Length; ++ i)
|
||
|
{
|
||
|
if (combined[i] == (combined[i-1] ^ 1))
|
||
|
{
|
||
|
distance ++;
|
||
|
i++;
|
||
|
}
|
||
|
}
|
||
|
return distance;
|
||
|
}
|
||
|
|
||
|
int [][] gen_gate_clause (int vid)
|
||
|
{
|
||
|
Variable var = solver.variable(vid);
|
||
|
int a = var.input(0);
|
||
|
int b = var.input(1);
|
||
|
int o = vid + vid;
|
||
|
sharp_assert (a != INVALID && b != INVALID);
|
||
|
int [][] result;
|
||
|
if (var.type == NodeType.AND)
|
||
|
{
|
||
|
result = new int [3][];
|
||
|
result[0] = new int [] { a, NEGATE(o)};
|
||
|
result[1] = new int [] { b, NEGATE(o)};
|
||
|
result[2] = new int [] { NEGATE(a), NEGATE(b), o};
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sharp_assert (var.type == NodeType.XOR);
|
||
|
result = new int [4][];
|
||
|
result[0] = new int [] { NEGATE(a), b, o};
|
||
|
result[1] = new int [] { a, NEGATE(b), o};
|
||
|
result[2] = new int [] { a, b, NEGATE(o)};
|
||
|
result[3] = new int [] { NEGATE(a), NEGATE(b), NEGATE(o)};
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
MyHashtable find_all_involved()
|
||
|
{
|
||
|
if (empty == null)
|
||
|
fatal ("Not UNSAT, Cannot Generate Core");
|
||
|
|
||
|
MyHashtable hash = new MyHashtable();
|
||
|
foreach (int uid in empty.reasons)
|
||
|
hash.Add (uid, 1);
|
||
|
|
||
|
long oldpos = storage.Position;
|
||
|
storage.Seek(0, SeekOrigin.End);
|
||
|
while (storage.Position > 0)
|
||
|
{
|
||
|
ResolveNode nd = ResolveNode.DeSerializeBackward (storage);
|
||
|
if (hash.Contains (nd.uid))
|
||
|
foreach (int uid in nd.reasons)
|
||
|
{
|
||
|
if (!hash.Contains(uid))
|
||
|
hash[uid] = 1;
|
||
|
else
|
||
|
hash[uid] = (int)hash[uid] + 1;
|
||
|
}
|
||
|
}
|
||
|
storage.Seek (oldpos, SeekOrigin.Begin);
|
||
|
return hash;
|
||
|
}
|
||
|
|
||
|
void prepare_original_clauses (int a_gid, int b_gid, MyHashtable uid2lits, MyHashtable uid2sig, MyHashtable involved, int[] var_flag)
|
||
|
{
|
||
|
for (int i=0; i< var_flag.Length; ++i)
|
||
|
var_flag[i] = 0;
|
||
|
for (int i=0; i< solver.clauses.size(); ++i)
|
||
|
{
|
||
|
Clause cl = clause(i);
|
||
|
if (cl == null || !involved.Contains(cl.uid))
|
||
|
continue;
|
||
|
|
||
|
if (cl.type == ClType.ORIGINAL)
|
||
|
{
|
||
|
if (cl.gid(a_gid))
|
||
|
{
|
||
|
sharp_assert (!cl.gid(b_gid));
|
||
|
foreach (int lit in cl.literals)
|
||
|
var_flag [VID(lit)] |= A_LOCAL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sharp_assert (cl.gid(b_gid));
|
||
|
foreach (int lit in cl.literals)
|
||
|
var_flag [VID(lit)] |= B_LOCAL;
|
||
|
}
|
||
|
}
|
||
|
uid2lits[cl.uid] = cl.literals;
|
||
|
}
|
||
|
|
||
|
for (int i=0; i< solver.original_clauses.size(); ++i)
|
||
|
{
|
||
|
Clause cl = clause(solver.original_clauses[i]);
|
||
|
sharp_assert (cl != null);
|
||
|
sharp_assert (cl.type == ClType.ORIGINAL);
|
||
|
|
||
|
if (!involved.Contains(cl.uid))
|
||
|
continue;
|
||
|
|
||
|
int signal;
|
||
|
if (cl.gid(a_gid))
|
||
|
{
|
||
|
sharp_assert (!cl.gid(b_gid));
|
||
|
signal = solver.zero();
|
||
|
foreach (int lit in cl.literals)
|
||
|
{
|
||
|
if (var_flag[VID(lit)] == GLOBAL)
|
||
|
signal = solver.bor (signal, lit);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sharp_assert (cl.gid(b_gid));
|
||
|
signal = solver.one();
|
||
|
}
|
||
|
uid2sig[cl.uid] = signal;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public int gen_interpolant_from_clauses (int a_gid, int b_gid)
|
||
|
{
|
||
|
//solver.dump_file = new StreamWriter ("dump_file");
|
||
|
//solver.dump_file.WriteLine ("{0} = INIT_VARS", solver.num_variables());
|
||
|
|
||
|
sharp_assert (solver.is_pure_clause_based());
|
||
|
solver.convert_vars_to_pi();
|
||
|
|
||
|
MyHashtable uid2lits = new MyHashtable();
|
||
|
MyHashtable uid2sig = new MyHashtable();
|
||
|
MyHashtable involved = find_all_involved();
|
||
|
int [] var_flag = new int [ solver.variables.size() ];
|
||
|
prepare_original_clauses ( a_gid, b_gid, uid2lits, uid2sig, involved, var_flag);
|
||
|
|
||
|
long oldpos = storage.Position;
|
||
|
storage.Seek(0, SeekOrigin.Begin);
|
||
|
while (storage.Position < storage.Length)
|
||
|
{
|
||
|
ResolveNode nd = ResolveNode.DeSerializeForward (storage);
|
||
|
if (!involved.Contains (nd.uid))
|
||
|
continue;
|
||
|
|
||
|
int uid = nd.reasons[0];
|
||
|
sharp_assert (involved.Contains(uid));
|
||
|
sharp_assert (uid2lits.Contains(uid));
|
||
|
sharp_assert (uid2sig.Contains(uid));
|
||
|
int [] lits = (int[])uid2lits[uid];
|
||
|
int signal = (int)uid2sig[uid];
|
||
|
|
||
|
int count = (int)involved[uid] - 1 ;
|
||
|
if ( count == 0)
|
||
|
{
|
||
|
uid2lits.Remove(uid);
|
||
|
uid2sig.Remove(uid);
|
||
|
involved.Remove(uid);
|
||
|
}
|
||
|
else
|
||
|
involved[uid] = count;
|
||
|
|
||
|
for (int i=1; i< nd.reasons.Length; ++i)
|
||
|
{
|
||
|
uid = nd.reasons[i];
|
||
|
sharp_assert (uid < (1 << 29));
|
||
|
sharp_assert (involved.Contains(uid));
|
||
|
sharp_assert (uid2lits.Contains(uid));
|
||
|
sharp_assert (uid2sig.Contains(uid));
|
||
|
int [] lits1 = (int[]) uid2lits[uid];
|
||
|
int signal1 = (int)uid2sig[uid];
|
||
|
|
||
|
count = (int)involved[uid] - 1 ;
|
||
|
if ( count == 0)
|
||
|
{
|
||
|
uid2lits.Remove(uid);
|
||
|
uid2sig.Remove(uid);
|
||
|
involved.Remove(uid);
|
||
|
}
|
||
|
else
|
||
|
involved[uid] = count;
|
||
|
|
||
|
int pivot = find_pivot (lits, lits1);
|
||
|
lits = resolve(lits, lits1);
|
||
|
if (var_flag[pivot] == A_LOCAL)
|
||
|
signal = solver.bor (signal, signal1);
|
||
|
else
|
||
|
signal = solver.band (signal, signal1);
|
||
|
}
|
||
|
if (!uid2lits.Contains(nd.uid))
|
||
|
uid2lits[nd.uid] = lits;
|
||
|
sharp_assert (!uid2sig.Contains(nd.uid));
|
||
|
uid2sig[nd.uid] = signal;
|
||
|
|
||
|
}
|
||
|
storage.Seek (oldpos, SeekOrigin.Begin);
|
||
|
{
|
||
|
int uid = empty.reasons[0];
|
||
|
sharp_assert (involved.Contains(uid));
|
||
|
sharp_assert (uid2lits.Contains(uid));
|
||
|
sharp_assert (uid2sig.Contains(uid));
|
||
|
int [] lits = (int[])uid2lits[uid];
|
||
|
int signal = (int)uid2sig[uid];
|
||
|
|
||
|
int count = (int)involved[uid] - 1 ;
|
||
|
if ( count == 0)
|
||
|
{
|
||
|
uid2lits.Remove(uid);
|
||
|
uid2sig.Remove(uid);
|
||
|
involved.Remove(uid);
|
||
|
}
|
||
|
else
|
||
|
involved[uid] = count;
|
||
|
|
||
|
for (int i=1; i< empty.reasons.Length; ++i)
|
||
|
{
|
||
|
uid = empty.reasons[i];
|
||
|
sharp_assert (involved.Contains(uid));
|
||
|
sharp_assert (uid2lits.Contains(uid));
|
||
|
sharp_assert (uid2sig.Contains(uid));
|
||
|
int [] lits1 = (int[]) uid2lits[uid];
|
||
|
int signal1 = (int)uid2sig[uid];
|
||
|
|
||
|
count = (int)involved[uid] - 1 ;
|
||
|
if ( count == 0)
|
||
|
{
|
||
|
uid2lits.Remove(uid);
|
||
|
uid2sig.Remove(uid);
|
||
|
involved.Remove(uid);
|
||
|
}
|
||
|
else
|
||
|
involved[uid] = count;
|
||
|
|
||
|
int pivot = find_pivot (lits, lits1);
|
||
|
lits = resolve(lits, lits1);
|
||
|
if (var_flag[pivot] == A_LOCAL)
|
||
|
signal = solver.bor (signal, signal1);
|
||
|
else
|
||
|
signal = solver.band (signal, signal1);
|
||
|
}
|
||
|
sharp_assert (lits.Length == 0);
|
||
|
sharp_assert (involved.Count == 0);
|
||
|
sharp_assert (uid2lits.Count == 0);
|
||
|
sharp_assert (uid2sig.Count == 0);
|
||
|
//solver.dump_file.WriteLine ("{0} = CONSTRAINT", signal);
|
||
|
//solver.dump_file.Close();
|
||
|
return signal;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool is_node (int uid)
|
||
|
{
|
||
|
return (uid > (1<<UIDSHIFT));
|
||
|
}
|
||
|
int node_uid (int uid)
|
||
|
{
|
||
|
sharp_assert (is_node(uid));
|
||
|
return (~(3 << UIDSHIFT)) & uid;
|
||
|
}
|
||
|
int cls_idx(int uid)
|
||
|
{
|
||
|
sharp_assert (is_node(uid));
|
||
|
return uid >> UIDSHIFT;
|
||
|
}
|
||
|
|
||
|
int not (int s) { return s ^ 1; }
|
||
|
|
||
|
/* for AND
|
||
|
* 1: (a + c')
|
||
|
* 2: (b + c')
|
||
|
* 3: (a' + b' + c)
|
||
|
* for XOR
|
||
|
* 4: (a' + b + c)
|
||
|
* 5: (a + b' + c)
|
||
|
* 6: (a + b + c')
|
||
|
* 7: (a' + b' + c')
|
||
|
*/
|
||
|
|
||
|
int [] get_cls (int vid, int cl_idx)
|
||
|
{
|
||
|
int [] result;
|
||
|
sharp_assert (solver.is_gate(vid + vid));
|
||
|
int a = solver.variable(vid).input(0);
|
||
|
int b = solver.variable(vid).input(1);
|
||
|
int c = vid + vid;
|
||
|
switch(cl_idx)
|
||
|
{
|
||
|
case 1:
|
||
|
result = new int[]{a, not(c)};
|
||
|
break;
|
||
|
case 2:
|
||
|
result = new int[]{b, not(c)};
|
||
|
break;
|
||
|
case 3:
|
||
|
result = new int[]{not(a), not(b), c};
|
||
|
break;
|
||
|
case 4:
|
||
|
result = new int[]{not(a), b, c};
|
||
|
break;
|
||
|
case 5:
|
||
|
result = new int[]{a, not(b), c};
|
||
|
break;
|
||
|
case 6:
|
||
|
result = new int[]{a, b, not(c)};
|
||
|
break;
|
||
|
case 7:
|
||
|
result = new int[]{not(a), not(b), not(c)};
|
||
|
break;
|
||
|
default:
|
||
|
sharp_assert (false);
|
||
|
result = null;
|
||
|
break;
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
void prepare_original_nodes (int a_flag, int b_flag, MyHashtable uid2lits, MyHashtable uid2sig, MyHashtable involved)
|
||
|
{
|
||
|
MyHashtable uid2vid = new MyHashtable();
|
||
|
|
||
|
for (int i=1; i< solver.variables.size(); ++i)
|
||
|
{
|
||
|
Variable var = solver.variable(i);
|
||
|
if (var != null && (var.flag(a_flag) || var.flag(b_flag)))
|
||
|
uid2vid[var.uid] = i;
|
||
|
}
|
||
|
|
||
|
foreach (object obj in involved)
|
||
|
{
|
||
|
int uid = (int)((DictionaryEntry) obj).Key;
|
||
|
if (!is_node(uid) || !uid2vid.Contains(node_uid(uid)))
|
||
|
continue;
|
||
|
int nid = node_uid (uid);
|
||
|
int cls_id = cls_idx (uid);
|
||
|
int vid = (int) uid2vid[nid];
|
||
|
int [] lits = get_cls(vid, cls_id);
|
||
|
int sig;
|
||
|
sharp_assert (solver.variable(vid).flag(a_flag) || solver.variable(vid).flag(b_flag));
|
||
|
if (solver.variable(vid).flag(b_flag))
|
||
|
sig = solver.one();
|
||
|
else
|
||
|
{
|
||
|
sig = solver.zero();
|
||
|
foreach (int lit in lits)
|
||
|
{
|
||
|
sharp_assert (solver.node(lit).flag(a_flag));
|
||
|
if (solver.node(lit).flag(b_flag))
|
||
|
sig = solver.bor(sig, lit);
|
||
|
}
|
||
|
}
|
||
|
uid2lits[uid] = lits;
|
||
|
uid2sig[uid] = sig;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public int gen_interpolant_from_signals (int a_node, int a_cls_id, int b_node, int b_cls_id)
|
||
|
{
|
||
|
//solver.dump_file = new StreamWriter ("dump_file");
|
||
|
//solver.dump_file.WriteLine ("{0} = INIT_VARS", solver.num_variables());
|
||
|
|
||
|
int a_flag = solver.alloc_flag();
|
||
|
int b_flag = solver.alloc_flag();
|
||
|
solver.mark_transitive_fanins(a_node, a_flag);
|
||
|
solver.mark_transitive_fanins(b_node, b_flag);
|
||
|
|
||
|
MyHashtable uid2lits = new MyHashtable();
|
||
|
MyHashtable uid2sig = new MyHashtable();
|
||
|
MyHashtable involved = find_all_involved();
|
||
|
prepare_original_nodes (a_flag, b_flag, uid2lits, uid2sig, involved);
|
||
|
uid2lits[solver.clause(a_cls_id).uid] = solver.clause(a_cls_id).literals;
|
||
|
uid2lits[solver.clause(b_cls_id).uid] = solver.clause(b_cls_id).literals;
|
||
|
if (solver.node(a_node).flag(b_flag))
|
||
|
uid2sig[solver.clause(a_cls_id).uid] = a_node;
|
||
|
else
|
||
|
uid2sig[solver.clause(a_cls_id).uid] = solver.zero();
|
||
|
uid2sig[solver.clause(b_cls_id).uid] = solver.one();
|
||
|
|
||
|
long oldpos = storage.Position;
|
||
|
storage.Seek(0, SeekOrigin.Begin);
|
||
|
while (storage.Position < storage.Length)
|
||
|
{
|
||
|
ResolveNode nd = ResolveNode.DeSerializeForward (storage);
|
||
|
if (!involved.Contains (nd.uid))
|
||
|
continue;
|
||
|
|
||
|
int [] lits;
|
||
|
int signal;
|
||
|
int uid = nd.reasons[0];
|
||
|
sharp_assert (involved.Contains(uid));
|
||
|
sharp_assert (uid2sig.Contains(uid));
|
||
|
lits = (int[])uid2lits[uid];
|
||
|
signal = (int)uid2sig[uid];
|
||
|
|
||
|
int count = (int)involved[uid] - 1 ;
|
||
|
if ( count == 0)
|
||
|
{
|
||
|
uid2lits.Remove(uid);
|
||
|
uid2sig.Remove(uid);
|
||
|
involved.Remove(uid);
|
||
|
}
|
||
|
else
|
||
|
involved[uid] = count;
|
||
|
|
||
|
for (int i=1; i< nd.reasons.Length; ++i)
|
||
|
{
|
||
|
uid = nd.reasons[i];
|
||
|
sharp_assert (uid < (1 << 29));
|
||
|
sharp_assert (involved.Contains(uid));
|
||
|
sharp_assert (uid2lits.Contains(uid));
|
||
|
sharp_assert (uid2sig.Contains(uid));
|
||
|
int [] lits1 = (int[]) uid2lits[uid];
|
||
|
int signal1 = (int)uid2sig[uid];
|
||
|
|
||
|
count = (int)involved[uid] - 1 ;
|
||
|
if ( count == 0)
|
||
|
{
|
||
|
uid2lits.Remove(uid);
|
||
|
uid2sig.Remove(uid);
|
||
|
involved.Remove(uid);
|
||
|
}
|
||
|
else
|
||
|
involved[uid] = count;
|
||
|
|
||
|
int pivot = find_pivot (lits, lits1);
|
||
|
lits = resolve(lits, lits1);
|
||
|
if (!solver.variable(pivot).flag(b_flag))
|
||
|
{
|
||
|
sharp_assert (solver.variable(pivot).flag(a_flag));
|
||
|
signal = solver.bor (signal, signal1);
|
||
|
}
|
||
|
else
|
||
|
signal = solver.band (signal, signal1);
|
||
|
}
|
||
|
if (!uid2lits.Contains(nd.uid))
|
||
|
uid2lits[nd.uid] = lits;
|
||
|
sharp_assert (!uid2sig.Contains(nd.uid));
|
||
|
uid2sig[nd.uid] = signal;
|
||
|
}
|
||
|
storage.Seek (oldpos, SeekOrigin.Begin);
|
||
|
{
|
||
|
int uid = empty.reasons[0];
|
||
|
sharp_assert (involved.Contains(uid));
|
||
|
sharp_assert (uid2lits.Contains(uid));
|
||
|
sharp_assert (uid2sig.Contains(uid));
|
||
|
int [] lits = (int[])uid2lits[uid];
|
||
|
int signal = (int)uid2sig[uid];
|
||
|
|
||
|
int count = (int)involved[uid] - 1 ;
|
||
|
if ( count == 0)
|
||
|
{
|
||
|
uid2lits.Remove(uid);
|
||
|
uid2sig.Remove(uid);
|
||
|
involved.Remove(uid);
|
||
|
}
|
||
|
else
|
||
|
involved[uid] = count;
|
||
|
|
||
|
for (int i=1; i< empty.reasons.Length; ++i)
|
||
|
{
|
||
|
uid = empty.reasons[i];
|
||
|
sharp_assert (involved.Contains(uid));
|
||
|
sharp_assert (uid2lits.Contains(uid));
|
||
|
sharp_assert (uid2sig.Contains(uid));
|
||
|
int [] lits1 = (int[]) uid2lits[uid];
|
||
|
int signal1 = (int)uid2sig[uid];
|
||
|
|
||
|
count = (int)involved[uid] - 1 ;
|
||
|
if ( count == 0)
|
||
|
{
|
||
|
uid2lits.Remove(uid);
|
||
|
uid2sig.Remove(uid);
|
||
|
involved.Remove(uid);
|
||
|
}
|
||
|
else
|
||
|
involved[uid] = count;
|
||
|
|
||
|
int pivot = find_pivot (lits, lits1);
|
||
|
lits = resolve(lits, lits1);
|
||
|
if (!solver.variable(pivot).flag(b_flag))
|
||
|
{
|
||
|
sharp_assert (solver.variable(pivot).flag(a_flag));
|
||
|
signal = solver.bor (signal, signal1);
|
||
|
}
|
||
|
else
|
||
|
signal = solver.band (signal, signal1);
|
||
|
}
|
||
|
sharp_assert (lits.Length == 0);
|
||
|
sharp_assert (involved.Count == 0);
|
||
|
sharp_assert (uid2lits.Count == 0);
|
||
|
sharp_assert (uid2sig.Count == 0);
|
||
|
//solver.dump_file.WriteLine ("{0} = CONSTRAINT", signal);
|
||
|
//solver.dump_file.Close();
|
||
|
|
||
|
solver.free_flag(a_flag);
|
||
|
solver.free_flag(b_flag);
|
||
|
return signal;
|
||
|
}
|
||
|
}
|
||
|
// gretay -- change start
|
||
|
public int gen_interpolant_from_signals_ex (int a_node, int a_cls_id, int b_node, int b_cls_id, int[] c_cls_id, int[] c_interp)
|
||
|
{
|
||
|
//solver.dump_file = new StreamWriter ("dump_file");
|
||
|
//solver.dump_file.WriteLine ("{0} = INIT_VARS", solver.num_variables());
|
||
|
|
||
|
int a_flag = solver.alloc_flag();
|
||
|
int b_flag = solver.alloc_flag();
|
||
|
solver.mark_transitive_fanins(a_node, a_flag);
|
||
|
solver.mark_transitive_fanins(b_node, b_flag);
|
||
|
|
||
|
assert(c_cls_id.Length == c_interp.Length);
|
||
|
|
||
|
MyHashtable uid2lits = new MyHashtable();
|
||
|
MyHashtable uid2sig = new MyHashtable();
|
||
|
MyHashtable involved = find_all_involved();
|
||
|
prepare_original_nodes (a_flag, b_flag, uid2lits, uid2sig, involved);
|
||
|
|
||
|
// init A info
|
||
|
int a_uid = solver.clause(a_cls_id).uid;
|
||
|
if (involved.Contains(a_uid))
|
||
|
{
|
||
|
uid2lits[a_uid] = solver.clause(a_cls_id).literals;
|
||
|
int s = solver.zero();
|
||
|
foreach (int lit in solver.clause(a_cls_id).literals)
|
||
|
{
|
||
|
sharp_assert (solver.node(lit).flag(a_flag));
|
||
|
if (solver.node(lit).flag(b_flag))
|
||
|
s = solver.bor(s, lit);
|
||
|
}
|
||
|
uid2sig[a_uid] = s;
|
||
|
//uid2sig[a_uid] = a_node;
|
||
|
}
|
||
|
// init B info
|
||
|
int b_uid = solver.clause(b_cls_id).uid;
|
||
|
if (involved.Contains(b_uid))
|
||
|
{
|
||
|
uid2lits[b_uid] = solver.clause(b_cls_id).literals;
|
||
|
uid2sig[b_uid] = solver.one();
|
||
|
}
|
||
|
// init C info
|
||
|
for (int i = 0; i < c_cls_id.Length; i++ )
|
||
|
{
|
||
|
Clause cl = solver.clause(c_cls_id[i]);
|
||
|
if (involved.Contains(cl.uid))
|
||
|
{
|
||
|
uid2lits[cl.uid] = cl.literals;
|
||
|
uid2sig[cl.uid] = c_interp[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
long oldpos = storage.Position;
|
||
|
storage.Seek(0, SeekOrigin.Begin);
|
||
|
while (storage.Position < storage.Length)
|
||
|
{
|
||
|
ResolveNode nd = ResolveNode.DeSerializeForward (storage);
|
||
|
if (!involved.Contains (nd.uid))
|
||
|
continue;
|
||
|
|
||
|
int [] lits;
|
||
|
int signal;
|
||
|
int uid = nd.reasons[0];
|
||
|
sharp_assert (involved.Contains(uid));
|
||
|
sharp_assert (uid2sig.Contains(uid));
|
||
|
lits = (int[])uid2lits[uid];
|
||
|
signal = (int)uid2sig[uid];
|
||
|
|
||
|
int count = (int)involved[uid] - 1 ;
|
||
|
if ( count == 0)
|
||
|
{
|
||
|
uid2lits.Remove(uid);
|
||
|
uid2sig.Remove(uid);
|
||
|
involved.Remove(uid);
|
||
|
}
|
||
|
else
|
||
|
involved[uid] = count;
|
||
|
|
||
|
for (int i=1; i< nd.reasons.Length; ++i)
|
||
|
{
|
||
|
uid = nd.reasons[i];
|
||
|
sharp_assert (uid < (1 << 29));
|
||
|
sharp_assert (involved.Contains(uid));
|
||
|
sharp_assert (uid2lits.Contains(uid));
|
||
|
sharp_assert (uid2sig.Contains(uid));
|
||
|
int [] lits1 = (int[]) uid2lits[uid];
|
||
|
int signal1 = (int)uid2sig[uid];
|
||
|
|
||
|
count = (int)involved[uid] - 1 ;
|
||
|
if ( count == 0)
|
||
|
{
|
||
|
uid2lits.Remove(uid);
|
||
|
uid2sig.Remove(uid);
|
||
|
involved.Remove(uid);
|
||
|
}
|
||
|
else
|
||
|
involved[uid] = count;
|
||
|
|
||
|
int pivot = find_pivot (lits, lits1);
|
||
|
lits = resolve(lits, lits1);
|
||
|
if ( (solver.variable(pivot).flag(a_flag))
|
||
|
&& (!solver.variable(pivot).flag(b_flag)))
|
||
|
{
|
||
|
signal = solver.bor (signal, signal1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
signal = solver.band (signal, signal1);
|
||
|
}
|
||
|
}
|
||
|
if (!uid2lits.Contains(nd.uid))
|
||
|
uid2lits[nd.uid] = lits;
|
||
|
sharp_assert (!uid2sig.Contains(nd.uid));
|
||
|
uid2sig[nd.uid] = signal;
|
||
|
|
||
|
}
|
||
|
storage.Seek (oldpos, SeekOrigin.Begin);
|
||
|
{
|
||
|
int uid = empty.reasons[0];
|
||
|
sharp_assert (involved.Contains(uid));
|
||
|
sharp_assert (uid2lits.Contains(uid));
|
||
|
sharp_assert (uid2sig.Contains(uid));
|
||
|
int [] lits = (int[])uid2lits[uid];
|
||
|
int signal = (int)uid2sig[uid];
|
||
|
|
||
|
int count = (int)involved[uid] - 1 ;
|
||
|
if ( count == 0)
|
||
|
{
|
||
|
uid2lits.Remove(uid);
|
||
|
uid2sig.Remove(uid);
|
||
|
involved.Remove(uid);
|
||
|
}
|
||
|
else
|
||
|
involved[uid] = count;
|
||
|
|
||
|
for (int i=1; i< empty.reasons.Length; ++i)
|
||
|
{
|
||
|
uid = empty.reasons[i];
|
||
|
sharp_assert (involved.Contains(uid));
|
||
|
sharp_assert (uid2lits.Contains(uid));
|
||
|
sharp_assert (uid2sig.Contains(uid));
|
||
|
int [] lits1 = (int[]) uid2lits[uid];
|
||
|
int signal1 = (int)uid2sig[uid];
|
||
|
|
||
|
count = (int)involved[uid] - 1 ;
|
||
|
if ( count == 0)
|
||
|
{
|
||
|
uid2lits.Remove(uid);
|
||
|
uid2sig.Remove(uid);
|
||
|
involved.Remove(uid);
|
||
|
}
|
||
|
else
|
||
|
involved[uid] = count;
|
||
|
|
||
|
int pivot = find_pivot (lits, lits1);
|
||
|
lits = resolve(lits, lits1);
|
||
|
|
||
|
if ( (solver.variable(pivot).flag(a_flag))
|
||
|
&& (!solver.variable(pivot).flag(b_flag)))
|
||
|
{
|
||
|
signal = solver.bor (signal, signal1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
signal = solver.band (signal, signal1);
|
||
|
}
|
||
|
}
|
||
|
sharp_assert (lits.Length == 0);
|
||
|
sharp_assert (involved.Count == 0);
|
||
|
sharp_assert (uid2lits.Count == 0);
|
||
|
sharp_assert (uid2sig.Count == 0);
|
||
|
//solver.dump_file.WriteLine ("{0} = CONSTRAINT", signal);
|
||
|
//solver.dump_file.Close();
|
||
|
|
||
|
solver.free_flag(a_flag);
|
||
|
solver.free_flag(b_flag);
|
||
|
//solver.free_flag(c_flag);
|
||
|
return signal;
|
||
|
}
|
||
|
}
|
||
|
// gretay -- change end
|
||
|
|
||
|
}
|
||
|
}
|