solve_ideal: use ideal point for finding set of solutions for two-objective TSP
    Parameters:
        - n: number of cities
        - c,t: alternative edge weights, to compute two objective functions
        - segments: number of segments for finding various non-dominated solutions
    Returns list of candidate solutions

def solve_ideal(n,c,t,segments):
    """solve_ideal: use ideal point for finding set of solutions for two-objective TSP
    Parameters:
        - n: number of cities
        - c,t: alternative edge weights, to compute two objective functions
        - segments: number of segments for finding various non-dominated solutions
    Returns list of candidate solutions
    """
    model = base_model(n,c,t)   # base model for minimizing cost or time
    x,u,C,T = model.data

    # store the set of solutions for plotting
    cand = []
    # print("optimizing time"
    model.setObjective(T, "minimize")
    stat1 = optimize(model,cand)

    # print("optimizing cost"
    model.setObjective(C, "minimize")
    stat2 = optimize(model,cand)    #find the minimum cost routes

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

    times = [ti for (ti,ci) in cand]
    costs = [ci for (ti,ci) in cand]
    min_time = min(times)
    min_cost = min(costs)
    # print("ideal point:",min_time,",",min_cost

    #===============================================================
    # Objective function is f1^2 + f2^2 where f=Sum tx-min_time and g=Sum cx-min_cost
    f1 = model.addVar(vtype="C", name="f1")
    f2 = model.addVar(vtype="C", name="f2")

    model.addCons(f1 == T - min_time, "obj1")
    model.addCons(f2 == C - min_cost, "obj2")

    # print("optimizing distance to ideal point:"
    for i in range(segments+1):
        lambda_ = float(i)/segments
        # print(lambda_
        z = model.addVar(name="z")
        Obj = model.addCons(lambda_*f1*f1 + (1-lambda_)*f2*f2 == z)
        model.setObjective(z, "minimize")
        optimize(model, cand)    #  find the minimum cost routes
    return cand