Skip to main content
Code Review

Return to Revisions

3 of 5
Added programming-challenge tag and text from programming challenge.
pacmaninbw
  • 26.1k
  • 13
  • 47
  • 113

Where could I optmize this slow 3sat algorithm

i'm currently trying to solve this problem: https://open.kattis.com/problems/satisfiability

Alice recently started to work for a hardware design company and as a part of her job, she needs to identify defects in fabricated integrated circuits. An approach for identifying these defects boils down to solving a satisfiability instance. She needs your help to write a program to do this task.

Input
The first line of input contains a single integer, not more than 5, indicating the number of test cases to follow. The first line of each test case contains two integers n and m where 1≤n≤20 indicates the number of variables and 1≤m≤100 indicates the number of clauses. Then, m lines follow corresponding to each clause. Each clause is a disjunction of literals in the form Xi or ~Xi for some 1≤i≤n, where ~Xi indicates the negation of the literal Xi. The "or" operator is denoted by a ‘v’ character and is seperated from literals with a single space.

Output
For each test case, display satisfiable on a single line if there is a satisfiable assignment; otherwise display unsatisfiable.

And I have this code:

import sys
cases = int(sys.stdin.readline())
def GetReverse(literal):
 if literal[0] == '~':
 return literal[1:]
 else:
 return '~' + literal
for i in range(cases):
 vars, clauses = map(int, sys.stdin.readline().split())
mySets = []
firstClause = sys.stdin.readline().strip().split(" v ")
for c in firstClause:
 this = set()
 this.add(c)
 mySets.append(this)
for i in range(clauses-1):
 tempSets = []
 currentClause = sys.stdin.readline().strip().split(" v ")
 for s in mySets:
 for literal in currentClause:
 if not s.__contains__(GetReverse(literal)):
 newset = s.copy()
 newset.add(literal)
 tempSets.append(newset)
 mySets = tempSets
if mySets:
 print("satisfiable")
else:
 print("unsatisfiable")

This code basically maintains "mySets" which is a list of sets, which all represent possible combinations of literals that could make the entire statement true. every time we parse a new clause, we check if it's negation exists already in a set, if it does, the set is not included.

for i in range(clauses-1):
tempSets = []
currentClause = sys.stdin.readline().strip().split(" v ")
for s in mySets:
 for literal in currentClause:
 if not s.__contains__(GetReverse(literal)):
 newset = s.copy()
 newset.add(literal)
 tempSets.append(newset)
mySets = tempSets

It's obvious that the problem lies somewhere here, indented forloops just arent great, but 3sat should be at least exponential anyway. Could i do the same thing as I do here, using one less loop? thanks a lot

lang-py

AltStyle によって変換されたページ (->オリジナル) /