Skip to content
Snippets Groups Projects
randmu.py 15 KiB
Newer Older
  • Learn to ignore specific revisions
  • #!/usr/bin/python3
    #
    # Ideal:
    
    #   Start with a single variable. While formula is still below the
    #   target size, replace a random variable by a random
    #   connective. once the target size has been reached, replace all
    #   unguarded variables by propositional atoms. Replace all remaining
    #   variables by either an allowed fixpoint variable or a
    #   propositional atom
    
    import random
    import string
    import argparse
    import os
    
    
    variables = []
    
    syntax = 'cool'
    
    
    
    def _gensym():
        i = 0
        while True:
            i = i + 1
    
            yield "G%d" % i
    
    
    
    gensym = iter(_gensym())
    
    
    
    class Connective:
        pass
    
    
    
    class Propositional(Connective):
        pass
    
    
    
    class And(Propositional):
        def __init__(self):
            self._left = Variable(self)
            self._right = Variable(self)
    
    
        def __str__(self):
            left = str(self._left)
            right = str(self._right)
    
            if syntax == 'tatl':
                return "((%s) /\ (%s))" % (left, right)
            else:
                return "((%s) & (%s))" % (left, right)
    
    
    
        def replace(self, what, withw):
            if what == self._left:
                self._left = withw
            else:
                assert self._right == what
                self._right = withw
    
    
        def finalize(self, atoms, guarded, unguarded, fixpoint):
    
    Christoph's avatar
    Christoph committed
            self._left.finalize(atoms, guarded, unguarded, fixpoint)
            self._right.finalize(atoms, guarded, unguarded, fixpoint)
    
    
    
    
    class Or(Propositional):
        def __init__(self):
            self._left = Variable(self)
            self._right = Variable(self)
    
    
        def __str__(self):
            left = str(self._left)
            right = str(self._right)
    
            if syntax == 'tatl':
                return "((%s) \/ (%s))" % (left, right)
            else:
                return "((%s) | (%s))" % (left, right)
    
    
    
        def replace(self, what, withw):
            if what == self._left:
                self._left = withw
            else:
                assert self._right == what
                self._right = withw
    
    
        def finalize(self, atoms, guarded, unguarded, fixpoint):
    
    Christoph's avatar
    Christoph committed
            self._left.finalize(atoms, guarded, unguarded, fixpoint)
            self._right.finalize(atoms, guarded, unguarded, fixpoint)
    
    
    
    
    class Modal(Connective):
        pass
    
    
    class Box(Modal):
        def __init__(self):
            self._subformula = Variable(self)
    
    
        def __str__(self):
            subformula = str(self._subformula)
    
            if syntax == 'ctl':
                return "AX (%s)" % (subformula,)
            else:
                return "[] (%s)" % (subformula,)
    
    
    
        def replace(self, what, withw):
            assert self._subformula == what
            self._subformula = withw
    
    
        def finalize(self, atoms, guarded, unguarded, fixpoint):
    
    Christoph's avatar
    Christoph committed
            self._subformula.finalize(atoms, guarded + unguarded, [], fixpoint)
    
    
    
    
    class Diamond(Modal):
        def __init__(self):
            self._subformula = Variable(self)
    
    
        def __str__(self):
            subformula = str(self._subformula)
    
            if syntax == 'ctl':
                return "EX (%s)" % (subformula,)
            else:
                return "<> (%s)" % (subformula,)
    
    
    
        def replace(self, what, withw):
            assert self._subformula == what
            self._subformula = withw
    
    
        def finalize(self, atoms, guarded, unguarded, fixpoint):
    
    Christoph's avatar
    Christoph committed
            self._subformula.finalize(atoms, guarded + unguarded, [], fixpoint)
    
    
    
    
    class Fixpoint(Connective):
        pass
    
    class Mu(Fixpoint):
        def __init__(self):
            self._subformula = Variable(self)
            self._var = next(gensym)
    
    
        def __str__(self):
            subformula = str(self._subformula)
    
            if syntax == 'cool':
    
                return "(μ %s . (%s))" % (self._var, subformula)
    
                return "(mu %s . (%s))" % (self._var, subformula)
    
    
    
        def replace(self, what, withw):
            assert self._subformula == what
            self._subformula = withw
    
    
        def finalize(self, atoms, guarded, unguarded, fixpoint):
    
    Christoph's avatar
    Christoph committed
            if fixpoint == 'nu':
                guarded = []
                unguarded = []
    
    Christoph's avatar
    Christoph committed
            self._subformula.finalize(atoms, guarded, unguarded + [self._var], 'mu')
    
    
    
    
    class Nu(Fixpoint):
        def __init__(self):
            self._subformula = Variable(self)
            self._var = next(gensym)
    
    
        def __str__(self):
            subformula = str(self._subformula)
    
            if syntax == 'cool':
    
                return "(ν %s . (%s))" % (self._var, subformula)
    
                return "(nu %s . (%s))" % (self._var, subformula)
    
    
    
        def replace(self, what, withw):
            assert self._subformula == what
            self._subformula = withw
    
    
        def finalize(self, atoms, guarded, unguarded, fixpoint):
    
    Christoph's avatar
    Christoph committed
            if fixpoint == 'mu':
                guarded = []
                unguarded = []
    
    Christoph's avatar
    Christoph committed
            self._subformula.finalize(atoms, guarded, unguarded + [self._var], 'nu')
    
    class CTL(Connective):
        pass
    
    
    
    class AG(CTL):
        def __init__(self):
            self._subformula = Variable(self)
    
    
        def __str__(self):
            subformula = str(self._subformula)
            return "AG (%s)" % (subformula,)
    
    
        def replace(self, what, withw):
            assert self._subformula == what
            self._subformula = withw
    
    
        def finalize(self, atoms, guarded, unguarded, fixpoint):
            self._subformula.finalize(atoms, guarded + unguarded, [], fixpoint)
    
    
    
    class AF(CTL):
        def __init__(self):
            self._subformula = Variable(self)
    
    
        def __str__(self):
            subformula = str(self._subformula)
            return "AF (%s)" % (subformula,)
    
    
        def replace(self, what, withw):
            assert self._subformula == what
            self._subformula = withw
    
    
        def finalize(self, atoms, guarded, unguarded, fixpoint):
            self._subformula.finalize(atoms, guarded + unguarded, [], fixpoint)
    
    
    
    class EG(CTL):
        def __init__(self):
            self._subformula = Variable(self)
    
    
        def __str__(self):
            subformula = str(self._subformula)
            return "EG (%s)" % (subformula,)
    
    
        def replace(self, what, withw):
            assert self._subformula == what
            self._subformula = withw
    
    
        def finalize(self, atoms, guarded, unguarded, fixpoint):
            self._subformula.finalize(atoms, guarded + unguarded, [], fixpoint)
    
    
    
    class EF(CTL):
        def __init__(self):
            self._subformula = Variable(self)
    
    
        def __str__(self):
            subformula = str(self._subformula)
            return "EF (%s)" % (subformula,)
    
    
        def replace(self, what, withw):
            assert self._subformula == what
            self._subformula = withw
    
    
        def finalize(self, atoms, guarded, unguarded, fixpoint):
            self._subformula.finalize(atoms, guarded + unguarded, [], fixpoint)
    
    
    
    class AU(CTL):
        def __init__(self):
            self._left = Variable(self)
            self._right = Variable(self)
    
    
        def __str__(self):
            left = str(self._left)
            right = str(self._right)
            return "A((%s) U (%s))" % (left, right)
    
    
        def replace(self, what, withw):
            if what == self._left:
                self._left = withw
            else:
                assert self._right == what
                self._right = withw
    
    
        def finalize(self, atoms, guarded, unguarded, fixpoint):
            self._left.finalize(atoms, guarded, unguarded, fixpoint)
            self._right.finalize(atoms, guarded, unguarded, fixpoint)
    
    
    
    class AR(CTL):
        def __init__(self):
            self._left = Variable(self)
            self._right = Variable(self)
    
    
        def __str__(self):
            left = str(self._left)
            right = str(self._right)
            return "A((%s) R (%s))" % (left, right)
    
    
        def replace(self, what, withw):
            if what == self._left:
                self._left = withw
            else:
                assert self._right == what
                self._right = withw
    
    
        def finalize(self, atoms, guarded, unguarded, fixpoint):
            self._left.finalize(atoms, guarded, unguarded, fixpoint)
            self._right.finalize(atoms, guarded, unguarded, fixpoint)
    
    
    
    class EU(CTL):
        def __init__(self):
            self._left = Variable(self)
            self._right = Variable(self)
    
    
        def __str__(self):
            left = str(self._left)
            right = str(self._right)
            return "E((%s) U (%s))" % (left, right)
    
    
        def replace(self, what, withw):
            if what == self._left:
                self._left = withw
            else:
                assert self._right == what
                self._right = withw
    
    
        def finalize(self, atoms, guarded, unguarded, fixpoint):
            self._left.finalize(atoms, guarded, unguarded, fixpoint)
            self._right.finalize(atoms, guarded, unguarded, fixpoint)
    
    
    
    class ER(CTL):
        def __init__(self):
            self._left = Variable(self)
            self._right = Variable(self)
    
    
        def __str__(self):
            left = str(self._left)
            right = str(self._right)
            return "E((%s) R (%s))" % (left, right)
    
    
        def replace(self, what, withw):
            if what == self._left:
                self._left = withw
            else:
                assert self._right == what
                self._right = withw
    
    
        def finalize(self, atoms, guarded, unguarded, fixpoint):
            self._left.finalize(atoms, guarded, unguarded, fixpoint)
            self._right.finalize(atoms, guarded, unguarded, fixpoint)
    
    
    
    
    class ATL:
        def coalition(self):
    
            if not hasattr(self, '_coalition'):
                self._coalition = []
                while len(self._coalition) == 0:
                    self._coalition = []
                    for i in range(1, 6):
                        if random.getrandbits(1) == 1:
                            self._coalition.append(str(i))
    
            if syntax == 'tatl':
                return ",".join(self._coalition)
            else:
                return " ".join(self._coalition)
    
    
    
    
    class Next(ATL):
        def __init__(self):
            self._subformula = Variable(self)
    
    
        def __str__(self):
            subformula = str(self._subformula)
            if syntax == 'tatl':
    
                return "<<%s>>X(%s)" % (self.coalition(), subformula,)
    
                return "[{%s}](%s)" % (self.coalition(), subformula,)
    
    
    
        def replace(self, what, withw):
            assert self._subformula == what
            self._subformula = withw
    
    
        def finalize(self, atoms, guarded, unguarded, fixpoint):
            self._subformula.finalize(atoms, guarded + unguarded, [], fixpoint)
    
    
    
    class Always(ATL):
        def __init__(self):
            self._subformula = Variable(self)
    
    
        def __str__(self):
            subformula = str(self._subformula)
            if syntax == 'tatl':
    
                return "<<%s>>G(%s)" % (self.coalition(), subformula,)
    
                return "(ν X . ((%s) & [{%s}]X))" % (subformula,self.coalition())
    
    
    
        def replace(self, what, withw):
            assert self._subformula == what
            self._subformula = withw
    
    
        def finalize(self, atoms, guarded, unguarded, fixpoint):
            self._subformula.finalize(atoms, guarded + unguarded, [], fixpoint)
    
    
    
    class Eventually(ATL):
        def __init__(self):
            self._subformula = Variable(self)
    
    
        def __str__(self):
            subformula = str(self._subformula)
            if syntax == 'tatl':
                return "<<%s>>F(%s)" % (self.coalition(), subformula,)
            else:
    
                return "(μ X . ((%s) | [{%s}]X))" % (subformula, self.coalition())
    
    
    
        def replace(self, what, withw):
            assert self._subformula == what
            self._subformula = withw
    
    
        def finalize(self, atoms, guarded, unguarded, fixpoint):
            self._subformula.finalize(atoms, guarded + unguarded, [], fixpoint)
    
    
    
    class Until(ATL):
        def __init__(self):
            self._left = Variable(self)
            self._right = Variable(self)
    
    
        def __str__(self):
            left = str(self._left)
            right = str(self._right)
            if syntax == 'tatl':
                return "<<%s>>((%s) U (%s))" % (self.coalition(),left, right)
            else:
    
                return "(μ X . ((%s) | ((%s) & [{%s}]X)))" % (right,left,self.coalition())
    
    
    
        def replace(self, what, withw):
            if what == self._left:
                self._left = withw
            else:
                assert self._right == what
                self._right = withw
    
    
        def finalize(self, atoms, guarded, unguarded, fixpoint):
            self._left.finalize(atoms, guarded, unguarded, fixpoint)
            self._right.finalize(atoms, guarded, unguarded, fixpoint)
    
    
    
    
    connectives = []
    
    
    
    class Variable:
        def __init__(self, parent):
            self._parent = parent
            variables.append(self)
    
    
        def __str__(self):
            return "(undecided)"
    
    
        def replace(self):
            assert self._parent != None
            replacement = random.choice(connectives)()
            variables.remove(self)
            self._parent.replace(self, replacement)
    
    
        def finalize(self, atoms, guarded, unguarded, fixpoint):
    
    Christoph's avatar
    Christoph committed
            choice = random.choice(guarded + atoms)
            if choice in atoms:
                choice = random.choice([choice, "~%s" % choice])
    
            variables.remove(self)
            self._parent.replace(self, choice)
    
        global connectives
        if args.logic == 'afmu':
            connectives = [And, And, Or, Or, Box, Diamond, Mu, Nu]
            os.makedirs(os.path.join(args.destdir, 'cool'))
            os.makedirs(os.path.join(args.destdir, 'mlsolver'))
    
        elif args.logic == 'CTL':
    
            connectives = [And, And, Or, Or, Box, Diamond, AF, AG, EF, EG, AU, EU]
    
            os.makedirs(os.path.join(args.destdir, 'ctl'))
    
    
        elif args.logic == 'ATL':
            connectives = [And, And, Or, Or, Next, Always, Eventually, Until]
            os.makedirs(os.path.join(args.destdir, 'cool'))
            os.makedirs(os.path.join(args.destdir, 'tatl'))
    
    
        for i in range(0, args.count):
            global variables
    
            global syntax
    
            variables = []
            formula = random.choice(connectives)()
    
            for _ in range(0, args.constructors):
                random.choice(variables).replace()
    
            formula.finalize(list(string.ascii_lowercase[:args.atoms]), [], [], 'none')
    
            if args.logic == 'afmu':
                with open(os.path.join(args.destdir, 'cool', 'random.%04d.cool' % i), 'w') as f:
                    syntax = 'cool'
                    f.write(str(formula))
    
                with open(os.path.join(args.destdir, 'mlsolver', 'random.%04d.mlsolver' % i), 'w') as f:
                    syntax = 'mlsolver'
                    f.write(str(formula))
    
            elif args.logic == 'CTL':
                with open(os.path.join(args.destdir, 'ctl', 'random.%04d.ctl' % i), 'w') as f:
    
    Christoph's avatar
    Christoph committed
                    syntax = 'ctl'
    
                    f.write(str(formula))
    
            elif args.logic == 'ATL':
                with open(os.path.join(args.destdir, 'cool', 'random.%04d.cool' % i), 'w') as f:
                    syntax = 'cool'
                    f.write(str(formula))
    
                with open(os.path.join(args.destdir, 'tatl', 'random.%04d.tatl' % i), 'w') as f:
                    syntax = 'tatl'
                    f.write(str(formula))
    
    
        print(args.destdir)
    
    if __name__ == '__main__':
        parser = argparse.ArgumentParser(description="Generator for random μ-Calculus-Formulas")
        parser.add_argument('--atoms', type=int, required=True,
                            help="Number of propositional arguments to use")
        parser.add_argument('--constructors', type=int, required=True,
                            help="Number of connectives to build")
        parser.add_argument('--count', type=int, required=True,
                            help="Number of formulas to generate")
        parser.add_argument('--destdir', type=str, required=True,
                            help="Directory to place created formulas in")
    
        parser.add_argument('--logic', choices=['CTL', 'ATL', 'afmu'], required=True)
    
    
        args = parser.parse_args()
    
        main(args)