def test_ipopt_solver(model_name): current_dir = pathlib.Path(__file__).parent osil_file = current_dir / 'models' / (model_name + '.osil') pyomo_model = read_pyomo_model(osil_file) problem = problem_from_pyomo_model(pyomo_model) atol = rtol = 1e-4 galini = Galini() galini.update_configuration({ 'galini': { 'constraint_violation_tol': 1e-2, }, 'logging': { 'stdout': True, }, 'branch_and_cut': { 'tolerance': atol, 'relative_tolerance': rtol, 'root_node_feasible_solution_search_timelimit': 0, 'cuts': { 'maxiter': 100, } }, 'cuts_generator': { 'generators': ['outer_approximation'], }, 'ipopt': { 'ipopt': { 'acceptable_constr_viol_tol': 1e-3 }, }, }) set_timelimit(30) start_timelimit() solver = BranchAndBoundSolver(galini) solver.before_solve(pyomo_model, problem) solution = solver.solve(problem) assert solution.status.is_success() sol_file = current_dir / 'solutions' / (model_name + '.sol') expected_solution = read_solution(sol_file) expected_objective = expected_solution['objective'] assert solution.objective is not None assert is_close(expected_objective, solution.objective.value, atol=atol, rtol=rtol) expected_variables = expected_solution['variables'] for var_sol in solution.variables: assert is_close( expected_variables[var_sol.name], var_sol.value, atol=atol, rtol=rtol, )
def test_at_root_node(galini, problem): solver_ipopt = galini.instantiate_solver('ipopt') solver_mip = galini.instantiate_solver("mip") run_id = 'test_run' # Test at root node start_timelimit() algo = BranchAndCutAlgorithm(galini, FakeSolver(), telemetry=None) algo._cuts_generators_manager.before_start_at_root(run_id, problem, None) relaxation = _linear_relaxation(problem) relaxed_problem = relaxation.relax(problem) nbs_cuts = [] mip_sols = [] for iteration in range(5): mip_solution = solver_mip.solve(relaxed_problem, logger=None) assert mip_solution.status.is_success() mip_sols.append(mip_solution.objective.value) # Generate new cuts new_cuts = algo._cuts_generators_manager.generate( run_id, problem, None, relaxed_problem, mip_solution, None, None) # Add cuts as constraints nbs_cuts.append(len(list(new_cuts))) for cut in new_cuts: new_cons = Constraint(cut.name, cut.expr, cut.lower_bound, cut.upper_bound) relaxation._relax_constraint(problem, relaxed_problem, new_cons) assert (np.allclose(mip_sols, [-200.0, -196.85714285714283, -196.5, -196.0, -196.0])) assert (nbs_cuts == [2, 2, 2, 0, 0]) # Test when branched on x0 in [0.5, 1] x0 = problem.variable_view(problem.variables[0]) x0.set_lower_bound(0.5) relaxed_problem = relaxation.relax(problem) algo._cuts_generators_manager.before_start_at_node(run_id, problem, None) mip_sols = [] mip_solution = None for iteration in range(5): mip_solution = solver_mip.solve(relaxed_problem, logger=None) assert mip_solution.status.is_success() mip_sols.append(mip_solution.objective.value) # Generate new cuts new_cuts = algo._cuts_generators_manager.generate( run_id, problem, None, relaxed_problem, mip_solution, None, None) # Add cuts as constraints for cut in new_cuts: new_cons = Constraint(cut.name, cut.expr, cut.lower_bound, cut.upper_bound) relaxation._relax_constraint(problem, relaxed_problem, new_cons) assert (np.allclose(mip_sols, [ -193.88095238095238, -187.96808510638297, -187.42857142857147, -187.10869565217394, -187.10869565217394 ]))
def test_adjacency_matrix(galini, problem): solver_ipopt = galini.instantiate_solver('ipopt') solver_mip = galini.instantiate_solver("mip") run_id = 'test_run' # Test adjacency matrix start_timelimit() triangle_cuts_gen = TriangleCutsGenerator( galini, galini._config.cuts_generator.triangle) triangle_cuts_gen.before_start_at_root(run_id, problem, None) assert (np.allclose(triangle_cuts_gen._get_adjacency_matrix(problem), [[1, 1, 1, 0, 0, 1, 0, 1], [1, 0, 1, 1, 1, 0, 1, 1], [1, 1, 1, 1, 0, 1, 1, 1], [0, 1, 1, 1, 1, 1, 1, 1], [0, 1, 0, 1, 0, 1, 1, 1], [1, 0, 1, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1, 0, 0], [1, 1, 1, 1, 1, 1, 0, 1]]))
def test_triange_cut_violations(galini, problem): run_id = 'test_run' start_timelimit() triangle_cuts_gen = TriangleCutsGenerator( galini, galini._config.cuts_generator.triangle) triangle_cuts_gen.before_start_at_root(run_id, problem, None) # Test triangle cut violations relaxation = _linear_relaxation(problem) relaxed_problem = relaxation.relax(problem) known_solution = { 'x[0]': 0.5, 'x[1]': 0.5, 'x[2]': 0.5, 'x[3]': 0.5, 'x[4]': 0.5, 'x[5]': 1.0, 'x[6]': 0.5, 'x[7]': 0.5, '_objvar': -2.00, '_aux_bilinear_x[4]_x[7]': 0.5, '_aux_bilinear_x[5]_x[6]': 0.5, '_aux_bilinear_x[3]_x[7]': 0.0, '_aux_bilinear_x[5]_x[7]': 0.5, '_aux_bilinear_x[3]_x[6]': 0.5, '_aux_bilinear_x[0]_x[7]': 0.5, '_aux_bilinear_x[1]_x[3]': 0.0, '_aux_bilinear_x[3]_x[4]': 0.5, '_aux_bilinear_x[1]_x[2]': 0.0, '_aux_bilinear_x[0]_x[5]': 0.5, '_aux_bilinear_x[0]_x[0]': 0.5, '_aux_bilinear_x[0]_x[1]': 0.5, '_aux_bilinear_x[1]_x[4]': 0.5, '_aux_bilinear_x[3]_x[3]': 0.0, '_aux_bilinear_x[7]_x[7]': 0.0, '_aux_bilinear_x[3]_x[5]': 0.5, '_aux_bilinear_x[1]_x[6]': 0.5, '_aux_bilinear_x[5]_x[5]': 1.0, '_aux_bilinear_x[1]_x[7]': 0.0, '_aux_bilinear_x[2]_x[2]': 0.5, '_aux_bilinear_x[2]_x[3]': 0.5, '_aux_bilinear_x[4]_x[6]': 0.0, '_aux_bilinear_x[2]_x[5]': 0.5, '_aux_bilinear_x[4]_x[5]': 0.5, '_aux_bilinear_x[2]_x[6]': 0.0, '_aux_bilinear_x[2]_x[7]': 0.5, '_aux_bilinear_x[0]_x[2]': 0.5, } mip_solution = Solution(status=FakeStatus(), optimal_obj=OptimalObjective('f', -200.0), optimal_vars=[ OptimalVariable(v.name, known_solution[v.name]) for v in relaxed_problem.variables ]) triangle_viol = triangle_cuts_gen._get_triangle_violations( relaxed_problem, mip_solution) expected_triangle_viol = [[0, 0, 0.5], [0, 1, -0.5], [0, 2, -0.5], [0, 3, -0.5], [1, 0, 0.5], [1, 1, -0.5], [1, 2, -0.5], [1, 3, -0.5], [2, 0, 0.0], [2, 1, 0.0], [2, 2, -0.5], [2, 3, -0.5], [3, 0, 0.0], [3, 1, 0.0], [3, 2, 0.0], [3, 3, -1.0], [4, 0, 0.0], [4, 1, -0.5], [4, 2, 0.0], [4, 3, -0.5], [5, 0, -1.0], [5, 1, 0.0], [5, 2, 0.0], [5, 3, 0.0], [6, 0, 0.0], [6, 1, -1.0], [6, 2, 0.0], [6, 3, 0.0], [7, 0, -1.0], [7, 1, 0.0], [7, 2, 0.0], [7, 3, 0.0], [8, 0, -0.5], [8, 1, -0.5], [8, 2, 0.5], [8, 3, -0.5], [9, 0, -0.5], [9, 1, -0.5], [9, 2, 0.5], [9, 3, -0.5], [10, 0, -0.5], [10, 1, -0.5], [10, 2, -0.5], [10, 3, 0.5], [11, 0, 0.5], [11, 1, -0.5], [11, 2, -0.5], [11, 3, -0.5], [12, 0, -0.5], [12, 1, 0.5], [12, 2, -0.5], [12, 3, -0.5], [13, 0, 0.0], [13, 1, 0.0], [13, 2, -0.5], [13, 3, -0.5], [14, 0, -0.5], [14, 1, 0.5], [14, 2, -0.5], [14, 3, -0.5], [15, 0, 0.5], [15, 1, -0.5], [15, 2, -0.5], [15, 3, -0.5], [16, 0, -0.5], [16, 1, 0.0], [16, 2, -0.5], [16, 3, 0.0], [17, 0, 0.0], [17, 1, -0.5], [17, 2, 0.0], [17, 3, -0.5], [18, 0, 0.0], [18, 1, 0.0], [18, 2, -0.5], [18, 3, -0.5], [19, 0, 0.5], [19, 1, -0.5], [19, 2, -0.5], [19, 3, -0.5], [20, 0, -0.5], [20, 1, 0.5], [20, 2, -0.5], [20, 3, -0.5], [21, 0, 0.0], [21, 1, -0.5], [21, 2, 0.0], [21, 3, -0.5], [22, 0, -0.5], [22, 1, 0.0], [22, 2, -0.5], [22, 3, 0.0], [23, 0, -0.5], [23, 1, 0.0], [23, 2, -0.5], [23, 3, 0.0], [24, 0, 0.0], [24, 1, -0.5], [24, 2, 0.0], [24, 3, -0.5]] assert len(triangle_viol) == len(expected_triangle_viol) for actual, expected in zip(triangle_viol, expected_triangle_viol): assert np.allclose(actual, expected)
def execute_with_problem(self, model, problem, args): galini = Galini() if args.config: galini.update_configuration(args.config) solver_cls = galini.get_solver(args.solver.lower()) if solver_cls is None: available = ', '.join(solvers_reg.keys()) print('Solver {} not available. Available solvers: {}'.format( args.solver, available)) sys.exit(1) apply_logging_config(galini.get_configuration_group('logging')) solver = solver_cls(galini) galini_group = galini.get_configuration_group('galini') timelimit = galini_group.get('timelimit') elapsed_counter = galini.telemetry.create_gauge('elapsed_time', 0.0) set_timelimit(timelimit) start_timelimit() start_time = current_time() solver.before_solve(model, problem) solution = solver.solve( problem, known_optimal_objective=args.known_optimal_objective) elapsed_counter.set_value(seconds_elapsed_since(start_time)) if solution is None: raise RuntimeError('Solver did not return a solution') obj_table = OutputTable('Objectives', [ { 'id': 'name', 'name': 'Objective', 'type': 't' }, { 'id': 'value', 'name': 'Value', 'type': 'f' }, ]) value = solution.objective.value if not problem.objective.original_sense.is_minimization(): if value is not None: value = -value obj_table.add_row({ 'name': solution.objective.name, 'value': value, }) var_table = OutputTable('Variables', [ { 'id': 'name', 'name': 'Variable', 'type': 't' }, { 'id': 'value', 'name': 'Value', 'type': 'f' }, ]) for var in solution.variables: var_table.add_row({ 'name': var.name, 'value': var.value, }) counter_table = OutputTable('Counters', [ { 'id': 'name', 'name': 'Name', 'type': 't' }, { 'id': 'value', 'name': 'Value', 'type': 'f' }, ]) for counter in galini.telemetry.counters_values(): counter_table.add_row(counter) print_output_table([obj_table, var_table, counter_table], args)