solve_segment: segmentation for finding set of solutions for two-objective TSP
    Parameters:
        - I: set of members in the staff
        - T: number of periods in a cycle
        - N: number of working periods required for staff's elements in a cycle
        - J: set of shifts in each period (shift 0 == rest)
        - S: subset of shifts that must be kept at least consecutive days
        - c[i,t,j]: cost of a shit j of staff's element i on period t
        - b[t,j]: number of staff elements required in period t, shift j
    Returns list of candidate solutions

def solve_segment(I,T,N,J,S,c,b):
    """
    solve_segment: segmentation for finding set of solutions for two-objective TSP
    Parameters:
        - I: set of members in the staff
        - T: number of periods in a cycle
        - N: number of working periods required for staff's elements in a cycle
        - J: set of shifts in each period (shift 0 == rest)
        - S: subset of shifts that must be kept at least consecutive days
        - c[i,t,j]: cost of a shit j of staff's element i on period t
        - b[t,j]: number of staff elements required in period t, shift j
    Returns list of candidate solutions
    """
    model = staff_mo(I,T,N,J,S,c,b)     # model for minimizing time
    x,y,C,U = model.data
    model.setRealParam("limits/time", 60)

    # store the set of solutions for plotting
    cand = []

    # first objective: cost
    stat1 = optimize(model,cand,C)
    stat2 = optimize(model,cand,U)

    if stat1 != "optimal" or stat2 != "optimal":
        return []

    ulist = [int(ui+.5) for (ui,ci) in cand]
    max_u = max(ulist)
    min_u = min(ulist)

    # add a time upper bound constraint, moving between min and max values
    UConstr = model.addCons(U <= max_u, "UConstr")


    for u_lim in range(max_u-1, min_u, -1):
        print("limiting u to",u_lim)
        UConstr.setAttr("RHS",u_lim)
        optimize(model,cand,C)

    return cand