def disable(self, evaluations, domain): #assert not self.disabled super(StreamInstance, self).disable(evaluations, domain) if not self.external.is_fluent(): # self.fluent_facts: if self.external.is_negated() and not self.successes: add_fact(evaluations, self.get_blocked_fact(), result=INTERNAL_EVALUATION) return if self._axiom_predicate is not None: return index = len(self.external.disabled_instances) self.external.disabled_instances.append(self) self._axiom_predicate = '_ax{}-{}'.format( self.external.blocked_predicate, index) add_fact(evaluations, self.get_blocked_fact(), result=INTERNAL_EVALUATION) # TODO: allow reporting back which components lead to failure static_fact = Fact(self._axiom_predicate, self.external.inputs) preconditions = [static_fact] + list(self.fluent_facts) derived_fact = Fact(self.external.blocked_predicate, self.external.inputs) self._disabled_axiom = make_axiom(parameters=self.external.inputs, preconditions=preconditions, derived=derived_fact) domain.axioms.append(self._disabled_axiom)
def fact_from_evaluation(evaluation): fact = Fact(evaluation.head.function, evaluation.head.args) if is_atom(evaluation): return fact elif is_negated_atom(evaluation): return Not(fact) return Equal(fact, evaluation.value)
def _disable_fluent(self, evaluations, domain): assert self.external.is_fluent() if self.successes or (self._axiom_predicate is not None): return self.disabled = True index = len(self.external.disabled_instances) self.external.disabled_instances.append(self) self._axiom_predicate = '_ax{}-{}'.format(self.external.blocked_predicate, index) add_fact(evaluations, self.get_blocked_fact(), result=INTERNAL_EVALUATION) # TODO: allow reporting back minimum unsatisfiable subset static_fact = Fact(self._axiom_predicate, self.external.inputs) preconditions = [static_fact] + list(self.fluent_facts) derived_fact = Fact(self.external.blocked_predicate, self.external.inputs) self._disabled_axiom = make_axiom( parameters=self.external.inputs, preconditions=preconditions, derived=derived_fact) domain.axioms.append(self._disabled_axiom)
def remap_inputs(self, bindings): # TODO: speed this procedure up #if not any(o in bindings for o in self.instance.get_objects()): # return self input_objects = apply_mapping(self.instance.input_objects, bindings) fluent_facts = [Fact(get_prefix(f), apply_mapping(get_args(f), bindings)) for f in self.instance.fluent_facts] new_instance = self.external.get_instance(input_objects, fluent_facts=fluent_facts) new_instance.opt_index = self.instance.opt_index return self.__class__(new_instance, self.output_objects, self.opt_index, self.call_index, self.list_index, self.optimistic)
def __init__(self, optimizer, constraint, domain, fluents): self.optimizer = optimizer self.constraint = constraint inputs = get_args(constraint) outputs = [] certified = [constraint] name = '{}-{}'.format(optimizer.name, get_prefix(constraint)) gen_fn = get_gen_fn(optimizer.procedure, inputs, outputs, certified) #gen_fn = empty_gen() info = StreamInfo(effort_fn=get_effort_fn(optimizer.name), simultaneous=DEFAULT_SIMULTANEOUS) self.stream_fact = Fact('_{}'.format(name), concatenate(inputs, outputs)) super(ConstraintStream, self).__init__(name, gen_fn, inputs, domain, outputs, certified, info, fluents=fluents)
def __init__(self, optimizer, variable, inputs, domain, certified, info): self.optimizer = optimizer self.variable = variable outputs = [variable] name = '{}-{}'.format(optimizer.name, get_parameter_name(variable)) gen_fn = get_gen_fn(optimizer.procedure, inputs, outputs, certified) #gen_fn = empty_gen() #info = StreamInfo(effort_fn=get_effort_fn(optimizer_name, inputs, outputs)) #info = StreamInfo(opt_gen_fn=PartialInputs(unique=DEFAULT_UNIQUE, num=DEFAULT_NUM)) # Each stream could certify a stream-specific fact as well # TODO: will I need to adjust simultaneous here as well? info = StreamInfo(opt_gen_fn=PartialInputs(unique=DEFAULT_UNIQUE), simultaneous=DEFAULT_SIMULTANEOUS) self.stream_fact = Fact('_{}'.format(name), concatenate(inputs, outputs)) # TODO: just add to certified? super(VariableStream, self).__init__(name, gen_fn, inputs, domain, outputs, certified, info)
def __init__(self, name, gen_fn, inputs, domain, outputs, certified, info, fluents=[]): super(Stream, self).__init__(name, info, inputs, domain) self.outputs = tuple(outputs) self.certified = tuple(map(convert_constants, certified)) self.constants.update(a for i in certified for a in get_args(i) if not is_parameter(a)) for p, c in Counter(self.outputs).items(): if not is_parameter(p): raise ValueError('Output [{}] for stream [{}] is not a parameter'.format(p, name)) if c != 1: raise ValueError('Output [{}] for stream [{}] is not unique'.format(p, name)) for p in set(self.inputs) & set(self.outputs): raise ValueError('Parameter [{}] for stream [{}] is both an input and output'.format(p, name)) certified_parameters = {a for i in certified for a in get_args(i) if is_parameter(a)} for p in (certified_parameters - set(self.inputs + self.outputs)): raise ValueError('Parameter [{}] for stream [{}] is not included within outputs'.format(p, name)) for p in (set(self.outputs) - certified_parameters): print('Warning! Output [{}] for stream [{}] is not covered by a certified condition'.format(p, name)) # TODO: automatically switch to unique if only used once self.gen_fn = get_debug_gen_fn(self, shared=True) if gen_fn == DEBUG else gen_fn assert callable(self.gen_fn) self.num_opt_fns = 0 if self.is_test() else 1 # Always unique if no outputs if isinstance(self.info.opt_gen_fn, PartialInputs): #self.info.opt_gen_fn.register(self) if self.info.opt_gen_fn.unique: self.num_opt_fns = 0 #self.bound_list_fn = None # TODO: generalize to a hierarchical sequence #self.opt_fns = [get_unique_fn(self), get_shared_fn(self)] # get_unique_fn | get_shared_fn self.fluents = fluents #self.fluents = [] if gen_fn == DEBUG else fluents if NEGATIVE_BLOCKED: self.blocked_predicate = '~{}{}'.format(self.name, NEGATIVE_SUFFIX) # Args are self.inputs else: self.blocked_predicate = '~{}'.format(self.name) self.disabled_instances = [] # For tracking disabled axioms self.stream_fact = Fact('_{}'.format(name), concatenate(inputs, outputs)) # TODO: just add to certified? if self.is_negated(): if self.outputs: raise ValueError('Negated streams cannot have outputs: {}'.format(self.outputs)) #assert len(self.certified) == 1 # TODO: is it okay to have more than one fact? for certified in self.certified: if not (set(self.inputs) <= set(get_args(certified))): raise ValueError('Negated streams must have certified facts including all input parameters')
def replace_expression(parent, fn): prefix = get_prefix(parent) if prefix == EQ: assert (len(parent) == 3) value = parent[2] if isinstance(parent[2], collections.Sequence): value = replace_expression(value, fn) return prefix, replace_expression(parent[1], fn), value elif prefix in (CONNECTIVES + OBJECTIVES): children = parent[1:] return (prefix, ) + tuple( replace_expression(child, fn) for child in children) elif prefix in QUANTIFIERS: assert (len(parent) == 3) parameters = parent[1] child = parent[2] return prefix, parameters, replace_expression(child, fn) name = get_prefix(parent).lower() args = get_args(parent) return Fact(name, map(fn, args))
def get_blocked_fact(self): if self.external.is_fluent(): assert self._axiom_predicate is not None return Fact(self._axiom_predicate, self.input_objects) return Fact(self.external.blocked_predicate, self.input_objects)
def get_fluent_values(self): return [ Fact(get_prefix(f), values_from_objects(get_args(f))) for f in self.fluent_facts ]
def substitute_fact(fact, mapping): return Fact(get_prefix(fact), apply_mapping(get_args(fact), mapping))
def convert_constants(fact): # TODO: take the constant map as an input # TODO: throw an error if undefined return Fact(get_prefix(fact), [ p if is_parameter(p) else Object.from_name(p) for p in get_args(fact) ])
def get_push_facts(poses, confs): return [Fact('Push', args) for args in zip(poses, confs, poses[1:], confs[1:])]