Beispiel #1
0
def test_abstraction():
    x = Expression.make('x')
    y = Expression.make('y')
    z = Expression.make('z')

    assert lam(x, x) == I
    assert lam(x, y) == APP(K, y)

    assert lam(y, APP(APP(x, y), y)) == APP(W, x)
    assert lam(z, APP(APP(x, z), APP(y, z))) == APP(APP(S, x), y)
    assert lam(z, APP(APP(x, z), y)) == APP(APP(C, x), y)
    assert lam(z, APP(x, APP(y, z))) == COMP(x, y)

    assert lam(z, COMP(APP(x, z), APP(y, z))) == APP(APP(S, COMP(B, x)), y)
    assert lam(z, COMP(APP(x, z), y)) == COMP(APP(CB, y), x)
    assert lam(z, COMP(x, APP(y, z))) == COMP(APP(B, x), y)
    assert lam(y, COMP(x, y)) == APP(B, x)
    assert lam(x, COMP(x, y)) == APP(CB, y)

    assert lam(z, JOIN(APP(x, z), APP(y, z))) == JOIN(x, y)
    assert lam(z, JOIN(x, APP(y, z))) == COMP(APP(J, x), y)
    assert lam(z, JOIN(APP(x, z), y)) == COMP(APP(J, y), x)
    assert lam(y, JOIN(x, y)) == APP(J, x)
    assert lam(x, JOIN(x, y)) == APP(J, y)

    assert lam(z, RAND(APP(x, z), APP(y, z))) == RAND(x, y)
    assert lam(z, RAND(x, APP(y, z))) == COMP(APP(R, x), y)
    assert lam(z, RAND(APP(x, z), y)) == COMP(APP(R, y), x)
    assert lam(y, RAND(x, y)) == APP(R, x)
    assert lam(x, RAND(x, y)) == APP(R, y)
Beispiel #2
0
def validate(expr):
    assert expr.is_rel(), expr
    assert expr.name in ['LESS', 'EQUAL']
    if expr.name != 'EQUAL':
        print 'WARNING: not validating {0}'.format(expr)
        return
    while True:
        try:
            lhs, rhs = expr.args
            lhs = head_normalize(lhs)
            rhs = head_normalize(rhs)
            assert len(lhs) == len(rhs),\
                'Failed to validate\n  {0}\nbecause\n  {1} != {2}'.format(
                    expr, lhs, rhs)
            assert lhs[0] == rhs[0],\
                'Failed to validate\n  {0}\nbecause  \n{1} != {2}'.format(
                    expr, lhs[0], rhs[0])
            for args in zip(lhs[1:], rhs[1:]):
                validate(Expression.make(expr.name, *args))
            break
        except RequireVariable:
            lhs, rhs = expr.args
            fresh = get_fresh(expr.vars)
            lhs = APP(lhs, fresh)
            rhs = APP(rhs, fresh)
            expr = Expression.make(expr.name, lhs, rhs)
        except SkipValidation:
            print 'WARNING: not validating {0}'.format(expr)
            return
Beispiel #3
0
 def __call__(self, term):
     nargs = len(term.args)
     if nargs == 0:
         return self._fillings if term is HOLE else ()
     elif nargs == 1:
         name = term.name
         key, = term.args
         return tuple(Expression.make(name, f) for f in self(key))
     elif nargs == 2:
         name = term.name
         lhs, rhs = term.args
         return tuple(itertools.chain(
             (Expression.make(name, f, rhs) for f in self(lhs)),
             (Expression.make(name, lhs, f) for f in self(rhs)),
         ))
