|
1 | | -from pyscipopt import Model, SCIP_PARAMSETTING, Nodesel, SCIP_NODETYPE, quicksum |
| 1 | +from pyscipopt import Model, SCIP_PARAMSETTING, Nodesel, SCIP_NODETYPE |
2 | 2 | from pyscipopt.scip import Node |
3 | 3 |
|
4 | 4 |
|
@@ -197,80 +197,47 @@ def nodecomp(self, node1, node2): |
197 | 197 | else: |
198 | 198 | return 1 |
199 | 199 |
|
200 | | -def random_mip_1(disable_sepa=True, disable_heur=True, disable_presolve=True, node_lim=2000, small=False): |
201 | | - model = Model() |
202 | | - |
203 | | - x0 = model.addVar(lb=-2, ub=4) |
204 | | - r1 = model.addVar() |
205 | | - r2 = model.addVar() |
206 | | - y0 = model.addVar(lb=3) |
207 | | - t = model.addVar(lb=None) |
208 | | - l = model.addVar(vtype="I", lb=-9, ub=18) |
209 | | - u = model.addVar(vtype="I", lb=-3, ub=99) |
210 | | - |
211 | | - more_vars = [] |
212 | | - if small: |
213 | | - n = 100 |
214 | | - else: |
215 | | - n = 500 |
216 | | - for i in range(n): |
217 | | - more_vars.append(model.addVar(vtype="I", lb=-12, ub=40)) |
218 | | - model.addCons(quicksum(v for v in more_vars) <= (40 - i) * quicksum(v for v in more_vars[::2])) |
219 | | - |
220 | | - for i in range(100): |
221 | | - more_vars.append(model.addVar(vtype="I", lb=-52, ub=10)) |
222 | | - if small: |
223 | | - model.addCons(quicksum(v for v in more_vars[50::2]) <= (40 - i) * quicksum(v for v in more_vars[65::2])) |
224 | | - else: |
225 | | - model.addCons(quicksum(v for v in more_vars[50::2]) <= (40 - i) * quicksum(v for v in more_vars[405::2])) |
226 | | - |
227 | | - model.addCons(r1 >= x0) |
228 | | - model.addCons(r2 >= -x0) |
229 | | - model.addCons(y0 == r1 + r2) |
230 | | - model.addCons(t + l + 7 * u <= 300) |
231 | | - model.addCons(t >= quicksum(v for v in more_vars[::3]) - 10 * more_vars[5] + 5 * more_vars[9]) |
232 | | - model.addCons(more_vars[3] >= l + 2) |
233 | | - model.addCons(7 <= quicksum(v for v in more_vars[::4]) - x0) |
234 | | - model.addCons(quicksum(v for v in more_vars[::2]) + l <= quicksum(v for v in more_vars[::4])) |
235 | | - |
236 | | - model.setObjective(t - quicksum(j * v for j, v in enumerate(more_vars[20:-40]))) |
237 | | - |
238 | | - if disable_sepa: |
239 | | - model.setSeparating(SCIP_PARAMSETTING.OFF) |
240 | | - if disable_heur: |
241 | | - model.setHeuristics(SCIP_PARAMSETTING.OFF) |
242 | | - if disable_presolve: |
243 | | - model.setPresolve(SCIP_PARAMSETTING.OFF) |
244 | | - model.setParam("limits/nodes", node_lim) |
245 | | - |
246 | | - return model |
247 | | - |
248 | 200 | def test_hybridestim_vs_default(): |
249 | 201 | """ |
250 | 202 | Test that the Python hybrid estimate node selector performs similarly |
251 | 203 | to the default SCIP C implementation. |
252 | 204 | """ |
253 | | - import random |
254 | | - random.seed(42) |
| 205 | + import os |
255 | 206 |
|
256 | | - # Test with default SCIP hybrid estimate node selector |
257 | | - m_default = random_mip_1(node_lim=2000, small=True) |
| 207 | + # Get the path to the 10teams instance |
| 208 | + instance_path = os.path.join(os.path.dirname(__file__), "..", "..", "tests", "data", "10teams.mps") |
258 | 209 |
|
| 210 | + # Test with default SCIP hybrid estimate node selector |
| 211 | + m_default = Model() |
| 212 | + m_default.readProblem(instance_path) |
| 213 | + |
| 214 | + # Disable presolving, heuristics, and separation to focus on node selection |
| 215 | + m_default.setPresolve(SCIP_PARAMSETTING.OFF) |
| 216 | + m_default.setHeuristics(SCIP_PARAMSETTING.OFF) |
| 217 | + m_default.setSeparating(SCIP_PARAMSETTING.OFF) |
| 218 | + m_default.setParam("limits/nodes", 2000) |
259 | 219 | m_default.setParam("nodeselection/hybridestim/stdpriority", 1_000_000) |
260 | 220 |
|
261 | 221 | m_default.optimize() |
262 | 222 |
|
263 | 223 | default_lp_iterations = m_default.getNLPIterations() |
264 | 224 | default_nodes = m_default.getNNodes() |
265 | | - default_obj = m_default.getObjVal() |
266 | | - |
| 225 | + default_obj = m_default.getObjVal() if m_default.getNSols() > 0 else None |
| 226 | + |
267 | 227 | print(f"Default SCIP hybrid estimate node selector (C implementation):") |
268 | 228 | print(f" Nodes: {default_nodes}") |
269 | 229 | print(f" LP iterations: {default_lp_iterations}") |
270 | 230 | print(f" Objective: {default_obj}") |
271 | 231 |
|
272 | 232 | # Test with Python implementation |
273 | | - m_python = random_mip_1(node_lim=2000, small=True) |
| 233 | + m_python = Model() |
| 234 | + m_python.readProblem(instance_path) |
| 235 | + |
| 236 | + # Disable presolving, heuristics, and separation to focus on node selection |
| 237 | + m_python.setPresolve(SCIP_PARAMSETTING.OFF) |
| 238 | + m_python.setHeuristics(SCIP_PARAMSETTING.OFF) |
| 239 | + m_python.setSeparating(SCIP_PARAMSETTING.OFF) |
| 240 | + m_python.setParam("limits/nodes", 2000) |
274 | 241 |
|
275 | 242 | # Include our Python hybrid estimate node selector |
276 | 243 | hybridestim_nodesel = HybridEstim( |
|
0 commit comments