def recurse(condition): existential_parts = [] other_parts = [] for part in condition.parts: part = recurse(part) if isinstance(part, pddl.ExistentialCondition): existential_parts.append(part) else: other_parts.append(part) if not existential_parts: return condition # Rule (1): Combine nested quantifiers. if isinstance(condition, pddl.ExistentialCondition): new_parameters = condition.parameters + existential_parts[ 0].parameters new_parts = existential_parts[0].parts return pddl.ExistentialCondition(new_parameters, new_parts) # Rule (2): Pull quantifiers out of conjunctions. assert isinstance(condition, pddl.Conjunction) new_parameters = [] new_conjunction_parts = other_parts for part in existential_parts: new_parameters += part.parameters new_conjunction_parts += part.parts new_conjunction = pddl.Conjunction(new_conjunction_parts) return pddl.ExistentialCondition(new_parameters, (new_conjunction, ))
def convert_condition(condition): import pddl class_name = condition.__class__.__name__ if class_name in ('Truth', 'FunctionComparison'): # TODO: currently ignoring numeric conditions return pddl.Truth() elif class_name == 'Atom': return pddl.Atom(condition.predicate, convert_args(condition.args)) elif class_name == 'NegatedAtom': return pddl.NegatedAtom(condition.predicate, convert_args(condition.args)) elif class_name == 'Conjunction': return pddl.conditions.Conjunction( list(map(convert_condition, condition.parts))) elif class_name == 'Disjunction': return pddl.Disjunction(list(map(convert_condition, condition.parts))) elif class_name == 'ExistentialCondition': return pddl.ExistentialCondition( convert_parameters(condition.parameters), list(map(convert_condition, condition.parts))) elif class_name == 'UniversalCondition': return pddl.UniversalCondition( convert_parameters(condition.parameters), list(map(convert_condition, condition.parts))) raise NotImplementedError(class_name)
def recurse(condition, used_variables): if isinstance(condition, pddl.Literal): typed_vars = [] conjunction_parts = [] new_args = [] for term in condition.args: typed, parts, new_term = term.compile_objectfunctions_aux( used_variables) typed_vars += typed conjunction_parts += parts new_args.append(new_term) if conjunction_parts == []: return condition else: new_literal = condition.__class__(condition.predicate, new_args) conjunction_parts.append(new_literal) conjunction = pddl.Conjunction(conjunction_parts) return pddl.ExistentialCondition(typed_vars, [conjunction]) elif isinstance(condition, pddl.FunctionComparison): typed_vars = [] conjunction_parts = [] new_parts = [] for part in condition.parts: typed, parts, new_part = part.compile_objectfunctions_aux( used_variables) typed_vars += typed conjunction_parts += parts new_parts.append(new_part) if conjunction_parts == []: return condition else: new_comparison = condition.__class__(condition.comparator, new_parts) conjunction_parts.append(new_comparison) conjunction = pddl.Conjunction(conjunction_parts) return pddl.ExistentialCondition(typed_vars, [conjunction]) else: new_parts = [ recurse(part, used_variables) for part in condition.parts ] return condition.change_parts(new_parts)
def parse_condition_aux(alist, negated, type_dict, predicate_dict): """Parse a PDDL condition. The condition is translated into NNF on the fly.""" # if DEBUG: print ("parsing condition aux %s" % [alist]) tag = alist[0] if is_function_comparison( alist ): # NFD conditions are always comparisons between 2 numeric expressions args = [parse_expression(arg) for arg in alist[1:]] assert len(args) == 2, args if negated: return pddl.NegatedFunctionComparison(tag, args, True) else: return pddl.FunctionComparison(tag, args, True) elif tag in ("and", "or", "not", "imply"): args = alist[1:] if tag == "imply": assert len(args) == 2 if tag == "not": assert len(args) == 1 return parse_condition_aux(args[0], not negated, type_dict, predicate_dict) elif tag in ("forall", "exists"): parameters = parse_typed_list(alist[1]) args = alist[2:] assert len(args) == 1 else: # if is_object_comparison(alist): # print("DEBUG: Object comparison!") # print(alist) return parse_literal(alist, type_dict, predicate_dict, negated=negated) if tag == "imply": parts = [ parse_condition_aux(args[0], not negated, type_dict, predicate_dict), parse_condition_aux(args[1], negated, type_dict, predicate_dict) ] tag = "or" else: parts = [ parse_condition_aux(part, negated, type_dict, predicate_dict) for part in args ] if tag == "and" and not negated or tag == "or" and negated: return pddl.Conjunction(parts) elif tag == "or" and not negated or tag == "and" and negated: return pddl.Disjunction(parts) elif tag == "forall" and not negated or tag == "exists" and negated: return pddl.UniversalCondition(parameters, parts) elif tag == "exists" and not negated or tag == "forall" and negated: return pddl.ExistentialCondition(parameters, parts)
def parse_condition_aux(alist, negated, type_dict, predicate_dict): """Parse a PDDL condition. The condition is translated into NNF on the fly.""" tag = alist[0] if tag in ("and", "or", "not", "imply"): args = list() for arg in alist[1:]: if arg[0] == "=": continue if arg[0] == "not" and arg[1][0] == "=": continue args.append(arg) if tag == "imply": assert len(args) == 2 if tag == "not": assert len(args) == 1 return parse_condition_aux(args[0], not negated, type_dict, predicate_dict) elif tag in ("forall", "exists"): parameters = parse_typed_list(alist[1]) args = alist[2:] assert len(args) == 1 else: return parse_literal(alist, type_dict, predicate_dict, negated=negated) if tag == "imply": parts = [ parse_condition_aux(args[0], not negated, type_dict, predicate_dict), parse_condition_aux(args[1], negated, type_dict, predicate_dict) ] tag = "or" else: parts = [ parse_condition_aux(part, negated, type_dict, predicate_dict) for part in args ] if tag == "and" and not negated or tag == "or" and negated: return pddl.Conjunction(parts) elif tag == "or" and not negated or tag == "and" and negated: return pddl.Disjunction(parts) elif tag == "forall" and not negated or tag == "exists" and negated: return pddl.UniversalCondition(parameters, parts) elif tag == "exists" and not negated or tag == "forall" and negated: return pddl.ExistentialCondition(parameters, parts)
def recurse(condition): disjunctive_parts = [] other_parts = [] for part in condition.parts: part = recurse(part) if isinstance(part, pddl.Disjunction): disjunctive_parts.append(part) else: other_parts.append(part) if not disjunctive_parts: return condition # Rule (1): Associativity of disjunction. if isinstance(condition, pddl.Disjunction): result_parts = other_parts for part in disjunctive_parts: result_parts.extend(part.parts) return pddl.Disjunction(result_parts) # Rule (2): Distributivity disjunction/existential quantification. if isinstance(condition, pddl.ExistentialCondition): parameters = condition.parameters result_parts = [ pddl.ExistentialCondition(parameters, (part, )) for part in disjunctive_parts[0].parts ] return pddl.Disjunction(result_parts) # Rule (3): Distributivity disjunction/conjunction. assert isinstance(condition, pddl.Conjunction) result_parts = [pddl.Conjunction(other_parts)] while disjunctive_parts: previous_result_parts = result_parts result_parts = [] parts_to_distribute = disjunctive_parts.pop().parts for part1 in previous_result_parts: for part2 in parts_to_distribute: result_parts.append(pddl.Conjunction((part1, part2))) return pddl.Disjunction(result_parts)
def recurse(condition, used_variables): if isinstance(condition, pddl.Literal): typed_vars = [] conjunction_parts = [] new_args = [] for term in condition.args: typed, parts, new_term = term.compile_objectfunctions_aux( used_variables) typed_vars += typed conjunction_parts += parts new_args.append(new_term) if conjunction_parts == []: return condition else: new_literal = condition.__class__(condition.predicate, new_args) conjunction_parts.append(new_literal) conjunction = pddl.Conjunction(conjunction_parts) return pddl.ExistentialCondition(typed_vars, [conjunction]) elif isinstance(condition, pddl.ModuleCall): # FIXME no idea what this does, but hopefully the right thing... # This is only for object fluents? # So probably I don't need this at all and can # fallback to default? (return condition?) typed_vars = [] conjunction_parts = [] new_args = [] for term in condition.args: typed, parts, new_term = term.compile_objectfunctions_aux( used_variables) typed_vars += typed conjunction_parts += parts new_args.append(new_term) if conjunction_parts == []: return condition else: new_literal = condition.__class__(condition.name, new_args) conjunction_parts.append(new_literal) conjunction = pddl.Conjunction(conjunction_parts) return pddl.ExistentialCondition(typed_vars, [conjunction]) elif isinstance(condition, pddl.FunctionComparison): typed_vars = [] conjunction_parts = [] new_parts = [] for part in condition.parts: typed, parts, new_part = part.compile_objectfunctions_aux( used_variables) typed_vars += typed conjunction_parts += parts new_parts.append(new_part) if conjunction_parts == []: return condition else: new_comparison = condition.__class__(condition.comparator, new_parts) conjunction_parts.append(new_comparison) conjunction = pddl.Conjunction(conjunction_parts) return pddl.ExistentialCondition(typed_vars, [conjunction]) else: new_parts = [ recurse(part, used_variables) for part in condition.parts ] return condition.change_parts(new_parts)