예제 #1
0
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,
        )
예제 #2
0
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)

    galini = Galini()
    galini.update_configuration({
        'galini': {
            'constraint_violation_tol': 1e-2,
        },
        'ipopt': {
            'ipopt': {
                'acceptable_constr_viol_tol': 1e-3
            },
        },
    })
    solver = IpoptNLPSolver(galini)
    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 np.isclose(expected_objective, solution.objective.value)

    if False:
        expected_variables = expected_solution['variables']
        assert len(expected_variables) == len(solution.variables)
        for variable, expected in zip(solution.variables, expected_variables):
            assert np.isclose(expected, variable.value)
예제 #3
0
def test_outer_approximation_cuts(problem):
    galini = Galini()
    galini.update_configuration(
        {'logging': {
            'level': 'DEBUG',
            'stdout': False,
        }})
    config = galini.get_configuration_group(
        'cuts_generator.outer_approximation')
    generator = OuterApproximationCutsGenerator(galini, config)

    bounds, mono, cvx = propagate_special_structure(problem)

    cvx_relaxation = ConvexRelaxation(problem, bounds, mono, cvx)
    relaxed_problem = RelaxedProblem(cvx_relaxation, problem).relaxed

    linear_relaxation = LinearRelaxation(relaxed_problem, bounds, mono, cvx)
    linear_problem = RelaxedProblem(linear_relaxation, relaxed_problem).relaxed

    solution = Solution(FakeStatus(FakeStatusEnum.Success),
                        [OptimalObjective('_objvar', 8.00)], [
                            OptimalVariable('x[0]', 4.0),
                            OptimalVariable('x[1]', 2.0),
                            OptimalVariable('_aux_0', 12.0),
                            OptimalVariable('_aux_1', 0.0),
                            OptimalVariable('_objvar', 8.0),
                            OptimalVariable('_aux_bilinear_x[0]_x[0]', 12.0),
                            OptimalVariable('_aux_bilinear_x[1]_x[1]', 0.0),
                        ])

    cuts = generator.generate(
        run_id=0,
        problem=problem,
        relaxed_problem=relaxed_problem,
        linear_problem=linear_problem,
        mip_solution=solution,
        tree=None,
        node=None,
    )
    assert len(cuts) == 2

    objective_cuts = [c for c in cuts if c.is_objective]
    constraint_cuts = [c for c in cuts if not c.is_objective]

    assert len(objective_cuts) == 0

    assert len(constraint_cuts) == 2
    _cut_map = [
        _check_g0,
        _check_g1,
    ]
    for i, cut in enumerate(constraint_cuts):
        _cut_map[i](cut)
예제 #4
0
def test_cut_selection_strategy(problem, cut_selection_strategy,
                                expected_solution):
    galini = Galini()
    relaxation = _linear_relaxation(problem)
    run_id = 'test_run_sdp'

    galini.update_configuration({
        'branch_and_cut': {
            'cuts': {
                'use_lp_cut_phase': True,
                'use_milp_cut_phase': True,
            },
        },
        'cuts_generator': {
            'generators': ['sdp'],
            'sdp': {
                'domain_eps': 1e-3,
                'thres_sdp_viol': -1e-15,
                'min_sdp_cuts_per_round': 0,
                'max_sdp_cuts_per_round': 5e3,
                'dim': 3,
                'big_m': 10e3,
                'thres_min_opt_sel': 0,
                'selection_size': 4,
                'cut_sel_strategy': cut_selection_strategy,
            },
        }
    })
    config = galini._config
    sdp_cuts_gen = SdpCutsGenerator(galini, config.cuts_generator.sdp)
    algo = BranchAndCutAlgorithm(galini, FakeSolver(), telemetry=None)
    relaxed_problem = relaxation.relax(problem)
    algo._cuts_generators_manager.before_start_at_root(run_id, problem, None)
    nbs_cuts = []
    mip_sols = []
    if cut_selection_strategy == "RANDOM":
        np.random.seed(0)
    for iteration in range(5):
        set_timelimit(60)
        mip_solution = algo._mip_solver.solve(relaxed_problem)
        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, expected_solution)
예제 #5
0
def galini():
    galini_ = Galini()
    galini_.update_configuration({
        'cuts_generator': {
            'generators': ['triangle'],
            'triangle': {
                'domain_eps': 1e-3,
                'thres_triangle_viol': 1e-7,
                'max_tri_cuts_per_round': 10e3,
                'selection_size': 2,
                'min_tri_cuts_per_round': 0,
            },
        }
    })
    return galini_
