def unsolvable_sas_task(msg): print "%s! Generating unsolvable task..." % msg variables = sas_tasks.SASVariables([2], [-1]) init = sas_tasks.SASInit([0]) goal = sas_tasks.SASGoal([(0, 1)]) operators = [] temp_operators = [] axioms = [] num_axioms = [] comp_axioms = [] objects = [] oplinit = [] condition_modules = [] effect_modules = [] cost_modules = [] grounding_modules = [] strips_to_sas = {} module_inits = [] module_exits = [] subplan_generators = [] init_cons_pred = [] init_cons_numer = [] return sas_tasks.SASTask(variables, init, goal, operators, temp_operators, axioms, num_axioms, comp_axioms, oplinit, objects, condition_modules, effect_modules, cost_modules, grounding_modules, sas_tasks.SASTranslation(strips_to_sas), module_inits, module_exits, subplan_generators, init_cons_pred, init_cons_numer)
def translate_task(strips_to_sas, ranges, init, goals, actions, axioms, metric): axioms, axiom_init, axiom_layer_dict = axiom_rules.handle_axioms( actions, axioms, goals) init = init + axiom_init #axioms.sort(key=lambda axiom: axiom.name) #for axiom in axioms: # axiom.dump() init_values = [rang - 1 for rang in ranges] # Closed World Assumption: Initialize to "range - 1" == Nothing. for fact in init: pair = strips_to_sas.get(fact) pairs = strips_to_sas.get(fact, []) # empty for static init facts for var, val in pairs: assert init_values[ var] == ranges[var] - 1, "Inconsistent init facts!" init_values[var] = val init = sas_tasks.SASInit(init_values) goal_pairs = translate_strips_conditions(goals, strips_to_sas, ranges).items() goal = sas_tasks.SASGoal(goal_pairs) operators = translate_strips_operators(actions, strips_to_sas, ranges) axioms = translate_strips_axioms(axioms, strips_to_sas, ranges) axiom_layers = [-1] * len(ranges) for atom, layer in axiom_layer_dict.iteritems(): assert layer >= 0 [(var, val)] = strips_to_sas[atom] axiom_layers[var] = layer variables = sas_tasks.SASVariables(ranges, axiom_layers) return sas_tasks.SASTask(variables, init, goal, operators, axioms, metric)
def translate_task(strips_to_sas, ranges, translation_key, mutex_dict, mutex_ranges, mutex_key, init, goals, actions, axioms, metric, implied_facts): with timers.timing("Processing axioms", block=True): axioms, axiom_init, axiom_layer_dict = axiom_rules.handle_axioms( actions, axioms, goals) init = init + axiom_init #axioms.sort(key=lambda axiom: axiom.name) #for axiom in axioms: # axiom.dump() if DUMP_TASK: # Remove init facts that don't occur in strips_to_sas: they're constant. nonconstant_init = filter(strips_to_sas.get, init) dump_task(nonconstant_init, goals, actions, axioms, axiom_layer_dict) init_values = [rang - 1 for rang in ranges] # Closed World Assumption: Initialize to "range - 1" == Nothing. for fact in init: pairs = strips_to_sas.get(fact, []) # empty for static init facts for var, val in pairs: curr_val = init_values[var] if curr_val != ranges[var] - 1 and curr_val != val: assert False, "Inconsistent init facts! [fact = %s]" % fact init_values[var] = val init = sas_tasks.SASInit(init_values) goal_dict_list = translate_strips_conditions(goals, strips_to_sas, ranges, mutex_dict, mutex_ranges) if goal_dict_list is None: # "None" is a signal that the goal is unreachable because it # violates a mutex. return unsolvable_sas_task("Goal violates a mutex") #assert len(goal_dict_list) == 1, "Negative goal not supported" ## we could substitute the negative goal literal in ## normalize.substitute_complicated_goal, using an axiom. We currently ## don't do this, because we don't run into this assertion, if the ## negative goal is part of finite domain variable with only two ## values, which is most of the time the case, and hence refrain from ## introducing axioms (that are not supported by all heuristics) goal_pairs = list(goal_dict_list[0].items()) goal = sas_tasks.SASGoal(goal_pairs) operators = translate_strips_operators(actions, strips_to_sas, ranges, mutex_dict, mutex_ranges, implied_facts) axioms = translate_strips_axioms(axioms, strips_to_sas, ranges, mutex_dict, mutex_ranges) axiom_layers = [-1] * len(ranges) for atom, layer in axiom_layer_dict.items(): assert layer >= 0 [(var, val)] = strips_to_sas[atom] axiom_layers[var] = layer variables = sas_tasks.SASVariables(ranges, axiom_layers, translation_key) mutexes = [sas_tasks.SASMutexGroup(group) for group in mutex_key] return sas_tasks.SASTask(variables, mutexes, init, goal, operators, axioms, metric)
def trivial_task(solvable): variables = sas_tasks.SASVariables( [2], [-1], [["Atom dummy(val1)", "Atom dummy(val2)"]], 0) # We create no mutexes: the only possible mutex is between # dummy(val1) and dummy(val2), but the preprocessor would filter # it out anyway since it is trivial (only involves one # finite-domain variable). num_variables = sas_tasks.SASNumericVariables( ['total-cost'], [-1], ['I']) # no numeric variables mutexes = [] init = sas_tasks.SASInit([0], [0]) if solvable: goal_fact = (0, 0) else: goal_fact = (0, 1) goal = sas_tasks.SASGoal([goal_fact]) operators = [] axioms = [] comp_axioms = [] numeric_axioms = [] global_constraint = (0, 0) metric = ('<', 0) init_constant_predicates = [] init_constant_numerics = [] return sas_tasks.SASTask(variables, num_variables, mutexes, init, goal, operators, axioms, comp_axioms, numeric_axioms, global_constraint, metric, init_constant_predicates, init_constant_numerics)
def unsolvable_sas_task(msg): print "%s! Generating unsolvable task..." % msg variables = sas_tasks.SASVariables([2], [-1]) init = sas_tasks.SASInit([0]) goal = sas_tasks.SASGoal([(0, 1)]) operators = [] axioms = [] return sas_tasks.SASTask(variables, init, goal, operators, axioms)
def unsolvable_sas_task(msg): print "%s! Generating unsolvable task..." % msg write_translation_key([]) write_mutex_key([]) variables = sas_tasks.SASVariables([2], [-1]) init = sas_tasks.SASInit([0]) goal = sas_tasks.SASGoal([(0, 1)]) operators = [] axioms = [] metric = True return sas_tasks.SASTask(variables, init, goal, operators, axioms, metric)
def unsolvable_sas_task(msg): print("%s! Generating unsolvable task..." % msg) variables = sas_tasks.SASVariables([2], [-1], [["False", "True"]]) init = sas_tasks.SASInit([0]) goal = sas_tasks.SASGoal([(0, 1)]) operators = [] axioms = [] mutexes = [] metric = 0 return sas_tasks.SASTask(variables, mutexes, init, goal, operators, axioms, metric)
def unsolvable_sas_task(msg): print("%s! Generating unsolvable task..." % msg) variables = sas_tasks.SASVariables( [2], [-1], [["Atom dummy(val1)", "Atom dummy(val2)"]]) # We create no mutexes: the only possible mutex is between # dummy(val1) and dummy(val2), but the preprocessor would filter # it out anyway since it is trivial (only involves one # finite-domain variable). mutexes = [] init = sas_tasks.SASInit([0]) goal = sas_tasks.SASGoal([(0, 1)]) operators = [] axioms = [] metric = True return sas_tasks.SASTask(variables, mutexes, init, goal, operators, axioms, metric)
def translate_task(strips_to_sas, ranges, mutex_dict, mutex_ranges, init, goals, actions, axioms, metric, implied_facts): with timers.timing("Processing axioms", block=True): axioms, axiom_init, axiom_layer_dict = axiom_rules.handle_axioms( actions, axioms, goals) init = init + axiom_init #axioms.sort(key=lambda axiom: axiom.name) #for axiom in axioms: # axiom.dump() init_values = [rang - 1 for rang in ranges] # Closed World Assumption: Initialize to "range - 1" == Nothing. for fact in init: pair = strips_to_sas.get(fact) pairs = strips_to_sas.get(fact, []) # empty for static init facts for var, val in pairs: assert init_values[ var] == ranges[var] - 1, "Inconsistent init facts!" init_values[var] = val init = sas_tasks.SASInit(init_values) goal_dict_list = translate_strips_goal(goals, strips_to_sas, ranges, mutex_dict, mutex_ranges) assert len(goal_dict_list) == 1, "Negative goal not supported" ## we could substitute the negative goal literal in ## normalize.substitute_complicated_goal, using an axiom. We currently ## don't do this, because we don't run into this assertion, if the ## negative goal is part of finite domain variable with only two ## values, which is most of the time the case, and hence refrain from ## introducing axioms (that are not supported by all heuristics) goal_pairs = goal_dict_list[0].items() goal = sas_tasks.SASGoal(goal_pairs) operators = translate_strips_operators(actions, strips_to_sas, ranges, mutex_dict, mutex_ranges, implied_facts) axioms = translate_strips_axioms(axioms, strips_to_sas, ranges, mutex_dict, mutex_ranges) axiom_layers = [-1] * len(ranges) for atom, layer in axiom_layer_dict.iteritems(): assert layer >= 0 [(var, val)] = strips_to_sas[atom] axiom_layers[var] = layer variables = sas_tasks.SASVariables(ranges, axiom_layers) return sas_tasks.SASTask(variables, init, goal, operators, axioms, metric)
def trivial_task(solvable): variables = sas_tasks.SASVariables( [2], [-1], [["Atom dummy(val1)", "Atom dummy(val2)"]]) # We create no mutexes: the only possible mutex is between # dummy(val1) and dummy(val2), but the preprocessor would filter # it out anyway since it is trivial (only involves one # finite-domain variable). mutexes = [] init = sas_tasks.SASInit([0]) if solvable: goal_fact = (0, 0) else: goal_fact = (0, 1) goal = sas_tasks.SASGoal([goal_fact]) operators = [] axioms = [] metric = True return sas_tasks.SASTask(variables, mutexes, init, goal, operators, axioms, metric)
def translate_task(strips_to_sas, ranges, translation_key, mutex_dict, mutex_ranges, mutex_key, init, init_unknown, init_oneof, init_formula, goals, actions, observation_actions, axioms, metric, implied_facts): with timers.timing("Processing axioms", block=True): axioms, axiom_init, axiom_layer_dict = axiom_rules.handle_axioms( actions, axioms, goals) init = init + axiom_init #axioms.sort(key=lambda axiom: axiom.name) #for axiom in axioms: # axiom.dump() if DUMP_TASK: # Remove init facts that don't occur in strips_to_sas: they're constant. nonconstant_init = filter(strips_to_sas.get, init) dump_task(nonconstant_init, goals, actions, axioms, axiom_layer_dict) # Closed World Assumption false_facts = list(range(len(ranges))) for fact in init_unknown: pairs = strips_to_sas.get(fact, []) for pair in pairs: false_facts.remove(pair[0]) facts = [] for fact in init: assert fact not in init_unknown pairs = strips_to_sas.get(fact, []) for pair in pairs: false_facts.remove(pair[0]) if pairs: facts = facts + pairs for var in false_facts: assert fact not in init_unknown facts.append((var, ranges[var] - 1)) facts_oneof = [] for oneof in init_oneof: assert len(oneof) >= 2 for fact in oneof: assert fact in init_unknown l = [] for one in oneof: l = l + strips_to_sas.get(one, []) facts_oneof.append(l) # move to conditions.py? def translate_formula(formula, result, strips_to_sas, ranges, mutex_dict, mutex_ranges): if isinstance(formula, pddl.conditions.Atom): assert formula in init_unknown result.append(strips_to_sas.get(formula, [])) elif isinstance(formula, pddl.conditions.NegatedAtom): dict_list = translate_strips_conditions([formula], strips_to_sas, ranges, mutex_dict, mutex_ranges) assert len(dict_list) == 1 result.append(dict_list[0].items()) elif isinstance(formula, pddl.conditions.Disjunction): result.append("or(") for part in formula.parts: translate_formula(part, result, strips_to_sas, ranges, mutex_dict, mutex_ranges) result.append(")") elif isinstance(formula, pddl.conditions.Conjunction): result.append("and(") for part in formula.parts: translate_formula(part, result, strips_to_sas, ranges, mutex_dict, mutex_ranges) result.append(")") else: assert False, print(formula) formulae = [] for formula in init_formula: result = [] translate_formula(formula, result, strips_to_sas, ranges, mutex_dict, mutex_ranges) formulae.append(result) init = sas_tasks.SASInit(facts, facts_oneof, formulae) goal_dict_list = translate_strips_conditions(goals, strips_to_sas, ranges, mutex_dict, mutex_ranges) if goal_dict_list is None: # "None" is a signal that the goal is unreachable because it # violates a mutex. return unsolvable_sas_task("Goal violates a mutex") assert len(goal_dict_list) == 1, "Negative goal not supported" ## we could substitute the negative goal literal in ## normalize.substitute_complicated_goal, using an axiom. We currently ## don't do this, because we don't run into this assertion, if the ## negative goal is part of finite domain variable with only two ## values, which is most of the time the case, and hence refrain from ## introducing axioms (that are not supported by all heuristics) goal_pairs = list(goal_dict_list[0].items()) goal = sas_tasks.SASGoal(goal_pairs) operators = translate_strips_operators(actions, strips_to_sas, ranges, mutex_dict, mutex_ranges, implied_facts) observation_operators = translate_strips_operators(observation_actions, strips_to_sas, ranges, mutex_dict, mutex_ranges, implied_facts) axioms = translate_strips_axioms(axioms, strips_to_sas, ranges, mutex_dict, mutex_ranges) axiom_layers = [-1] * len(ranges) for atom, layer in axiom_layer_dict.items(): assert layer >= 0 [(var, val)] = strips_to_sas[atom] axiom_layers[var] = layer variables = sas_tasks.SASVariables(ranges, axiom_layers, translation_key) mutexes = [sas_tasks.SASMutexGroup(group) for group in mutex_key] return sas_tasks.SASTask(variables, mutexes, init, goal, operators + observation_operators, axioms, metric)
def translate_task(strips_to_sas, ranges, init, goals, actions, durative_actions, axioms, num_axioms, num_axioms_by_layer, max_num_layer, num_axiom_map, const_num_axioms): axioms, axiom_init, axiom_layer_dict, true_atoms, false_atoms = axiom_rules.handle_axioms( actions, durative_actions, axioms, goals) init = init + axiom_init # filter trivial true_atoms from goal goals = [g for g in goals if g not in true_atoms ] # FIXME: empty goal would be handled nicely by search # if any atom in goal is false, the task is unsolvable for fa in false_atoms: if fa in goals: print "False atom in goal:" fa.dump() return unsolvable_sas_task("False atom in goal") comp_axioms = [{}, []] goal_dict_list = translate_strips_conditions(goals, strips_to_sas, ranges, comp_axioms) assert len(goal_dict_list) == 1, "Negative goal not supported" ## we could substitute the negative goal literal in ## normalize.substitute_complicated_goal, using an axiom. We currently ## don't do this, because we don't run into this assertion, if the ## negative goal is part of finite domain variable with only two ## values, which is most of the time the case, and hence refrain from ## introducing axioms (that are not supported by all heuristics) goal_pairs = goal_dict_list[0].items() goal = sas_tasks.SASGoal(goal_pairs) # FIXME: remove this, defunct anyways operators = translate_strips_operators(actions, strips_to_sas, ranges, comp_axioms) temp_operators = translate_temporal_strips_operators( durative_actions, strips_to_sas, ranges, comp_axioms, true_atoms, false_atoms) axioms = translate_strips_axioms(axioms, strips_to_sas, ranges, comp_axioms) sas_num_axioms = [ translate_numeric_axiom(axiom, strips_to_sas) for axiom in num_axioms if axiom not in const_num_axioms and axiom.effect not in num_axiom_map ] axiom_layers = [-1] * len(ranges) ## each numeric axiom gets its own layer (a wish of a colleague for ## knowledge compilation or search. If you use only the translator, ## you can change this) num_axiom_layer = 0 for layer in num_axioms_by_layer: num_axioms_by_layer[layer].sort(lambda x, y: cmp(x.name, y.name)) for axiom in num_axioms_by_layer[layer]: if axiom.effect not in num_axiom_map: [(var, val)] = strips_to_sas[axiom.effect] if layer == -1: axiom_layers[var] = -1 else: axiom_layers[var] = num_axiom_layer num_axiom_layer += 1 for axiom in comp_axioms[1]: axiom_layers[axiom.effect] = num_axiom_layer for atom, layer in axiom_layer_dict.iteritems(): assert layer >= 0 [(var, val)] = strips_to_sas[atom] axiom_layers[var] = layer + num_axiom_layer + 1 variables = sas_tasks.SASVariables(ranges, axiom_layers) init_values = [rang - 1 for rang in ranges] # Closed World Assumption: Initialize to "range - 1" == Nothing. for fact in init: if isinstance(fact, pddl.Atom): pairs = strips_to_sas.get(fact, []) # empty for static init facts for var, val in pairs: assert init_values[ var] == ranges[var] - 1, "Inconsistent init facts!" init_values[var] = val else: # isinstance(fact,pddl.FunctionAssignment) pairs = strips_to_sas.get(fact.fluent, []) #empty for constant functions for (var, _) in pairs: val = fact.expression.value assert init_values[ var] == ranges[var] - 1, "Inconsistent init facts!" init_values[var] = val for axiom in const_num_axioms: var = strips_to_sas.get(axiom.effect)[0][0] val = axiom.parts[0].value init_values[var] = val init = sas_tasks.SASInit(init_values) return sas_tasks.SASTask(variables, init, goal, operators, temp_operators, axioms, sas_num_axioms, comp_axioms[1])
def translate_task(strips_to_sas, module_effects_to_sas, module_groundings_to_sas, ranges, init, goals, actions, durative_actions, axioms, num_axioms, num_axioms_by_layer, max_num_layer, num_axiom_map, const_num_axioms, oplinit, objects, modules, module_inits, module_exits, subplan_generators, init_constant_predicates, init_constant_numerics): axioms, axiom_init, axiom_layer_dict, true_atoms, false_atoms = axiom_rules.handle_axioms( actions, durative_actions, axioms, goals) init = init + axiom_init # filter trivial true_atoms from goal goals = [g for g in goals if g not in true_atoms ] # FIXME: empty goal would be handled nicely by search # if any atom in goal is false, the task is unsolvable for fa in false_atoms: if fa in goals: print "False atom in goal:" fa.dump() return unsolvable_sas_task("False atom in goal") comp_axioms = [{}, []] goal_dict_list = translate_strips_conditions(goals, strips_to_sas, ranges, comp_axioms) assert len(goal_dict_list) == 1, "Negative goal not supported" ## we could substitute the negative goal literal in ## normalize.substitute_complicated_goal, using an axiom. We currently ## don't do this, because we don't run into this assertion, if the ## negative goal is part of finite domain variable with only two ## values, which is most of the time the case, and hence refrain from ## introducing axioms (that are not supported by all heuristics) goal_pairs = goal_dict_list[0].items() goal = sas_tasks.SASGoal(goal_pairs) # FIXME: remove this, defunct anyways operators = translate_strips_operators(actions, strips_to_sas, module_effects_to_sas, ranges, comp_axioms) temp_operators = translate_temporal_strips_operators( durative_actions, strips_to_sas, module_effects_to_sas, module_groundings_to_sas, ranges, comp_axioms, true_atoms, false_atoms) axioms = translate_strips_axioms(axioms, strips_to_sas, ranges, comp_axioms) sas_num_axioms = [ translate_numeric_axiom(axiom, strips_to_sas) for axiom in num_axioms if axiom not in const_num_axioms and axiom.effect not in num_axiom_map ] axiom_layers = [-1] * len(ranges) ## each numeric axiom gets its own layer (a wish of a colleague for ## knowledge compilation or search. If you use only the translator, ## you can change this) num_axiom_layer = 0 for layer in num_axioms_by_layer: num_axioms_by_layer[layer].sort(lambda x, y: cmp(x.name, y.name)) for axiom in num_axioms_by_layer[layer]: if axiom.effect not in num_axiom_map: [(var, val)] = strips_to_sas[axiom.effect] if layer == -1: axiom_layers[var] = -1 else: axiom_layers[var] = num_axiom_layer num_axiom_layer += 1 for axiom in comp_axioms[1]: axiom_layers[axiom.effect] = num_axiom_layer for atom, layer in axiom_layer_dict.iteritems(): assert layer >= 0 [(var, val)] = strips_to_sas[atom] axiom_layers[var] = layer + num_axiom_layer + 1 variables = sas_tasks.SASVariables(ranges, axiom_layers) init_values = [rang - 1 for rang in ranges] # Closed World Assumption: Initialize to "range - 1" == Nothing. for fact in init: if isinstance(fact, pddl.Atom): pairs = strips_to_sas.get(fact, []) # empty for static init facts for var, val in pairs: assert init_values[ var] == ranges[var] - 1, "Inconsistent init facts!" init_values[var] = val else: # isinstance(fact,pddl.FunctionAssignment) pairs = strips_to_sas.get(fact.fluent, []) #empty for constant functions for (var, _) in pairs: val = fact.expression.value assert init_values[ var] == ranges[var] - 1, "Inconsistent init facts!" init_values[var] = val for axiom in const_num_axioms: var = strips_to_sas.get(axiom.effect)[0][0] val = axiom.parts[0].value init_values[var] = val init = sas_tasks.SASInit(init_values) # TODO: move this block to translate_modules strips_condition_modules = [ module for module in modules if module.type == "conditionchecker" ] strips_effect_modules = [ module for module in modules if module.type == "effect" ] strips_cost_modules = [ module for module in modules if module.type == "cost" ] strips_grounding_modules = [ module for module in modules if module.type == "grounding" ] strips_condition_modules.sort(lambda x, y: cmp(str(x), str(y))) strips_effect_modules.sort(lambda x, y: cmp(str(x), str(y))) strips_cost_modules.sort(lambda x, y: cmp(str(x), str(y))) strips_grounding_modules.sort(lambda x, y: cmp(str(x), str(y))) condition_modules = [] effect_modules = [] cost_modules = [] grounding_modules = [] for mod in strips_condition_modules: assert mod.parent is not None sas_params = [] for (ground_param, pddl_param) in zip(mod.parameters, mod.parent.parameters): sas_params.append( (pddl_param.name, ground_param.type, ground_param.name)) # strips_to_sas call is very hacky assert len(strips_to_sas[mod.toModuleCall()]) == 1 assert len(strips_to_sas[mod.toModuleCall()][0]) == 2 mod_var = strips_to_sas[mod.toModuleCall()][0][0] condition_modules.append( sas_tasks.SASConditionModule(mod.modulecall, sas_params, mod_var)) for mod in strips_effect_modules: assert mod.parent is not None sas_params = [] for (ground_param, pddl_param) in zip(mod.parameters, mod.parent.parameters): sas_params.append( (pddl_param.name, ground_param.type, ground_param.name)) sas_effs = [] for eff in mod.effects: assert len(strips_to_sas[eff]) == 1 assert len(strips_to_sas[eff][0]) == 2 sas_effs.append(strips_to_sas[eff][0][0]) # missing eff num + eff vars effect_modules.append( sas_tasks.SASEffectModule( mod.modulecall, sas_params, module_effects_to_sas[mod.toModuleCall()][0], sas_effs)) for mod in strips_cost_modules: assert mod.parent is not None # ? sas_params = [] for (ground_param, pddl_param) in zip(mod.parameters, mod.parent.parameters): sas_params.append( (pddl_param.name, ground_param.type, ground_param.name)) # make sure strips_to_sas is not mixed badly with condition modules assert len(strips_to_sas[mod.toModuleCall()]) == 1 assert len(strips_to_sas[mod.toModuleCall()][0]) == 2 mod_var = strips_to_sas[mod.toModuleCall()][0][0] cost_modules.append( sas_tasks.SASConditionModule(mod.modulecall, sas_params, mod_var)) for mod in strips_grounding_modules: assert mod.parent is not None sas_params = [] for (ground_param, pddl_param) in zip(mod.parameters, mod.parent.parameters): sas_params.append( (pddl_param.name, ground_param.type, ground_param.name)) grounding_modules.append( sas_tasks.SASGroundingModule( mod.modulecall, sas_params, module_groundings_to_sas[mod.toModuleCall()][0])) return sas_tasks.SASTask(variables, init, goal, operators, temp_operators, axioms, sas_num_axioms, comp_axioms[1], oplinit, objects, condition_modules, effect_modules, cost_modules, grounding_modules, sas_tasks.SASTranslation(strips_to_sas), module_inits, module_exits, subplan_generators, init_constant_predicates, init_constant_numerics)
def translate_task(strips_to_sas, ranges, translation_key, numeric_strips_to_sas, num_count, mutex_dict, mutex_ranges, mutex_key, init, num_init, goal_list, global_constraint, actions, axioms, num_axioms, num_axioms_by_layer, num_axiom_map, const_num_axioms, metric, implied_facts, init_constant_predicates, init_constant_numerics): with timers.timing("Processing axioms", block=True): axioms, axiom_init, axiom_layer_dict = axiom_rules.handle_axioms( actions, axioms, goal_list, global_constraint) init = init + axiom_init if options.dump_task: # Remove init facts that don't occur in strips_to_sas: they're constant. nonconstant_init = filter(strips_to_sas.get, init) dump_task(nonconstant_init, goal_list, actions, axioms, axiom_layer_dict) init_values = [rang - 1 for rang in ranges] # Closed World Assumption: Initialize to "range - 1" == Nothing. for fact in init: pairs = strips_to_sas.get(fact, []) # empty for static init facts for var, val in pairs: curr_val = init_values[var] if curr_val != ranges[var] - 1 and curr_val != val: assert False, "Inconsistent init facts! [fact = %s]" % fact init_values[var] = val comparison_axioms = [{}, []] goal_dict_list = translate_strips_conditions(goal_list, strips_to_sas, ranges, numeric_strips_to_sas, mutex_dict, mutex_ranges, comparison_axioms) global_constraint_dict_list = translate_strips_conditions( [global_constraint], strips_to_sas, ranges, numeric_strips_to_sas, mutex_dict, mutex_ranges, comparison_axioms) # print("goal_dict_list = %s" % goal_dict_list) # print("comparison_axioms = %s" %comparison_axioms) if goal_dict_list is None: # "None" is a signal that the goal_list is unreachable because it # violates a mutex. return unsolvable_sas_task("Goal violates a mutex") assert len(goal_dict_list) == 1, "Negative goal not supported" ## we could substitute the negative goal literal in ## normalize.substitute_complicated_goal, using an axiom. We currently ## don't do this, because we don't run into this assertion, if the ## negative goal is part of finite domain variable with only two ## values, which is most of the time the case, and hence refrain from ## introducing axioms (that are not supported by all heuristics) goal_pairs = list(goal_dict_list[0].items()) if not goal_pairs: return solvable_sas_task("Empty goal") sas_goal = sas_tasks.SASGoal(goal_pairs) assert len( global_constraint_dict_list ) == 1 # the key is the axiom fluent, the value (0) the evaluation to true num_init_values = [0.0 ] * num_count # initialize numeric varialbes with 0.0 # if DEBUG: # print("Strips-to-sas dict is") # for entry in strips_to_sas: # print("%s -> %s"%(entry, strips_to_sas[entry])) # print("Numeric Strips-to-sas dict is") # for entry in numeric_strips_to_sas: # print("%s -> %s"%(entry,numeric_strips_to_sas[entry])) relevant_numeric = [] for fact in num_init: var = numeric_strips_to_sas.get(fact.fluent, -1) if var > -1: val = fact.expression.value num_init_values[var] = val if fact.fluent.ntype == 'R': # the corresponding numeric variable is "regular" and therefore relevant relevant_numeric.append(var) operators = translate_strips_operators(actions, strips_to_sas, ranges, numeric_strips_to_sas, mutex_dict, mutex_ranges, implied_facts, comparison_axioms, num_init_values, relevant_numeric) axioms = translate_strips_axioms(axioms, strips_to_sas, ranges, numeric_strips_to_sas, mutex_dict, mutex_ranges, comparison_axioms) sas_num_axioms = [ translate_numeric_axiom(axiom, strips_to_sas, numeric_strips_to_sas) for axiom in num_axioms if axiom not in const_num_axioms and axiom.effect not in num_axiom_map ] axiom_layers = [-1] * len(ranges) # default axiom layer is -1 ## each numeric axiom gets its own layer (a wish of a colleague for ## knowledge compilation or search. If you use only the translator, ## you can change this) num_axiom_layers = [-1] * num_count num_axiom_layer = 0 for layer in num_axioms_by_layer: num_axioms_by_layer[layer].sort(lambda x, y: cmp(x.name, y.name)) for axiom in num_axioms_by_layer[layer]: if axiom.effect not in num_axiom_map: var = numeric_strips_to_sas[axiom.effect] if layer == -1: num_axiom_layers[var] = -1 else: num_axiom_layers[var] = num_axiom_layer num_axiom_layer += 1 # print("comparison_axioms = %s" %comparison_axioms) comp_axiom_init = [2] * len( comparison_axioms[1] ) # initializing comparison axioms with value 3 (none of those) init_values.extend(comp_axiom_init) # for axiom in comparison_axioms[1]: axiom_layers[axiom.effect] = num_axiom_layer for atom, layer in axiom_layer_dict.iteritems(): assert layer >= 0 [(var, val)] = strips_to_sas[atom] axiom_layers[var] = layer + num_axiom_layer + 1 add_key_to_comp_axioms(comparison_axioms, translation_key) variables = sas_tasks.SASVariables(ranges, axiom_layers, translation_key, num_axiom_layer) num_variables = [-1] * num_count num_var_types = ['U'] * num_count # variable type is unknown for entry in numeric_strips_to_sas: num_variables[numeric_strips_to_sas[entry]] = entry num_var_types[numeric_strips_to_sas[entry]] = entry.ntype assert num_count == len(num_variables), "%d nc <-> variables %d" % ( num_count, len(num_variables)) numeric_variables = sas_tasks.SASNumericVariables(num_variables, num_axiom_layers, num_var_types) mutexes = [sas_tasks.SASMutexGroup(group) for group in mutex_key] for axiom in const_num_axioms: # print("Axiom = %s" % axiom) # print("Axiom.effect = %s" % axiom.effect) # print("corresponding variable = %s" % numeric_strips_to_sas.get(axiom.effect)) var = numeric_strips_to_sas.get(axiom.effect) val = axiom.parts[0].value num_init_values[var] = val sas_init = sas_tasks.SASInit(init_values, num_init_values) # print("SASInit is") # sas_init.dump() # look up metric fluent if metric[1] == -1: # minimize unit cost, no metric fluent specified assert metric[0] == '<' sas_metric = metric else: assert metric[ 1] in numeric_strips_to_sas, "Metric fluent %s missing in strips_to_sas_dict" % metric[ 1] # look up (possibly derived) metric fluent to be optimized sas_metric = (metric[0], numeric_strips_to_sas[metric[1]]) # print ("debug check metric: metric=") # print (metric) # print ("sas_metric fluent %d" % sas_metric[1]) # print ("Returning task with global constraint = ",global_constraint_dict_list[0].items()[0]) return sas_tasks.SASTask(variables, numeric_variables, mutexes, sas_init, sas_goal, operators, axioms, comparison_axioms[1], sas_num_axioms, global_constraint_dict_list[0].items()[0], sas_metric, init_constant_predicates, init_constant_numerics)