as2 = Assignment(dv, 'dv-false', 3) dv.add_domain_value(as1) dv.add_domain_value(as2) tpnu.add_decision_variable(dv) # Initialize temporal constraints tc1 = TemporalConstraint(str(uuid4()), 'tc1', 1, 2, 0, 10) tc1.controllable = False tpnu.add_temporal_constraint(tc1) tc2 = TemporalConstraint(str(uuid4()), 'tc2', 2, 3, 0, 10) tc2.controllable = False tpnu.add_temporal_constraint(tc2) tc3 = TemporalConstraint(str(uuid4()), 'tc3', 1, 3, 0, 15) tc3.add_guard(as1) tc3.relaxable_ub = True tc3.relaxable_lb = False tc3.relax_cost_ub = 1 tpnu.add_temporal_constraint(tc3) # tpnu = Tpnu.from_tpn_autogen() print(tpnu) print(tpnu.decision_variables) print(tpnu.num_nodes) print(tpnu.temporal_constraints) print(tpnu.chance_constraints) print(tpnu.node_number_to_id) print(tpnu.start_node) f_type = FeasibilityType.DYNAMIC_CONTROLLABILITY o_type = ObjectiveType.MIN_COST
def parseCCTP(inFilename): e = xml.etree.ElementTree.parse(inFilename).getroot() tpnu_name = e.find('NAME').text tpnu = Tpnu('', tpnu_name) # In TPN format every node (or event in TPN terminology) has a non-unique name # and an unique id. Both of those are strings. For efficiency DC checking algorithms # denote each node by a number, such that we can cheaply check their equality. # parse the event event_ids = set() tpnu.node_id_to_name = {} # tpnu.node_name_to_number = {} tpnu.node_number_to_id = {} tpnu.node_id_to_number = {} for event_obj in e.findall('EVENT'): eid, ename = event_obj.find('ID').text, event_obj.find('NAME').text event_ids.add(eid) tpnu.node_id_to_name[eid] = ename for eid in event_ids: next_number = len(tpnu.node_number_to_id) + 1 tpnu.node_number_to_id[next_number] = eid tpnu.node_id_to_number[eid] = next_number # tpnu.node_name_to_number[tpnu.node_id_to_name[eid]] = next_number tpnu.num_nodes = len(tpnu.node_number_to_id) start_id = e.find('START').text tpnu.start_node = tpnu.node_id_to_number[start_id] if (tpnu.num_nodes < 1): return None # parse the decision variables assignment_map_with_id = {} assignment_map_with_name = {} for variable_obj in e.findall('DECISION-VARIABLE'): dv_name = variable_obj.find('DECISION-NAME').text if variable_obj.find('ID') is not None: dv_id = variable_obj.find('ID').text else: dv_id = dv_name decision_variable = DecisionVariable(dv_id, dv_name) # construct the assignment for the variable for value_obj in variable_obj.findall('VALUE'): # value_id = value_obj.find('ID').text value_name = value_obj.find('VALUE-NAME').text value_utility = float(value_obj.find('VALUE-UTILITY').text) assignment = Assignment(decision_variable, value_name, value_utility) # add the assignment to the variable, and a dictionary for future reference decision_variable.add_domain_value(assignment) # using the id of the variable and the value of the assignment as key assignment_map_with_id[(dv_id, value_name)] = assignment assignment_map_with_name[(dv_name, value_name)] = assignment tpnu.add_decision_variable(decision_variable) # parse variables' guards for variable_obj in e.findall('DECISION-VARIABLE'): if variable_obj.find('ID') is not None: dv_id = variable_obj.find('ID').text else: dv_id = variable_obj.find('DECISION-NAME').text decision_variable = tpnu.decision_variables[dv_id] # the guard could be a conjunctive set of assignment for guard_obj in variable_obj.findall('GUARD'): # guard_id = guard_obj.find('ID').text guard_variable = guard_obj.find('GUARD-VARIABLE').text guard_value = guard_obj.find('GUARD-VALUE').text # retrieve the assignment if (guard_variable, guard_value) in assignment_map_with_id: guard_assignment = assignment_map_with_id[(guard_variable, guard_value)] elif (guard_variable, guard_value) in assignment_map_with_name: guard_assignment = assignment_map_with_name[( guard_variable, guard_value)] # and add to the guards of this decision variable decision_variable.add_guard(guard_assignment) # parse the temporal constraints and episodes # if line below confuses you, that's expected... We need better automated code generation for parsing... for constraint_obj in e.findall('CONSTRAINT'): # duration can be one of three types - controllable, uncertain and probabilistic # here we are only handling the first two cases, which are sorted into two lists # in our resulting stnu class. lower_bound = float(constraint_obj.find('LOWERBOUND').text) upper_bound = float(constraint_obj.find('UPPERBOUND').text) from_event = constraint_obj.find('START').text to_event = constraint_obj.find('END').text constraint_id = constraint_obj.find('ID').text constraint_name = constraint_obj.find('NAME').text constraint = TemporalConstraint(constraint_id, constraint_name, tpnu.node_id_to_number[from_event], tpnu.node_id_to_number[to_event], lower_bound, upper_bound) # check if the constraint is controllable and relaxable type = constraint_obj.find('TYPE').text if "Controllable" in type: constraint.controllable = True elif "Uncontrollable" in type: constraint.controllable = False if constraint_obj.find('MEAN') is not None: constraint.mean = float(constraint_obj.find('MEAN').text) if constraint_obj.find('VARIANCE') is not None: constraint.probabilistic = True constraint.std = np.sqrt( float(constraint_obj.find('VARIANCE').text)) if constraint_obj.find('LBRELAXABLE') is not None: if "T" in constraint_obj.find('LBRELAXABLE').text: constraint.relaxable_lb = True lb_cost = constraint_obj.find('LB-RELAX-COST-RATIO').text constraint.relax_cost_lb = float(lb_cost) if constraint_obj.find('UBRELAXABLE') is not None: if "T" in constraint_obj.find('UBRELAXABLE').text: constraint.relaxable_ub = True ub_cost = constraint_obj.find('UB-RELAX-COST-RATIO').text constraint.relax_cost_ub = float(ub_cost) # Next we deal with the guard conditions # the approach is identical to that for decision variables for guard_obj in constraint_obj.findall('GUARD'): # guard_id = guard_obj.find('ID').text guard_variable = guard_obj.find('GUARD-VARIABLE').text guard_value = guard_obj.find('GUARD-VALUE').text # retrieve the assignment if (guard_variable, guard_value) in assignment_map_with_id: guard_assignment = assignment_map_with_id[(guard_variable, guard_value)] elif (guard_variable, guard_value) in assignment_map_with_name: guard_assignment = assignment_map_with_name[( guard_variable, guard_value)] # and add to the guards of this decision variable constraint.add_guard(guard_assignment) tpnu.add_temporal_constraint(constraint) # Parse Chance Constraint # risk_bound = float(e.find('RISK-BOUND').text) # risk_bound_relax_cost = float(e.find('RISK-BOUND-RELAX-COST').text) risk_bound = 0.05 risk_bound_relax_cost = 100 cc_constraint = ChanceConstraint("CC-1", "CC-Constraint", risk_bound) if risk_bound_relax_cost > 0: cc_constraint.relaxable_bound = True cc_constraint.relax_cost = risk_bound_relax_cost tpnu.add_chance_constraint(cc_constraint) tpnu.start_node = tpnu.node_id_to_number[start_id] return tpnu
def parseCCTP(inFilename): e = xml.etree.ElementTree.parse(inFilename).getroot() tpnu_name = e.find('NAME').text tpnu = Tpnu('', tpnu_name) # In TPN format every node (or event in TPN terminology) has a non-unique name # and an unique id. Both of those are strings. For efficiency DC checking algorithms # denote each node by a number, such that we can cheaply check their equality. # parse the event event_ids = set() tpnu.node_id_to_name = {} tpnu.node_number_to_id = {} tpnu.node_id_to_number = {} for event_obj in e.findall('EVENT'): eid, ename = event_obj.find('ID').text, event_obj.find('NAME').text event_ids.add(eid) tpnu.node_id_to_name[eid] = ename for eid in event_ids: next_number = len(tpnu.node_number_to_id) + 1 tpnu.node_number_to_id[next_number] = eid tpnu.node_id_to_number[eid] = next_number tpnu.num_nodes = len(tpnu.node_number_to_id) start_id = e.find('START').text tpnu.start_node = tpnu.node_id_to_number[start_id] if (tpnu.num_nodes < 1): return None # parse the decision variables assignment_map_with_id = {} assignment_map_with_name = {} for variable_obj in e.findall('DECISION-VARIABLE'): dv_name = variable_obj.find('DECISION-NAME').text if variable_obj.find('ID') is not None: dv_id = variable_obj.find('ID').text else: dv_id = dv_name decision_variable = DecisionVariable(dv_id,dv_name) # construct the assignment for the variable for value_obj in variable_obj.findall('VALUE'): # value_id = value_obj.find('ID').text value_name = value_obj.find('VALUE-NAME').text value_utility = float(value_obj.find('VALUE-UTILITY').text) assignment = Assignment(decision_variable, value_name, value_utility) # add the assignment to the variable, and a dictionary for future reference decision_variable.add_domain_value(assignment) # using the id of the variable and the value of the assignment as key assignment_map_with_id[(dv_id,value_name)] = assignment assignment_map_with_name[(dv_name,value_name)] = assignment tpnu.add_decision_variable(decision_variable) # parse variables' guards for variable_obj in e.findall('DECISION-VARIABLE'): if variable_obj.find('ID') is not None: dv_id = variable_obj.find('ID').text else: dv_id = variable_obj.find('DECISION-NAME').text decision_variable = tpnu.decision_variables[dv_id] # the guard could be a conjunctive set of assignment for guard_obj in variable_obj.findall('GUARD'): # guard_id = guard_obj.find('ID').text guard_variable = guard_obj.find('GUARD-VARIABLE').text guard_value = guard_obj.find('GUARD-VALUE').text # retrieve the assignment if (guard_variable,guard_value) in assignment_map_with_id: guard_assignment = assignment_map_with_id[(guard_variable,guard_value)] elif (guard_variable,guard_value) in assignment_map_with_name: guard_assignment = assignment_map_with_name[(guard_variable,guard_value)] # and add to the guards of this decision variable decision_variable.add_guard(guard_assignment) # parse the temporal constraints and episodes # if line below confuses you, that's expected... We need better automated code generation for parsing... for constraint_obj in e.findall('CONSTRAINT'): # duration can be one of three types - controllable, uncertain and probabilistic # here we are only handling the first two cases, which are sorted into two lists # in our resulting stnu class. lower_bound = float(constraint_obj.find('LOWERBOUND').text) upper_bound = float(constraint_obj.find('UPPERBOUND').text) from_event = constraint_obj.find('START').text to_event = constraint_obj.find('END').text constraint_id = constraint_obj.find('ID').text constraint_name = constraint_obj.find('NAME').text constraint = TemporalConstraint(constraint_id, constraint_name, tpnu.node_id_to_number[from_event], tpnu.node_id_to_number[to_event], lower_bound, upper_bound) # check if the constraint is controllable and relaxable type = constraint_obj.find('TYPE').text if "Controllable" in type: constraint.controllable = True elif "Uncontrollable" in type: constraint.controllable = False if constraint_obj.find('MEAN') is not None: constraint.mean = float(constraint_obj.find('MEAN').text) if constraint_obj.find('VARIANCE') is not None: constraint.probabilistic = True constraint.std = np.sqrt(float(constraint_obj.find('VARIANCE').text)) if constraint_obj.find('LBRELAXABLE') is not None: if "T" in constraint_obj.find('LBRELAXABLE').text: constraint.relaxable_lb = True lb_cost = constraint_obj.find('LB-RELAX-COST-RATIO').text constraint.relax_cost_lb = float(lb_cost) if constraint_obj.find('UBRELAXABLE') is not None: if "T" in constraint_obj.find('UBRELAXABLE').text: constraint.relaxable_ub = True ub_cost = constraint_obj.find('UB-RELAX-COST-RATIO').text constraint.relax_cost_ub = float(ub_cost) # Next we deal with the guard conditions # the approach is identical to that for decision variables for guard_obj in constraint_obj.findall('GUARD'): # guard_id = guard_obj.find('ID').text guard_variable = guard_obj.find('GUARD-VARIABLE').text guard_value = guard_obj.find('GUARD-VALUE').text # retrieve the assignment if (guard_variable,guard_value) in assignment_map_with_id: guard_assignment = assignment_map_with_id[(guard_variable,guard_value)] elif (guard_variable,guard_value) in assignment_map_with_name: guard_assignment = assignment_map_with_name[(guard_variable,guard_value)] # and add to the guards of this decision variable constraint.add_guard(guard_assignment) tpnu.add_temporal_constraint(constraint) # Parse Chance Constraint # risk_bound = float(e.find('RISK-BOUND').text) # risk_bound_relax_cost = float(e.find('RISK-BOUND-RELAX-COST').text) risk_bound = 0.05 risk_bound_relax_cost = 100 cc_constraint = ChanceConstraint("CC-1", "CC-Constraint", risk_bound) if risk_bound_relax_cost > 0: cc_constraint.relaxable_bound = True cc_constraint.relax_cost = risk_bound_relax_cost tpnu.add_chance_constraint(cc_constraint) tpnu.start_node = tpnu.node_id_to_number[start_id] return tpnu