Пример #1
0
 def get_group(name):
     special = {
         'LESS': 'PositiveOrder',
         'NLESS': 'NegativeOrder',
         '<variable>': 'Exists',
     }
     return special.get(name, signature.get_arity(name))
Пример #2
0
 def __init__(self, name, *args):
     assert isinstance(name, str)
     assert re.match('[a-zA-Z][a-zA-Z_]*$', name),\
         'invalid name: {0}'.format(name)
     args = list(args)
     arity = signature.get_arity(name)
     assert len(args) == signature.get_nargs(arity)
     for arg in args:
         assert isinstance(arg, Expression), arg
     self._name = name
     self._args = args
     self._arity = arity
     self._polish = ' '.join([name] + [arg._polish for arg in args])
     self._hash = hash(self._polish)
     if arity == 'Variable':
         self._var = self
         self._vars = set([self])
     elif arity == 'NullaryFunction':
         self._var = Expression(name + '_')
         self._vars = set()
     elif arity in [
             'InjectiveFunction',
             'BinaryFunction',
             'SymmetricFunction',
     ]:
         var = re.sub('[ _]+', '_', self.polish).rstrip('_')
         self._var = Expression(var)
         self._vars = union(arg.vars for arg in args)
     else:
         self._var = None
         self._vars = union(arg.vars for arg in args)
Пример #3
0
def IterInvBinary_program(self, program, stack=None, poll=None):
    ARITY = signature.get_arity(self.fun).replace('Function', '').upper()
    program.append('FOR_{ARITY}_FUNCTION_VAL {fun} {lhs} {rhs} {val}'.format(
        ARITY=ARITY,
        fun=self.fun,
        lhs=self.var1,
        rhs=self.var2,
        val=self.value))
    if poll:
        raise NotImplementedError('cannot poll IterInvBinary')
        # program.append('IF_BLOCK {val}'.format(val=self.var1))  # arbitrary
    self.body.program(program)
Пример #4
0
def get_symbols_used_in(sequents, exprs):
    symbols = {}
    tokens = set()
    for seq in sequents:
        assert isinstance(seq, Sequent), seq
        for expr in seq.antecedents | seq.succedents:
            tokens |= set(expr.polish.split())
    for expr in exprs:
        assert isinstance(expr, Expression), expr
        tokens |= set(expr.polish.split())
    for token in list(tokens):
        if signature.get_arity(token) in signature.RELATION_ARITIES:
            try:
                tokens.add(try_negate_name(token))
            except NotNegatable:
                pass
    valid_arities = signature.FUNCTION_ARITIES | signature.RELATION_ARITIES
    for c in tokens:
        arity = signature.get_arity(c)
        if arity in valid_arities:
            symbols.setdefault(signature.get_arity(c), []).append(c)
    for val in symbols.itervalues():
        val.sort()
    return symbols
Пример #5
0
def get_functions_used_in(sequents, exprs):
    functions = dict((arity, []) for arity in signature.FUNCTION_ARITIES)
    symbols = set()
    for seq in sequents:
        assert isinstance(seq, Sequent), seq
        for expr in seq.antecedents | seq.succedents:
            symbols |= set(expr.polish.split())
    for expr in exprs:
        assert isinstance(expr, Expression), expr
        symbols |= set(expr.polish.split())
    for c in symbols:
        if signature.is_fun(c):
            functions[signature.get_arity(c)].append(c)
    for val in functions.itervalues():
        val.sort()
    return functions
Пример #6
0
def IterInvBinaryRange_program(self, program, stack=None, poll=None):
    PARITY = ('LHS' if self.lhs_fixed else 'RHS')
    ARITY = signature.get_arity(self.fun).replace('Function', '').upper()

    line = 'FOR_{ARITY}_FUNCTION_{PARITY}_VAL {fun} {lhs} {rhs} {val}'.format(
        ARITY=ARITY,
        PARITY=PARITY,
        fun=self.fun,
        lhs=self.var1,
        rhs=self.var2,
        val=self.value)
    program.append(line)
    if poll:
        raise NotImplementedError('cannot poll IterInvBinaryRange')
        # program.append('IF_BLOCK {val}'.format(val=var))  # arbitrary
    self.body.program(program)
