coin-or / python-mip

Python-MIP: collection of Python tools for the modeling and solution of Mixed-Integer Linear programs
Eclipse Public License 2.0
516 stars 90 forks source link

MIP Start #233

Open bohong0528 opened 2 years ago

bohong0528 commented 2 years ago

Describe the bug I'm trying to use the initial feasible solution from start attribute to solve MIP problems, when I use CBC solver to do so which is fine but while using Gurobi I found out the start attribite used by Gurobi is in upper case (m.Start instead of m.start). I'm nor sure it is an issue but I think it is better to use the same wording.

To Reproduce So I use a if-else to implement this

        if m.solver_name == 'GRB':
            m.Start = [(m.x[v], m.x[v].x) for v in range(m.num_int)]
        else:
            m.start = [(m.x[v], m.x[v].x) for v in ​range(m.num_int)]            

set_start function in gurobi.py

    def set_start(self, start: List[Tuple[Var, float]]) -> None:
        # collecting data
        nz = len(start)
        cind = ffi.new("int[]", [el[0].idx for el in start])
        cval = ffi.new("double[]", [el[1] for el in start])

        st = GRBsetdblattrlist(self._model, "Start".encode("utf-8"), nz, cind, cval)
        if st != 0:
            raise ParameterNotAvailable("Error modifying attribute Start")
        self.__updated = False

set_start function in cbc.py

    def set_start(self, start: List[Tuple[Var, numbers.Real]]) -> None:
        n = len(start)
        dv = ffi.new("double[]", [start[i][1] for i in range(n)])
        keep_alive_str = [
            ffi.new("char[]", str.encode(start[i][0].name)) for i in range(n)
        ]
        var_names = ffi.new("char *[]", keep_alive_str)
        mdl = self._model
        cbclib.Cbc_setMIPStart(mdl, n, var_names, dv)

Expected behavior Both using "start" or "Start"

Desktop (please complete the following information):

rschwarz commented 2 years ago

I don't think I understand the issue. The Start attribute of Gurobi is an internal datastructure, which should not be used by the user on the python-mip side, right? This is also something that can't be changed within python-mip.

The proper API to use is the property start of mip.Model. This can be used to set an initial solution (where solver.set_start will then be called). It can also be used to get that solution, which will return the internal model.__start attribute, which is just a reference to whatever the user passed before.

So, model.Start should not be used (and will not actually pass anything to Gurobi?), while model.start should work for both Gurobi and CBC.

Do you have a small, reproducible example where model.start does not work?