Skip to content

Commit

Permalink
Merge pull request #7 from Gurobi/tests-solcheck-cli
Browse files Browse the repository at this point in the history
Add tests for solcheck CLI
  • Loading branch information
mattmilten authored Sep 18, 2024
2 parents d6b8ebd + ac8091a commit f249aa8
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/gurobi_modelanalyzer/solcheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,6 @@ def optimize(self):
def main_cli():
import argparse
import gurobipy as gp
import questionary as qy

parser = argparse.ArgumentParser(
prog="gurobi_solcheck", description="Check if a solution is feasible"
Expand Down Expand Up @@ -266,6 +265,8 @@ def main_cli():
if args.model:
mfn = args.model
else:
import questionary as qy

print("Entering interactive mode")
mfn = qy.path(
"Select a model file",
Expand Down
129 changes: 129 additions & 0 deletions tests/test_solcheck.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import io
import os
import pathlib
import hashlib
import subprocess
import contextlib
from unittest import TestCase

import gurobipy as gp
from gurobi_modelanalyzer import SolCheck

here = pathlib.Path(__file__).parent
cwd = pathlib.Path(os.getcwd())


class TestSolCheck(TestCase):
Expand Down Expand Up @@ -77,3 +81,128 @@ def test_infeasible_solution(self):
abs_sum_violations += abs(c._Violation)

self.assertEqual(abs_sum_violations, 1.5)


class TestSolCheckCLI(TestCase):
def setUp(self):
self.afirofix_md5 = "f265f0c9554f2b480092757a83e47207"

def tearDown(self):
output_files = [
cwd.joinpath("afirofix.sol"),
cwd.joinpath("misc07fix.vio"),
cwd.joinpath("misc07fix.sol"),
cwd.joinpath("misc07fix.ilp"),
]
for file in output_files:
if file.exists():
os.remove(file)

def test_suboptimal_solution(self):
afirofix_file = cwd.joinpath("afirofix.sol")
self.assertFalse(afirofix_file.exists())
cmd = (
f"gurobi_solcheck --model {str(here / 'dataset' / 'afiro.mps')} "
+ f"--sol {str(here / 'dataset' / 'afiro.sol')} --result afirofix"
)
result = subprocess.getoutput(cmd)
self.assertIn(
"Solution is feasible for feasibility tolerance of 1e-06",
result,
)
self.assertIn("Difference: -5.0613", result)
self.assertTrue(afirofix_file.exists())

md5_ret = None
with open(afirofix_file, "rb") as f:
d = f.read()
md5_ret = hashlib.md5(d).hexdigest()

self.assertEqual(self.afirofix_md5, md5_ret)

def test_suboptimal_json_solution(self):
afirofix_file = cwd.joinpath("afirofix.sol")
self.assertFalse(afirofix_file.exists())
cmd = (
f"gurobi_solcheck --model {str(here / 'dataset' / 'afiro.mps')} "
+ f"--sol {str(here / 'dataset' / 'afiro.json')} --result afirofix"
)
result = subprocess.getoutput(cmd)
self.assertIn(
"Solution is feasible for feasibility tolerance of 1e-06",
result,
)
self.assertIn("Difference: -5.0613", result)
self.assertTrue(afirofix_file.exists())

md5_ret = None
with open(afirofix_file, "rb") as f:
d = f.read()
md5_ret = hashlib.md5(d).hexdigest()

self.assertEqual(self.afirofix_md5, md5_ret)

def test_infeasible_solution(self):
misc07fix_vio_file = cwd.joinpath("misc07fix.vio")
self.assertFalse(misc07fix_vio_file.exists())
cmd = (
f"gurobi_solcheck --model {str(here / 'dataset' / 'misc07.mps')} "
+ f"--sol {str(here / 'dataset' / 'misc07.sol')} --result misc07fix"
)
result = subprocess.getoutput(cmd)
self.assertTrue(misc07fix_vio_file.exists())

# Check log for expected output
self.assertIn(
"Model is infeasible",
result,
)
self.assertIn(
"Solution is infeasible for feasibility tolerance of 1e-06", result
)
self.assertIn(
"Relaxing to find smallest violation from fixed solution",
result,
)
self.assertIn("Fixed values are 1.5 from a feasible solution", result)

def test_infeasible_solution_infmethodV(self):
misc07fix_sol_file = cwd.joinpath("misc07fix.sol")
self.assertFalse(misc07fix_sol_file.exists())
cmd = (
f"gurobi_solcheck --model {str(here / 'dataset' / 'misc07.mps')} "
+ f"--sol {str(here / 'dataset' / 'misc07.sol')} --result misc07fix "
+ "--infmethod V "
)
result = subprocess.getoutput(cmd)
self.assertTrue(misc07fix_sol_file.exists())

# Check log for expected output
self.assertIn("Model is infeasible", result)
self.assertIn(
"Relaxing to find smallest violation from fixed solution",
result,
)
self.assertIn("Fixed values are 409.5 from a feasible solution", result)

def test_infeasible_solution_infmethodI(self):
misc07fix_ilp_file = cwd.joinpath("misc07fix.ilp")
self.assertFalse(misc07fix_ilp_file.exists())
cmd = (
f"gurobi_solcheck --model {str(here / 'dataset' / 'misc07.mps')} "
+ f"--sol {str(here / 'dataset' / 'misc07.sol')} --result misc07fix "
+ "--infmethod I "
)
result = subprocess.getoutput(cmd)
self.assertTrue(misc07fix_ilp_file.exists())

# Check log for expected output
self.assertIn("Model is infeasible", result)
self.assertIn(
"Solution is infeasible for feasibility tolerance of 1e-06", result
)
self.assertIn(
"Computing Irreducible Inconsistent Subsystem (IIS)",
result,
)
self.assertIn("IIS computed: 1 constraints, 2 bounds", result)

0 comments on commit f249aa8

Please sign in to comment.