Beispiel #1
0
    def add_atom(self, atom):
        if not is_atom(atom):
            return False
        head = atom.head
        if head in self.atoms:
            return False
        self.atoms.add(head)
        # TODO: doing this in a way that will eventually allow constants

        for i, stream in enumerate(self.streams):
            for j, domain_atom in enumerate(stream.domain):
                if get_prefix(head) != get_prefix(domain_atom):
                    continue
                if len(head.args) != len(get_args(domain_atom)):
                    raise ValueError(head, domain_atom)
                if any(
                        isinstance(b, Object) and (a != b)
                        for (a, b) in zip(head.args, get_args(domain_atom))):
                    continue
                self.atoms_from_domain[(i, j)].append(head)
                values = [
                    self.atoms_from_domain[(i, k)] if j != k else [head]
                    for k in range(len(stream.domain))
                ]
                domain = list(map(head_from_fact, stream.domain))
                #domain = stream.domain
                for combo in product(*values):
                    mapping = get_mapping(domain, combo)
                    if mapping is None:
                        continue
                    input_objects = tuple(mapping[p] for p in stream.inputs)
                    self._add_instance(stream, input_objects)
        return True
Beispiel #2
0
def fd_from_fact(fact):
    # TODO: convert to evaluation?
    prefix = get_prefix(fact)
    if prefix == NOT:
        return fd_from_fact(fact[1]).negate()
    if prefix == EQ:
        _, head, value = fact
        predicate = get_prefix(head)
        args = map(pddl_from_object, get_args(head))
        fluent = pddl.f_expression.PrimitiveNumericExpression(symbol=predicate,
                                                              args=args)
        expression = pddl.f_expression.NumericConstant(value)
        return pddl.f_expression.Assign(fluent, expression)
    args = map(pddl_from_object, get_args(fact))
    return pddl.Atom(prefix, args)
Beispiel #3
0
    def __init__(self, name, gen_fn, inputs, domain, outputs, certified, info):
        if info is None:
            info = StreamInfo(p_success=None, overhead=None)
        for p, c in Counter(outputs).items():
            if c != 1:
                raise ValueError(
                    'Output [{}] for stream [{}] is not unique'.format(
                        p, name))
        for p in set(inputs) & set(outputs):
            raise ValueError(
                'Parameter [{}] for stream [{}] is both an input and output'.
                format(p, name))
        parameters = {
            a
            for i in certified for a in get_args(i) if is_parameter(a)
        }
        for p in (parameters - set(inputs + outputs)):
            raise ValueError(
                'Parameter [{}] for stream [{}] is not included within outputs'
                .format(p, name))
        super(Stream, self).__init__(name, info, inputs, domain)
        # Each stream could certify a stream-specific fact as well
        if gen_fn == DEBUG:
            #gen_fn = from_fn(lambda *args: tuple(object() for _ in self.outputs))
            gen_fn = from_fn(lambda *args: tuple(
                DebugValue(name, args, o) for o in self.outputs))
        self.gen_fn = gen_fn
        self.outputs = tuple(outputs)
        self.certified = tuple(certified)
        self.constants.update(a for i in certified for a in get_args(i)
                              if not is_parameter(a))

        # TODO: generalize to a hierarchical sequence
        always_unique = False
        if always_unique:
            self.num_opt_fns = 0
            #self.opt_list_fn = get_unique_fn(self)
            self.opt_gen_fn = get_constant_gen_fn(self, None)
        else:
            self.num_opt_fns = 1
            self.opt_gen_fn = get_shared_gen_fn(self) if (
                self.info.opt_gen_fn is None) else self.info.opt_gen_fn
Beispiel #4
0
 def __init__(self, name, info, inputs, domain):
     super(External, self).__init__(name, info)
     for p, c in Counter(inputs).items():
         if c != 1:
             raise ValueError(
                 'Input [{}] for stream [{}] is not unique'.format(p, name))
     parameters = {
         a
         for i in domain for a in get_args(i) if is_parameter(a)
     }
     for p in (parameters - set(inputs)):
         raise ValueError(
             'Parameter [{}] for stream [{}] is not included within inputs'.
             format(p, name))
     self.inputs = tuple(inputs)
     self.domain = tuple(domain)
     self.constants = {
         a
         for i in domain for a in get_args(i) if not is_parameter(a)
     }
     self.instances = {}
Beispiel #5
0
 def __init__(self, head, fn, domain, info):
     if info is None:
         info = FunctionInfo(p_success=self._default_p_success,
                             overhead=self._default_overhead)
     super(Function, self).__init__(get_prefix(head), info, get_args(head),
                                    domain)
     self.head = head
     opt_fn = lambda *args: self._codomain()
     if fn == DEBUG:
         fn = opt_fn
     self.fn = fn
     self.opt_fn = opt_fn if (
         self.info.opt_fn is None) else self.info.opt_fn
Beispiel #6
0
def visualize_constraints(constraints, filename='constraint_network.pdf', use_functions=True):
    from pygraphviz import AGraph

    graph = AGraph(strict=True, directed=False)
    graph.node_attr['style'] = 'filled'
    graph.node_attr['shape'] = 'circle'
    graph.node_attr['fontcolor'] = 'black'
    graph.node_attr['colorscheme'] = 'SVG'
    graph.edge_attr['colorscheme'] = 'SVG'

    functions = set()
    heads = set()
    for fact in constraints:
        if get_prefix(fact) == EQ:
            functions.add(fact[1])
        else:
            heads.add(fact)
    heads.update(functions)

    objects = {a for head in heads for a in get_args(head)}
    optimistic_objects = filter(lambda o: isinstance(o, OptimisticObject), objects)
    for opt_obj in optimistic_objects:
        graph.add_node(str(opt_obj), shape='circle', color=PARAMETER_COLOR)

    for head in heads:
        if not use_functions and (head in functions):
            continue
        # TODO: prune values w/o free parameters?
        name = str_from_tuple(head)
        color = COST_COLOR if head in functions else CONSTRAINT_COLOR
        graph.add_node(name, shape='box', color=color)
        for arg in get_args(head):
            if arg in optimistic_objects:
                graph.add_edge(name, str(arg))
    graph.draw(filename, prog='dot')
    return graph
