#!/usr/bin/env python3
|
|
|
|
import numpy as np
|
|
import random
|
|
from . import kSAT
|
|
import math
|
|
|
|
def generateRandomKSAT(numberOfClauses,
|
|
numberOfVariables,
|
|
numberOfVariablesPerClause):
|
|
|
|
instance = kSAT.kSAT()
|
|
|
|
clauses = [[] for i in range(numberOfClauses)]
|
|
|
|
#make sure every variable is bound to at least one clause
|
|
for varIndex in range(numberOfVariables):
|
|
|
|
clauseIndex = random.choice(range(numberOfClauses))
|
|
|
|
while (len(clauses[clauseIndex]) >= numberOfVariablesPerClause or
|
|
varIndex + 1 in clauses[clauseIndex]):
|
|
clauseIndex = random.choice(range(numberOfClauses))
|
|
|
|
clauses[clauseIndex].append(varIndex + 1)
|
|
|
|
for i in range(len(clauses)):
|
|
clauses[i].sort()
|
|
|
|
#fill in the missing bindings
|
|
for clauseIndex, clause in enumerate(clauses):
|
|
tmpClause = []
|
|
|
|
clauseIsUnique = False
|
|
while not clauseIsUnique:
|
|
|
|
tmpClause = clause.copy()
|
|
|
|
numRemainingBindings = numberOfVariablesPerClause - len(tmpClause)
|
|
variablesNotYetInClause = __getVariablesNotYetInClause(tmpClause,
|
|
numberOfVariables)
|
|
|
|
remainingBindings = random.sample(variablesNotYetInClause,
|
|
numRemainingBindings)
|
|
|
|
tmpClause += remainingBindings
|
|
|
|
for i in range(len(tmpClause)):
|
|
tmpClause[i] *= random.choice([-1, 1])
|
|
|
|
tmpClause.sort()
|
|
|
|
if tmpClause not in clauses:
|
|
clauseIsUnique = True
|
|
|
|
clauses[clauseIndex] = tmpClause
|
|
|
|
instance.addClause(tmpClause)
|
|
|
|
return instance
|
|
|
|
|
|
def __getVariablesNotYetInClause(clause, numberOfTotalVars):
|
|
missingVariables = []
|
|
|
|
prevVar = 1;
|
|
for currVar in clause:
|
|
missingVariables += list(range(prevVar, currVar))
|
|
|
|
prevVar = currVar + 1
|
|
|
|
missingVariables += list(range(prevVar, numberOfTotalVars + 1))
|
|
|
|
return missingVariables
|
|
|
|
def number_of_possible_clauses(number_of_variables, variables_per_clause):
|
|
return int(__binom(number_of_variables, variables_per_clause)
|
|
* __number_of_sign_placements(variables_per_clause))
|
|
|
|
def number_of_possible_instances(number_of_clauses,
|
|
number_of_variables,
|
|
variables_per_clause):
|
|
return int(__binom(number_of_possible_clauses(number_of_variables,
|
|
variables_per_clause),
|
|
number_of_clauses))
|
|
|
|
def __binom(n, k):
|
|
if n == k:
|
|
return 1
|
|
elif k == 1:
|
|
return n
|
|
else:
|
|
return math.factorial(n) / (math.factorial(k) * math.factorial(n - k))
|
|
|
|
def __number_of_sign_placements(variables_per_clause):
|
|
result = 0;
|
|
|
|
for i in range(variables_per_clause + 1):
|
|
result += __binom(variables_per_clause, i)
|
|
|
|
return result
|