def set_new_node( self, node, depth, er_bound, prob, parent_likelihood ): #creating new nodes (precisely, it's not actually instantiating, but fill values of newly instantiated node) # sets the fields of a new node b = node.state.belief node.risk = bound_prob(avg_func(b, self.r)) # Depth of a node is its dist to the root node.depth = depth node.set_prob(prob) node.set_likelihood( prob * parent_likelihood) #likelehood=parent likelihood * prob # Probability of violating constraints in a belief state. (never # change) if is_terminal_belief(b, self.term, self.terminal_prob): #terminal belif: self.set_terminal_node(node) elif node.depth == self.fixed_horizon: # self.set_terminal_node(node) node.value = avg_func(b, self.h) node.terminal = True # new node is non terminal node.best_action = None # no action associated yet node.exec_risk_bound = bound_prob(er_bound) # execution risk bound # avg heuristic estimate of execution risk at node node.set_exec_risk(node.risk) node.risk_upper = node.exec_risk else: # the value of a node is the average of the heuristic only when it's # first created. After that, the value is given as a function of # its children node.value = avg_func(b, self.h) node.terminal = False # new node is non terminal node.best_action = None # no action associated yet node.exec_risk_bound = bound_prob(er_bound) # execution risk bound # avg heuristic estimate of execution risk at node node.set_exec_risk(node.risk)
def set_terminal_node(self, node): # set fields of a terminal node b = node.state.belief node.set_terminal(True) node.set_value(avg_func(b, self.h)) node.set_exec_risk(node.risk) node.set_best_action(None) self.graph.remove_all_hyperedges(node) # terminal node has no edges
def set_new_node(self, node, depth, er_bound, prob, parent_likelihood): # sets the fields of a new node if self.continuous_belief: b = node.state node.risk = bound_prob(self.r(b)) node.depth = depth node.set_prob(prob) node.set_likelihood(prob * parent_likelihood) if self.term(node.state): self.set_terminal_node(node) else: # the value of a node is the average of the heuristic only when it's # first created. After that, the value is given as a function of # its children node.value = self.h(node) node.terminal = False # new node is non terminal node.best_action = None # no action associated yet node.exec_risk_bound = bound_prob( er_bound) # execution risk bound # avg heuristic estimate of execution risk at node node.set_exec_risk(node.risk) else: b = node.state.belief node.risk = bound_prob(avg_func(b, self.r)) # Depth of a node is its dist to the root node.depth = depth node.set_prob(prob) node.set_likelihood(prob * parent_likelihood) # Probability of violating constraints in a belief state. (never # change) if is_terminal_belief(b, self.term, self.terminal_prob): self.set_terminal_node(node) else: # the value of a node is the average of the heuristic only when it's # first created. After that, the value is given as a function of # its children node.value = avg_func(b, self.h) node.terminal = False # new node is non terminal node.best_action = None # no action associated yet node.exec_risk_bound = bound_prob( er_bound) # execution risk bound # avg heuristic estimate of execution risk at node node.set_exec_risk(node.risk)
def expand_best_partial_solution(self): # expands a node in the graph currently contained in the best # partial solution. Add new nodes and edges on the graph # nodes_to_expand = self.opennodes # self.opennodes = None nodes_to_expand = [self.choose_node()] # choose best node for node in nodes_to_expand: self.debug('\n ******* expanding node *******') self.debug(node.state.state_print()) # print(node.state.state_print()) self.debug('******************************\n') belief = node.state.belief # belief state associated to the node parent_risk = node.risk # execution risk for current node parent_bound = node.exec_risk_bound # er bound for current node parent_depth = node.depth # dist of parent to root parent_likelihood = node.likelihood # likelihood that node is reached in policy if self.cc_type == 'everywhere': parent_bound = self.cc self.debug('compute_exec_risk_bounds: parent_bound ', parent_bound, ' parent_risk ', parent_risk) # if the current node is guaranteed to violate constraints and a violation # is set to halt process: make node terminal if self.halt_on_violation and np.isclose(parent_risk, 1.0): all_node_actions = [] else: # else get the available actions from model all_node_actions = self.get_all_actions(belief, self.A) action_added = False # flag if a new action has been added if len(all_node_actions) > 0: added_count = 0 for act in all_node_actions: self.debug("\n", act) child_obj_list, prob_list, prob_safe_list, new_child_idxs = self.obtain_child_objs_and_probs( belief, self.T, self.O, self.r, act) # initializes the new child nodes for c_idx in new_child_idxs: self.set_new_node(child_obj_list[c_idx], parent_depth + 1, 0.0, prob_list[c_idx], parent_likelihood) # if parent bound Delta is ~ 1.0, the child nodes are guaranteed to have # their risk bound equal to 1 if (not np.isclose(parent_bound, 1.0)): # computes execution risk bounds for the child nodes er_bounds, er_bound_infeasible = self.compute_exec_risk_bounds( parent_bound, parent_risk, child_obj_list, prob_safe_list) else: er_bounds = [1.0] * len(child_obj_list) er_bound_infeasible = False # Only creates new operator if all er bounds a non-negative if not er_bound_infeasible: # updates the values of the execution risk for all children # that will be added to the graph for idx, child in enumerate(child_obj_list): child.exec_risk_bound = er_bounds[idx] # average instantaneous value (cost or reward) avg_op_value = avg_func(belief, self.V, act) act_obj = RAOStarGraphOperator(name=str(act), op_value=avg_op_value, properties={ 'prob': prob_list, 'prob_safe': prob_safe_list }) # an "Action" object crerated # add edge (Action) to graph self.graph.add_hyperedge(parent_obj=node, child_obj_list=child_obj_list, prob_list=prob_list, op_obj=act_obj) action_added = True added_count += 1 else: self.debug( ' action not added - error bound infeasible') if not action_added: # self.debug('action not added') # self.set_terminal_node(node) if not is_terminal_belief(node.state.belief, self.term, self.terminal_prob): self.mark_deadend(node) if not node.terminal and not node.deadend: self.set_terminal_node(node) # returns the list of node either added actions to or marked terminal return nodes_to_expand