Added zip instead of py.
1.1 --- a/downloads/sml.py Mon Jul 18 01:54:27 2011 +0200
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,447 +0,0 @@
1.4 -"""
1.5 -Name: sml - Simple Modal Logic Lib.
1.6 -Description: sml provides classes for simple modal logic formulae construction and reduction. It also features a disfunctional parser for the SML syntax.
1.7 -Author: Eugen Sawin <sawine@informatik.uni-freiburg.de>
1.8 -"""
1.9 -
1.10 -TMP_DIMACS = "dimacs~"
1.11 -TMP_SOLUTION = "solution~"
1.12 -
1.13 -def main():
1.14 - # edit your formulae here
1.15 - p = Variable("p")
1.16 - q = Variable("q")
1.17 - r = Variable("r")
1.18 - s = Variable("s")
1.19 - formula1 = Imp(Eq(p, q), r)
1.20 - formula2 = Not(Or(p, q))
1.21 - formula3 = Not(Not(p))
1.22 - formula4 = Imp(Box(Imp(Diamond(p), p)), Box(Imp(p, Box(p))))
1.23 - formula5 = Imp(And(Or(p, q), r), Not(s))
1.24 - formula6 = And(Or(p, Or(q, Not(s))), And(Or(r, Not(s)), Or(Not(p), s)))
1.25 - formula = formula6 # choose your formula here
1.26 -
1.27 - args = parse_arguments()
1.28 - if (args.formula):
1.29 - scanner = Scanner(TOKENS)
1.30 - parser = Parser(SYNTAX, scanner)
1.31 - (accepted, out, tree_nodes) = parser.parse(args.formula)
1.32 - if not accepted:
1.33 - print EXCUSE
1.34 - return
1.35 - tree = SyntaxTree(out, tree_nodes)
1.36 - formula = tree.root
1.37 -
1.38 - original = formula
1.39 - print "formula: \t\t\t%s [%i]" % (formula, formula.depth())
1.40 - formula = expand_imp_eq(formula)
1.41 - print "expanded -> and <->: \t\t%s [%i]" % (formula, formula.depth())
1.42 - formula = de_morgan(formula)
1.43 - print "reduced ~: \t\t\t%s [%i]" % (formula, formula.depth())
1.44 - formula = reduce_iter(formula)
1.45 - print "reduced iterated modalities: \t%s [%i]" % (formula, formula.depth())
1.46 - formula = reduce_iter(dist_mod((formula)))
1.47 - print "distributed modalities+: \t%s [%i]" % (formula, formula.depth())
1.48 - formula = mcnf(formula)
1.49 - print "alpha mcnf: \t\t\t%s [%i]" % (formula, formula.depth())
1.50 - #cnf_formula = cnf(original)
1.51 - #print "alpha cnf: \t\t\t%s [%i]" % (cnf_formula, cnf_formula.depth())
1.52 -
1.53 - if not args.dimacs:
1.54 - dimacs_file = TMP_DIMACS
1.55 - else:
1.56 - dimacs_file = args.dimacs
1.57 - solution = sat_test(original, dimacs_file)
1.58 - if solution:
1.59 - print "satisfiable: \t\t\t%s " % (", ".join([str(s) for s in solution]))
1.60 - else:
1.61 - print "not satisfiable"
1.62 -
1.63 -from subprocess import call, PIPE
1.64 -
1.65 -def sat_test(formula, dimacs_file):
1.66 - out, variables = dimacs(formula)
1.67 - with open(dimacs_file, "w") as f:
1.68 - f.write(out)
1.69 - call(["minisat2", "-verb=0", dimacs_file, TMP_SOLUTION], stdout=PIPE)
1.70 - with open(TMP_SOLUTION) as f:
1.71 - solved, assignment = f.readlines()
1.72 - solved = solved[0] == "S"
1.73 - if solved:
1.74 - positive = set()
1.75 - for a in assignment.split():
1.76 - neg = a[0] == "-"
1.77 - if not neg:
1.78 - positive.add(int(a))
1.79 - solution = []
1.80 - for v, n in variables.iteritems():
1.81 - if n in positive:
1.82 - solution.append(Variable(v))
1.83 - else:
1.84 - solution.append(Not(Variable(v)))
1.85 - return solution
1.86 -
1.87 -def dimacs(formula):
1.88 - def clausify(f):
1.89 - if f.id == AND:
1.90 - c1 = clausify(f.values[0])
1.91 - c2 = clausify(f.values[1])
1.92 - if c1:
1.93 - clauses.append(clausify(f.values[0]))
1.94 - if c2:
1.95 - clauses.append(clausify(f.values[1]))
1.96 - if f.id == OR:
1.97 - clause = []
1.98 - clause.extend(clausify(f.values[0]))
1.99 - clause.extend(clausify(f.values[1]))
1.100 - return clause
1.101 - if f.id == NOT:
1.102 - return ["-" + clausify(f.values[0])]
1.103 - if f.id == VARIABLE:
1.104 - if f.values[0] in variables:
1.105 - n = variables[f.values[0]]
1.106 - else:
1.107 - n = len(variables) + 1
1.108 - variables[f.values[0]] = n
1.109 - return str(n)
1.110 -
1.111 - variables = {}
1.112 - clauses = []
1.113 - clausify(formula)
1.114 - out = "c DIMACS CNF input file generated by sml\n"
1.115 - out += "c Author: Eugen Sawin <sawine@informatik.uni-freiburg.de>\n"
1.116 - out += "p cnf %i %i\n" % (len(variables), len(clauses))
1.117 - out += " 0\n".join([" ".join(c) for c in clauses]) + " 0\n"
1.118 - return out, variables
1.119 -
1.120 -def values(fun, f):
1.121 - return [fun(v) for v in f.values]
1.122 -
1.123 -def expand_imp_eq(formula):
1.124 - expmap = {IMP: lambda (a, b): Or(Not(a), b),
1.125 - EQ: lambda (a, b): And(Or(Not(a), b), Or(a, Not(b)))}
1.126 - if not isinstance(formula, Operator):
1.127 - return formula
1.128 - if formula.id in expmap:
1.129 - return expmap[formula.id](values(expand_imp_eq, formula))
1.130 - return formula.__class__(*values(expand_imp_eq, formula))
1.131 -
1.132 -def de_morgan(formula):
1.133 - negmap = {AND: lambda (a, b): Or(negate(a), negate(b)),
1.134 - OR: lambda (a, b): And(negate(a), negate(b)),
1.135 - BOX: lambda (a,): Diamond(negate(a)),
1.136 - DIAMOND: lambda (a,): Box(negate(a)),
1.137 - VARIABLE: lambda (a,): Not(Variable(a)),
1.138 - NOT: lambda (a,): a}
1.139 - def negate(f):
1.140 - return negmap[f.id](f.values)
1.141 - if not isinstance(formula, Operator):
1.142 - return formula
1.143 - if formula.id == NOT:
1.144 - return negate(formula.values[0])
1.145 - return formula.__class__(*values(de_morgan, formula))
1.146 -
1.147 -def reduce_iter(formula):
1.148 - redset = set(((BOX, BOX), (DIAMOND, DIAMOND), (DIAMOND, BOX), (BOX, DIAMOND)))
1.149 - if not isinstance(formula, Operator) or not isinstance(formula.values[0], Operator):
1.150 - return formula
1.151 - ids = (formula.id, formula.values[0].id)
1.152 - if ids in redset:
1.153 - return reduce_iter(formula.values[0])
1.154 - return formula.__class__(*values(reduce_iter, formula))
1.155 -
1.156 -def dist_mod(formula):
1.157 - distmap = {(BOX, AND): lambda (a, b): And(Box(a), Box(b)),
1.158 - (DIAMOND, OR): lambda (a, b): Or(Diamond(a), Diamond(b)),
1.159 - (BOX, OR): lambda (a, b): (isinstance(a, Box) or isinstance(b, Box))
1.160 - and Or(Box(a), Box(b)) or Box(Or(a, b)),
1.161 - (DIAMOND, AND): lambda (a, b): (isinstance(a, Diamond) or isinstance(b, Diamond))
1.162 - and And(Diamond(a), Diamond(b)) or Diamond(And(a, b))}
1.163 - if not isinstance(formula, Operator) or not isinstance(formula.values[0], Operator):
1.164 - return formula
1.165 - ids = (formula.id, formula.values[0].id)
1.166 - if ids in distmap:
1.167 - return distmap[ids](values(dist_mod, formula.values[0]))
1.168 - return formula.__class__(*values(dist_mod, formula))
1.169 -
1.170 -def mcnf(formula):
1.171 - if formula.id == OR:
1.172 - conj_id = int(formula.values[1].id == AND)
1.173 - return And(Or(formula.values[conj_id].values[0], formula.values[1 - conj_id]),
1.174 - Or(formula.values[conj_id].values[1], formula.values[1 - conj_id]));
1.175 - return formula
1.176 -
1.177 -def cnf(formula):
1.178 - def part(f):
1.179 - for v in f.values:
1.180 - if v.id != VARIABLE:
1.181 - sub_formulae.append(v)
1.182 - part(v)
1.183 -
1.184 - def conjunct(f):
1.185 - if len(bicon):
1.186 - return And(f, conjunct(bicon.pop()))
1.187 - return f
1.188 -
1.189 - sub_formulae = [formula]
1.190 - part(formula)
1.191 - sub_formulae.reverse()
1.192 - known = {}
1.193 - bicon = []
1.194 - for s in sub_formulae:
1.195 - for i, v in enumerate(s.values):
1.196 - if v in known:
1.197 - s.values[i] = known[v]
1.198 - bicon.append(Eq(Variable("x" + str(len(bicon))), s))
1.199 - known[s] = bicon[-1].values[0]
1.200 - return mcnf(dist_mod(reduce_iter(de_morgan(expand_imp_eq(conjunct(known[formula]))))))
1.201 -
1.202 -""" The Parser - Do NOT look below this line! """
1.203 -import re
1.204 -
1.205 -NOT = "~"
1.206 -AND = "&"
1.207 -OR = "|"
1.208 -IMP = "->"
1.209 -EQ = "<->"
1.210 -BOX = "[]"
1.211 -DIAMOND = "<>"
1.212 -VARIABLE = "VAR"
1.213 -LB = "("
1.214 -RB = ")"
1.215 -
1.216 -class Operator(object):
1.217 - def __init__(self, id, arity, *values):
1.218 - self.id = id
1.219 - self.arity = arity
1.220 - self.values = list(values)
1.221 - def depth(self):
1.222 - if self.arity == 0:
1.223 - return 0
1.224 - if self.id in (BOX, DIAMOND):
1.225 - return 1 + self.values[0].depth()
1.226 - if self.id == NOT:
1.227 - return self.values[0].depth()
1.228 - return max(self.values[0].depth(), self.values[1].depth())
1.229 - def __eq__(self, other):
1.230 - return self.id == other.id and self.values == other.values # commutative types not considered yet
1.231 - def __str__(self):
1.232 - out = self.id
1.233 - if self.arity == 0:
1.234 - out = str(self.values[0])
1.235 - if self.arity == 1:
1.236 - out = self.id + str(self.values[0])
1.237 - elif self.arity == 2:
1.238 - out = "(" + str(self.values[0]) + " " + self.id + " " + str(self.values[1]) + ")"
1.239 - return out
1.240 -
1.241 -class Not(Operator):
1.242 - arity = 1
1.243 - def __init__(self, *values):
1.244 - Operator.__init__(self, NOT, Not.arity, *values)
1.245 - def __call__(self):
1.246 - pass
1.247 -
1.248 -class And(Operator):
1.249 - arity = 2
1.250 - def __init__(self, *values):
1.251 - Operator.__init__(self, AND, And.arity, *values)
1.252 -
1.253 -class Or(Operator):
1.254 - arity = 2
1.255 - def __init__(self, *values):
1.256 - Operator.__init__(self, OR, Or.arity, *values)
1.257 -
1.258 -class Imp(Operator):
1.259 - arity = 2
1.260 - def __init__(self, *values):
1.261 - Operator.__init__(self, IMP, Imp.arity, *values)
1.262 -
1.263 -class Eq(Operator):
1.264 - arity = 2
1.265 - def __init__(self, *values):
1.266 - Operator.__init__(self, EQ, Eq.arity, *values)
1.267 -
1.268 -class Box(Operator):
1.269 - arity = 1
1.270 - def __init__(self, *values):
1.271 - Operator.__init__(self, BOX, Box.arity, *values)
1.272 -
1.273 -class Diamond(Operator):
1.274 - arity = 1
1.275 - def __init__(self, *values):
1.276 - Operator.__init__(self, DIAMOND, Diamond.arity, *values)
1.277 -
1.278 -class Variable(Operator):
1.279 - arity = 0
1.280 - def __init__(self, *values):
1.281 - Operator.__init__(self, VARIABLE, Variable.arity, *values)
1.282 -
1.283 -class Lb(Operator):
1.284 - arity = -1
1.285 - def __init__(self, *values):
1.286 - Operator.__init__(self, LB, Lb.arity, *values)
1.287 -
1.288 -class Rb(Operator):
1.289 - arity = -1
1.290 - def __init__(self, *values):
1.291 - Operator.__init__(self, RB, Rb.arity, *values)
1.292 -
1.293 -class Formula(object):
1.294 - def __init__(self):
1.295 - pass
1.296 -
1.297 -TOKENS = {re.compile("\("): Lb,
1.298 - re.compile("\)"): Rb,
1.299 - re.compile("~"): Not,
1.300 - re.compile("&"): And,
1.301 - re.compile("\|"): Or,
1.302 - re.compile("->"): Imp,
1.303 - re.compile("<->"): Eq,
1.304 - re.compile("\[\]"): Box,
1.305 - re.compile("<>"): Diamond,
1.306 - re.compile("[a-z]+"): Variable}
1.307 -
1.308 -class Scanner(object):
1.309 - def __init__(self, tokens, source=None):
1.310 - self.tokens = tokens
1.311 - self.reset(source)
1.312 - def next(self):
1.313 - while self.i < len(self.source):
1.314 - re.purge()
1.315 - for p, token in self.tokens.iteritems():
1.316 - m = p.match(self.source[self.i:])
1.317 - if m:
1.318 - self.i += m.end(0)
1.319 - value = m.group(0)
1.320 - return (token, value)
1.321 - self.i += 1
1.322 - return (None, None)
1.323 - def reset(self, source):
1.324 - self.i = 0
1.325 - self.source = source
1.326 -
1.327 -S = Formula
1.328 -A = "A"
1.329 -#0 S: (Variable,),
1.330 -#1 S: (Not, S),
1.331 -#2 S: (Lb, A, Rb),
1.332 -#3 S: (Box, S),
1.333 -#4 S: (Diamond, S),
1.334 -#5 A: (S, And, S),
1.335 -#6 A: (S, Or, S),
1.336 -#7 A: (S, Imp, S),
1.337 -#8 A: (S, Eq, S)
1.338 -SYNTAX = ((Variable,),
1.339 - (Not, S),
1.340 - (Lb, A, Rb),
1.341 - (Box, S),
1.342 - (Diamond, S),
1.343 - (S, And, S),
1.344 - (S, Or, S),
1.345 - (S, Imp, S),
1.346 - (S, Eq, S))
1.347 -
1.348 -class Parser(object):
1.349 - def __init__(self, syntax, scanner):
1.350 - self.syntax = syntax
1.351 - self.scanner = scanner
1.352 - def parse(self, source):
1.353 - table = {(S, Variable): 0,
1.354 - (S, Not): 1,
1.355 - (S, Lb): 2,
1.356 - (S, Box): 3,
1.357 - (S, Diamond): 4,
1.358 - (A, S, And): 5,
1.359 - (A, S, Or): 6,
1.360 - (A, S, Imp): 7,
1.361 - (A, S, Eq): 8,
1.362 - (A, Variable, And): 5,
1.363 - (A, Variable, Or): 6,
1.364 - (A, Variable, Imp): 7,
1.365 - (A, Variable, Eq): 8,
1.366 - (A, Not, Variable, And): 5,
1.367 - (A, Not, Variable, Or): 6,
1.368 - (A, Not, Variable, Imp): 7,
1.369 - (A, Not, Variable, Eq): 8}
1.370 - stack = [S]
1.371 - tree_nodes = []
1.372 - tree = None
1.373 - out = []
1.374 - self.scanner.reset(source)
1.375 - (token, value) = self.scanner.next()
1.376 - (lookahead, la_value) = self.scanner.next()
1.377 - (lookahead2, la2_value) = self.scanner.next()
1.378 - accepted = True
1.379 - while token and len(stack):
1.380 - top = stack[-1]
1.381 - if top == token:
1.382 - tree_nodes.append((token, value))
1.383 - stack.pop()
1.384 - #tree_nodes.append((stack.pop(), value))
1.385 - (token, value) = (lookahead, la_value)
1.386 - (lookahead, la_value) = (lookahead2, la2_value)
1.387 - #(lookahead, _) = self.scanner.next()
1.388 - (lookahead2, la2_value) = self.scanner.next()
1.389 - else:
1.390 - action = None
1.391 - if (top, token) in table:
1.392 - action = table[(top, token)]
1.393 - elif (top, token, lookahead) in table:
1.394 - action = table[(top, token, lookahead)]
1.395 - elif (top, token, lookahead, lookahead2) in table:
1.396 - action = table[(top, token, lookahead, lookahead2)]
1.397 - if action is None:
1.398 - accepted = False
1.399 - break
1.400 -
1.401 - out.append(action)
1.402 - stack.pop()
1.403 - stack.extend(reversed(self.syntax[action]))
1.404 - accepted = accepted and not len(stack)
1.405 - return (accepted, out, tree_nodes)
1.406 -
1.407 -class SyntaxTree(object):
1.408 - def __init__(self, seq, tree_nodes):
1.409 - seq.reverse()
1.410 - tree_nodes.reverse()
1.411 - self.root = self.compile(seq, tree_nodes)[0]
1.412 - def compile(self, seq, tree_nodes):
1.413 - stack = []
1.414 - while len(seq):
1.415 - s = seq.pop()
1.416 - if s == 0:
1.417 - c, v = tree_nodes.pop()
1.418 - while c != Variable:
1.419 - c, v = tree_nodes.pop()
1.420 - stack.append(Variable(v))
1.421 - elif s == 1:
1.422 - stack.append(Not(self.compile(seq, tree_nodes)))
1.423 - elif s == 2:
1.424 - stack.extend(self.compile(seq, tree_nodes))
1.425 - elif s == 3:
1.426 - stack.append(Box(self.compile(seq, tree_nodes)))
1.427 - elif s == 4:
1.428 - stack.append(Diamond(self.compile(seq, tree_nodes)))
1.429 - elif s == 5:
1.430 - stack.append(And(self.compile(seq, tree_nodes)))
1.431 - elif s == 6:
1.432 - stack.append(Or(self.compile(seq, tree_nodes)))
1.433 - elif s == 7:
1.434 - stack.append(Imp(self.compile(seq, tree_nodes)))
1.435 - elif s == 8:
1.436 - stack.append(Eq(self.compile(seq, tree_nodes)))
1.437 - return stack
1.438 -
1.439 -from argparse import ArgumentParser
1.440 -
1.441 -def parse_arguments():
1.442 - parser = ArgumentParser(description="Tries to parse simple modal logic syntax and reduces the formula. Edit your formula directly in the code file for best results.")
1.443 - parser.add_argument("-f", "--formula", help="provide your own formula here, or better don't")
1.444 - parser.add_argument("-d", "--dimacs", help="output file for the CNF DIMACS output")
1.445 - return parser.parse_args()
1.446 -
1.447 -EXCUSE = """The formula was not accepted by me, because I do not like you. It is not personal. I seem to have some issues with formulae with inner nesting and I generally suffer from my hasty implementation. I would like to thank you for your coorporation by providing the formula within the code file itself. Thank you. ~The Parser"""
1.448 -
1.449 -if __name__ == "__main__":
1.450 - main()
2.1 Binary file downloads/sml.zip has changed