コード例 #1
0
ファイル: tests.py プロジェクト: Optimised/cdru
    def test_kirk_zipcar11(self):

        # build a kirk problem
        # first create a Tpnu
        tpnu = Tpnu('id','trip')
        # event
        # create events for this tpnu
        node_number_to_id = {}
        start_event = 1
        end_event = 2

        node_number_to_id[1] = 'start'
        node_number_to_id[2] = 'end'

        event_idx = 3
        constraint_idx = 1;

        # decision variable
        # create a decision variable to represent the choies over restaurants
        tpnu_decision_variable = DecisionVariable('dv','where to go?')
        tpnu.add_decision_variable(tpnu_decision_variable)

        # Then iterate through all goals and add them as domain assignments
        goal = 'somewhere'
        assignment = Assignment(tpnu_decision_variable, 'somewhere', 10.0)
        tpnu_decision_variable.add_domain_value(assignment)

        home_to_restaurant = TemporalConstraint('ep-'+str(constraint_idx), 'go to '+str(goal)+'-'+str(constraint_idx), start_event, event_idx, 36.065506858138214, 44.08006393772449)
        constraint_idx += 1
        event_idx += 1

        eat_at_restaurant = TemporalConstraint('ep-'+str(constraint_idx), 'dine at '+str(goal)+'-'+str(constraint_idx), event_idx-1, end_event, 0, 30)
        constraint_idx += 1

        node_number_to_id[event_idx-1] = 'arrive-'+str(goal)

        home_to_restaurant.add_guard(assignment)
        eat_at_restaurant.add_guard(assignment)

        tpnu.add_temporal_constraint(home_to_restaurant)
        tpnu.add_temporal_constraint(eat_at_restaurant)


        # temporal constraints
        # create constraints for the duration of the trip
        tpnu_constraint = TemporalConstraint('tc-'+str(constraint_idx), 'tc-'+str(constraint_idx), start_event, end_event, 0, 15)
        constraint_idx += 1
        tpnu_constraint.relaxable_ub = True
        tpnu_constraint.relax_cost_ub = 0.1
        tpnu.add_temporal_constraint(tpnu_constraint)

        tpnu.num_nodes = event_idx-1
        tpnu.node_number_to_id = node_number_to_id

        # next formulate a search problem using this tpnu
        search_problem = SearchProblem(tpnu)
        search_problem.initialize()

        solution = search_problem.next_solution()
コード例 #2
0
    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
