#!/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) #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 = list(np.sort(tmpClause)) 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 __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