MOSEK / Tutorials

A collection of tutorials for the MOSEK package
107 stars 31 forks source link

How to input inital variable for mixed integer optimizer hot-start? #6

Closed attoman closed 1 year ago

attoman commented 1 year ago

While I'm trying an example for the TSP problem, I'm trying a hot-start by entering pre-prepared initial variables. In the case of the TSP problem, it seems that mixed integer optimizer is used. At this time, if the initial input for hot-start is entered as follows, it seems that the initial value is not set properly.

Here is my code.

''' def tsp(n, A, C, remove_selfloops, remove_2_hop_loops, init_value = None): with Model() as M: M.setLogHandler(sys.stdout) M.setSolverParam("presolveUse", "off") x = M.variable("x", [n,n], Domain.binary()) if init_value is None: pass else: x.setLevel(init_value) M.constraint(Expr.sum(x,0), Domain.equalsTo(1.0)) M.constraint(Expr.sum(x,1), Domain.equalsTo(1.0)) M.constraint(x, Domain.lessThan( A ))

    M.objective(ObjectiveSense.Minimize, Expr.dot(C ,x))

    if remove_2_hop_loops:
        M.constraint(Expr.add(x, x.transpose()), Domain.lessThan(1.0))

    if remove_selfloops:
        M.constraint(x.diag(), Domain.equalsTo(0.))
    it = 1

    M.writeTask("tsp-0-%s-%s.ptf" % ('t' if remove_selfloops else 'f', 't' if remove_2_hop_loops else 'f'))

    while True:
        print("\n\n--------------------\nIteration",it)
        M.solve()

        print('\nsolution cost:', M.primalObjValue())
        print('\nsolution:')

        cycles = []

        for i in range(n):
            xi = x.slice([i,0],[i+1,n])
            print(xi.level())

            for j in range(n):
                if xi.level()[j] <= 0.5 : continue

                found = False
                for c in cycles:
                    if len( [ a for a in c if i in a or j in a ] )> 0:
                        c.append( [i,j] )
                        found = True
                        break

                if not found:
                    cycles.append([ [ i,j ]])

        print('\ncycles:')
        print([c for c in cycles])

        if len(cycles)==1:
            break;

        for c in cycles:
            M.constraint(Expr.sum(x.pick(c)), Domain.lessThan( 1.0 * len(c) - 1 ))

        # if it == 2:
        #     break;

        it = it +1

    return x.level(), c, M.primalObjValue()
return [], [], []

X_warm = torch.zeros((n,n)) for i in range(tour_indices.shape[1]): X_warm[i][tour_indices[0][i]] = 1 for j in range(len(indx[0])): X_warm[indx[0][j]][indx[1][j]] = 1 for k in range(n): X_warm[k][k] = 0 X_warm = X_warm.to("cpu") X_warm_np = X_warm.numpy(force=True) X_warm_np_flat = X_warm_np.flatten() X_init_constraint_np = np.ones((n,n)) X_init_constraint_sparse = Matrix.sparse(X_init_constraint_np) X_warm_np = X_warm_np.astype(np.float64) X_warm_sparse = Matrix.sparse(X_warm_np) costs = Matrix.sparse(C_np) x_sol, c, length_sol = tsp(n, X_init_constraint_sparse, costs , True, True, init_value = X_warm_np_flat.tolist())

'''

tour_indices is tour node order.

Any way to solve this problem? Doesn't Mosek provide initial value setting for hot-start in mixed integer optimizer? Or if there is another way to solve this, please guide me.

szelidvihar commented 1 year ago

Hi,

You can check out how to set initial solutions for the mixed integer optimizer at https://docs.mosek.com/latest/pythonfusion/tutorial-mio-shared.html#specifying-an-initial-solution

According to that, since you are specifying all the variables (the only variable is x), Mosek should check if it is a feasible solution automatically. You can check if this is done by checking the information item "mioInitialFeasibleSolution":

M.getSolverIntInfo('mioInitialFeasibleSolution')

If this is 1, then initial feasible solution was used. If 0, then there was no initial solution supplied, or it was not feasible.

attoman commented 1 year ago

Thanks for your comments.