Reading MPS Files
- Dominant language
- Python
- Stars
- 2.5k
- Forks
- 432
- PR merge metrics
- No merged PRs in 30d
Description
Hi,
I am trying to read an MPS file as part of an optimisation competition (https://github.com/ds4dm/ml4co-competition). The dataset is located in instances.tar.gz (https://drive.google.com/file/d/1MytdY3IwX_aFRWdoc0mMfDN9Xg1EKUuq/view). This is quite a big data set, so here's a single 300kB .mps file from the data set which I am trying to read in as a pulp LpProblem: https://drive.google.com/file/d/1rpOx4GomiPzSry733hIXtCW1yccmG1iD/view?usp=sharing
Once downloaded, I am using the below to load the .mps instance:
```python
import pulp
path = '../milp/datasets/instances/1_item_placement/train/item_placement_1.mps'
variables, instance = pulp.LpProblem.fromMPS(path)
```
This appears to read the .mps file without crashing, however it seems to load the problem as a maximisation problem when I believe it is meant to be a minimisation problem. Furthermore, when I run:
```python
status = instance.solve()
```
I get the following error:
```
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
in
----> 1 status = instance.solve()
2 print(f'status: {status}')
3 print(f"objective: {instance.objective.value()}")
4 # for var in instance.variables():
5 # print(f"{var.name}: {var.value()}")
/scratch/zciccwf/py36/envs/rlgnn/lib/python3.7/site-packages/pulp/pulp.py in solve(self, solver, **kwargs)
1735 #time it
1736 self.solutionTime = -clock()
-> 1737 status = solver.actualSolve(self, **kwargs)
1738 self.solutionTime += clock()
1739 self.restoreObjective(wasNone, dummyVar)
/scratch/zciccwf/py36/envs/rlgnn/lib/python3.7/site-packages/pulp/apis/coin_api.py in actualSolve(self, lp, **kwargs)
99 def actualSolve(self, lp, **kwargs):
100 """Solve a well formulated lp problem"""
--> 101 return self.solve_CBC(lp, **kwargs)
102
103 def available(self):
/scratch/zciccwf/py36/envs/rlgnn/lib/python3.7/site-packages/pulp/apis/coin_api.py in solve_CBC(self, lp, use_mps)
112 tmpLp, tmpMps, tmpSol, tmpMst = self.create_tmp_files(lp.name, 'lp', 'mps', 'sol', 'mst')
113 if use_mps:
--> 114 vs, variablesNames, constraintsNames, objectiveName = lp.writeMPS(tmpMps, rename = 1)
115 cmds = ' '+tmpMps+" "
116 if lp.sense == constants.LpMaximize:
/scratch/zciccwf/py36/envs/rlgnn/lib/python3.7/site-packages/pulp/pulp.py in writeMPS(self, filename, mpsSense, rename, mip)
1609 - The file is created
1610 """
-> 1611 return mpslp.writeMPS(self, filename, mpsSense = mpsSense, rename = rename, mip = mip)
1612
1613
/scratch/zciccwf/py36/envs/rlgnn/lib/python3.7/site-packages/pulp/mps_lp.py in writeMPS(LpProblem, filename, mpsSense, rename, mip)
222
223 with open(filename, "w") as f:
--> 224 f.write("*SENSE:"+ const.LpSenses[mpsSense]+"\n")
225 f.write("NAME " + model_name + "\n")
226 f.write("ROWS\n")
KeyError: 0
```
Setting `sense=1` seems to prevent the above crash, however it results in `pulp` saying the problem is infeasible:
```python
variables, instance = pulp.LpProblem.fromMPS(path, sense=1)
status = instance.solve()
print(f'status: {status}')
print(f"objective: {instance.objective.value()}")
```
```
status: -1
objective: 13303590269.825811
```
I do not think the problem is with the .mps file, because the following code appears to work with the `mip` library:
```python
import mip
path = '../milp/datasets/instances/1_item_placement/train/item_placement_1.mps'
instance = mip.Model()
instance.read(path)
status = instance.optimize(max_seconds=300)
if status == mip.OptimizationStatus.OPTIMAL:
print('optimal solution cost {} found'.format(instance.objective_value))
elif status == mip.OptimizationStatus.FEASIBLE:
print('sol.cost {} found, best possible: {}'.format(instance.objective_value, instance.objective_bound))
elif status == mip.OptimizationStatus.NO_SOLUTION_FOUND:
print('no feasible solution found, lower bound is: {}'.format(instance.objective_bound))
```
```
sol.cost 60.796965159000024 found, best possible: 28.922094929823203
```
Do you know if there might be any bugs with `pulp.LpProblem.fromMPS()`?
Contributor guide
Research direction
Reproduce the failure with LpProblem.fromMPS(path) using the supplied MPS file, then inspect pulp/pulp.py, mps_lp.py, and the fromMPS/writeMPS path shown in the traceback. Compare the parsed objective sense and solver behavior with the mip result; done means valid minimization input no longer raises KeyError or reports the supplied feasible instance as infeasible, with regression coverage.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 42/100