예제 #1
0
def enforce_binary(x_searchers, t_max):
    """Enforce variable to be binary"""

    old_x_searchers = x_searchers

    m = ext.get_m_from_tuple(x_searchers)
    S = ext.get_set_searchers(m)[0]

    x_keys = old_x_searchers.keys()

    # loop searchers
    for s in S:
        # loop through time
        for t in range(t_max + 1):
            v_t = [k[1] for k in x_keys if s == k[0] and t == k[2]]
            var_value = [old_x_searchers.get((s, v, t)) for v in v_t]

            # find max value idx at time t
            mx = var_value.index(max(var_value))

            # everything else is zero
            for v in v_t:
                if v == v_t[mx]:
                    x_searchers[(s, v, t)] = 1
                else:
                    x_searchers[(s, v, t)] = 0

    # for debugging only!
    if old_x_searchers != x_searchers:
        print('-X-X-X-X-X-X- Eureka! -X-X-X-X-X-X-')

    return x_searchers
예제 #2
0
def plot_searchers_position(g, folder_name, my_layout, x_searchers: dict,
                            t: int):
    """plot results of searchers position"""

    m = ext.get_m_from_tuple(x_searchers)

    V, n = ext.get_set_vertices(g)
    S = ext.get_set_searchers(m)[0]
    g.vs["color"] = "white"

    for s in S:
        for v in V:
            my_value = x_searchers.get((s, v, t))

            if my_value == 1:
                v_idx = ext.get_python_idx(v)
                g.vs[v_idx]["color"] = "blue"

    name_file = folder_name + "/" + g["name"] + "_t" + str(t) + ".png"
    plot(g,
         name_file,
         layout=my_layout,
         figsize=(3, 3),
         bbox=(400, 400),
         margin=15,
         dpi=400)

    return name_file
예제 #3
0
def plot_searchers_and_target(g, folder_path, my_layout, target, searchers, t):
    """plot results of searchers position
    and true position of the target"""

    m = len(list(searchers.keys()))
    S = ext.get_set_searchers(list(range(m)))[0]
    g.vs["color"] = "white"

    for s_id in S:
        s = searchers[s_id]
        my_searcher_vertex = s.path_taken[t]
        v_idx = ext.get_python_idx(my_searcher_vertex)
        g.vs[v_idx]["color"] = "blue"

        # plot target
        v_target = target.stored_v_true[t]
        v_t_idx = ext.get_python_idx(v_target)
        if target.capture_time == t:
            g.vs[v_t_idx]["color"] = "green"
        else:
            g.vs[v_t_idx]["color"] = "red"

    name_file = folder_path + "/" + g["name"] + "_t" + str(t) + ".png"
    plot(g,
         name_file,
         layout=my_layout,
         figsize=(3, 3),
         bbox=(400, 400),
         margin=15,
         dpi=400)
    plt.close()
    return name_file
예제 #4
0
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
예제 #5
0
def next_from_path(path: dict, t_plan: int):
    """ get new position of searchers as new_pos = {s: v}"""

    m = ext.get_m_from_tuple(path)
    S = ext.get_set_searchers(m)[0]

    new_pos = dict()
    for s_id in S:
        new_pos[s_id] = path[(s_id, t_plan)]

    return new_pos
예제 #6
0
def test_get_set_and_idx_searchers():
    list_input = [5, 2]
    S, m = ext.get_set_searchers(list_input)
    S_, m_ = ext.get_idx_searchers(list_input)
    assert S == [1, 2]
    assert S_ == [0, 1]
    assert m == 2
    assert m_ == 2

    dict_input = {1: 10, 2: 9, 3: 8}
    S, m = ext.get_set_searchers(dict_input)
    S_, m_ = ext.get_idx_searchers(dict_input)
    assert S == [1, 2, 3]
    assert S_ == [0, 1, 2]
    assert m == 3
    assert m_ == 3

    dict_input2 = dict()
    # x_s(s, v, t)
    dict_input2[(1, 1, 0)] = 1
    dict_input2[(1, 2, 1)] = 1
    dict_input2[(1, 3, 2)] = 1
    dict_input2[(2, 4, 0)] = 1
    dict_input2[(2, 5, 1)] = 1
    dict_input2[(2, 6, 2)] = 1
    S, m = ext.get_set_searchers(dict_input2)
    S_, m_ = ext.get_idx_searchers(dict_input2)
    assert S == [1, 2]
    assert S_ == [0, 1]
    assert m == 2
    assert m_ == 2

    int_input = 5
    S, m = ext.get_set_searchers(int_input)
    S_, m_ = ext.get_idx_searchers(int_input)
    assert S == [1, 2, 3, 4, 5]
    assert S_ == [0, 1, 2, 3, 4]
    assert m == 5
    assert m_ == 5
