def is_violation(model_data, config, solve_data): nom_value = model_data.master_nominal_scenario_value denom = float(max(1, abs(nom_value))) tol = config.robust_feasibility_tolerance active_objective = next( model_data.separation_model.component_data_objects(Objective, active=True)) if value(active_objective) / denom > tol: violating_param_realization = list(p.value for p in list( model_data.separation_model.util.uncertain_param_vars.values())) list_of_violations = get_all_sep_objective_values( model_data=model_data, config=config) solve_data.violating_param_realization = violating_param_realization solve_data.list_of_scaled_violations = [ l / denom for l in list_of_violations ] solve_data.found_violation = True return True else: violating_param_realization = list(p.value for p in list( model_data.separation_model.util.uncertain_param_vars.values())) list_of_violations = get_all_sep_objective_values( model_data=model_data, config=config) solve_data.violating_param_realization = violating_param_realization solve_data.list_of_scaled_violations = [ l / denom for l in list_of_violations ] solve_data.found_violation = False return False
def get_all_sep_objective_values(model_data, config): """ Returns all violations from separation """ list_of_violations_across_objectives = [] for o in model_data.separation_model.util.separation_objectives: try: list_of_violations_across_objectives.append(value(o.expr)) except: for v in model_data.separation_model.util.first_stage_variables: config.progress_logger.info(v.name + " " + str(v.value)) for v in model_data.separation_model.util.second_stage_variables: config.progress_logger.info(v.name + " " + str(v.value)) raise ArithmeticError( "Objective function " + str(o) + " led to a math domain error. " "Does this objective (meaning, its parent performance constraint) " "contain log(x) or 1/x functions or others with tricky domains?" ) return list_of_violations_across_objectives
def solve_separation_problem(model_data, config): # Timing variables global_solve_time = 0 local_solve_time = 0 # List of objective functions objectives_map = model_data.separation_model.util.map_obj_to_constr constraint_map_to_master = model_data.separation_model.util.map_new_constraint_list_to_original_con # Add additional or remaining separation objectives to the dict # (those either not assigned an explicit priority or those added by Pyros for ssv bounds) config_sep_priority_dict = config.separation_priority_order actual_sep_priority_dict = ComponentMap() for perf_con in model_data.separation_model.util.performance_constraints: actual_sep_priority_dict[perf_con] = config_sep_priority_dict.get( perf_con.name, 0) # "Bin" the objectives based on priorities sorted_unique_priorities = sorted(list( set(actual_sep_priority_dict.values())), reverse=True) set_of_deterministic_constraints = model_data.separation_model.util.deterministic_constraints if hasattr(model_data.separation_model, "epigraph_constr"): set_of_deterministic_constraints.add( model_data.separation_model.epigraph_constr) for is_global in (False, True): solver = config.global_solver if \ (is_global or config.bypass_local_separation) else config.local_solver solve_data_list = [] for val in sorted_unique_priorities: # Descending ordered by value # The list of performance constraints with this priority perf_constraints = [ constr_name for constr_name, priority in actual_sep_priority_dict.items() if priority == val ] for perf_con in perf_constraints: #config.progress_logger.info("Separating constraint " + str(perf_con)) try: separation_obj = objectives_map[perf_con] except: raise ValueError( "Error in mapping separation objective to its master constraint form." ) separation_obj.activate() if perf_con in set_of_deterministic_constraints: nom_constraint = perf_con else: nom_constraint = constraint_map_to_master[perf_con] try: model_data.master_nominal_scenario_value = value( model_data.master_nominal_scenario.find_component( nom_constraint)) except: raise ValueError( "Unable to access nominal scenario value for the constraint " + str(nom_constraint)) if config.uncertainty_set.geometry == Geometry.DISCRETE_SCENARIOS: solve_data_list.append( discrete_solve(model_data=model_data, config=config, solver=solver, is_global=is_global)) if all(s.termination_condition in globally_acceptable for sep_soln_list in solve_data_list for s in sep_soln_list) or \ (is_global == False and all(s.termination_condition in locally_acceptable for sep_soln_list in solve_data_list for s in sep_soln_list)): exit_separation_loop = False else: exit_separation_loop = True else: solve_data = SeparationResult() exit_separation_loop = solver_call_separation( model_data=model_data, config=config, solver=solver, solve_data=solve_data, is_global=is_global) solve_data_list.append([solve_data]) # === Keep track of total solve times if is_global or config.bypass_local_separation: if config.uncertainty_set.geometry == Geometry.DISCRETE_SCENARIOS: for sublist in solve_data_list: for s in sublist: global_solve_time += get_time_from_solver( s.results) else: global_solve_time += get_time_from_solver( solve_data.results) else: if config.uncertainty_set.geometry == Geometry.DISCRETE_SCENARIOS: for sublist in solve_data_list: for s in sublist: local_solve_time += get_time_from_solver( s.results) else: local_solve_time += get_time_from_solver( solve_data.results) # === Terminate for timing if exit_separation_loop: return solve_data_list, [], [], is_global, local_solve_time, global_solve_time separation_obj.deactivate() # Do we return? # If their are multiple violations in this bucket, pick the worst-case idx_i, idx_j = get_index_of_max_violation( model_data=model_data, config=config, solve_data_list=solve_data_list) violating_realizations = [ v for v in solve_data_list[idx_i][idx_j].violating_param_realization ] violations = solve_data_list[idx_i][idx_j].list_of_scaled_violations if any(s.found_violation for solve_list in solve_data_list for s in solve_list): #config.progress_logger.info( # "Violation found in constraint %s with realization %s" % ( # list(objectives_map.keys())[idx_i], violating_realizations)) return solve_data_list, violating_realizations, violations, is_global, local_solve_time, global_solve_time return solve_data_list, [], [], is_global, local_solve_time, global_solve_time