-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclassicalEncoder.py
More file actions
97 lines (88 loc) · 4.48 KB
/
classicalEncoder.py
File metadata and controls
97 lines (88 loc) · 4.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import math
import copy
from read_input import Clique
class classicalBayesianEncoder():
def __init__(self):
self.endOfLine = "0\n"
self.cnfFileName = "encodingBayesian.cnf"
self.weightFileName = "weightFile.txt"
def integer2Bits(self, numBits, value):
bitArray = []
for i in range(numBits-1, -1, -1):
bitArray.append(value & (1 << i) != 0)
return bitArray[::-1]
def bits2Integer(self, bits):
res = 0
for i in range(len(bits)):
if bits[i]:
res += math.pow(2, i)
return int(res)
def locateWeightValue(self, integerBits, conditionalTable):
if integerBits[0]:
secondIdx = 1
else:
secondIdx = 0
# print(integerBits)
firstIdx = self.bits2Integer(integerBits[1:])
# print(firstIdx)
return conditionalTable[firstIdx][secondIdx]
def CNFHeader(self, cnfFile, weightFile, numVariables, cliques, queries):
totalNumVariables = 2 * numVariables
totalNumClauses = 2 * numVariables
for clique in cliques:
totalNumVariables += int(math.pow(2, len(clique.variables)))
totalNumClauses += int(math.pow(2, len(clique.variables))) * (len(clique.variables) + 1)
totalNumClauses += len(queries)
cnfFile.write("c CS4244 Encoding Bayesian Network to CNF formula\n")
cnfFile.write("p cnf " + str(totalNumVariables) + " " + str(totalNumClauses) + "\n")
weightFile.write("p " + str(totalNumVariables) + "\n")
def TypeOneConstraints(self, cnfFile, weightFile, numVariables):
for i in range(numVariables):
cnfFile.write("-"+str(2*i)+" "+str(2*i+1)+" "+self.endOfLine)
cnfFile.write("-"+str(2*i+1)+" "+str(2*i)+" "+self.endOfLine)
weightFile.write("w -"+str(2*i)+" "+str(1.0)+" "+self.endOfLine)
weightFile.write("w "+str(2*i)+" "+str(1.0)+" "+self.endOfLine)
weightFile.write("w -"+str(2*i+1)+" "+str(1.0)+" "+self.endOfLine)
weightFile.write("w "+str(2*i+1)+" "+str(1.0)+" "+self.endOfLine)
def TypeTwoConstraints(self, cnfFile, weightFile, numVariables, cliques):
parameterVariableID = 2 * numVariables
for clique in cliques:
variables = copy.deepcopy(clique.variables)
totalNumCombinations = int(math.pow(2, len(variables)))
for i in range(totalNumCombinations):
integerBits = self.integer2Bits(len(variables), i)
leftImplication = ""
rightImplication = ""
for j in range(len(integerBits)):
variableId = variables[len(integerBits) - 1 - j]
if integerBits[j]:
indicatorVariable = 2 * variableId
else:
indicatorVariable = 2 * variableId + 1
rightImplication = "-" + str(parameterVariableID) + " " + str(indicatorVariable) + " " + self.endOfLine
cnfFile.write(rightImplication)
leftImplication += "-" + str(indicatorVariable) + " "
leftImplication += str(parameterVariableID) + " " + self.endOfLine
cnfFile.write(leftImplication)
positiveWeightValue = self.locateWeightValue(integerBits, clique.conditionalTable)
weightFile.write("w -"+str(parameterVariableID)+" "+str(positiveWeightValue)+" "+self.endOfLine)
weightFile.write("w "+str(parameterVariableID)+" "+str(1.0)+" "+self.endOfLine)
parameterVariableID += 1
def queriesProcessing(self, cnfFile, queries):
for key, value in queries.items():
if value:
indicatorVariable = 2 * key
else:
indicatorVariable = 2 * key + 1
cnfFile.write(str(indicatorVariable)+" "+self.endOfLine)
def encoding(self, numVariables, cliques, queries):
print("Processing CNF and WMC...")
cnfFile = open(self.cnfFileName, "w")
weightFile = open(self.weightFileName, "w")
self.CNFHeader(cnfFile, weightFile, numVariables, cliques, queries)
self.TypeOneConstraints(cnfFile, weightFile, numVariables)
self.TypeTwoConstraints(cnfFile, weightFile, numVariables, cliques)
self.queriesProcessing(cnfFile, queries)
cnfFile.close()
weightFile.close()
print("Processed.")