Beispiel #4
0
def define_a(
        max_solutions=15,
        max_memory=pomagma.analyst.synthesize.MAX_MEMORY,
        verbose=1,
        address=pomagma.analyst.ADDRESS):
    '''
    Search for definition of A = Join {<r, s> | r o s [= I}.
    Tip: use pyprofile and snakeviz to profile this function:
    $ pyprofile -o define_a.pstats -s time src/examples/synthesize.py define_a
    $ snakeviz define_a.pstats
    '''
    assert max_solutions > 0, max_solutions
    assert 0 < max_memory and max_memory < 1, max_memory
    facts = parse_facts(A_THEORY)
    hole = Expression.make('hole')
    initial_sketch = parse_expr('HOLE')
    language = {
        'APP': 1.0,
        # 'COMP': 1.6,
        'JOIN': 3.0,
        'B': 1.0,
        'C': 1.3,
        'A': 2.0,
        'BOT': 2.0,
        'TOP': 2.0,
        'I': 2.2,
        # 'Y': 2.3,
        'K': 2.6,
        'S': 2.7,
        'J': 2.8,
        'DIV': 3.0,
    }
    with pomagma.analyst.connect(address) as db:
        results = synthesize_from_facts(
            db=db,
            facts=facts,
            var=hole,
            initial_sketch=initial_sketch,
            language=language,
            max_solutions=max_solutions,
            max_memory=max_memory,
            verbose=verbose)
    print 'Possible Fillings:'
    APP = Expression_2('APP')
    f = Expression.make('f')
    for complexity, term, filling in results:
        print simplify_expr(APP(filling, f))
    return results
Beispiel #5
0
def unguard_vars(expr):
    if expr.name == 'VAR':
        return expr.args[0]
    elif expr.is_var():
        return expr
    else:
        args = map(unguard_vars, expr.args)
        return Expression.make(expr.name, *args)
Beispiel #6
0
def guard_vars(expr):
    """Whereas pomagma.compiler follows the variable naming convention defined
    in pomagma.compiler.signature.is_var(), pomagma.analyst.validate and the
    puddle editor require VAR guarded variables."""
    if expr.name == 'VAR':
        return expr
    elif expr.is_var():
        return VAR(expr)
    else:
        args = map(guard_vars, expr.args)
        return Expression.make(expr.name, *args)
Beispiel #7
0
def weaken_sequent(fact):
    if fact.arity == 'UnaryMeta':
        return Expression.make(fact.name, weaken_sequent(fact.args[0]))
    else:
        assert fact.is_rel(), fact
        if fact.name == 'EQUAL':
            lhs, rhs = fact.args
            if lhs == TOP or rhs == BOT:
                return LESS(lhs, rhs)
            elif rhs == TOP or lhs == BOT:
                return LESS(rhs, lhs)
        return fact
Beispiel #8
0
def test_compile_S():
    # Compiling incremental search given: APP APP_x_y APP_y_z
    # cost = 2.70067540518
    # if S
    # for x let APP_S_x
    # for y if APP x y let APP_APP_S_x_y
    # for z if APP y z let APP_APP_APP_S_x_y_z
    # ensure EQUAL APP_APP_APP_S_x_y_z APP_APP_x_z_APP_y_z
    S = Expression.make('S')
    _test_sequent(
        [],
        [EQUAL(APP(APP(APP(S, x), y), z), APP(APP(x, z), APP(y, z)))])
Beispiel #9
0
def desugar_expr(self):
    expr = Expression.make(self.name, *map(desugar_expr, self.args))
    if expr.name == 'FUN':
        var, body = expr.args
        assert var.is_var(), var
        expr = body.abstract(var)
    elif expr.name == 'FIX':
        var, body = expr.args
        assert var.is_var(), var
        expr = APP(Y, body.abstract(var))
    elif expr.name == 'PAIR':
        x, y = expr.args
        expr = COMP(APP(CI, y), APP(CI, x))
    elif expr.name == 'ABIND':
        r, s, body = expr.args
        assert r.is_var(), r
        assert s.is_var(), s
        expr = APP(A, body.abstract(s).abstract(r))
    elif expr.name == 'FIXES':
        typ, inhab = expr.args
        expr = EQUAL(APP(typ, inhab), inhab)
    return expr