Beispiel #7
0
def compile_to_exogenous_actions(evaluations, domain, streams):
    import pddl
    # TODO: automatically derive fluents
    # TODO: version of this that operates on fluents of length one?
    # TODO: better instantiation when have full parameters
    # TODO: conversion from stream cost to real cost units?
    # TODO: any predicates derived would need to be replaced as well
    fluent_predicates = get_fluents(domain)
    domain_predicates = {get_prefix(a) for s in streams for a in s.domain}
    if not (domain_predicates & fluent_predicates):
        return

    certified_predicates = {get_prefix(a) for s in streams for a in s.certified}
    future_map = {p: 'f-{}'.format(p) for p in certified_predicates}
    augment_evaluations(evaluations, future_map)
    rename_future = lambda a: rename_atom(a, future_map)
    for stream in list(streams):
        if not isinstance(stream, Stream):
            raise NotImplementedError(stream)
        # TODO: could also just have conditions asserting that one of the fluent conditions fails
        streams.append(create_static_stream(stream, evaluations, fluent_predicates, rename_future))
        stream_atom = streams[-1].certified[0]
        parameters = [pddl.TypedObject(p, 'object') for p in get_args(stream_atom)]
        # TODO: add to predicates as well?
        domain.predicate_dict[get_prefix(stream_atom)] = pddl.Predicate(get_prefix(stream_atom), parameters)
        precondition = pddl.Conjunction(tuple(map(fd_from_fact, (stream_atom,) + tuple(stream.domain))))
        effects = [pddl.Effect(parameters=[], condition=pddl.Truth(),
                               literal=fd_from_fact(fact)) for fact in stream.certified]
        effort = 1 # TODO: use stream info
        #effort = 1 if unit_cost else result.instance.get_effort()
        #if effort == INF:
        #    continue
        fluent = pddl.PrimitiveNumericExpression(symbol=TOTAL_COST, args=[])
        expression = pddl.NumericConstant(int_ceil(effort)) # Integer
        cost = pddl.Increase(fluent=fluent, expression=expression) # Can also be None
        domain.actions.append(pddl.Action(name='call-{}'.format(stream.name),
                                          parameters=parameters,
                                          num_external_parameters=len(parameters),
                                          precondition=precondition, effects=effects, cost=cost))
        stream.certified = tuple(set(stream.certified) |
                                 set(map(rename_future, stream.certified)))
Beispiel #8
0
def rename_atom(atom, mapping):
    name = get_prefix(atom)
    if name not in mapping:
        return atom
    return (mapping[name],) + get_args(atom)
Beispiel #9
0
def compile_to_exogenous_axioms(evaluations, domain, streams):
    import pddl
    fluent_predicates = get_fluents(domain)
    domain_predicates = {get_prefix(a) for s in streams for a in s.domain}
    if not (domain_predicates & fluent_predicates):
        return

    certified_predicates = {get_prefix(a) for s in streams for a in s.certified}
    future_map = {p: 'f-{}'.format(p) for p in certified_predicates}
    augment_evaluations(evaluations, future_map)
    rename_future = lambda a: rename_atom(a, future_map)
    derived_map = {p: 'd-{}'.format(p) for p in certified_predicates}
    rename_derived = lambda a: rename_atom(a, derived_map)

    for action in domain.actions:
        action.precondition = replace_predicates(derived_map, action.precondition)
        for effect in action.effects:
            assert(isinstance(effect, pddl.Effect))
            effect.condition = replace_predicates(derived_map, effect.condition)
    for axiom in domain.axioms:
        axiom.condition = replace_predicates(derived_map, axiom.condition)

    #fluent_predicates.update(certified_predicates)
    for stream in list(streams):
        if not isinstance(stream, Stream):
            raise NotImplementedError(stream)
        streams.append(create_static_stream(stream, evaluations, fluent_predicates, rename_future))
        stream_atom = streams[-1].certified[0]
        domain.predicate_dict[get_prefix(stream_atom)] = pddl.Predicate(get_prefix(stream_atom), get_args(stream_atom))
        precondition = pddl.Conjunction(tuple(map(fd_from_fact, (stream_atom,) + tuple(map(rename_derived, stream.domain)))))
        for fact in stream.certified:
            derived_fact = fd_from_fact(rename_derived(fact))
            external_params = derived_fact.args
            internal_params = tuple(p for p in (stream.inputs + stream.outputs)
                                        if p not in derived_fact.args)
            parameters = tuple(pddl.TypedObject(p, 'object')
                                     for p in (external_params + internal_params))
            #precondition = pddl.Conjunction(tuple(map(fd_from_fact, [stream_atom] +
            #                                        list(map(rename_derived, stream.domain)))))
            #precondition = pddl.Disjunction([fd_from_fact(fact), precondition]) # TODO: quantifier
            domain.axioms.extend([
                pddl.Axiom(name=derived_fact.predicate, parameters=parameters,
                           num_external_parameters=len(external_params),
                           condition=precondition),
                pddl.Axiom(name=derived_fact.predicate,  parameters=parameters[:len(external_params)],
                           num_external_parameters=len(external_params),
                           condition=fd_from_fact(fact))])
        stream.certified = tuple(set(stream.certified) |
                                 set(map(rename_future, stream.certified)))