예제 #6
0
def derivative_check(model_name, model, order):
    galini = Galini()
    galini.update_configuration({
        'galini': {
            'constraint_violation_tol': 1e-2,
        },
        'ipopt': {
            'ipopt': {
                'acceptable_constr_viol_tol': 1e-3,
                'derivative_test': order,
                'max_iter': 1,
            },
            'logging': {
                'level': 'J_ITERSUMMARY',
            }
        },
        'logging': {
            'stdout': True,
            'level': 'DEBUG',
        }
    })
    solver = IpoptNLPSolver(galini)
    solver = IpoptNLPSolver(galini)
    # setup Ipopt journalist
    output_str = io.StringIO()
    app = IpoptApplication()
    journalist = app.journalist()
    journalist.delete_all_journals()
    journalist.add_journal(
        PythonJournal('Default', EJournalLevel.J_ITERSUMMARY, output_str))

    solver.solve(model, ipopt_application=app)
    output = output_str.getvalue()
    output_str.close()

    check_ok = 'No errors detected by derivative checker.' in output
    if not check_ok:
        print(output)
        assert check_ok
예제 #7
0
    def execute_with_model(self, model, args):
        galini = Galini()

        if args.config:
            galini.update_configuration(args.config)

        solution = galini.solve(
            model,
            args.algorithm,
            known_optimal_objective=args.known_optimal_objective)

        status_table = OutputTable('Solution', [{
            'id': 'status',
            'name': 'Status',
            'type': 't'
        }])

        if solution is None:
            status_table.add_row({'status': 'unboundedOrInfeasible'})
            print_output_table([status_table], args)
            return

        status_table.add_row({'status': solution.status.description()})

        obj_table = OutputTable('Objectives', [
            {
                'id': 'name',
                'name': 'Objective',
                'type': 't'
            },
            {
                'id': 'value',
                'name': 'Value',
                'type': 'f'
            },
        ])

        obj_table.add_row({
            'name': 'objective',
            'value': solution.objective,
        })

        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([status_table, obj_table, var_table, counter_table],
                           args)
예제 #8
0
def test_cut_selection_strategy(problem, cut_selection_strategy,
                                expected_solution):
    galini = Galini()
    relaxed_problem, relax_data = _linear_relaxation(problem)

    galini.update_configuration({
        'cuts_generator': {
            'generators': ['sdp'],
            'sdp': {
                'domain_eps': 1e-3,
                'thres_sdp_viol': -1e-15,
                'min_sdp_cuts_per_round': 0,
                'max_sdp_cuts_per_round': 5e3,
                'dim': 3,
                'big_m': 10e3,
                'thres_min_opt_sel': 0,
                'selection_size': 4,
                'cut_sel_strategy': cut_selection_strategy,
            },
        }
    })

    storage = FakeStorage(relaxation_data=relax_data)
    node = FakeNode(storage)

    galini.timelimit.start_now()

    config = galini._config
    sdp_cuts_gen = SdpCutsGenerator(galini, config.cuts_generator.sdp)
    sdp_cuts_gen.before_start_at_root(problem, relaxed_problem)

    nbs_cuts = []
    mip_sols = []

    if cut_selection_strategy == "RANDOM":
        np.random.seed(0)

    mip_solver = _instantiate_mip_solver()
    _update_solver_options(mip_solver)

    relaxed_problem._cuts = pe.ConstraintList()

    for iteration in range(5):
        mip_res = mip_solver.solve(relaxed_problem)
        mip_solution = load_solution_from_model(mip_res, relaxed_problem)
        assert mip_solution.status.is_success()
        mip_sols.append(mip_solution.objective)
        # Generate new cuts
        new_cuts = sdp_cuts_gen.generate(problem, relaxed_problem,
                                         mip_solution, None, node)

        # Add cuts as constraints
        nbs_cuts.append(len(list(new_cuts)))

        for cut in new_cuts:
            relaxed_cut = relax_inequality(relaxed_problem, cut,
                                           RelaxationSide.BOTH,
                                           storage.relaxation_data)
            relaxed_problem._cuts.add(relaxed_cut)

        update_relaxation_data(relaxed_problem, storage.relaxation_data)
        rebuild_relaxations(relaxed_problem,
                            storage.relaxation_data,
                            use_linear_relaxation=True)

    assert np.allclose(mip_sols, expected_solution)