Beispiel #10
0
def as_succedent(expr, bound):
    while expr.name in ['OPTIONALLY', 'NONEGATE']:
        expr = expr.args[0]
    antecedents = set()
    if expr.arity == 'Equation':
        args = []
        for arg in expr.args:
            if arg.is_var() or arg.var in bound:
                args.append(arg.var)
            elif arg.args:
                args.append(as_atom(arg))
                for argarg in arg.args:
                    antecedents |= as_antecedents(argarg, bound)
            else:
                assert arg.arity == 'NullaryFunction', arg
                args.append(arg.var)
                antecedents.add(arg)
        succedent = Expression.make(expr.name, *args)
    else:
        assert expr.args, expr.args
        succedent = as_atom(expr)
        for arg in expr.args:
            antecedents |= as_antecedents(arg, bound)
    return antecedents, succedent
Beispiel #11
0
def write_event_programs(programs, sequents):

    event_tasks = {}
    for sequent in sequents:
        for event in compiler.get_events(sequent):
            name = 'Variable' if event.is_var() else event.name
            plans = sorted(compiler.compile_given(sequent, event))
            cost = add_costs(c for (c, _, _) in plans)
            tasks = event_tasks.setdefault(name, [])
            tasks.append((cost, event, sequent, plans))

    group_tasks = {}
    for name, tasks in event_tasks.iteritems():
        groupname = signature.get_arity(name)
        group_tasks.setdefault(groupname, {})[name] = sorted(tasks)

    group_tasks = sorted(group_tasks.iteritems())
    group_id = 0
    for groupname, group in group_tasks:
        group = sorted(group.iteritems())
        arity = signature.get_arity(group[0][0])

        for eventname, tasks in group:
            total_cost = add_costs(c for (c, _, _, _) in tasks)
            programs += [
                '',
                '# ' + '-' * 76,
                '# plans {}.*: total cost = {:0.1f}'.format(
                    group_id,
                    total_cost),
                '# given {}'.format(eventname),
            ]

            plan_id = 0
            for _, event, sequent, plans in tasks:
                diagonal = (
                    len(event.args) == 2 and event.args[0] == event.args[1])
                if diagonal:
                    lhs = event.args[0]
                    assert lhs.arity == 'Variable'
                    rhs = Expression.make(lhs.name + '_')
                    event = Expression.make(event.name, lhs, rhs)

                if arity == 'Variable':
                    given = 'GIVEN_EXISTS {var}'.format(var=event.name)
                elif arity == 'UnaryRelation':
                    given = 'GIVEN_UNARY_RELATION {rel} {key}'.format(
                        rel=event.name,
                        key=event.args[0])
                elif arity == 'BinaryRelation':
                    given = 'GIVEN_BINARY_RELATION {rel} {lhs} {rhs}'.format(
                        rel=event.name,
                        lhs=event.args[0],
                        rhs=event.args[1])
                elif arity == 'NullaryFunction':
                    given = 'GIVEN_NULLARY_FUNCTION {fun} {val}'\
                        .format(
                            fun=event.name,
                            val=event.var.name)
                elif arity == 'InjectiveFunction':
                    given = 'GIVEN_INJECTIVE_FUNCTION {fun} {key} {val}'\
                        .format(
                            fun=event.name,
                            key=event.args[0],
                            val=event.var.name)
                elif arity == 'BinaryFunction':
                    given = 'GIVEN_BINARY_FUNCTION {fun} {lhs} {rhs} {val}'\
                        .format(
                            fun=event.name,
                            lhs=event.args[0],
                            rhs=event.args[1],
                            val=event.var.name)
                elif arity == 'SymmetricFunction':
                    given = 'GIVEN_SYMMETRIC_FUNCTION {fun} {lhs} {rhs} {val}'\
                        .format(
                            fun=event.name,
                            lhs=event.args[0],
                            rhs=event.args[1],
                            val=event.var.name)
                else:
                    raise ValueError('invalid arity: {}'.format(arity))
                header = [given]

                if diagonal:
                    header.append('IF_EQUAL {lhs} {rhs}'.format(
                        lhs=event.args[0],
                        rhs=event.args[1]))

                for cost, seq, plan in plans:
                    programs += [
                        '',
                        '# plan {}.{}: cost = {:0.1f}'.format(
                            group_id,
                            plan_id,
                            cost),
                        '# using {}'.format(sequent),
                        '# infer {}'.format(seq),
                    ]
                    programs += header
                    plan.program(programs)
                    plan_id += 1

            group_id += 1
