Generate Logic-Based Discrete Benders Decomposition - #1
Conversation
| CONFIG, default_nlp_init_method=restore_vars_to_original_values | ||
| ) | ||
| _add_tolerance_configs(CONFIG) | ||
| _add_ldsda_configs(CONFIG) |
There was a problem hiding this comment.
You might also need to add configs for LDBD.
There was a problem hiding this comment.
like
_add_ldbd_configs(CONFIG)
?
| # iteration = 1 | ||
| # Main loop for generating Benders cuts and solving the master problem | ||
| if 'tolerance' not in config: | ||
| config.declare('tolerance', ConfigValue(default=1e-5, domain=float, description="Convergence tolerance")) |
| objective_value = value(self.master_problem.z) | ||
|
|
||
| # Optionally, print the values for debugging | ||
| print(f"Solved master problem. Objective value (z): {objective_value}") |
There was a problem hiding this comment.
Replace print with logging.
| Ensure that we use the correct solver, like Gurobi, for the master problem. | ||
| """ | ||
| # Ensure that we are using the correct solver for the master problem | ||
| milp_solver = config.mip_solver if config.mip_solver else "gurobi" |
There was a problem hiding this comment.
Since the default value of config.mip_solver is gurobi, we can remove the check here.
| # subproblem_model.pprint() # Display all model components before solving | ||
|
|
||
| # Step 5: Solve the subproblem using Gurobi | ||
| solver = SolverFactory('gurobi') |
There was a problem hiding this comment.
Use config.mip_solver.
There was a problem hiding this comment.
Or create a new config for this.
|
|
||
| # Step 6: Solve the subproblem for the newly generated external variable values | ||
| # Evaluate the subproblem objective value for the new external variable values from the master problem | ||
| primal_improved, new_sub_obj_value = self._solve_GDP_subproblem(external_var_values, 'Benders cut generation', config) |
There was a problem hiding this comment.
It might be better to set the search type to 'Benders iteration' or 'Benders subproblem', instead of 'Benders cut generation'.
| logger.info(f"z_value: {z_value}, subproblem objective: {new_sub_obj_value}, z_diff: {z_diff}") | ||
|
|
||
| # If the solution converged, stop the loop | ||
| if z_diff <= tolerance: |
There was a problem hiding this comment.
Use self.LB and self.UB and move the bound check in the self.any_termination_criterion_met method.
| TransformationFactory('contrib.detect_fixed_vars').apply_to(subproblem) | ||
| TransformationFactory('contrib.propagate_fixed_vars').apply_to(subproblem) | ||
| TransformationFactory('contrib.deactivate_trivial_constraints').apply_to(subproblem, tmp=False, ignore_infeasible=False) | ||
| TransformationFactory('gdp.bigm').apply_to(subproblem) |
There was a problem hiding this comment.
Move bigm reformulation before fbbt.
| self.explored_point_dict = {} | ||
|
|
||
| # Debugging: Print or log the initial current point, explored set, and explored dictionary | ||
| print(f"Initial current point: {self.current_point}") |
There was a problem hiding this comment.
You can use logger.debug for the debugging output.
| for i, external_var_info in enumerate(util_block.external_var_info_list): | ||
| var_name = f'external_var_{i}' | ||
| initial_value = self.current_point[i] # Set initial point value for first iteration | ||
| var = Var(within=NonNegativeIntegers, bounds=(external_var_info.LB, external_var_info.UB), initialize=initial_value) |
There was a problem hiding this comment.
I think this (including the following setattr) is too complicated. I personally don't care about the names of the variables here. Do you use the name external_var_{i} somewhere else in the code?
There was a problem hiding this comment.
You can define a list of variables like
subproblem_model.p = Var(range(num_disjunctions), within=Reals, initialize=0.0), since you already know the number of the variables.
Then set the initial value, LB and UB one by one.
AlbertLee125
left a comment
There was a problem hiding this comment.
m = build_model()
pyo.SolverFactory("gdpopt.ldbd").solve(
m,
minlp_solver="gams",
minlp_solver_args=dict(
solver="knitro",
add_options=["option optcr=0.001;"],
# tee=True,
keepfiles=True,
),
starting_point=[3, 3, 3],
logical_constraint_list=[
m.lim["mixer"].name,
m.lim["reactor"].name,
m.lim["centrifuge"].name,
],
direction_norm="Linf",
tee=True,
infinity_output=1e+8
)
This is the input how I ran the small batch. I think it is good to know. I just wrote it on the Pull Request. And the config infinity_output is the value that replaces infinity. The code is designed for the minimizatioin problem. I will make a option for the minimization problem.
Removed the tabulate dependency and replaced it with simple logger output. Fixed _solve_GDP_subproblem so primal_bound is None when the solver fails (not just on preprocessing infeasibility).
Address requested changes
* TXP-7757: removed most deprecation warnings up to current unpublished release * Fixed more warnings * Missing version agnostic functions * Fixed version specific LPStatus enums + renamed get-lb/ub methods * Suggested improvements
[Xpress] Remove deprecation warnings (#1)
Fix no results returned when no discrete variables are present in Min…
I have generated the ldbd.py based on Zedong's LD-SDA code. The codes have room to improve by setting the format and setting up some of the configuration for the application. I desparately need help from everyone.