示例#1
0
def optimise_eef(cfg, full_red=False):
    """Optimise using the reduced extended edge formulation (Constantino et al., EJOR, 2013).

    Note that this implementation does not yet include chains, and throws an exception
    if a chain cap greater than zero is used.

    Args:
        cfg: an OptConfig object
        full_red: True if cycles should be generated in order to reduce number of variables further

    Returns:
        an OptSolution object
    """

    if cfg.edge_success_prob != 1:
        raise ValueError(
            "This formulation does not support failure-aware matching.")

    m = create_ip_model(cfg.timelimit, cfg.verbose)
    m.params.method = 2
    m.params.presolve = 0

    # For each vertex v, a list of variables corresponding to in-edges to v
    vtx_to_in_edges = [[] for __ in cfg.digraph.vs]

    add_chain_vars_and_constraints(cfg.digraph, cfg.ndds, cfg.max_chain, m,
                                   vtx_to_in_edges)

    vars_and_edges = add_eef_vars_and_constraints(cfg.max_cycle, cfg.digraph,
                                                  m, full_red,
                                                  cfg.eef_alt_constraints,
                                                  vtx_to_in_edges)

    obj_expr = quicksum(edge.score * var
                        for var, edge, low_v_id in vars_and_edges)
    if cfg.max_chain > 0:
        obj_expr += quicksum(e.score * e.edge_var for ndd in cfg.ndds
                             for e in ndd.edges)
        obj_expr += quicksum(e.score * var for e in cfg.digraph.es
                             for var in e.grb_vars)

    m.setObjective(obj_expr, GRB.MAXIMIZE)
    optimise(m, cfg)

    cycle_start_vv = []
    cycle_next_vv = {}

    for var, edge, low_v_id in vars_and_edges:
        if var.x > 0.1:
            cycle_next_vv[edge.src.id] = edge.tgt.id
            cycle_start_vv.append(edge.src.id)

    return OptSolution(ip_model=m,
                       cycles=kidney_utils.selected_edges_to_cycles(
                           cfg.digraph, cycle_start_vv, cycle_next_vv),
                       chains=[] if cfg.max_chain == 0 else
                       kidney_utils.get_optimal_chains(cfg.digraph, cfg.ndds),
                       digraph=cfg.digraph)
示例#2
0
def optimise_eef(cfg, full_red=False):
    """Optimise using the reduced extended edge formulation (Constantino et al., EJOR, 2013).

    Note that this implementation does not yet include chains, and throws an exception
    if a chain cap greater than zero is used.

    Args:
        cfg: an OptConfig object
        full_red: True if cycles should be generated in order to reduce number of variables further

    Returns:
        an OptSolution object
    """

    if cfg.edge_success_prob != 1:
        raise ValueError("This formulation does not support failure-aware matching.")

    m = create_ip_model(cfg.timelimit, cfg.verbose)
    m.params.method = 2
    m.params.presolve = 0

    # For each vertex v, a list of variables corresponding to in-edges to v
    vtx_to_in_edges = [[] for __ in cfg.digraph.vs]

    add_chain_vars_and_constraints(cfg.digraph, cfg.ndds, cfg.max_chain, m, vtx_to_in_edges)

    vars_and_edges = add_eef_vars_and_constraints(
        cfg.max_cycle, cfg.digraph, m, full_red, cfg.eef_alt_constraints, vtx_to_in_edges
    )

    obj_expr = quicksum(edge.score * var for var, edge, low_v_id in vars_and_edges)
    if cfg.max_chain > 0:
        obj_expr += quicksum(e.score * e.edge_var for ndd in cfg.ndds for e in ndd.edges)
        obj_expr += quicksum(e.score * var for e in cfg.digraph.es for var in e.grb_vars)

    m.setObjective(obj_expr, GRB.MAXIMIZE)
    optimise(m, cfg)

    cycle_start_vv = []
    cycle_next_vv = {}

    for var, edge, low_v_id in vars_and_edges:
        if var.x > 0.1:
            cycle_next_vv[edge.src.id] = edge.tgt.id
            cycle_start_vv.append(edge.src.id)

    return OptSolution(
        ip_model=m,
        cycles=kidney_utils.selected_edges_to_cycles(cfg.digraph, cycle_start_vv, cycle_next_vv),
        chains=[] if cfg.max_chain == 0 else kidney_utils.get_optimal_chains(cfg.digraph, cfg.ndds),
        digraph=cfg.digraph,
    )
