diff --git a/pulp/apis/coin.py b/pulp/apis/coin.py index 7ca52a29..84276b9f 100644 --- a/pulp/apis/coin.py +++ b/pulp/apis/coin.py @@ -99,6 +99,7 @@ def __init__( logPath=None, timeMode="elapsed", maxNodes=None, + randomSeed=None, ): """ :param bool mip: if False, assume LP even if integer variables @@ -117,6 +118,7 @@ def __init__( :param int strong: number of variables to look at in strong branching (range is 0 to 2147483647) :param str timeMode: "elapsed": count wall-time to timeLimit; "cpu": count cpu-time :param int maxNodes: max number of nodes during branching. Stops the solving when reached. + :param int randomSeed: random seed passed to CBC (``-randomSeed``) for reproducible results """ if warmStart and not keepFiles and operating_system == "win": warnings.warn( @@ -141,6 +143,7 @@ def __init__( logPath=logPath, timeMode=timeMode, maxNodes=maxNodes, + randomSeed=randomSeed, ) def copy(self): @@ -274,6 +277,7 @@ def getOptions(self): strong="strong {}", timeMode="timeMode {}", maxNodes="maxNodes {}", + randomSeed="randomSeed {}", ) return [ diff --git a/pulp/tests/test_coin_cmd.py b/pulp/tests/test_coin_cmd.py index d077f721..be4c8a0b 100644 --- a/pulp/tests/test_coin_cmd.py +++ b/pulp/tests/test_coin_cmd.py @@ -220,6 +220,44 @@ def test_strong(self): ) self.assertEqual("10", option_value) + def test_random_seed(self): + """ + Test if setting randomSeed=20 adds randomSeed 20 to the command line. + """ + # randomSeed is a public constructor argument that flows into optionsDict. + self.assertEqual(20, solvers.COIN_CMD(randomSeed=20).optionsDict["randomSeed"]) + name = self._testMethodName + prob = LpProblem(name, const.LpMinimize) + x = prob.add_variable("x", 0, 4) + y = prob.add_variable("y", -1, 1) + z = prob.add_variable("z", 0) + w = prob.add_variable("w", 0) + prob += x + 4 * y + 9 * z, "obj" + prob += x + y <= 5, "c1" + prob += x + z >= 10, "c2" + prob += -y + z == 7, "c3" + prob += w >= 0, "c4" + logFilename = name + ".log" + self.solver.optionsDict["logPath"] = logFilename + self.solver.optionsDict["randomSeed"] = 20 + pulpTestCheck( + prob, + self.solver, + [const.LpStatusOptimal], + {x: 4, y: -1, z: 6, w: 0}, + ) + if not os.path.exists(logFilename): + raise PulpError(f"Test failed for solver: {self.solver}") + if not os.path.getsize(logFilename): + raise PulpError(f"Test failed for solver: {self.solver}") + command_line = COIN_CMD_CBCOptionsTest.read_command_line_from_log_file( + logFilename + ) + option_value = COIN_CMD_CBCOptionsTest.extract_option_from_command_line( + command_line, option="randomSeed", grp_pattern="\\d+" + ) + self.assertEqual("20", option_value) + class COIN_CMDTest(BaseSolverTest.PuLPTest): solveInst = solvers.COIN_CMD