You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

207 lines
6.0 KiB

6 years ago
6 years ago
5 years ago
6 years ago
6 years ago
  1. #!/usr/bin/env python3
  2. import numpy as np
  3. class kSAT:
  4. def __init__(self):
  5. self.__clauses = []
  6. self.__numVariables = 0
  7. def getBindings(self):
  8. return self.__clauses
  9. def getNumberOfClauses(self):
  10. return len(self.__clauses)
  11. def getClause(self, clauseIndex):
  12. return self.__clauses[clauseIndex]
  13. def addClause(self, clause):
  14. #counting variables (assuming variables are assigned
  15. # consistently from 1 to numTotalVars)
  16. for varBinding in clause:
  17. if np.absolute(varBinding) > self.__numVariables:
  18. self.__numVariables = np.absolute(varBinding)
  19. self.__clauses.append(clause)
  20. def getDegreesOfVariables(self):
  21. degrees = {}
  22. for clause in self.__clauses:
  23. for binding in clause:
  24. varLabel = abs(binding)
  25. if varLabel not in degrees:
  26. degrees[varLabel] = 1
  27. else:
  28. degrees[varLabel] += 1
  29. return degrees
  30. def evaluate(satInstance, assignments):
  31. evaluations = []
  32. for assignment in assignments:
  33. evaluations.append(satInstance.checkAssignment(assignment))
  34. return evaluations
  35. def checkAssignment(self, assignment):
  36. if not self.__assignmentIsComplete(assignment):
  37. print("wrong number of variables in assignment")
  38. return False
  39. for clause in self.__clauses:
  40. clauseResult = False
  41. for binding in clause:
  42. varIndex = np.absolute(binding) - 1
  43. if ((binding > 0 and assignment[varIndex] == True) or
  44. (binding < 0 and assignment[varIndex] == False)):
  45. clauseResult = True
  46. if clauseResult == False:
  47. return False
  48. return True
  49. def __assignmentIsComplete(self, assignment):
  50. if (len(assignment) != self.getNumberOfVariables() or
  51. None in assignment):
  52. return False
  53. return True
  54. def getNumberOfVariables(self):
  55. return self.__numVariables
  56. def toString(self):
  57. kSATString = ""
  58. for clauseIndex in range(len(self.__clauses) - 1):
  59. kSATString += self.__kSATClauseToString(clauseIndex)
  60. kSATString += " * "
  61. kSATString += self.__kSATClauseToString(len(self.__clauses) - 1)
  62. return kSATString
  63. def getLableOfBinding(self, clauseIndex, binding):
  64. #return label = "%d%d" % (clauseIndex
  65. # self.__clauses[clauseIndex][varInClauseIndex])
  66. return (clauseIndex, binding)
  67. def getConflicts(self):
  68. conflicts = []
  69. for clauseIndex in range(len(self.__clauses)):
  70. clause = self.__clauses[clauseIndex]
  71. for binding in clause:
  72. clauseToCheckIndex = 0
  73. #search for conflict with binding
  74. for clauseToCheckIndex in range(clauseIndex, len(self.__clauses)):
  75. for bindingToCheck in self.__clauses[clauseToCheckIndex]:
  76. if binding == bindingToCheck * -1:
  77. conflLable1 = self.getLableOfBinding(clauseIndex,
  78. binding)
  79. conflLable2 = self.getLableOfBinding(clauseToCheckIndex,
  80. bindingToCheck)
  81. conflicts.append((conflLable1, conflLable2))
  82. return conflicts
  83. def writeDIMACS(self, path):
  84. outputFile = open(path, "w")
  85. outputFile.write("c A SAT instance\n")
  86. outputFile.write("p cnf %d %d \n" % (self.getNumberOfVariables(),
  87. self.getNumberOfClauses()))
  88. for clause in self.getBindings():
  89. for binding in clause:
  90. outputFile.write("%d " % binding)
  91. outputFile.write("0\n")
  92. outputFile.close()
  93. def readDIMACS(self, path):
  94. inputFile = open(path, "r")
  95. line = inputFile.readline()
  96. self.reset()
  97. while line != "":
  98. if line[0] != "c" and line[0] != "p":
  99. bindings = [int(binding) for binding in line.split()]
  100. self.addClause(bindings[:len(bindings) -1])
  101. line = inputFile.readline()
  102. inputFile.close()
  103. def writeJSONLike(self):
  104. jsonLike = {}
  105. jsonLike["clauses"] = []
  106. for clause in self.__clauses:
  107. tmpClause = []
  108. for literal in clause:
  109. tmpClause.append(int(literal))
  110. jsonLike["clauses"].append(tmpClause)
  111. return jsonLike
  112. def readJSONLike(self, jsonLike):
  113. self.reset()
  114. for clause in jsonLike["clauses"]:
  115. self.addClause(clause)
  116. def reset(self):
  117. self.__clauses = []
  118. self.__numVariables = 0
  119. def __kSATClauseToString(self, clauseIndex):
  120. clause = self.__clauses[clauseIndex]
  121. varCount = 0
  122. isFirstVar = True;
  123. clauseString = "(";
  124. for weight in clause:
  125. varCount += 1
  126. if not isFirstVar:
  127. clauseString += " + "
  128. clauseString += self.__kSATVariableToString(weight)
  129. isFirstVar = False
  130. clauseString += ")"
  131. return clauseString
  132. def __kSATVariableToString(self, weight):
  133. name = "x%d" % np.absolute(weight)
  134. if weight < 0:
  135. return "!" + name
  136. else:
  137. return name