コード例 #3
0
    def from_tpn_autogen(tpn):

        tpn_id = tpn.get_id()
        tpn_name = tpn.get_name()

        tpnu = Tpnu(tpn_id, tpn_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 in tpn.get_events().get_event():
            eid, ename = event.get_id(), event.get_name()
            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)

        assignment_map = {}
        # parse the decision variables
        for tpn_dv in tpn.get_decision_variables().get_decision_variable():
            dv_id = tpn_dv.get_id()
            dv_name = tpn_dv.get_name()
            decision_variable = DecisionVariable(dv_id, dv_name)

            # construct the assignment for the variable
            for domain_value in tpn_dv.get_domain().get_domainval():
                value_name = domain_value.get_value()
                value_utility = domain_value.get_utility()
                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[(dv_id, value_name)] = assignment

            tpnu.add_decision_variable(decision_variable)

        # parse their guards
        for tpn_dv in tpn.get_decision_variables().get_decision_variable():
            dv_id = tpn_dv.get_id()
            decision_variable = tpnu.decision_variables[dv_id]

            # the guard could be a single value
            # or a conjunctive set of assignment
            single_guard = tpn_dv.get_guard().get_decision_variable_equals()
            guard_list = tpn_dv.get_guard().get_and()

            if single_guard is not None:
                guard_variable_id = single_guard.get_variable()
                guard_value = single_guard.get_value()

                # retrieve the assignment
                guard_assignment = assignment_map[(guard_variable_id,
                                                   guard_value)]
                # and add to the guards of this decision variable
                decision_variable.add_guard(guard_assignment)

            if guard_list is not None:
                for guard in guard_list.get_guard():
                    guard_variable_id = guard.get_decision_variable_equals(
                    ).get_variable()
                    guard_value = guard.get_decision_variable_equals(
                    ).get_value()

                    # retrieve the assignment
                    guard_assignment = assignment_map[(guard_variable_id,
                                                       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 temporal_constraint in tpn.get_temporal_constraints(
        ).get_temporal_constraint() + tpn.get_episodes().get_episode():
            # 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.

            controllable_duration = temporal_constraint.get_duration(
            ).get_bounded_duration()
            uncertain_duration = temporal_constraint.get_duration(
            ).get_set_bounded_uncertain_duration()

            duration = controllable_duration or uncertain_duration
            lower_bound = duration.get_lower_bound()
            upper_bound = duration.get_upper_bound()
            from_event = temporal_constraint.get_from_event()
            to_event = temporal_constraint.get_to_event()
            constraint_id = temporal_constraint.get_id()
            constraint_name = temporal_constraint.get_name()
            constraint = TemporalConstraint(constraint_id, constraint_name,
                                            tpnu.node_id_to_number[from_event],
                                            tpnu.node_id_to_number[to_event],
                                            lower_bound, upper_bound)

            if controllable_duration is not None:
                constraint.controllable = True
                constraint.relaxable_ub = True

            elif uncertain_duration is not None:
                constraint.controllable = False

            # Next we deal with the guard conditions
            # the approach is identical to that for decision variables

            # the guard could be a single value
            # or a conjunctive set of assignment
            single_guard = temporal_constraint.get_guard(
            ).get_decision_variable_equals()
            guard_list = temporal_constraint.get_guard().get_and()

            if single_guard is not None:
                guard_variable_id = single_guard.get_variable()
                guard_value = single_guard.get_value()

                # retrieve the assignment
                guard_assignment = assignment_map[(guard_variable_id,
                                                   guard_value)]
                # and add to the guards of this decision variable
                constraint.add_guard(guard_assignment)

            if guard_list is not None:
                for guard in guard_list.get_guard():
                    guard_variable_id = guard.get_decision_variable_equals(
                    ).get_variable()
                    guard_value = guard.get_decision_variable_equals(
                    ).get_value()

                    # retrieve the assignment
                    guard_assignment = assignment_map[(guard_variable_id,
                                                       guard_value)]
                    # and add to the guards of this decision variable
                    constraint.add_guard(guard_assignment)

            tpnu.add_temporal_constraint(constraint)

        return tpnu
コード例 #4
0
#  example_file = 'Zipcar-1.cctp'

#  cdru_dir = dirname(__file__)
#  examples_dir = join(cdru_dir, join('..', 'examples'))
#  path = join(examples_dir, example_file)
#  tpnu = getProblemFromFile(path)

# NOTE: Limitation: Assumes num_nodes = N, then events are indexed by 1, 2, ..., N
# TODO: Currently, Tpnu.from_tpn_autogen does map eventID to numbers, but it does not take TPNU as input, if we want to use arbitrary event names, we need to add such a function/mapping
tpnu = Tpnu(str(uuid4()), 'example-tpnu')
tpnu.start_node = 1
tpnu.num_nodes = 3

# Initialize a decision variable
dv = DecisionVariable(str(uuid4()), 'dv')
as1 = Assignment(dv, 'dv-true', 10)
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)
コード例 #5
0
ファイル: tpnu.py プロジェクト: yu-peng/cdru
    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
コード例 #6
0
ファイル: tpnu.py プロジェクト: yu-peng/cdru
    def from_tpn_autogen(tpn):

        tpn_id = tpn.get_id()
        tpn_name = tpn.get_name()

        tpnu = Tpnu(tpn_id, tpn_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 in tpn.get_events().get_event():
            eid, ename = event.get_id(), event.get_name()
            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)

        assignment_map = {}
        # parse the decision variables
        for tpn_dv in tpn.get_decision_variables().get_decision_variable():
            dv_id = tpn_dv.get_id()
            dv_name = tpn_dv.get_name()
            decision_variable = DecisionVariable(dv_id,dv_name)

            # construct the assignment for the variable
            for domain_value in tpn_dv.get_domain().get_domainval():
                value_name = domain_value.get_value()
                value_utility = domain_value.get_utility()
                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[(dv_id,value_name)] = assignment

            tpnu.add_decision_variable(decision_variable)

        # parse their guards
        for tpn_dv in tpn.get_decision_variables().get_decision_variable():
            dv_id = tpn_dv.get_id()
            decision_variable = tpnu.decision_variables[dv_id]

            # the guard could be a single value
            # or a conjunctive set of assignment
            single_guard = tpn_dv.get_guard().get_decision_variable_equals()
            guard_list = tpn_dv.get_guard().get_and()

            if single_guard is not None:
                guard_variable_id = single_guard.get_variable()
                guard_value = single_guard.get_value()

                # retrieve the assignment
                guard_assignment = assignment_map[(guard_variable_id,guard_value)]
                # and add to the guards of this decision variable
                decision_variable.add_guard(guard_assignment)

            if guard_list is not None:
                for guard in guard_list.get_guard():
                    guard_variable_id = guard.get_decision_variable_equals().get_variable()
                    guard_value = guard.get_decision_variable_equals().get_value()

                    # retrieve the assignment
                    guard_assignment = assignment_map[(guard_variable_id,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 temporal_constraint in tpn.get_temporal_constraints().get_temporal_constraint() + tpn.get_episodes().get_episode():
            # 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.

            controllable_duration = temporal_constraint.get_duration().get_bounded_duration()
            uncertain_duration = temporal_constraint.get_duration().get_set_bounded_uncertain_duration()


            duration = controllable_duration or uncertain_duration
            lower_bound = duration.get_lower_bound()
            upper_bound = duration.get_upper_bound()
            from_event = temporal_constraint.get_from_event()
            to_event = temporal_constraint.get_to_event()
            constraint_id = temporal_constraint.get_id()
            constraint_name = temporal_constraint.get_name()
            constraint = TemporalConstraint(constraint_id, constraint_name, tpnu.node_id_to_number[from_event], tpnu.node_id_to_number[to_event], lower_bound, upper_bound)

            if controllable_duration is not None:
                constraint.controllable = True
                constraint.relaxable_ub = True

            elif uncertain_duration is not None:
                constraint.controllable = False

            # Next we deal with the guard conditions
            # the approach is identical to that for decision variables

            # the guard could be a single value
            # or a conjunctive set of assignment
            single_guard = temporal_constraint.get_guard().get_decision_variable_equals()
            guard_list = temporal_constraint.get_guard().get_and()

            if single_guard is not None:
                guard_variable_id = single_guard.get_variable()
                guard_value = single_guard.get_value()

                # retrieve the assignment
                guard_assignment = assignment_map[(guard_variable_id,guard_value)]
                # and add to the guards of this decision variable
                constraint.add_guard(guard_assignment)

            if guard_list is not None:
                for guard in guard_list.get_guard():
                    guard_variable_id = guard.get_decision_variable_equals().get_variable()
                    guard_value = guard.get_decision_variable_equals().get_value()

                    # retrieve the assignment
                    guard_assignment = assignment_map[(guard_variable_id,guard_value)]
                    # and add to the guards of this decision variable
                    constraint.add_guard(guard_assignment)

            tpnu.add_temporal_constraint(constraint)

        return tpnu