def get_group(name): special = { 'LESS': 'PositiveOrder', 'NLESS': 'NegativeOrder', '<variable>': 'Exists', } return special.get(name, signature.get_arity(name))
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)
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)
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
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
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)
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
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()
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
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)
def make_template(name): assert isinstance(name, str), name holes = [HOLE] * get_nargs(get_arity(name)) return Expression.make(name, *holes)