예제 #7
0
def add_searcher_variables(md, g, start: list, vertices_t: dict,
                           deadline: int):
    """Add variables related to the searchers on the model:
    X : searchers location at each time step
    Y : searchers movement from t to t + 1"""

    [X, Y] = ext.init_dict_variables(2)

    S, m = ext.get_set_searchers(start)

    var_for_test = {}
    list_x_name = []
    list_y_name = []

    # T_ext = {0, 1,..., tau}
    T_ext = ext.get_set_time_u_0(deadline)

    # searcher s is located at vertex v at time t
    for s in S:
        for t in T_ext:
            # get vertices that searcher s can be at time t (last t needs to be dummy goal vertex)
            # v_t returns the label of the vertices
            v_t = vertices_t.get((s, t))
            for v in v_t:
                # variable for: searcher position --  for each node the searcher can be at each time
                dummy_x_name = "x[%d,%d,%d]" % (s, v, t)
                if dummy_x_name not in list_x_name:
                    # if didn't add already, do it
                    X[s, v, t] = md.addVar(vtype="BINARY", name=dummy_x_name)
                    list_x_name.append(dummy_x_name)

                # find Y[s, u, v, t] : from u, searcher s can move to u at t + 1
                # returns vertices labels
                my_next_v = cm.get_next_vertices(g, s, v, t, vertices_t, T_ext)
                if my_next_v is not None:
                    for u in my_next_v:
                        dummy_y_name = "y[%d,%d,%d,%d]" % (s, v, u, t)
                        if dummy_y_name not in list_y_name:
                            Y[s, v, u, t] = md.addVar(vtype="BINARY",
                                                      name=dummy_y_name)
                            list_y_name.append(dummy_y_name)

    var_for_test.update({'x': list_x_name})
    var_for_test.update({'y': list_y_name})

    my_vars = {'x': X, 'y': Y}
    return my_vars, var_for_test
예제 #8
0
def init_temp_path(searchers: dict, horizon: int):
    """If no path was computed yet, assume all searchers will stay at the start position
    :param searchers: dictionary of searcher class
    :param horizon: planning horizon (h)"""

    Tau = ext.get_set_time_u_0(horizon)
    start = ext.get_searchers_positions(searchers)
    # S_ and Tau
    S, m = ext.get_set_searchers(start)

    temp_pi = dict()
    temp_pi['current_searcher'] = None

    for s in S:
        s_idx = ext.get_python_idx(s)
        v = start[s_idx]
        for t in Tau:
            temp_pi[s, t] = v

    return temp_pi
예제 #9
0
def add_searcher_constraints(md, g, my_vars: dict, start: list,
                             vertices_t: dict, deadline: int):
    """Define constraints pertinent to the searchers path """
    # get variables
    X = get_var(my_vars, 'x')
    Y = get_var(my_vars, 'y')

    S, m = ext.get_set_searchers(start)
    Tau_ext = ext.get_set_time_u_0(deadline)

    # legality of the paths, for all s = {1,...m}
    for s in S:
        # 0, 1, 2... T
        for t in Tau_ext:
            v_t = vertices_t.get((s, t))
            # each searcher can only be at one place at each time (including the start vertex), Eq. (1, 7)
            if t == 0:
                md.addConstr(X[s, v_t[0], 0] == 1)

            for u in v_t:
                my_next_v = cm.get_next_vertices(g, s, u, t, vertices_t,
                                                 Tau_ext)
                my_previous_v = cm.get_previous_vertices(
                    g, s, u, t, vertices_t)
                if my_next_v is not None:
                    # (Eq. 9) searcher can only move to: i in delta_prime(v) AND V^tau(t+1)
                    # sum == 1 if searcher is at u, sum == zero if searcher is not at u (depends on X[s, u, t])
                    md.addConstr(
                        quicksum(Y[s, u, i, t] for i in my_next_v) == X[s, u,
                                                                        t])

                    if my_previous_v is not None:
                        # (Eq. 8) searcher can only move to v from j in delta_prime(v) AND V^tau(t-1)
                        md.addConstr(
                            quicksum(Y[s, i, u, t - 1]
                                     for i in my_previous_v) == X[s, u, t])
예제 #10
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))
예제 #11
0
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
예제 #12
0
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