44"""
55
66import os
7+ import shutil
78import subprocess
8- import tempfile
99import typing as t
1010
1111from nnf import And , Or , Var , dimacs , Model
@@ -26,9 +26,12 @@ def solve(
2626 if not sentence .is_CNF ():
2727 raise ValueError ("Sentence must be in CNF" )
2828
29- SOLVER = os .path .join (
30- os .path .dirname (os .path .abspath (__file__ )), 'bin' , 'kissat'
31- )
29+ if shutil .which ('kissat' ) is not None :
30+ SOLVER = 'kissat'
31+ else :
32+ SOLVER = os .path .join (
33+ os .path .dirname (os .path .abspath (__file__ )), 'bin' , 'kissat'
34+ )
3235 assert os .path .isfile (SOLVER ), "Cannot seem to find kissat solver."
3336
3437 args = [SOLVER ]
@@ -37,20 +40,24 @@ def solve(
3740 var_labels = dict (enumerate (sentence .vars (), start = 1 ))
3841 var_labels_inverse = {v : k for k , v in var_labels .items ()}
3942
40- infd , infname = tempfile .mkstemp (text = True )
41- try :
42- with open (infd , 'w' ) as f :
43- dimacs .dump (sentence , f , mode = 'cnf' , var_labels = var_labels_inverse )
43+ cnf = dimacs .dumps (sentence , mode = 'cnf' , var_labels = var_labels_inverse )
4444
45+ try :
4546 proc = subprocess .Popen (
46- args + [ infname ] ,
47+ args ,
4748 stdout = subprocess .PIPE ,
49+ stdin = subprocess .PIPE ,
4850 universal_newlines = True
4951 )
50- log , _ = proc .communicate ()
51-
52- finally :
53- os .remove (infname )
52+ log , _ = proc .communicate (cnf )
53+ except OSError as err :
54+ if err .errno == 8 :
55+ print ("Error: Attempting to run the kissat binary on an" )
56+ print (" incompatible system. Consider compiling kissat" )
57+ print (" natively so it is accessible via the command line." )
58+ raise RuntimeError ("Unable to run kissat." )
59+ else :
60+ raise RuntimeError ("Unrecognized OSError: %d" % err .errno )
5461
5562 # Two known exit codes for the solver
5663 if proc .returncode not in [10 , 20 ]:
@@ -60,11 +67,11 @@ def solve(
6067 )
6168 )
6269
63- if 's UNSATISFIABLE' in log :
70+ # Unsatisfiable
71+ if proc .returncode == 20 :
6472 return None
6573
66- if 's SATISFIABLE' not in log :
67- raise RuntimeError ("Something went wrong. Log:\n \n {}" .format (log ))
74+ assert proc .returncode == 10 , "Bad error code. Log:\n \n {}" .format (log )
6875
6976 variable_lines = [
7077 line [2 :] for line in log .split ("\n " ) if line .startswith ("v " )
0 commit comments