Beispiel #12
0
from parsable import parsable

import pomagma.analyst
from pomagma.analyst.synthesize import synthesize_from_facts
from pomagma.compiler.expressions import Expression, Expression_2
from pomagma.compiler.parser import parse_string_to_expr, parse_theory_string
from pomagma.compiler.simplify import simplify_expr
from pomagma.compiler.sugar import desugar_expr

APP = Expression_2('APP')
K = Expression.make('K')
F = Expression.make('F')


def parse_expr(string):
    return desugar_expr(parse_string_to_expr(string))


def parse_facts(string):
    facts = parse_theory_string(string)['facts']
    facts = map(desugar_expr, facts)
    for fact in facts:
        for var in fact.vars:
            assert len(var.name) > 2, 'unbound variable: {}'.format(var)
    return facts


A_THEORY = (
    '''
    EQUAL conj FUN s FUN r FUN f COMP r COMP f s
    EQUAL conj FUN s FUN r FUN f COMP COMP r f s
Beispiel #13
0
def parse_tokens_to_expr(tokens):
    head = tokens.pop()
    arity = get_arity(head)
    nargs = get_nargs(arity)
    args = [parse_tokens_to_expr(tokens) for _ in xrange(nargs)]
    return Expression.make(head, *args)
Beispiel #14
0
def test_compile_I():
    I = Expression.make('I')
    _test_sequent(
        [],
        [EQUAL(APP(I, x), x)])
Beispiel #15
0
def test_compile_ap_quote():
    AP = Expression.make('AP')
    _test_sequent(
        [],
        [EQUAL(APP(APP(AP, QUOTE(x)), QUOTE(y)), QUOTE(APP(x, y)))])
Beispiel #16
0
def test_compile_qt_quote():
    QT = Expression.make('QT')
    _test_sequent(
        [],
        [EQUAL(APP(QT, QUOTE(x)), QUOTE(QUOTE(x)))])
Beispiel #17
0
def test_compile_eval():
    EVAL = Expression.make('EVAL')
    _test_sequent(
        [],
        [EQUAL(APP(EVAL, QUOTE(x)), x)])
Beispiel #18
0
def test_compile_comp_x_x_x():
    U = Expression.make('U')
    _test_sequent(
        [EQUAL(COMP(x, x), x)],
        [EQUAL(x, APP(U, x))])
Beispiel #19
0
def test_compile_bot():
    BOT = Expression.make('BOT')
    _test_sequent(
        [],
        [LESS(BOT, x)])
Beispiel #20
0
def test_compile_Y():
    Y = Expression.make('Y')
    _test_sequent(
        [],
        [EQUAL(APP(Y, f), APP(f, APP(Y, f)))])
Beispiel #21
0
def as_atom(expr):
    args = [arg.var for arg in expr.args]
    return Expression.make(expr.name, *args)
Beispiel #22
0
def test_compile_K():
    K = Expression.make('K')
    _test_sequent(
        [],
        [EQUAL(APP(APP(K, x), y), x)])
Beispiel #23
0
def get_fresh(bound):
    for name in 'abcdefghijklmnopqrstuvwxyz':
        fresh = Expression.make(name)
        if fresh not in bound:
            return fresh
    raise NotImplementedError('Exceeded fresh variable limit')
Beispiel #24
0
from pomagma.compiler.expressions import Expression
from pomagma.compiler.parser import parse_corpus
from pomagma.compiler.util import inputs
from pomagma.util import TODO

HOLE = Expression.make('HOLE')


class Corpus(object):
    '''
    Corpus is a general-recursive set of definitions with holes.
    '''

    def __init__(self):
        self._defs = {}

    def load(self, filename):
        with open(filename) as f:
            self._defs = parse_corpus(f, filename=filename)

    def dump(self, filename):
        with open(filename, 'w') as f:
            f.write('# Corpus written by {}'.format(__file__))
            for var, expr in sorted(self._defs.iteritems()):
                assert isinstance(var, basestring), var
                assert isinstance(expr, Expression), expr
                f.write('\nEQUAL {} {}'.format(var, expr))

    def __getitem__(self, var):
        assert isinstance(var, Expression), var
        assert var.is_var(), var
Beispiel #25
0
def abstract(self, var):
    assert isinstance(var, Expression)
    assert var.is_var()
    if self.name == 'VAR':
        self = self.args[0]
    if self.is_var():
        if self == var:
            return I
        else:
            return APP(K, self)
    elif self.is_fun():
        name = self.name
        if var not in self.vars:
            return APP(K, self)
        elif name == 'APP':
            # I,K,C,SW,COMP,eta abstraction
            lhs, rhs = self.args
            if var in lhs.vars:
                lhs_abs = lhs.abstract(var)
                if var in rhs.vars:
                    if rhs == var:
                        return APP(W, lhs_abs)
                    else:
                        return APP(APP(S, lhs_abs), rhs.abstract(var))
                else:
                    return APP(APP(C, lhs_abs), rhs)
            else:
                assert var in rhs.vars
                if rhs == var:
                    return lhs
                else:
                    return COMP(lhs, rhs.abstract(var))
        elif name == 'COMP':
            # K,B,CB,C,S,COMP,eta abstraction
            lhs, rhs = self.args
            if var in lhs.vars:
                lhs_abs = lhs.abstract(var)
                if var in rhs.vars:
                    return APP(APP(S, COMP(B, lhs_abs)), rhs.abstract(var))
                else:
                    if lhs == var:
                        return APP(CB, rhs)
                    else:
                        return COMP(APP(CB, rhs), lhs_abs)
            else:
                assert var in rhs.vars
                if rhs == var:
                    return APP(B, lhs)
                else:
                    return COMP(APP(B, lhs), rhs.abstract(var))
        elif name == 'JOIN':
            return abstract_symmetric(self, var, J, JOIN)
        elif name == 'RAND':
            return abstract_symmetric(self, var, R, RAND)
        else:
            raise AbstractionFailed
    elif self.is_rel():
        args = [arg.abstract(var) for arg in self.args]
        return Expression.make(self.name, *args)
    else:
        raise ValueError('bad expression: %s' % self.name)
Beispiel #26
0
def test_compile_B_comp():
    B = Expression.make('B')
    _test_sequent(
        [],
        [EQUAL(APP(APP(B, x), y), COMP(x, y))])
Beispiel #27
0
def test_compile_W():
    W = Expression.make('W')
    _test_sequent(
        [],
        [EQUAL(APP(APP(W, x), y), APP(APP(x, y), y))])
Beispiel #28
0
def test_compile_C():
    C = Expression.make('C')
    _test_sequent(
        [],
        [EQUAL(APP(APP(APP(C, x), y), z), APP(APP(x, z), y))])
Beispiel #29
0
 def insert(self, key, value='HOLE'):
     var = Expression.make(key)
     expr = Expression.make(value)
     self[var] = expr
Beispiel #30
0
def test_compile_B_app():
    B = Expression.make('B')
    _test_sequent(
        [],
        [EQUAL(APP(APP(APP(B, x), y), z), APP(x, APP(y, z)))])