示例#3
0
def optimise_uuef(cfg):
    """Optimise using the uncapped edge formulation.

    Args:
        cfg: an OptConfig object

    Returns:
        an OptSolution object
    """

    if cfg.edge_success_prob != 1:
        raise ValueError(
            "This formulation does not support failure-aware matching.")

    m = create_ip_model(cfg.timelimit, cfg.verbose)

    add_unlimited_vars_and_constraints(cfg.digraph, cfg.ndds, m)

    obj_expr = (quicksum(e.score * e.edge_var for ndd in cfg.ndds
                         for e in ndd.edges) + quicksum(e.score * var
                                                        for e in cfg.digraph.es
                                                        for var in e.grb_vars))

    m.setObjective(obj_expr, GRB.MAXIMIZE)
    optimise(m, cfg)

    # Try all possible cycle start positions
    cycle_start_vv = range(cfg.digraph.n)

    cycle_next_vv = {}
    for e in cfg.digraph.es:
        for var in e.grb_vars:
            if var.x > 0.1:
                cycle_next_vv[e.src.id] = e.tgt.id

    return OptSolution(
        ip_model=m,
        cycles=kidney_utils.selected_edges_to_cycles(cfg.digraph,
                                                     cycle_start_vv,
                                                     cycle_next_vv),
        chains=kidney_utils.get_optimal_chains(cfg.digraph, cfg.ndds),
        digraph=cfg.digraph)
示例#4
0
def optimise_uuef(cfg):
    """Optimise using the uncapped edge formulation.

    Args:
        cfg: an OptConfig object

    Returns:
        an OptSolution object
    """

    if cfg.edge_success_prob != 1:
        raise ValueError("This formulation does not support failure-aware matching.")

    m = create_ip_model(cfg.timelimit, cfg.verbose)

    add_unlimited_vars_and_constraints(cfg.digraph, cfg.ndds, m)

    obj_expr = quicksum(e.score * e.edge_var for ndd in cfg.ndds for e in ndd.edges) + quicksum(
        e.score * var for e in cfg.digraph.es for var in e.grb_vars
    )

    m.setObjective(obj_expr, GRB.MAXIMIZE)
    optimise(m, cfg)

    # Try all possible cycle start positions
    cycle_start_vv = range(cfg.digraph.n)

    cycle_next_vv = {}
    for e in cfg.digraph.es:
        for var in e.grb_vars:
            if var.x > 0.1:
                cycle_next_vv[e.src.id] = e.tgt.id

    return OptSolution(
        ip_model=m,
        cycles=kidney_utils.selected_edges_to_cycles(cfg.digraph, cycle_start_vv, cycle_next_vv),
        chains=kidney_utils.get_optimal_chains(cfg.digraph, cfg.ndds),
        digraph=cfg.digraph,
    )
示例#5
0
def optimise_hpief_prime(cfg, full_red=False, hpief_2_prime=False):
    """Optimise using the HPIEF' or HPIEF'' formulation.

    The HPIEF' model is based on HPIEF, but does not include cycle-edge variables at position zero.
    HPIEF'' also removes variables corresponding to edges at the last possible position of a cycle. 

    Args:
        cfg: an OptConfig object
        full_red: True if cycles should be generated in order to reduce number of variables further
        hpief_2_prime: Use HPIEF''? Default: HPIEF'

    Returns:
        an OptSolution object
    """

    if cfg.edge_success_prob != 1:
        raise ValueError(
            "This formulation does not support failure-aware matching.")

    if cfg.max_cycle < 3:
        hpief_2_prime = False

    m = create_ip_model(cfg.timelimit, cfg.verbose)
    m.params.method = 2
    m.params.presolve = 0

    # For each vertex v, a list of variables corresponding to in-edges to v
    vtx_to_in_edges = [[] for __ in cfg.digraph.vs]

    add_chain_vars_and_constraints(cfg.digraph, cfg.ndds, cfg.max_chain, m,
                                   vtx_to_in_edges)

    vars_and_edges = add_hpief_prime_vars_and_constraints(
        cfg.max_cycle, cfg.digraph, vtx_to_in_edges, m, full_red,
        hpief_2_prime)

    obj_terms = []
    for var, pos, edge, low_v_id in vars_and_edges:
        score = edge.score
        if pos == 1:
            score += cfg.digraph.adj_mat[low_v_id][edge.src.id].score
        if hpief_2_prime and pos == cfg.max_cycle - 2 and edge.tgt.id != low_v_id:
            score += cfg.digraph.adj_mat[edge.tgt.id][low_v_id].score
        obj_terms.append(score * var)

    obj_expr = quicksum(obj_terms)

    if cfg.max_chain > 0:
        obj_expr += quicksum(e.score * e.edge_var for ndd in cfg.ndds
                             for e in ndd.edges)
        obj_expr += quicksum(e.score * var for e in cfg.digraph.es
                             for var in e.grb_vars)

    m.setObjective(obj_expr, GRB.MAXIMIZE)
    optimise(m, cfg)

    cycle_start_vv = []
    cycle_next_vv = {}

    for var, pos, edge, low_v_id in vars_and_edges:
        if var.x > 0.1:
            cycle_next_vv[edge.src.id] = edge.tgt.id
            if pos == 1:
                cycle_start_vv.append(low_v_id)
                cycle_next_vv[low_v_id] = edge.src.id
            if hpief_2_prime and pos == cfg.max_cycle - 2 and edge.tgt.id != low_v_id:
                cycle_next_vv[edge.tgt.id] = low_v_id

    return OptSolution(ip_model=m,
                       cycles=kidney_utils.selected_edges_to_cycles(
                           cfg.digraph, cycle_start_vv, cycle_next_vv),
                       chains=[] if cfg.max_chain == 0 else
                       kidney_utils.get_optimal_chains(cfg.digraph, cfg.ndds),
                       digraph=cfg.digraph)
