320 lines
10 KiB
C#
320 lines
10 KiB
C#
// ----------------------------------------------------------------------------
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Diagnostics;
|
|
//using Microsoft.Zap;
|
|
namespace SharpSAT
|
|
{
|
|
public class Variable : SATCommon
|
|
{
|
|
|
|
//public bool branchable = true;
|
|
//public bool reasoning = true;
|
|
private ushort flags = 0;
|
|
public ushort gflag = 0;
|
|
|
|
public NodeType type = NodeType.UNKNOWN;
|
|
public IntVector outputs = new IntVector(2);
|
|
public int left = INVALID;
|
|
public int right = INVALID;
|
|
public int canonical = INVALID;
|
|
public int ref_count = 0;
|
|
public short lits_count_0= 0;
|
|
public short lits_count_1= 0;
|
|
public int uid = 0;
|
|
|
|
public short score_0 = 0;
|
|
public short score_1 = 0;
|
|
public int asgn_pos = -1;
|
|
public int ordered_pos = 0;
|
|
|
|
public short varValue = UNKNOWN;
|
|
public Antecedent antecedent= -1;
|
|
public int dlevel = -1;
|
|
|
|
public void set_gid (int i) { gflag |= (ushort) (1<<(i-1)); }
|
|
public void clear_gid(int i) { gflag &= (ushort) ~(1<<(i-1)); }
|
|
public void clear_all_gid() { gflag = 0; }
|
|
public bool gid (int i) { return (( gflag & (ushort) (1<<(i-1))) != 0); }
|
|
|
|
public void clear_all_flag() { flags = 0; }
|
|
public void set_flag(int idx) { flags |= (ushort) (1 << idx); }
|
|
public void clear_flag(int idx) { flags &= (ushort) (~(1<<idx));}
|
|
public bool flag(int idx) { return (flags & (ushort) (1<< idx)) != 0; }
|
|
|
|
public int score() { return (score_0 > score_1? score_0 : score_1); }
|
|
public int lits_count() { return lits_count_0 + lits_count_1; }
|
|
public bool is_pi() { return type == NodeType.PI; }
|
|
public bool is_gate() { return (type == NodeType.AND || type == NodeType.XOR); }
|
|
public int output(int i) { return outputs[i];}
|
|
public int input(int k) { return (k==0 ? left: right); }
|
|
}
|
|
|
|
|
|
public class Clause : SATCommon
|
|
{
|
|
public ClType type = ClType.UNKNOWN; //indicates the clause type
|
|
public ushort gflag = 0;
|
|
public int uid = 0;
|
|
public int[] literals = null;
|
|
public int activity = 0;
|
|
|
|
public void init (ClType tp, int [] lits, ushort gflg, int id)
|
|
{
|
|
type = tp;
|
|
literals = new int[lits.Length];
|
|
Array.Copy(lits, 0, literals, 0, lits.Length);
|
|
gflag = gflg;
|
|
uid = id;
|
|
activity = 0;
|
|
}
|
|
|
|
public bool gid (int i)
|
|
{
|
|
sharp_assert (i>=1 && i<= WORD_WIDTH);
|
|
return (( gflag & (ushort)(1<<(i-1))) != 0);
|
|
}
|
|
|
|
public void set_gid (int i)
|
|
{
|
|
sharp_assert (i>=1 && i<= WORD_WIDTH);
|
|
gflag |= (ushort)(1<<(i-1));
|
|
}
|
|
|
|
public void clear_gid(int i)
|
|
{
|
|
sharp_assert (i>=1 && i<= WORD_WIDTH);
|
|
gflag &= (ushort)~(1<<(i-1));
|
|
}
|
|
|
|
public int num_lits { get {return literals.Length; } }
|
|
|
|
public int literal (int n)
|
|
{
|
|
return literals[n];
|
|
}
|
|
}
|
|
|
|
public struct Antecedent
|
|
{
|
|
private int anteVal;
|
|
|
|
public static implicit operator Antecedent( int v ) { return new Antecedent(v); }
|
|
public static implicit operator int (Antecedent an) { return an.anteVal; }
|
|
public Antecedent (int v) { anteVal = v; }
|
|
public Antecedent (ImpType tp, int index)
|
|
{
|
|
anteVal = (index << 3) + (int) tp;
|
|
}
|
|
public ImpType type
|
|
{
|
|
get { return (ImpType) (anteVal & 0x7); }
|
|
set
|
|
{
|
|
uint a = (uint) anteVal & (~(uint) 0x7);
|
|
uint b = (uint) value;
|
|
anteVal = (int) (a | b);
|
|
//anteVal = (((uint)anteVal) & (~(uint)0x7)) | (uint) value;
|
|
}
|
|
}
|
|
|
|
public int index
|
|
{
|
|
get { return (anteVal >> 3); }
|
|
set { anteVal = ((anteVal & 7) | (value << 3)); }
|
|
}
|
|
}
|
|
|
|
public struct Implication
|
|
{
|
|
public int lit;
|
|
public Antecedent ante;
|
|
}
|
|
|
|
public class NodeHashMap : SATCommon
|
|
{
|
|
private const int XOR_MARK = (1 << 30);
|
|
private MyHashtable hash_table = new MyHashtable();
|
|
|
|
private class NodeHashMapKey
|
|
{
|
|
public int left;
|
|
public int right;
|
|
public NodeHashMapKey(int l, int r)
|
|
{
|
|
left = l;
|
|
right = r;
|
|
}
|
|
public override int GetHashCode()
|
|
{
|
|
long hashcode = left;
|
|
hashcode <<= 16;
|
|
hashcode ^= right;
|
|
int lsig = (int)(hashcode & 0xffffffff);
|
|
int msig = (int)(hashcode >> 32);
|
|
return lsig ^ msig;
|
|
}
|
|
public override bool Equals(object obj)
|
|
{
|
|
NodeHashMapKey other = obj as NodeHashMapKey;
|
|
if (other == null) return false;
|
|
return other.left == left && other.right == right;
|
|
}
|
|
}
|
|
|
|
public int lookup (NodeType op, int i1, int i2)
|
|
{
|
|
sharp_assert (op == NodeType.AND || op == NodeType.XOR);
|
|
//1. left input always has smaller index than right
|
|
if (i1 > i2) {
|
|
int temp = i1;
|
|
i1 = i2;
|
|
i2 = temp;
|
|
}
|
|
//2. For XOR gate, always require both inputs not negated
|
|
bool do_NEGATE = false;
|
|
if (op == NodeType.XOR) {
|
|
if (IS_NEGATED(i1)) {
|
|
i1 = NEGATE (i1);
|
|
do_NEGATE = !do_NEGATE;
|
|
}
|
|
if (IS_NEGATED(i2)) {
|
|
i2 = NEGATE(i2);
|
|
do_NEGATE = !do_NEGATE;
|
|
}
|
|
}
|
|
//3. put special mark on the XOR node
|
|
int l, r;
|
|
l = i1;
|
|
r = i2;
|
|
if (op == NodeType.XOR)
|
|
l += XOR_MARK;
|
|
//4. Lookup
|
|
NodeHashMapKey key = new NodeHashMapKey(l, r);
|
|
// ulong key = ((ulong)l << 32) + (ulong) r;
|
|
object item = hash_table[key];
|
|
if (item == null)
|
|
return INVALID;
|
|
int o = (int) item;
|
|
if (do_NEGATE)
|
|
o = NEGATE(o);
|
|
return o;
|
|
}
|
|
|
|
public void insert ( int n, NodeType op, int i1, int i2)
|
|
{
|
|
sharp_assert (op == NodeType.AND || op == NodeType.XOR);
|
|
sharp_assert (i1 < i2);
|
|
sharp_assert (! ( (op == NodeType.XOR) &&
|
|
( IS_NEGATED(i1) || IS_NEGATED(i2) )));
|
|
sharp_assert (!IS_NEGATED(n));
|
|
|
|
int l, r;
|
|
l = i1;
|
|
r = i2;
|
|
if (op == NodeType.XOR)
|
|
l += XOR_MARK;
|
|
NodeHashMapKey key = new NodeHashMapKey(l, r);
|
|
// ulong key = ((ulong)l << 32) + (ulong) r;
|
|
sharp_assert ( !hash_table.Contains(key));
|
|
hash_table[key] = n;
|
|
}
|
|
|
|
public void remove ( int n, NodeType op, int i1, int i2)
|
|
{
|
|
sharp_assert (op == NodeType.AND || op == NodeType.XOR);
|
|
sharp_assert (i1 < i2);
|
|
sharp_assert (! ( (op == NodeType.XOR) &&
|
|
( IS_NEGATED(i1) || IS_NEGATED(i2) )));
|
|
sharp_assert ( ! IS_NEGATED(n) );
|
|
//put special mark on the XOR node
|
|
int l, r;
|
|
l = i1;
|
|
r = i2;
|
|
if (op == NodeType.XOR)
|
|
l += XOR_MARK;
|
|
NodeHashMapKey key = new NodeHashMapKey(l, r);
|
|
// ulong key = ((ulong)l << 32) + (ulong) r;
|
|
|
|
sharp_assert ( (int)hash_table[key] == n);
|
|
hash_table.Remove(key);
|
|
}
|
|
}
|
|
|
|
|
|
class FreeList
|
|
{
|
|
VarVector variables;
|
|
IntVector free_list;
|
|
int delete_count;
|
|
const double compact_ratio = 0.5;
|
|
|
|
public FreeList (VarVector vars)
|
|
{
|
|
free_list = new IntVector(16);
|
|
variables = vars;
|
|
}
|
|
|
|
public void add (IntVector new_frees)
|
|
{
|
|
for (int i = 0; i < new_frees.size(); ++i)
|
|
free_list.push_back(new_frees[i]);
|
|
free_list.sort();
|
|
}
|
|
|
|
public void delete_index (int idx)
|
|
{
|
|
delete_count ++;
|
|
if ((double)delete_count / (double)free_list.size() > compact_ratio) {
|
|
IntVector temp = new IntVector(16);
|
|
for (int i = 0; i < free_list.size(); ++i) {
|
|
if (idx == i) //just deleted, so won't be in free_list anymore
|
|
continue;
|
|
if (variables[free_list[i]] == null ||
|
|
variables[free_list[i]].type == NodeType.FREE )
|
|
temp.push_back(free_list[i]);
|
|
}
|
|
free_list = temp;
|
|
}
|
|
}
|
|
public int find_greater_than (int v)
|
|
{
|
|
int idx = free_list.binary_search (v);
|
|
if (idx < 0)
|
|
idx = ~ idx;
|
|
else
|
|
idx ++;
|
|
for (int i = idx; i < free_list.size(); ++i) {
|
|
if (variables[free_list[i]] == null ||
|
|
variables[free_list[i]].type == NodeType.FREE )
|
|
{
|
|
int r = free_list[i];
|
|
delete_index(i);
|
|
return r;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
public class UnsatCore
|
|
{
|
|
public int [] core_clauses;
|
|
public int [] core_nodes;
|
|
}
|
|
|
|
public class MyHashtable : Hashtable {}
|
|
|
|
public interface SATHook
|
|
{
|
|
void OnBCP();
|
|
void OnBacktrack(int blevel);
|
|
void OnCaseSplit(int svar);
|
|
}
|
|
}
|