예제 #9
0
def test_sdp_cuts_after_branching(problem):
    galini = Galini()

    # Test when branched on x0 in [0.5, 1]
    x0 = problem.x[0]
    x0.setlb(0.5)
    relaxed_problem, relax_data = _linear_relaxation(problem)

    storage = FakeStorage(relaxation_data=relax_data)
    node = FakeNode(storage)

    galini.update_configuration({
        'cuts_generator': {
            'sdp': {
                'domain_eps': 1e-3,
                'thres_sdp_viol': -1e-15,
                'min_sdp_cuts_per_round': 0,
                'max_sdp_cuts_per_round': 5e3,
                'dim': 3,
                'big_m': 10e3,
                'thres_min_opt_sel': 0,
                'selection_size': 4,
                'cut_sel_strategy': "COMB_ONE_CON"
            },
        }
    })

    galini.timelimit.start_now()

    config = galini._config
    sdp_cuts_gen = SdpCutsGenerator(galini, config.cuts_generator.sdp)
    sdp_cuts_gen.before_start_at_root(problem, relaxed_problem)

    mip_sols = []

    relaxed_problem._cuts = pe.ConstraintList()

    mip_solver = _instantiate_mip_solver()
    _update_solver_options(mip_solver)

    for iteration in range(5):
        mip_res = mip_solver.solve(relaxed_problem)
        mip_solution = load_solution_from_model(mip_res, relaxed_problem)
        assert mip_solution.status.is_success()
        mip_sols.append(mip_solution.objective)
        # Generate new cuts
        new_cuts = sdp_cuts_gen.generate(problem, relaxed_problem,
                                         mip_solution, None, node)

        # Add cuts as constraints
        for cut in new_cuts:
            relaxed_cut = relax_inequality(relaxed_problem, cut,
                                           RelaxationSide.BOTH,
                                           storage.relaxation_data)
            relaxed_problem._cuts.add(relaxed_cut)

        update_relaxation_data(relaxed_problem, storage.relaxation_data)
        rebuild_relaxations(relaxed_problem,
                            storage.relaxation_data,
                            use_linear_relaxation=True)

    assert np.allclose(mip_sols, [
        -187.53571428571428, -178.17645682147835, -175.10310263115286,
        -175.0895610878696, -175.03389759123812
    ])
예제 #10
0
def test_sdp_cuts_after_branching(problem):
    galini = Galini()
    galini.update_configuration({
        'cuts_generator': {
            'generators': ['sdp'],
            'sdp': {
                'selection_size': 2,
            },
        }
    })
    run_id = 'test_run_sdp'

    relaxation = _linear_relaxation(problem)

    # Test when branched on x0 in [0.5, 1]
    x0 = problem.variable_view(problem.variables[0])
    x0.set_lower_bound(0.5)
    galini.update_configuration({
        'branch_and_cut': {
            'cuts': {
                'use_lp_cut_phase': True,
                'use_milp_cut_phase': True,
            },
        },
        'cuts_generator': {
            'sdp': {
                'domain_eps': 1e-3,
                'thres_sdp_viol': -1e-15,
                'min_sdp_cuts_per_round': 0,
                'max_sdp_cuts_per_round': 5e3,
                'dim': 3,
                'big_m': 10e3,
                'thres_min_opt_sel': 0,
                'selection_size': 4,
                'cut_sel_strategy': "COMB_ONE_CON"
            },
        }
    })
    config = galini._config
    sdp_cuts_gen = SdpCutsGenerator(galini, config.cuts_generator.sdp)
    algo = BranchAndCutAlgorithm(galini, FakeSolver(), telemetry=None)
    relaxed_problem = relaxation.relax(problem)
    algo._cuts_generators_manager.before_start_at_root(run_id, problem, None)
    mip_sols = []
    mip_solution = None
    for iteration in range(5):
        set_timelimit(60)
        mip_solution = algo._mip_solver.solve(relaxed_problem)
        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, [
        -187.53571428571428, -178.17645682147835, -175.10310263115286,
        -175.0895610878696, -175.03389759123812
    ])
    feas_solution = algo._nlp_solver.solve(relaxed_problem)
    assert (feas_solution.objective.value >= mip_sols[-1])
    sdp_cuts_gen.after_end_at_node(run_id, problem, None, mip_solution)
    sdp_cuts_gen.after_end_at_root(run_id, problem, None, mip_solution)
예제 #11
0
    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)
예제 #12
0
def user_config():
    user_config_path = Path(__file__).parent / 'user_config.toml'
    galini = Galini()
    galini.update_configuration(str(user_config_path))
    return galini._config
예제 #13
0
    m.x = pe.Var(bounds=(0, None))
    m.y = pe.Var(bounds=(0, None))
    m.z = pe.Var(bounds=(0, None))

    m.obj = pe.Objective(expr=m.x, sense=pe.maximize)

    m.lin = pe.Constraint(expr=m.x + m.y + m.z == 1)
    m.soc = pe.Constraint(expr=m.x**2 + m.y**2 <= m.z**2)
    m.rot = pe.Constraint(expr=m.x**2 <= m.y * m.z)

    return m


if __name__ == '__main__':
    from galini.galini import Galini

    galini = Galini()
    galini.update_configuration({
        'galini': {
            'timelimit': 100,
        },
        'logging': {
            'stdout': True,
        },
    })

    model = get_pyomo_model()
    solution = galini.solve(model)
    print(solution)