Exemple #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)
Exemple #2
0
def optimise_picef(cfg):
    """Optimise using the PICEF formulation.

    Args:
        cfg: an OptConfig object

    Returns:
        an OptSolution object
    """

    cycles = cfg.digraph.find_cycles(cfg.max_cycle)

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

    cycle_vars = [m.addVar(vtype=GRB.BINARY) for __ in cycles]
    m.update()

    vtx_to_vars = [[] for __ in cfg.digraph.vs]

    add_chain_vars_and_constraints(cfg.digraph, cfg.ndds, cfg.max_chain, m,
            vtx_to_vars, store_edge_positions=cfg.edge_success_prob!=1)

    for i, c in enumerate(cycles):
        for v in c:
            vtx_to_vars[v.id].append(cycle_vars[i])

    for l in vtx_to_vars:
        if len(l) > 0:
            m.addConstr(quicksum(l) <= 1)

    if cfg.max_chain==0:
        obj_expr = quicksum(failure_aware_cycle_score(c, cfg.digraph, cfg.edge_success_prob) * var
                            for c, var in zip(cycles, cycle_vars))
    elif cfg.edge_success_prob == 1:
        obj_expr = ( quicksum(cycle_score(c, cfg.digraph) * var for c, var in zip(cycles, cycle_vars)) +
                     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) )
    else:
        obj_expr = ( quicksum(failure_aware_cycle_score(c, cfg.digraph, cfg.edge_success_prob) * var
                              for c, var in zip(cycles, cycle_vars)) +
                     quicksum(e.score*cfg.edge_success_prob * e.edge_var
                              for ndd in cfg.ndds for e in ndd.edges) +
                     quicksum(e.score*cfg.edge_success_prob**(pos+1) * var
                            for e in cfg.digraph.es for var, pos in zip(e.grb_vars, e.grb_var_positions)))

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

    return OptSolution(ip_model=m,
                       cycles=[c for c, v in zip(cycles, cycle_vars) if v.x > 0.5],
                       chains=[] if cfg.max_chain==0 else kidney_utils.get_optimal_chains(
                            cfg.digraph, cfg.ndds, cfg.edge_success_prob),
                       digraph=cfg.digraph,
                       edge_success_prob=cfg.edge_success_prob)
Exemple #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)
Exemple #4
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)