coin-or / pulp

A python Linear Programming API
http://coin-or.github.io/pulp/
Other
2.1k stars 384 forks source link

Inconsistent solver arguments across solver types, quality of life suggestion #260

Closed seangrogan closed 4 years ago

seangrogan commented 4 years ago

Hello,

So I am running my code across computers that may or may not have certain solvers installed. I created a function to get "best available solver", i.e. this:

def _get_best_solver():
    solvers = [
    pulp.GUROBI,
    pulp.GUROBI_CMD,
    #etc 
    # solvers in the order of preference
    ]
    for solver in solvers:
        if solver().available():
            print(f"Solver {solver} is available")
            return solver
    assert False, "No solver found"`

def solve_mip():
    #build model
    solver = _get_best_solver()
    model.solve(solver(msg=True, timelimit=300))

I want to pass a time limit of (say) 300 seconds. The problem is that the solver class initializers seem to have different methods of assigning a time limit. E.g. CPLEX_CMD has timelimit, GUROBI, CPLEX_DLL, and CPLEX_PY has timeLimit (capital L), XPRESS, COIN has maxSeconds.

I'm not familiar with how to do pull requests, but I'd be willing to help make the changes

stumitchell commented 4 years ago

Yes this is annoying, I would love a pull request,

Please make the old arguments still work however maybe with a deprecation warning.

Stu Stuart Mitchell PhD Engineering Science Extraordinary Freelance Programmer and Optimisation Guru www.stuartmitchell.com

On Sat, Feb 1, 2020 at 5:34 AM Sean Grogan notifications@github.com wrote:

Hello,

So I am running my code across computers that may or may not have certain solvers installed. I created a function to get "best available solver", i.e. this:

def _get_best_solver(): solvers = [ pulp.GUROBI, pulp.GUROBI_CMD,

etc

# solvers in the order of preference
]
for solver in solvers:
    if solver().available():
        print(f"Solver {solver} is available")
        return solver
assert False, "No solver found"`

def solve_mip():

build model

solver = _get_best_solver()
model.solve(solver(msg=True, timelimit=300))

I want to pass a time limit of (say) 300 seconds. The problem is that the solver class initializers seem to have different methods of assigning a time limit. E.g. CPLEX_CMD has timelimit, GUROBI, CPLEX_DLL, and CPLEX_PY has timeLimit (capital L), XPRESS, COIN has maxSeconds.

I'm not familiar with how to do pull requests, but I'd be willing to help make the changes

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/coin-or/pulp/issues/260?email_source=notifications&email_token=AAFUIWKIRMGBTWWLFYPFM5DRARHH7A5CNFSM4KOJ2ROKYY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4IKGAU2A, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAFUIWLI3MMZMPFMJ2YZHYLRARHH7ANCNFSM4KOJ2ROA .

pchtsp commented 4 years ago

Maybe it is too ambitious but if you want to make a proposal of a solver factory, that would be great too.

I attach an example of doing this (making arguments more standard and also calling a solver with a string) that I use in some projects of mine.

On Sun, Feb 2, 2020 at 9:21 PM Stuart Mitchell notifications@github.com wrote:

Yes this is annoying, I would love a pull request,

Please make the old arguments still work however maybe with a deprecation warning.

Stu Stuart Mitchell PhD Engineering Science Extraordinary Freelance Programmer and Optimisation Guru www.stuartmitchell.com

On Sat, Feb 1, 2020 at 5:34 AM Sean Grogan notifications@github.com wrote:

Hello,

So I am running my code across computers that may or may not have certain solvers installed. I created a function to get "best available solver", i.e. this:

def _get_best_solver(): solvers = [ pulp.GUROBI, pulp.GUROBI_CMD,

etc

solvers in the order of preference

] for solver in solvers: if solver().available(): print(f"Solver {solver} is available") return solver assert False, "No solver found"`

def solve_mip():

build model

solver = _get_best_solver() model.solve(solver(msg=True, timelimit=300))

I want to pass a time limit of (say) 300 seconds. The problem is that the solver class initializers seem to have different methods of assigning a time limit. E.g. CPLEX_CMD has timelimit, GUROBI, CPLEX_DLL, and CPLEX_PY has timeLimit (capital L), XPRESS, COIN has maxSeconds.

I'm not familiar with how to do pull requests, but I'd be willing to help make the changes

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub < https://github.com/coin-or/pulp/issues/260?email_source=notifications&email_token=AAFUIWKIRMGBTWWLFYPFM5DRARHH7A5CNFSM4KOJ2ROKYY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4IKGAU2A , or unsubscribe < https://github.com/notifications/unsubscribe-auth/AAFUIWLI3MMZMPFMJ2YZHYLRARHH7ANCNFSM4KOJ2ROA

.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/coin-or/pulp/issues/260?email_source=notifications&email_token=ABJUZ46OOGDMHN6TP3M7WZTRA4TMPA5CNFSM4KOJ2ROKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEKR76WI#issuecomment-581173081, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABJUZ4ZBZWVAQYP554HUISDRA4TMPANCNFSM4KOJ2ROA .

tkralphs commented 4 years ago

Attachments get scrubbed when you respond by e-mail. Responding on the issue page itself by clicking on the link in e-mail provides a much better experience and you can attach files easily.

pchtsp commented 4 years ago

Thanks @tkralphs I add the files via the web: Ok, apparently I cannot attach a file with python extension so here it is in pastebin: https://pastebin.com/783i3Yvm

seangrogan commented 4 years ago

Hello!

I made a pull request in line with @stumitchell 's comments

https://github.com/coin-or/pulp/pull/261

pchtsp commented 4 years ago

I'm going to close this issue since the changes have been mostly done: timeLimit, gapRel, gapAbs, logPath, warmStart and some more arguments are shared across solvers now. They are all stored in the LpSolver under a combination of explicit arguments and keyword arguments that are stored in self.optionsDict.