示例#6
0
def optimise_hpief_prime(cfg, full_red=False, hpief_2_prime=False):
    """Optimise using the HPIEF' or HPIEF'' formulation.

    The HPIEF' model is based on HPIEF, but does not include cycle-edge variables at position zero.
    HPIEF'' also removes variables corresponding to edges at the last possible position of a cycle. 

    Args:
        cfg: an OptConfig object
        full_red: True if cycles should be generated in order to reduce number of variables further
        hpief_2_prime: Use HPIEF''? Default: HPIEF'

    Returns:
        an OptSolution object
    """

    if cfg.edge_success_prob != 1:
        raise ValueError("This formulation does not support failure-aware matching.")

    if cfg.max_cycle < 3:
        hpief_2_prime = False

    m = create_ip_model(cfg.timelimit, cfg.verbose)
    m.params.method = 2
    m.params.presolve = 0

    # For each vertex v, a list of variables corresponding to in-edges to v
    vtx_to_in_edges = [[] for __ in cfg.digraph.vs]

    add_chain_vars_and_constraints(cfg.digraph, cfg.ndds, cfg.max_chain, m, vtx_to_in_edges)

    vars_and_edges = add_hpief_prime_vars_and_constraints(
        cfg.max_cycle, cfg.digraph, vtx_to_in_edges, m, full_red, hpief_2_prime
    )

    obj_terms = []
    for var, pos, edge, low_v_id in vars_and_edges:
        score = edge.score
        if pos == 1:
            score += cfg.digraph.adj_mat[low_v_id][edge.src.id].score
        if hpief_2_prime and pos == cfg.max_cycle - 2 and edge.tgt.id != low_v_id:
            score += cfg.digraph.adj_mat[edge.tgt.id][low_v_id].score
        obj_terms.append(score * var)

    obj_expr = quicksum(obj_terms)

    if cfg.max_chain > 0:
        obj_expr += quicksum(e.score * e.edge_var for ndd in cfg.ndds for e in ndd.edges)
        obj_expr += quicksum(e.score * var for e in cfg.digraph.es for var in e.grb_vars)

    m.setObjective(obj_expr, GRB.MAXIMIZE)
    optimise(m, cfg)

    cycle_start_vv = []
    cycle_next_vv = {}

    for var, pos, edge, low_v_id in vars_and_edges:
        if var.x > 0.1:
            cycle_next_vv[edge.src.id] = edge.tgt.id
            if pos == 1:
                cycle_start_vv.append(low_v_id)
                cycle_next_vv[low_v_id] = edge.src.id
            if hpief_2_prime and pos == cfg.max_cycle - 2 and edge.tgt.id != low_v_id:
                cycle_next_vv[edge.tgt.id] = low_v_id

    return OptSolution(
        ip_model=m,
        cycles=kidney_utils.selected_edges_to_cycles(cfg.digraph, cycle_start_vv, cycle_next_vv),
        chains=[] if cfg.max_chain == 0 else kidney_utils.get_optimal_chains(cfg.digraph, cfg.ndds),
        digraph=cfg.digraph,
    )