Пример #7
0
 def __init__(self, name, *args):
     assert isinstance(name, str), type(name)
     assert re_name.match(name), name
     arity = signature.get_arity(name)
     assert len(args) == signature.get_nargs(arity), (args, arity)
     for arg in args:
         assert isinstance(arg, Expression), arg
     self._name = intern(name)
     self._args = args
     self._arity = arity
     self._polish = intern(' '.join([name] + [arg._polish for arg in args]))
     self._hash = hash(self._polish)
     self._sort = (len(self._polish), self._polish)
     # all other fields are lazily initialized
     self._var = None
     self._vars = None
     self._consts = None
     self._terms = None
Пример #8
0
def write_event_tasks(code, sequents):

    code(
        '''
        $bar
        // event tasks
        ''',
        bar=bar,
    ).newline()

    event_tasks = {}
    for sequent in sequents:
        for event in compiler.get_events(sequent):
            name = '<variable>' if event.is_var() else event.name
            tasks = event_tasks.setdefault(name, [])
            strategies = compiler.compile_given(sequent, event)
            strategies.sort(key=lambda (cost, _): cost)
            costs = [cost for cost, _ in strategies]
            cost = log_sum_exp(*costs)
            tasks.append((event, cost, strategies))

    def get_group(name):
        special = {
            'LESS': 'PositiveOrder',
            'NLESS': 'NegativeOrder',
            '<variable>': 'Exists',
        }
        return special.get(name, signature.get_arity(name))

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

    # TODO sort groups
    # event_tasks = event_tasks.items()
    # event_tasks.sort(key=lambda (name, tasks): (len(tasks), len(name), name))

    group_tasks = list(group_tasks.iteritems())
    group_tasks.sort()

    for groupname, group in group_tasks:
        group = list(group.iteritems())
        group.sort()

        body = Code()

        for eventname, tasks in group:
            subbody = Code()
            nargs = signature.get_nargs(signature.get_arity(group[0][0]))
            args = [[], ['arg'], ['lhs', 'rhs']][nargs]
            for arg in args:
                subbody('const Ob $arg = task.$arg;', arg=arg)
            if signature.is_fun(eventname):
                subbody(
                    '''
                    const Ob val = $eventname.find($args);
                    ''',
                    eventname=eventname,
                    args=', '.join(args))

            for event, _, strategies in tasks:
                subsubbody = Code()
                diagonal = (nargs == 2 and event.args[0] == event.args[1])
                if diagonal:
                    subsubbody(
                        '''
                        const Ob $local __attribute__((unused)) = $arg;
                        ''',
                        local=event.args[0],
                        arg=args[0],
                    )
                else:
                    for local, arg in zip(event.args, args):
                        subsubbody(
                            '''
                            const Ob $local __attribute__((unused)) = $arg;
                            ''',
                            local=local,
                            arg=arg,
                        )
                if event.is_fun():
                    subsubbody('const Ob $arg = val;', arg=event.var.name)
                elif event.is_var():
                    subsubbody('const Ob $arg = task.ob;', arg=event.name)
                subcost = 0
                for cost, strategy in strategies:
                    subsubbody.newline()
                    strategy.cpp(subsubbody)
                    subcost += cost
                if diagonal:
                    subbody(
                        '''
                        if (lhs == rhs) { // cost = $cost
                            $subsubbody
                        }
                        ''',
                        cost=cost,
                        subsubbody=wrapindent(subsubbody),
                    )
                else:
                    subbody(
                        '''
                        { // cost = $cost
                            $subsubbody
                        }
                        ''',
                        cost=cost,
                        subsubbody=wrapindent(subsubbody),
                    )

            if eventname in ['LESS', 'NLESS', '<variable>']:
                body(str(subbody)).newline()
            else:
                body(
                    '''
                if (task.fun == & $eventname) {
                    $subbody
                }
                ''',
                    eventname=eventname,
                    subbody=wrapindent(subbody),
                ).newline()

        code(
            '''
            void execute (const ${groupname}Task & task)
            {
                $body
            }
            ''',
            groupname=groupname,
            body=wrapindent(body),
        ).newline()

    nontrivial_arities = [groupname for groupname, _ in group_tasks]
    for arity in signature.FUNCTION_ARITIES:
        if arity not in nontrivial_arities:
            code(
                '''
                void execute (const ${arity}Task &) {}
                ''',
                arity=arity,
            ).newline()
Пример #9
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
Пример #10
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)
Пример #11
0
def make_template(name):
    assert isinstance(name, str), name
    holes = [HOLE] * get_nargs(get_arity(name))
    return Expression.make(name, *holes)