Skip to content

Commit

Permalink
Merge pull request #29 from AlbertLee125/dsda_changes
Browse files Browse the repository at this point in the history
Dsda_changes
  • Loading branch information
ZedongPeng authored Nov 19, 2024
2 parents 61e29e9 + 3c65598 commit 4bd41ef
Showing 1 changed file with 39 additions and 7 deletions.
46 changes: 39 additions & 7 deletions pyomo/contrib/gdpopt/ldsda.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from pyomo.contrib.gdpopt.nlp_initialization import restore_vars_to_original_values
from pyomo.contrib.gdpopt.util import SuppressInfeasibleWarning, get_main_elapsed_time
from pyomo.contrib.satsolver.satsolver import satisfiable
from pyomo.core import minimize, Suffix, TransformationFactory
from pyomo.core import minimize, Suffix, TransformationFactory, Objective, value
from pyomo.opt import SolverFactory
from pyomo.opt import TerminationCondition as tc
from pyomo.core.expr.logical_expr import ExactlyExpression
Expand Down Expand Up @@ -190,7 +190,7 @@ def _solve_GDP_subproblem(self, external_var_value, search_type, config):
'contrib.deactivate_trivial_constraints'
).apply_to(subproblem, tmp=False, ignore_infeasible=False)
except InfeasibleConstraintException:
return False
return False, None
minlp_args = dict(config.minlp_solver_args)
if config.time_limit is not None and config.minlp_solver == 'gams':
elapsed = get_main_elapsed_time(self.timing)
Expand All @@ -200,16 +200,19 @@ def _solve_GDP_subproblem(self, external_var_value, search_type, config):
result = SolverFactory(config.minlp_solver).solve(
subproblem, **minlp_args
)
# Retrieve the primal bound (objective value) from the subproblem
obj = next(subproblem.component_data_objects(Objective, active=True))
primal_bound = value(obj)
primal_improved = self._handle_subproblem_result(
result, subproblem, external_var_value, config, search_type
)
return primal_improved
return primal_improved, primal_bound
except RuntimeError as e:
config.logger.warning(
"Solver encountered RuntimeError. Treating as infeasible. "
"Msg: %s\n%s" % (str(e), traceback.format_exc())
)
return False
return False, None

def _get_external_information(self, util_block, config):
"""Function that obtains information from the model to perform the reformulation with external variables.
Expand Down Expand Up @@ -390,18 +393,47 @@ def neighbor_search(self, config):
locally_optimal = True
best_neighbor = None
self.best_direction = None # reset best direction
fmin = float('inf') # Initialize the best objective value
best_dist = 0 # Initialize the best distance
abs_tol = config.integer_tolerance # Use integer_tolerance for objective comparison

# Loop through all possible directions (neighbors)
for direction in self.directions:
# Generate a neighbor point by applying the direction to the current point
neighbor = tuple(map(sum, zip(self.current_point, direction)))

# Check if the neighbor is valid
if self._check_valid_neighbor(neighbor):
primal_improved = self._solve_GDP_subproblem(
# Solve the subproblem for this neighbor
primal_improved, primal_bound = self._solve_GDP_subproblem(
neighbor, 'Neighbor search', config
)

if primal_improved:
locally_optimal = False
best_neighbor = neighbor
self.best_direction = direction

# --- Tiebreaker Logic ---
if abs(fmin - primal_bound) < abs_tol:
# Calculate the Euclidean distance from the current point
dist = sum((x - y) ** 2 for x, y in zip(neighbor, self.current_point))

# Update the best neighbor if this one is farther away
if dist > best_dist:
best_neighbor = neighbor
self.best_direction = direction
best_dist = dist # Update the best distance
else:
# Standard improvement logic: update if the objective is better
fmin = primal_bound # Update the best objective value
best_neighbor = neighbor # Update the best neighbor
self.best_direction = direction # Update the best direction
best_dist = sum((x - y) ** 2 for x, y in zip(neighbor, self.current_point))
# --- End of Tiebreaker Logic ---

# Move to the best neighbor if an improvement was found
if not locally_optimal:
self.current_point = best_neighbor

return locally_optimal

def line_search(self, config):
Expand Down

0 comments on commit 4bd41ef

Please sign in to comment.