def test_no_whitespace_after_variable(self): write_lp_program(["max: x1 + x2;", "x1 = 30;", "x1|x2 <= 99.2;"]) try: ortoolslpparser.parse_lp_file(TEMP_FILE) self.assertTrue(False) except ValueError as e: self.assertEqual( e.args[0], "Unexpected next character \"|\" on line 3 " "(expected whitespace or combination sign character).")
def test_forgot_semicolon_constraint(self): write_lp_program([ "max: x1 + x2;", "x1 >= 0;", "x1 <= 30;", "x2 >= 24;", "x2 <= 50" ]) try: ortoolslpparser.parse_lp_file(TEMP_FILE) self.assertTrue(False) except ValueError as e: self.assertEqual(e.args[0], "Line 5 does not end with a semi-colon.")
def test_bad_right_hand_side_geq_geq(self): write_lp_program( ["max: x1 + x2;", "30 >= x1 >= 2.68.5;", "x2 >= 24;", "x2 <= 50;"]) try: ortoolslpparser.parse_lp_file(TEMP_FILE) self.assertTrue(False) except ValueError as e: self.assertEqual( e.args[0], "Right hand side (\" 2.68.5\") of inequality constraint on line 2 is not a " "float (e.g., variables are not allowed there!).")
def test_no_var_in_coefficients(self): write_lp_program([ "max: x1 + x2;", "x1 >= 0;", "30 <= 30;", "x2 >= 24;", "x2 <= 50;" ]) try: ortoolslpparser.parse_lp_file(TEMP_FILE) self.assertTrue(False) except ValueError as e: self.assertEqual( e.args[0], "Not a single variable present in the coefficients on line 3.")
def test_illegal_var(self): write_lp_program([ "max: x|1 + x2;", "x1 >= 0;", "x1 <= 30;", "x2 >= 24;", "x2 <= 50;" ]) try: ortoolslpparser.parse_lp_file(TEMP_FILE) self.assertTrue(False) except ValueError as e: self.assertEqual( e.args[0], "Unexpected next character \"|\" on line 1 " "(expected whitespace or combination sign character).")
def test_no_objective(self): write_lp_program( ["x1 + x2;", "x1 >= 0;", "x1 <= 30;", "x2 >= 24;", "x2 <= 50;"]) try: ortoolslpparser.parse_lp_file(TEMP_FILE) self.assertTrue(False) except ValueError as e: self.assertEqual( e.args[0], "Objective function on line 1 must start with \"max:\" or \"min:\"." )
def test_invalid_var_name_declarations(self): write_lp_program([ "max: x1 + x2;", "x1 >= 0;", "x1 <= 30;", "x2 >= 24;", "x2 <= 50;", "int x1, x3^;" ]) try: ortoolslpparser.parse_lp_file(TEMP_FILE) self.assertTrue(False) except ValueError as e: self.assertEqual( e.args[0], "Non-permitted variable name (\"x3^\") on line 6.")
def test_twice_declaration_same_line(self): write_lp_program([ "max: x1 + x2;", "x1 >= 0.0;", "x1 <= 30.9;", "24.4 >= x2 >= 29.8;", "int x2;", "int x1, x1;" ]) try: ortoolslpparser.parse_lp_file(TEMP_FILE) self.assertTrue(False) except ValueError as e: self.assertEqual(e.args[0], "Variable \"x1\" declared again on line 6.")
def test_semicolon_only(self): write_lp_program([ "max: x1 + x2;", "x1 >= 3;", "x1 <= 30.44;", "x2 >= 24;", "x2 <= 50;", ";" ]) try: ortoolslpparser.parse_lp_file(TEMP_FILE) self.assertTrue(False) except ValueError as e: self.assertEqual( e.args[0], "Line 6 ends with semi-colon but is empty otherwise.")
def test_invalid_var_name_start_underscore(self): write_lp_program([ "max: x1 + x2;", "x1 >= 0;", "x1 <= 30;", "x2 >= 24;", "x2 <= 50;", "_x3 <= 200;" ]) try: ortoolslpparser.parse_lp_file(TEMP_FILE) self.assertTrue(False) except ValueError as e: self.assertEqual( e.args[0], "Cannot process remainder coefficients of \"_x3\" on line 6.")
def test_invalid_var_name_constraint(self): write_lp_program([ "max: x1 + x2;", "x1 >= 0;", "x1 <= 30;", "x2 >= 24;", "x2 <= 50;", "x$3 <= 200;" ]) try: ortoolslpparser.parse_lp_file(TEMP_FILE) self.assertTrue(False) except ValueError as e: self.assertEqual( e.args[0], "Unexpected next character \"$\" on line 6 " "(expected whitespace or combination sign character).")
def test_invalid_var_name_objective_function(self): write_lp_program([ "max: x1^ + x2;", "x1^ >= 0;", "x1^ <= 30;", "x2 >= 24;", "x2 <= 50;" ]) try: ortoolslpparser.parse_lp_file(TEMP_FILE) self.assertTrue(False) except ValueError as e: self.assertEqual( e.args[0], "Unexpected next character \"^\" on line 1 " "(expected whitespace or combination sign character).")
def test_multi_equal(self): write_lp_program([ "max: x1 + x2;", "9 >= x1 >= 0 >= x2;", "x1 <= 30;", "x2 >= 24;", "x2 <= 50;" ]) try: ortoolslpparser.parse_lp_file(TEMP_FILE) self.assertTrue(False) except ValueError as e: self.assertEqual( e.args[0], "Too many (in)equality signs present for constraint on line 2." )
def test_twice_same_var_constraint(self): write_lp_program([ "max: x1 + x2;", "x1 + 2x1 >= 0.0;", "x1 <= 30.9;", "24.4 >= x2 >= 29.8;", ]) try: ortoolslpparser.parse_lp_file(TEMP_FILE) self.assertTrue(False) except ValueError as e: self.assertEqual( e.args[0], "Variable \"x1\" found more than once on line 2.")
def test_simple_integers_two_line(self): write_lp_program([ "max: x1 + x2 + x3;", "0 <= x1 <= 30.9;", "50.4 >= x2 >= 24.8;", "x3 <= 99.2;", "int x1, x2;", "int x3;", ]) parse_result = ortoolslpparser.parse_lp_file( TEMP_FILE, use_solver=pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING) solver = parse_result["solver"] status = solver.Solve() self.assertEqual(status, solver.OPTIMAL) self.assertEqual(solver.LookupVariable("x1").solution_value(), 30) self.assertEqual(solver.LookupVariable("x2").solution_value(), 50) self.assertEqual(solver.LookupVariable("x3").solution_value(), 99) self.assertAlmostEqual(solver.Objective().Value(), 179.0) self.assertEqual(len(parse_result["var_names"]), 3) self.assertTrue("x1" in parse_result["var_names"]) self.assertTrue("x2" in parse_result["var_names"]) self.assertTrue("x3" in parse_result["var_names"])
def test_no_variables(self): write_lp_program([ "max: x1 + x2;", "x1 >= 3;", " <= 30.44;", "x2 >= 24;", "x2 <= 50;", ]) try: ortoolslpparser.parse_lp_file(TEMP_FILE) self.assertTrue(False) except ValueError as e: self.assertEqual(e.args[0], "No variables present in equation on line 3.")
def test_infeasible(self): write_lp_program(["max: x1;", "x1 >= 10;", "x1 <= 5;"]) solver = ortoolslpparser.parse_lp_file(TEMP_FILE)["solver"] status = solver.Solve() self.assertNotEqual(status, solver.OPTIMAL)
def solve(filename): parse_result = ortoolslpparser.parse_lp_file(filename) solver = parse_result["solver"] result = solver.Solve() if result == solver.OPTIMAL: print("Value of objective function: %f" % solver.Objective().Value()) print("Actual values of the variables:") for var_name in parse_result["var_names"]: print("%s %.10f" % (var_name, solver.LookupVariable(var_name).solution_value())) else: print("Linear program was not solved.") error_msg = "UNKNOWN" if result == solver.OPTIMAL: error_msg = "OPTIMAL" elif result == solver.FEASIBLE: error_msg = "FEASIBLE" elif result == solver.INFEASIBLE: error_msg = "INFEASIBLE" elif result == solver.UNBOUNDED: error_msg = "UNBOUNDED" elif result == solver.ABNORMAL: error_msg = "ABNORMAL" elif result == solver.NOT_SOLVED: error_msg = "NOT SOLVED" print("Error result provided by OR-tools: %s (%d)" % (error_msg, result)) exit(1)
def test_triple_sign(self): write_lp_program([ "max: x1 +++x2;", "x1 >= 0.0;", "x1 <= 30.9;", "50.4 >= x2 >= 24.8;", ]) try: ortoolslpparser.parse_lp_file(TEMP_FILE) self.assertTrue(False) except ValueError as e: self.assertEqual( e.args[0], "Cannot process remainder coefficients of \"+x2\" on line 1.")
def test_no_inequality(self): write_lp_program([ "max: x1 + x2;", "x1 >= 3;", "x1 <= 30.44;", "x2 >= 24;", "x2;", ]) try: ortoolslpparser.parse_lp_file(TEMP_FILE) self.assertTrue(False) except ValueError as e: self.assertEqual( e.args[0], "No (in)equality sign present for constraint on line 5.")
def test_fail_multi_line_comment(self): write_lp_program([ "max: x1 + x2;", "/*x1 >= 0.0;*/;", "x1 <= 30.9;", "50.4 >= x2 >= 24.8;", ]) try: ortoolslpparser.parse_lp_file(TEMP_FILE) self.assertTrue(False) except ValueError as e: self.assertEqual( e.args[0], "Right hand side (\" 0.0;*/\") of inequality constraint on line 2 is not a " "float (e.g., variables are not allowed there!).")
def test_invalid_coefficient_char(self): write_lp_program([ "max: 33.33|x1 + x2;", "x1 >= 3;", "x1 <= 30.44;", "x2 >= 24;", "x2 <= 50;", ]) try: ortoolslpparser.parse_lp_file(TEMP_FILE) self.assertTrue(False) except ValueError as e: self.assertEqual( e.args[0], "Unexpected next character \"|\" on line 1 " "(expected whitespace or combination sign character).")
def test_int_none_only_comma(self): write_lp_program([ "max: x1 + x2;", "0 <= x1 <= 30.9;", "50.4 >= x2 >= 24.8;", "int , ;", ]) try: ortoolslpparser.parse_lp_file( TEMP_FILE, use_solver=pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING) self.assertTrue(False) except ValueError as e: self.assertEqual(e.args[0], "Non-permitted variable name (\"\") on line 4.")
def test_trailing_stuff(self): write_lp_program([ "max: 33.33x1 + x2 + ;", "x1 >= 3;", "x1 <= 30.44;", "x2 >= 24;", "x2 <= 50;", ]) try: ortoolslpparser.parse_lp_file(TEMP_FILE) self.assertTrue(False) except ValueError as e: self.assertEqual( e.args[0], "Cannot process remainder coefficients of \"\" on line 1.")
def test_empty_int_vars(self): write_lp_program([ "max: x1 + x2;", "0 <= x1 <= 30.9;", "50.4 >= x2 >= 24.8;", "int ;", ]) try: ortoolslpparser.parse_lp_file( TEMP_FILE, use_solver=pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING) self.assertTrue(False) except ValueError as e: self.assertEqual(e.args[0], "Declaration on line 4 has no variables.")
def test_double_semicolon(self): write_lp_program([ "max: x1 + x2;", "x1 >= 3;", "x1 <= 30.44;", "x2 >= 24;", "x2 <= 50;;", ]) try: ortoolslpparser.parse_lp_file(TEMP_FILE) self.assertTrue(False) except ValueError as e: self.assertEqual( e.args[0], "Right hand side (\" 50;\") of inequality constraint on line 5 is not a float " "(e.g., variables are not allowed there!).")
def test_unbound(self): write_lp_program([ "max: x1;", ]) solver = ortoolslpparser.parse_lp_file(TEMP_FILE)["solver"] status = solver.Solve() self.assertNotEqual(status, solver.OPTIMAL)
def test_multiple_eq(self): write_lp_program([ "max: 33.33x1 + x2;", "x1 >= 3;", "x1 <= 30.44;", "x1 = 29.3 = 29.3;", "x2 >= 24;", "x2 <= 50;", ]) try: ortoolslpparser.parse_lp_file(TEMP_FILE) self.assertTrue(False) except ValueError as e: self.assertEqual( e.args[0], "Equality constraint on line 4 has multiple equal signs.")
def test_declaration_of_sos_not_supported_second(self): write_lp_program([ "max: x1 + x2;", "0 <= x1 <= 30.9;", "50.4 >= x2 >= 24.8;", "int x1;", "sos x2;", ]) try: ortoolslpparser.parse_lp_file( TEMP_FILE, use_solver=pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING) self.assertTrue(False) except ValueError as e: self.assertEqual( e.args[0], "Declaration on line 5 should start with \"int \".")
def test_declaration_of_sos_not_supported_first(self): write_lp_program([ "max: x1 + x2;", "0 <= x1 <= 30.9;", "50.4 >= x2 >= 24.8;", "sos x1, x2;", ]) try: ortoolslpparser.parse_lp_file( TEMP_FILE, use_solver=pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING) self.assertTrue(False) except ValueError as e: self.assertEqual( e.args[0], "No (in)equality sign present for constraint on line 4.")