def get_vertices_and_steps(G, deadline, searchers): """Extract information from the user provided graph and information on searchers For each time step, find which vertices each searcher is allowed to be""" start = ext.get_searchers_positions(searchers) # S_ and Tau S, m = ext.get_set_searchers(start) Tau = ext.get_set_time(deadline) # get vertices V, n = ext.get_set_vertices(G) # shortest path lengths spl = ext.get_length_short_paths(G) # find V^tau(t) = {v in V} --> possible v(t) in optimal solution vertices_t = {} # find V^tau(v) = {t in Tau} --> possible t(v) in optimal solution times_v = {} start_idx = ext.get_python_idx(start) for s in S: s_idx = ext.get_python_idx(s) # initial position vertices_t[s, 0] = [start[s_idx]] # starting at t = 1 (idx = 1), it begins to move for t in Tau: vertices_t[s, t] = [] # find the nodes that are within t of distance (thus can be reached at t) for v in V: v_idx = ext.get_python_idx(v) dummy_var = spl[start_idx[s_idx]][v_idx] if dummy_var <= t: vertices_t[s, t].append(v) # find times allowed for each vertex for v in V: times_v[s, v] = [] if v == start[s_idx]: times_v[s, v] = [0] for t in Tau: if v in vertices_t[s, t]: times_v[s, v].append(t) # find dummy goal vertex and T + 1 v_g = ext.get_label_dummy_goal(V) t_g = ext.get_last_t(Tau) # append dummy goal vertices_t[s, t_g] = [v_g] # at T + 1, searcher is at dummy goal vertex times_v[s, v_g] = [ t_g ] # the only time allowed for the dummy goal vertex is T + 1 return start, vertices_t, times_v
def test_get_time(): deadline = 3 T = ext.get_set_time(deadline) assert T == [1, 2, 3] T_idx = ext.get_idx_time(deadline) assert T_idx == [0, 1, 2] T_ext = ext.get_set_time_u_0(deadline) T_ext2 = ext.get_set_time_u_0(T) assert T_ext == [0, 1, 2, 3] assert T_ext2 == [0, 1, 2, 3]
def set_solver_parameters(m, gamma, horizon, my_vars, timeout=30 * 60, pre_solve=-1): """ Define my objective function to be maximized """ h = ext.get_set_time(horizon) beta = get_var(my_vars, 'beta') m.setObjective(quicksum((gamma**t) * beta[0, t] for t in h), GRB.MAXIMIZE) m.setParam('TimeLimit', timeout) m.setParam('Threads', 8) m.setParam('Presolve', pre_solve) m.setParam('OutputFlag', 0)
def add_capture_constraints(md, g, my_vars: dict, searchers: dict, vertices_t, b0: list, M: list, deadline: int): """Define constraints about belief and capture events :param vertices_t: :param md: :param g: :param my_vars: :param searchers: :param b0 :param deadline """ # capture-related variables beta = get_var(my_vars, 'beta') alpha = get_var(my_vars, 'alpha') psi = get_var(my_vars, 'psi') false_neg, zeta = cm.check_false_negatives(searchers) # if false negative model, there will exist a delta if false_neg: delta = get_var(my_vars, 'delta') beta_s = get_var(my_vars, 'beta_s') else: delta = {} beta_s = {} # searchers position X = get_var(my_vars, 'x') # sets V = ext.get_set_vertices(g)[0] S, m = ext.get_set_searchers(searchers) Tau = ext.get_set_time(deadline) V_ext = ext.get_set_vertices_u_0(g) # initial belief (user input), t = 0 (Eq. 13) for i in V_ext: md.addConstr(beta[i, 0] == b0[i]) for t in Tau: # this is a dictionary my_vertices = cm.get_current_vertices(t, vertices_t, S) for v in V: # v_idx = ext.get_python_idx(v) # take Markovian model into account (Eq. 14) # NOTE M matrix is accessed by python indexing md.addConstr(alpha[v, t] == quicksum(M[u - 1][v - 1] * beta[u, t - 1] for u in V)) # find searchers position that could capture the target while it is in v list_u_capture = cm.get_u_for_capture(searchers, V, v) if list_u_capture and my_vertices: if false_neg: for s in S: md.addConstr( quicksum( X[s, u, t] for u in filter(lambda x: x in my_vertices[ s], list_u_capture)) >= psi[s, v, t]) md.addConstr( quicksum( X[s, u, t] for u in filter(lambda x: x in my_vertices[ s], list_u_capture)) <= psi[s, v, t]) else: md.addConstr( quicksum( quicksum(X[s, u, t] for u in filter( lambda x: x in my_vertices[s], list_u_capture)) for s in S) >= psi[v, t]) md.addConstr( quicksum( quicksum(X[s, u, t] for u in filter( lambda x: x in my_vertices[s], list_u_capture)) for s in S) <= m * psi[v, t]) if false_neg: for s in S: # first searcher if s == S[0]: md.addConstr(beta_s[0, v, t] == alpha[v, t]) # Eq. (38) md.addConstr(delta[s, v, t] <= 1 - psi[s, v, t]) # Eq. (39) md.addConstr(delta[s, v, t] <= beta_s[s - 1, v, t]) # Eq. (40) md.addConstr( delta[s, v, t] >= beta_s[s - 1, v, t] - psi[s, v, t]) # Eq. (37) md.addConstr(beta_s[s, v, t] == ((1 - zeta) * delta[s, v, t]) + (zeta * beta_s[s - 1, v, t])) # last searcher md.addConstr(beta[v, t] == beta_s[S[-1], v, t]) else: # (15) md.addConstr(beta[v, t] <= 1 - psi[v, t]) # (16) md.addConstr(beta[v, t] <= alpha[v, t]) # (17) md.addConstr(beta[v, t] >= alpha[v, t] - psi[v, t]) # probability of being intercepted == what is left md.addConstr(beta[0, t] == 1 - quicksum(beta[v, t] for v in V))
def add_target_variables(md, g, deadline: int, searchers=None): """Add variables related to the target and capture events: belief variable, B interception-related variables: belief vector composition, beta belief evolution, alpha capture event, zeta and psi """ # TODO change this to allow for different zetas (and unit-test it) V = ext.get_set_vertices(g)[0] T_ext = ext.get_set_time_u_0(deadline) T = ext.get_set_time(deadline) V_ext = ext.get_set_vertices_u_0(g) var_for_test = {} list_beta_name = [] list_alpha_name = [] list_delta_name = [] [beta, beta_s, alpha, psi, delta] = ext.init_dict_variables(5) if searchers is not None: false_neg, zeta = cm.check_false_negatives(searchers) S = ext.get_set_searchers(searchers)[0] else: false_neg = False S = None # alpha and psi: only exist from 1, 2.., T for t in T: for v in V: dummy_a_name = "[%d,%d]" % (v, t) alpha[v, t] = md.addVar(vtype="CONTINUOUS", lb=0.0, ub=1.0, name="alpha" + dummy_a_name) list_alpha_name.append(dummy_a_name) if false_neg: for s in S: dummy_delta_name = "[%d,%d,%d]" % (s, v, t) psi[s, v, t] = md.addVar(vtype="BINARY", name="psi" + dummy_delta_name) delta[s, v, t] = md.addVar(vtype="CONTINUOUS", lb=0.0, ub=1.0, name="delta" + dummy_delta_name) list_delta_name.append(dummy_delta_name) else: psi[v, t] = md.addVar(vtype="BINARY", name="psi" + dummy_a_name) for t in T_ext: for v in V_ext: dummy_b_name = "[%d,%d]" % (v, t) list_beta_name.append(dummy_b_name) beta[v, t] = md.addVar(vtype="CONTINUOUS", lb=0.0, ub=1.0, name="beta" + dummy_b_name) if false_neg: # include 0 for searcher s = 1, s-1 = 0 for s_ in [0] + S: dummy_bs_name = "[%d,%d,%d]" % (s_, v, t) beta_s[s_, v, t] = md.addVar(vtype="CONTINUOUS", lb=0.0, ub=1.0, name="beta_s" + dummy_bs_name) var_for_test.update({'beta': list_beta_name}) var_for_test.update({'alpha': list_alpha_name}) if false_neg: my_vars = { 'beta': beta, 'beta_s': beta_s, 'alpha': alpha, 'psi': psi, 'delta': delta } var_for_test.update({'delta': list_delta_name}) else: my_vars = {'beta': beta, 'alpha': alpha, 'psi': psi} return my_vars, var_for_test
def get_vertices_and_steps_distributed(G, deadline, searchers, temp_s_path): """Extract information from the user provided graph and information on searchers For each time step, find which vertices each searcher is allowed to be Since this is the distributed version, use info on temporary searchers path (temp_s_path)""" start = ext.get_searchers_positions(searchers) # S_ and Tau S, m = ext.get_set_searchers(start) Tau = ext.get_set_time(deadline) # get vertices V, n = ext.get_set_vertices(G) # shortest path lengths spl = ext.get_length_short_paths(G) # find V^tau(t) = {v in V} --> possible v(t) in optimal solution vertices_t = {} # find V^tau(v) = {t in Tau} --> possible t(v) in optimal solution times_v = {} for s in S: # initial position vertices_t[s, 0] = [temp_s_path[(s, 0)]] st_idx = ext.get_python_idx(vertices_t.get((s, 0))[0]) # starting at t = 1 (idx = 1), it begins to move for t in Tau: vertices_t[s, t] = [] if s == temp_s_path['current_searcher']: # if it's planning for this searcher, consider all possibilities # find the nodes that are within t of distance (thus can be reached at t) for v in V: v_idx = ext.get_python_idx(v) dummy_var = spl[st_idx][v_idx] if dummy_var <= t: vertices_t[s, t].append(v) else: # if is not the planning searcher, just use the info on the temporary path # either the start vertex of the pre-computed path v = temp_s_path[s, t] vertices_t[s, t].append(v) # find times allowed for each vertex for v in V: times_v[s, v] = [] if v == vertices_t[s, 0][0]: times_v[s, v] = [0] for t in Tau: if v in vertices_t[s, t]: times_v[s, v].append(t) # find dummy goal vertex and T + 1 v_g = ext.get_label_dummy_goal(V) t_g = ext.get_last_t(Tau) # append dummy goal vertices_t[s, t_g] = [v_g] # at T + 1, searcher is at dummy goal vertex times_v[s, v_g] = [ t_g ] # the only time allowed for the dummy goal vertex is T + 1 return start, vertices_t, times_v