Exemplo n.º 1
0
def main():
    m = build_column(min_trays=8, max_trays=17, xD=0.95, xB=0.95)
    # Fix feed conditions
    m.feed['benzene'].fix(50)
    m.feed['toluene'].fix(50)
    m.T_feed.fix(368)
    m.feed_vap_frac.fix(0.40395)
    # Initial values of reflux and reboil ratios
    m.reflux_ratio.set_value(1.4)
    m.reboil_ratio.set_value(1.3)
    # Fix to be total condenser
    m.partial_cond.deactivate()
    m.total_cond.indicator_var.fix(1)
    # Give initial values of the tray existence/absence
    for t in m.conditional_trays:
        m.tray[t].indicator_var.set_value(1)
        m.no_tray[t].indicator_var.set_value(0)
    # Run custom initialization routine
    initialize(m)

    m.BigM = Suffix(direction=Suffix.LOCAL)
    m.BigM[None] = 100

    SolverFactory('gdpopt').solve(m,
                                  tee=True,
                                  init_strategy='fix_disjuncts',
                                  mip_solver='glpk')
    log_infeasible_constraints(m, tol=1E-3)
    display_column(m)
    return m
Exemplo n.º 2
0
 def test_log_infeasible_constraints(self):
     """Test for logging of infeasible constraints."""
     m = self.build_model()
     output = StringIO()
     with LoggingIntercept(output, 'pyomo.util.infeasible', logging.INFO):
         log_infeasible_constraints(m)
     expected_output = [
         "CONSTR c: 1 < 2.0", "CONSTR c2: 1 != 4.0", "CONSTR c3: 1 > 0.0"
     ]
     self.assertEqual(output.getvalue().splitlines(), expected_output)
Exemplo n.º 3
0
    def solve_model(self, m):
        """Solve model"""

        # Solve model
        solve_status = self.opt.solve(m, tee=True, options=self.solver_options, keepfiles=self.keepfiles)

        # Log infeasible constraints if they exist
        log_infeasible_constraints(m)

        return m, solve_status
Exemplo n.º 4
0
 def test_log_infeasible_constraints(self):
     """Test for logging of infeasible constraints."""
     m = self.build_model()
     output = StringIO()
     with LoggingIntercept(output, 'pyomo.util.infeasible', logging.INFO):
         log_infeasible_constraints(m)
     expected_output = [
         "CONSTR c: 2.0 </= 1", "CONSTR c2: 1 =/= 4.0",
         "CONSTR c3: 1 </= 0.0", "CONSTR c5: 5.0 <?= missing variable value"
     ]
     self.assertEqual(expected_output, output.getvalue().splitlines())
Exemplo n.º 5
0
 def test_FP(self):
     """Test the feasibility pump algorithm."""
     with SolverFactory('mindtpy') as opt:
         for model in model_list:
             results = opt.solve(model,
                                 strategy='FP',
                                 mip_solver=required_solvers[1],
                                 nlp_solver=required_solvers[0],
                                 bound_tolerance=1E-5)
             log_infeasible_constraints(model)
             self.assertTrue(is_feasible(model, self.get_config(opt)))
Exemplo n.º 6
0
 def test_FP_Feasibility_Pump1(self):
     """Test the feasibility pump algorithm."""
     with SolverFactory('mindtpy') as opt:
         model = Feasibility_Pump1()
         print('\n Solving Feasibility_Pump1 with feasibility pump')
         results = opt.solve(model,
                             strategy='FP',
                             mip_solver=required_solvers[1],
                             nlp_solver=required_solvers[0],
                             bound_tolerance=1E-5)
         log_infeasible_constraints(model)
         self.assertTrue(is_feasible(model, self.get_config(opt)))
Exemplo n.º 7
0
 def test_FP_8PP(self):
     """Test the feasibility pump algorithm."""
     with SolverFactory('mindtpy') as opt:
         model = EightProcessFlowsheet(convex=True)
         print('\n Solving 8PP problem using feasibility pump')
         results = opt.solve(model,
                             strategy='FP',
                             mip_solver=required_solvers[1],
                             nlp_solver=required_solvers[0],
                             bound_tolerance=1E-5)
         log_infeasible_constraints(model)
         self.assertTrue(is_feasible(model, self.get_config(opt)))
Exemplo n.º 8
0
def print_infeasible_constraints(m,
                                 tol=1e-6,
                                 print_expression=False,
                                 print_variables=False,
                                 output_file=None):
    """
    print the infeasble constraints in the model
    """
    with _logging_handler(output_file) as logger:
        log_infeasible_constraints(m,
                                   tol=tol,
                                   logger=logger,
                                   log_expression=print_expression,
                                   log_variables=print_variables)
Exemplo n.º 9
0
 def test_FP_8PP_Norm_infinity_with_norm_constraint(self):
     """Test the feasibility pump algorithm."""
     with SolverFactory('mindtpy') as opt:
         model = EightProcessFlowsheet(convex=True)
         print(
             '\n Solving 8PP problem using feasibility pump with Norm infinity in mip regularization problem'
         )
         results = opt.solve(model,
                             strategy='FP',
                             mip_solver=required_solvers[1],
                             nlp_solver=required_solvers[0],
                             bound_tolerance=1E-5,
                             fp_main_norm='L_infinity',
                             fp_norm_constraint=False)
         log_infeasible_constraints(model)
         self.assertTrue(is_feasible(model, self.get_config(opt)))
Exemplo n.º 10
0
 def test_log_infeasible_constraints_verbose_variables(self):
     """Test for logging of infeasible constraints."""
     m = self.build_model()
     output = StringIO()
     with LoggingIntercept(output, 'pyomo.util.infeasible', logging.INFO):
         log_infeasible_constraints(m, log_variables=True)
     expected_output = [
         "CONSTR c1: 2.0 </= 1", "  - VAR x: 1",
         "CONSTR c2: 1 =/= 4.0", "  - VAR x: 1",
         "CONSTR c3: 1 </= 0.0", "  - VAR x: 1",
         "CONSTR c5: 5.0 <?= missing variable value <?= 10.0", "  - VAR z: None",
         "CONSTR c7: missing variable value =?= 6.0", "  - VAR z: None",
         "CONSTR c8: 3.0 </= 1 <= 6.0", "  - VAR x: 1",
         "CONSTR c9: 0.0 <= 1 </= 0.5", "  - VAR x: 1",
     ]
     self.assertEqual(expected_output, output.getvalue().splitlines())
Exemplo n.º 11
0
def print_results(m, results, start_time=None, finish_time=None):
    '''
        Prints out the result from pyomo opimizer, the solver status, the final value of the cost function
        and the time the solver took in minutes. If the result is infesable then the constraints violated are
        printed as well.
        
        Inputs:
        results - Pyomo
        
        Optional:
        start_time - start time in seconds (I used time.time() from the time library)
        finish_time - finish time in seconds (I used time.time() from the time library)
        '''
    print(results.solver.status)
    print(results.solver.termination_condition)
    print(m.Cost.expr())
    if start_time != None and finish_time != None:
        print('Time:', (finish_time - start_time) / 60, 'min')
    if results.solver.termination_condition == "infeasible":
        print(
            '___________________________________________________________________'
        )
        from pyomo.util.infeasible import log_infeasible_constraints
        log_infeasible_constraints(m)
Exemplo n.º 12
0
    def run_price_smoothing_heuristic_case(self,
                                           params,
                                           output_dir,
                                           overwrite=False):
        """Smooth prices over entire model horizon using approximated price functions"""

        # Get filename based on run mode
        if params['mode'] == 'bau_deviation_minimisation':
            filename = f"heuristic_baudev_ty-{params['transition_year']}_cp-{params['carbon_price']}.pickle"

        elif params['mode'] == 'price_change_minimisation':
            filename = f"heuristic_pdev_ty-{params['transition_year']}_cp-{params['carbon_price']}.pickle"

        elif params['mode'] == 'price_target':
            filename = f"heuristic_ptar_ty-{params['transition_year']}_cp-{params['carbon_price']}.pickle"

        else:
            raise Exception(f"Unexpected run mode: {params['mode']}")

        # Check if case already solved
        if (not overwrite) and (filename in os.listdir(output_dir)):
            print(f'Already solved: {filename}')
            return

        # Get hash for case
        case_id = self.get_hash(params)

        # Save case ID and associated model parameters
        self.save_hash(case_id, params, output_dir)

        # Start timer for model run
        t_start = time.time()

        self.algorithm_logger('run_price_smoothing_heuristic_case',
                              'Starting case with params: ' + str(params))

        # Load REP results
        with open(os.path.join(output_dir, params['rep_filename']), 'rb') as f:
            rep_results = pickle.load(f)

        # Get results corresponding to last iteration of REP solution
        rep_iteration = rep_results['stage_2_rep'][max(
            rep_results['stage_2_rep'].keys())]

        # Model parameters used to initialise classes that construct and run models
        start, end, scenarios = params['start'], params['end'], params[
            'scenarios']
        bau_initial_price = self.get_bau_initial_price(output_dir, start)

        # Classes used to construct and run primal and MPPDC programs
        primal = Primal(start, end, scenarios)
        baseline = BaselineUpdater(start, end, scenarios,
                                   params['transition_year'])

        # Construct primal program
        m_p = primal.construct_model()

        # Results to extract from primal program
        primal_keys = [
            'x_c', 'p', 'p_V', 'p_in', 'p_out', 'p_L', 'baseline',
            'permit_price', 'YEAR_EMISSIONS', 'YEAR_EMISSIONS_INTENSITY',
            'YEAR_SCHEME_REVENUE', 'TOTAL_SCHEME_REVENUE', 'C_MC', 'ETA',
            'DELTA', 'RHO', 'EMISSIONS_RATE', 'YEAR_CUMULATIVE_SCHEME_REVENUE',
            'YEAR_SCHEME_EMISSIONS_INTENSITY', 'OBJECTIVE'
        ]

        # Results to extract from baseline targeting model
        baseline_keys = [
            'YEAR_AVERAGE_PRICE', 'YEAR_AVERAGE_PRICE_0',
            'YEAR_ABSOLUTE_PRICE_DIFFERENCE',
            'TOTAL_ABSOLUTE_PRICE_DIFFERENCE', 'PRICE_WEIGHTS',
            'YEAR_SCHEME_REVENUE', 'YEAR_CUMULATIVE_SCHEME_REVENUE', 'baseline'
        ]

        # Container for iteration results
        i_results = dict()

        # Initialise price setting generator input as results obtained from final REP iteration
        psg_input = rep_iteration

        # Initialise iteration counter
        counter = 1

        while True:
            self.algorithm_logger('run_price_smoothing_heuristic_case',
                                  f'Starting iteration={counter}')

            # Identify price setting generators
            psg = baseline.prices.get_price_setting_generators_from_model_results(
                psg_input)

            # Construct model used to calibrate baseline
            m_b = baseline.construct_model(psg)

            # Update parameters
            m_b = baseline.update_parameters(m_b, psg_input)
            m_b.YEAR_AVERAGE_PRICE_0 = float(bau_initial_price)
            m_b.PRICE_WEIGHTS.store_values(params['price_weights'])

            # Activate constraints and objectives depending on case being run
            m_b.NON_NEGATIVE_TRANSITION_REVENUE_CONS.activate()

            if params['mode'] == 'bau_deviation_minimisation':
                # Set the price target to be BAU price
                bau_price_target = {y: bau_initial_price for y in m_b.Y}
                m_b.YEAR_AVERAGE_PRICE_TARGET.store_values(bau_price_target)

                # Activate price targeting constraints and objective
                m_b.PRICE_TARGET_DEVIATION_1.activate()
                m_b.PRICE_TARGET_DEVIATION_2.activate()
                m_b.OBJECTIVE_PRICE_TARGET_DIFFERENCE.activate()

                # Append name of objective so objective value can be extracted, and create filename for case
                baseline_keys.append('OBJECTIVE_PRICE_TARGET_DIFFERENCE')

            elif params['mode'] == 'price_change_minimisation':
                # Activate constraints penalised price deviations over successive years
                m_b.PRICE_CHANGE_DEVIATION_1.activate()
                m_b.PRICE_CHANGE_DEVIATION_2.activate()
                m_b.OBJECTIVE_PRICE_DEVIATION.activate()

                # Append name of objective so objective value can be extracted, and create filename for case
                baseline_keys.append('OBJECTIVE_PRICE_DEVIATION')

            elif params['mode'] == 'price_target':
                # Set target price trajectory to prices obtained from BAU model over same period
                m_b.YEAR_AVERAGE_PRICE_TARGET.store_values(
                    params['price_target'])

                # Activate price targeting constraints and objective function
                m_b.PRICE_TARGET_DEVIATION_1.activate()
                m_b.PRICE_TARGET_DEVIATION_2.activate()
                m_b.OBJECTIVE_PRICE_TARGET_DIFFERENCE.activate()

                # Append name of objective so objective value can be extracted, and create filename for case
                baseline_keys.append('OBJECTIVE_PRICE_TARGET_DIFFERENCE')

            else:
                raise Exception(f"Unexpected run mode: {params['mode']}")

            for y in m_b.Y:
                if y >= params['transition_year']:
                    m_b.YEAR_NET_SCHEME_REVENUE_NEUTRAL_CONS[y].activate()

            # Solve model
            m_b, m_b_status = baseline.solve_model(m_b)
            r_b = copy.deepcopy(
                {k: self.extract_result(m_b, k)
                 for k in baseline_keys})

            # Update baselines and permit prices in primal model
            for y in m_p.Y:
                m_p.baseline[y].fix(m_b.baseline[y].value)
                m_p.permit_price[y].fix(m_b.PERMIT_PRICE[y].value)

            # Solve primal program
            m_p, m_p_status = primal.solve_model(m_p)

            # Log all infeasible constraints
            log_infeasible_constraints(m_p)

            # Get results
            r_p = copy.deepcopy(
                {v: self.extract_result(m_p, v)
                 for v in primal_keys})
            r_p['PRICES'] = copy.deepcopy({
                k: m_p.dual[m_p.POWER_BALANCE[k]]
                for k in m_p.POWER_BALANCE.keys()
            })
            i_results[counter] = {'primal': r_p, 'auxiliary': r_b}

            # Max difference in capacity sizing decision between iterations
            max_capacity_difference = self.get_successive_iteration_difference(
                psg_input, r_p, 'x_c')
            print(f'Max capacity difference: {max_capacity_difference} MW')

            # Max absolute baseline difference between successive iterations
            max_baseline_difference = self.get_successive_iteration_difference(
                psg_input, r_p, 'baseline')
            print(
                f'{counter}: Maximum baseline difference = {max_baseline_difference} tCO2/MWh'
            )

            self.algorithm_logger('run_price_smoothing_heuristic_case',
                                  f'Finished iteration={counter}')

            # If baseline difference between successive iterations is sufficiently small then stop
            if max_baseline_difference < 0.05:
                break

            # Stop iterating if max iteration limit exceeded
            elif counter > 9:
                message = f'Max iterations exceeded. Exiting loop.'
                print(message)
                self.algorithm_logger('run_price_smoothing_heuristic_case',
                                      message)
                break

            else:
                # Update dictionary of price setting generator program inputs
                psg_input = r_p

            # Update iteration counter
            counter += 1

        self.algorithm_logger('run_price_smoothing_heuristic_case',
                              f'Finished solving model')

        # Combine results into a single dictionary
        results = {
            **rep_results, 'stage_3_price_targeting': i_results,
            'parameters': params
        }

        # Save results
        self.save_results(results, output_dir, filename)

        # Combine output for method (can be used for debugging)
        output = {
            'auxiliary_model': m_b,
            'auxiliary_status': m_b_status,
            'primal_model': m_p,
            'primal_status': m_p_status,
            'results': results
        }

        # Total iterations
        total_iterations = max(i_results.keys())

        # Save summary of the solution time
        solution_summary = {
            'case_id': case_id,
            'mode': params['mode'],
            'carbon_price': params['carbon_price'],
            'transition_year': params['transition_year'],
            'total_solution_time': time.time() - t_start,
            'total_iterations': total_iterations,
            'max_capacity_difference': max_capacity_difference,
            'max_baseline_difference': max_baseline_difference
        }
        self.save_solution_summary(solution_summary, output_dir)

        message = f"Finished heuristic case: " + str(solution_summary)
        self.algorithm_logger('run_price_smoothing_heuristic_case', message)

        return output
Exemplo n.º 13
0
amodel.EnforceUpTimeConstraintsSubsequent = Constraint(
    amodel.generator,
    amodel.periods,
    rule=enforce_up_time_constraints_subsequent)
amodel.EnforceDownTimeConstraintsInitial = Constraint(
    amodel.generator, rule=enforce_down_time_constraints_initial)
amodel.EnforceDownTimeConstraintsSubsequent = Constraint(
    amodel.generator,
    amodel.periods,
    rule=enforce_down_time_constraints_subsequent)
amodel.TotalCostObjective = Objective(rule=total_cost_objective_rule,
                                      sense=minimize)

#%% compile
instance = amodel.create_instance()
from pyomo.util.infeasible import log_infeasible_constraints
#instance.pprint()
opt = SolverFactory("gurobi", solver_io="python")
results = opt.solve(instance, tee=True, keepfiles=False)
log_infeasible_constraints(instance)
#, options_string="mip_tolerances_integrality=1e-9 mip_tolerances_mipgap=0"

for v in instance.component_objects(Var, active=True):
    print("Variable component object", v)
    print("Type of component object: ",
          str(type(v))[1:-1])  # Stripping <> for nbconvert
    varobject = getattr(instance, str(v))
    print("Type of object accessed via getattr: ", str(type(varobject))[1:-1])
    for index in varobject:
        print("   ", index, varobject[index].value)
Exemplo n.º 14
0
    def run_price_smoothing_mppdc_case(self,
                                       params,
                                       output_dir,
                                       overwrite=False):
        """Run case to smooth prices over model horizon, subject to total revenue constraint"""

        # Get case filename based on run mode
        if params['mode'] == 'bau_deviation_minimisation':
            filename = f"mppdc_baudev_ty-{params['transition_year']}_cp-{params['carbon_price']}.pickle"

        elif params['mode'] == 'price_change_minimisation':
            filename = f"mppdc_pdev_ty-{params['transition_year']}_cp-{params['carbon_price']}.pickle"

        elif params['mode'] == 'price_target':
            filename = f"mppdc_ptar_ty-{params['transition_year']}_cp-{params['carbon_price']}.pickle"

        else:
            raise Exception(f"Unexpected run mode: {params['mode']}")

        # Check if case already solved
        if (not overwrite) and (filename in os.listdir(output_dir)):
            print(f'Already solved: {filename}')
            return

        # Construct hash for case ID
        case_id = self.get_hash(params)

        # Save hash and associated parameters
        self.save_hash(case_id, params, output_dir)

        # Start timer for model run
        t_start = time.time()

        self.algorithm_logger(
            'run_price_smoothing_mppdc_case',
            'Starting MPPDC case with params: ' + str(params))

        # Load REP results
        with open(os.path.join(output_dir, params['rep_filename']), 'rb') as f:
            rep_results = pickle.load(f)

        # Get results corresponding to last iteration of REP solution
        rep_iteration = rep_results['stage_2_rep'][max(
            rep_results['stage_2_rep'].keys())]

        # Extract parameters from last iteration of REP program results
        start, end, scenarios = params['start'], params['end'], params[
            'scenarios']
        bau_initial_price = self.get_bau_initial_price(output_dir, start)

        # Classes used to construct and run primal and MPPDC programs
        mppdc = MPPDCModel(start, end, scenarios, params['transition_year'])
        primal = Primal(start, end, scenarios)

        # Construct MPPDC
        m_m = mppdc.construct_model(include_primal_constraints=True)

        # Construct primal model
        m_p = primal.construct_model()

        # Update MPPDC model parameters
        m_m.YEAR_AVERAGE_PRICE_0 = float(bau_initial_price)
        m_m.PRICE_WEIGHTS.store_values(params['price_weights'])

        # Activate necessary constraints depending on run mode
        m_m.NON_NEGATIVE_TRANSITION_REVENUE_CONS.activate()

        if params['mode'] == 'bau_deviation_minimisation':
            m_m.PRICE_BAU_DEVIATION_1.activate()
            m_m.PRICE_BAU_DEVIATION_2.activate()

        elif params['mode'] == 'price_change_minimisation':
            m_m.PRICE_CHANGE_DEVIATION_1.activate()
            m_m.PRICE_CHANGE_DEVIATION_2.activate()

        elif params['mode'] == 'price_target':
            m_m.YEAR_AVERAGE_PRICE_TARGET.store_values(params['price_target'])
            m_m.PRICE_TARGET_DEVIATION_1.activate()
            m_m.PRICE_TARGET_DEVIATION_2.activate()

        else:
            raise Exception(f"Unexpected run mode: {params['mode']}")

        for y in m_m.Y:
            if y >= params['transition_year']:
                m_m.YEAR_NET_SCHEME_REVENUE_NEUTRAL_CONS[y].activate()

        # Primal variables
        primal_vars = [
            'x_c', 'p', 'p_in', 'p_out', 'q', 'p_V', 'p_L', 'permit_price'
        ]
        fixed_vars = {v: rep_iteration[v] for v in primal_vars}

        # Results to extract from MPPDC model
        mppdc_keys = [
            'x_c', 'p', 'p_V', 'p_in', 'p_out', 'p_L', 'q', 'baseline',
            'permit_price', 'lamb', 'YEAR_EMISSIONS',
            'YEAR_EMISSIONS_INTENSITY', 'YEAR_SCHEME_EMISSIONS_INTENSITY',
            'YEAR_SCHEME_REVENUE', 'YEAR_CUMULATIVE_SCHEME_REVENUE',
            'TOTAL_SCHEME_REVENUE', 'YEAR_ABSOLUTE_PRICE_DIFFERENCE',
            'YEAR_AVERAGE_PRICE_0', 'YEAR_AVERAGE_PRICE',
            'YEAR_SUM_CUMULATIVE_PRICE_DIFFERENCE_WEIGHTED', 'OBJECTIVE',
            'YEAR_ABSOLUTE_PRICE_DIFFERENCE_WEIGHTED',
            'TOTAL_ABSOLUTE_PRICE_DIFFERENCE_WEIGHTED',
            'YEAR_CUMULATIVE_PRICE_DIFFERENCE_WEIGHTED', 'sd_1', 'sd_2',
            'STRONG_DUALITY_VIOLATION_COST', 'TRANSITION_YEAR', 'PRICE_WEIGHTS'
        ]

        # Container for iteration results
        i_results = {}

        # Initialise iteration counter
        counter = 1

        # Placeholder for max difference variables
        max_baseline_difference = None
        max_capacity_difference = None

        while True:
            self.algorithm_logger('run_price_smoothing_mppdc_case',
                                  f'Starting iteration={counter}')

            # Fix MPPDC variables
            m_m = mppdc.fix_variables(m_m, fixed_vars)

            # Solve MPPDC
            m_m, m_m_status = mppdc.solve_model(m_m)

            # Model timeout will cause sub-optimal termination condition
            if m_m_status.solver.termination_condition != TerminationCondition.optimal:
                i_results[counter] = None
                self.algorithm_logger('run_price_smoothing_mppdc_case',
                                      f'Sub-optimal solution')
                self.algorithm_logger(
                    'run_price_smoothing_mppdc_case',
                    f'User time: {m_m_status.solver.user_time}s')

                # No primal model solved
                m_p, m_p_status = None, None
                break

            # Log infeasible constraints
            log_infeasible_constraints(m_m)

            # Results from MPPDC program
            r_m = copy.deepcopy(
                {v: self.extract_result(m_m, v)
                 for v in mppdc_keys})
            i_results[counter] = r_m

            # Update primal program with baselines and permit prices obtained from MPPDC model
            for y in m_p.Y:
                m_p.baseline[y].fix(m_m.baseline[y].value)
                m_p.permit_price[y].fix(m_m.permit_price[y].value)

            # Solve primal model
            m_p, m_p_status = primal.solve_model(m_p)
            log_infeasible_constraints(m_p)

            # Results from primal program
            p_r = copy.deepcopy(
                {v: self.extract_result(m_p, v)
                 for v in primal_vars})
            p_r['PRICES'] = copy.deepcopy({
                k: m_p.dual[m_p.POWER_BALANCE[k]]
                for k in m_p.POWER_BALANCE.keys()
            })
            i_results[counter]['primal'] = p_r

            # Max absolute capacity difference between MPPDC and primal program
            max_capacity_difference = max(
                abs(m_m.x_c[k].value - m_p.x_c[k].value)
                for k in m_m.x_c.keys())
            print(f'Max capacity difference: {max_capacity_difference} MW')

            # Max absolute baseline difference between MPPDC and primal program
            max_baseline_difference = max(
                abs(m_m.baseline[k].value - m_p.baseline[k].value)
                for k in m_m.baseline.keys())
            print(
                f'Max baseline difference: {max_baseline_difference} tCO2/MWh')

            # Check if capacity variables have changed
            if max_baseline_difference < 0.05:
                break

            # Check if max iterations exceeded
            elif counter > 9:
                message = f'Max iterations exceeded. Exiting loop.'
                print(message)
                self.algorithm_logger('run_price_smoothing_mppdc_case',
                                      message)
                break

            else:
                # Update dictionary of fixed variables to be used in next iteration
                fixed_vars = {v: p_r[v] for v in primal_vars}

            self.algorithm_logger('run_price_smoothing_mppdc_case',
                                  f'Finished iteration={counter}')
            counter += 1

        self.algorithm_logger('run_price_smoothing_mppdc_case',
                              f'Finished solving model')

        # Combine results into a single dictionary
        results = {
            **rep_results, 'stage_3_price_targeting': i_results,
            'parameters': params
        }

        # Save results
        self.save_results(results, output_dir, filename)

        # Method output
        output = {
            'mppdc_model': m_m,
            'mppdc_status': m_m_status,
            'primal_model': m_p,
            'primal_status': m_p_status,
            'results': results
        }

        self.algorithm_logger('run_price_smoothing_mppdc_case',
                              'Finished MPPDC case')

        # Total iterations
        total_iterations = max(i_results.keys())

        # Save summary of the solution time
        solution_summary = {
            'case_id': case_id,
            'mode': params['mode'],
            'carbon_price': params['carbon_price'],
            'transition_year': params['transition_year'],
            'total_solution_time': time.time() - t_start,
            'total_iterations': total_iterations,
            'max_capacity_difference': max_capacity_difference,
            'max_baseline_difference': max_baseline_difference
        }
        self.save_solution_summary(solution_summary, output_dir)

        message = f"Finished MPPDC case: " + str(solution_summary)
        self.algorithm_logger('run_price_smoothing_mppdc_case', message)

        return output
Exemplo n.º 15
0
def calculate_Fenske(xD, xB):
    m = ConcreteModel()
    min_T, max_T = 300, 400
    m.comps = Set(initialize=['benzene', 'toluene'])
    m.trays = Set(initialize=['condenser', 'reboiler'])
    m.Kc = Var(m.comps,
               m.trays,
               doc='Phase equilibrium constant',
               domain=NonNegativeReals,
               initialize=1,
               bounds=(0, 1000))
    m.T = Var(m.trays,
              doc='Temperature [K]',
              domain=NonNegativeReals,
              bounds=(min_T, max_T))
    m.T['condenser'].fix(82 + 273.15)
    m.T['reboiler'].fix(108 + 273.15)
    m.P = Var(doc='Pressure [bar]', bounds=(0, 5))
    m.P.fix(1.01)
    m.T_ref = 298.15
    m.gamma = Var(m.comps,
                  m.trays,
                  doc='liquid activity coefficent of component on tray',
                  domain=NonNegativeReals,
                  bounds=(0, 10),
                  initialize=1)
    m.Pvap = Var(
        m.comps,
        m.trays,
        doc='pure component vapor pressure of component on tray in bar',
        domain=NonNegativeReals,
        bounds=(1E-3, 5),
        initialize=0.4)
    m.Pvap_X = Var(
        m.comps,
        m.trays,
        doc='Related to fraction of critical temperature (1 - T/Tc)',
        bounds=(0.25, 0.5),
        initialize=0.4)

    m.pvap_const = {
        'benzene': {
            'A': -6.98273,
            'B': 1.33213,
            'C': -2.62863,
            'D': -3.33399,
            'Tc': 562.2,
            'Pc': 48.9
        },
        'toluene': {
            'A': -7.28607,
            'B': 1.38091,
            'C': -2.83433,
            'D': -2.79168,
            'Tc': 591.8,
            'Pc': 41.0
        }
    }

    @m.Constraint(m.comps, m.trays)
    def phase_equil_const(_, c, t):
        return m.Kc[c, t] * m.P == (m.gamma[c, t] * m.Pvap[c, t])

    @m.Constraint(m.comps, m.trays)
    def Pvap_relation(_, c, t):
        k = m.pvap_const[c]
        x = m.Pvap_X[c, t]
        return (log(m.Pvap[c, t]) - log(k['Pc'])) * (1 - x) == (
            k['A'] * x + k['B'] * x**1.5 + k['C'] * x**3 + k['D'] * x**6)

    @m.Constraint(m.comps, m.trays)
    def Pvap_X_defn(_, c, t):
        k = m.pvap_const[c]
        return m.Pvap_X[c, t] == 1 - m.T[t] / k['Tc']

    @m.Constraint(m.comps, m.trays)
    def gamma_calc(_, c, t):
        return m.gamma[c, t] == 1

    m.relative_volatility = Var(m.trays, domain=NonNegativeReals)

    @m.Constraint(m.trays)
    def relative_volatility_calc(_, t):
        return m.Kc['benzene',
                    t] == (m.Kc['toluene', t] * m.relative_volatility[t])

    @m.Expression()
    def fenske(_):
        return log((xD / (1 - xD)) * (xB / (1 - xB))) / (log(
            sqrt(m.relative_volatility['condenser'] *
                 m.relative_volatility['reboiler'])))

    SolverFactory('ipopt').solve(m, tee=True)
    from pyomo.util.infeasible import log_infeasible_constraints
    log_infeasible_constraints(m, tol=1E-3)
    m.fenske.display()
Exemplo n.º 16
0
def generate_support(config, index, parcels, logger):
    cache = config["meta"]["cache"].joinpath(__CACHE_SUPPORT_DIR__)
    cache.mkdir(parents=True, exist_ok=True)
    cached_data = cache.joinpath("{}_{}.npy".format(index[0], index[1]))
    if cached_data.exists():
        return

    parcel = parcels.parcel_at_index(index)
    surface = parcel[1]  # we want to support the bottom
    crop_index, cropped = crop_nans(surface)
    logger.debug("Cropping NaNs took surface shape from {} to {}".format(surface.shape, cropped.shape))

    # Given the minimum feature size the user has requested, we can down-sample the original dataset to reduce
    # the complexity of the optimization problem to solve. There's no real loss in fidelity if we down-sample
    # here, we don't need a very smooth shape coming out of this algorithm to ensure a reasonable 3D mesh later.
    # Down-sampling here also is critical to have any reasonable guarantee that the optimization problem can be
    # solved in human timescales (minutes) instead of geological ones using the native resolution. Allow 30 pixels
    # per minimum feature diameter: inter-pixel distance is the 1/10th the minimum feature radius.
    pixel_size = (config["model"]["support"]["minimum_feature_radius_millimeters"] / 1e3) / 5
    scaling_factor = (config["printer"]["xy_resolution_microns"] / 1e6) / pixel_size
    # Any interpolations on data-sets with NaN values are prone to extrapolate the NaNs across the whole data-set.
    # Setting these values to some non-NaN value will result in the surface being "pulled" there at the edges when
    # we interpolate, so a Gaussian kernel is used to fill nearby values with values similar to those in the dataset.
    # As a boundary between NaN and non-NaN values without much curvature will result in NaN fills of about half
    # magnitude, we optimistically multiply by 1.75 here to reduce as much of the "pull" as possible.
    blurred = numpy.copy(cropped)
    if numpy.isnan(cropped).any():
        with_zeroes = numpy.where(numpy.isnan(cropped), 0, cropped)
        blur = ndimage.gaussian_filter(with_zeroes, sigma=10, mode="nearest")
        blurred = numpy.where(numpy.isnan(cropped), 1.75 * blur, cropped)

    scaled = ndimage.zoom(blurred, zoom=scaling_factor)
    if numpy.isnan(cropped).any():
        # Let's replace pixels in the scaled version with NaN when the raw data was all NaNs
        only_nans = numpy.where(numpy.isnan(cropped), 1, 0)
        scaled_nans = ndimage.zoom(only_nans, zoom=scaling_factor)
        scaled = numpy.where(scaled_nans == 1, numpy.nan, scaled)

    logger.debug(
        "Scaling surface to a pixel size of {}mm (using a scaling factor of 1:{:.2f}) results in a surface shape of {}.".format(
            config["model"]["support"]["minimum_feature_radius_millimeters"], 1 / scaling_factor, scaled.shape
        )
    )

    # Slice the total Z height in this parcel into layers as high as our pixels are wide, or our angle calculations
    # get all messy. Add one layer for the fixed variables modeling the build plate at the bottom.
    layers = math.floor((numpy.nanmax(scaled) - numpy.nanmin(scaled)) / pixel_size) + 2
    i, j, k = scaled.shape[0], scaled.shape[1], layers
    logger.debug(
        "Full abstract model with shape ({},{},{}) will contain up to {} variables.".format(
            scaled.shape[0], scaled.shape[1], layers, scaled.shape[0] * scaled.shape[1] * layers
        )
    )

    regularized_surface = numpy.floor((scaled - numpy.nanmin(scaled)) / pixel_size) + 1
    indices = numpy.where(numpy.isnan(regularized_surface), 0, regularized_surface)
    logger.debug(
        "After fixing surface pixels, those above them and NaN regions, {} variables remain.".format(
            int(numpy.ndarray.sum(indices))
        )
    )

    logger.debug("Instantiating model...")
    instance_start = datetime.now()
    feature_radius_pixels = math.sqrt(3) / 2
    model = concrete_model(
        (i, j, k), regularized_surface, feature_radius_pixels,
        config["model"]["support"]["self_supporting_angle_degrees"], 10.0, 1.0, logger
    )
    logger.debug("Instantiating model took {}.".format(datetime.now() - instance_start))
    fixing_start = datetime.now()
    logger.debug("Fixing variables...")
    for I in range(i + 1):
        for J in range(j + 1):
            model.nodal_support[I, J, 0].fix(1)  # build plate
    for I in range(i):
        for J in range(j):
            surface_index = indices[I, J]
            if surface_index == 0:
                continue  # no surface here

            model.elemental_density[I, J, surface_index].fix(1)  # surface
            for K in range(int(surface_index) + 1, k):
                model.elemental_density[I, J, K].fix(0)  # above the surface
    logger.debug("Fixing variables took {}.".format(datetime.now() - fixing_start))

    opt = pyo.SolverFactory('ipopt')
    solving_start = datetime.now()
    logger.debug("Solving for optimal support...")
    opt.solve(model, tee=True)
    logger.debug("Solving for optimal support took {}.".format(datetime.now() - solving_start))
    log_infeasible_constraints(model, logger=logger, log_variables=True, log_expression=True)
    output = numpy.empty((i, j, k - 1))
    output[:] = numpy.nan
    for I in range(i):
        for J in range(j):
            for K in range(1, k):  # ignore the build plate
                output[I, J, K - 1] = model.elemental_density[I, J, K].value

    # TODO: uncrop to size of original data
    numpy.save(cached_data, output)
Exemplo n.º 17
0
    def run_rep_case(self, params, output_dir, overwrite=False):
        """Run carbon tax scenario"""

        # Extract case parameters
        start, end, scenarios = params['start'], params['end'], params[
            'scenarios']
        permit_prices = params['permit_prices']

        # First run carbon tax case
        baselines = {y: float(0) for y in range(start, end + 1)}

        # Check that carbon tax is same for all years in model horizon
        assert len(set(permit_prices.values(
        ))) == 1, f'Permit price trajectory is not flat: {permit_prices}'

        # Extract carbon price in first year (same as all other used). To be used in filename.
        carbon_price = permit_prices[start]

        # Filename for REP case
        filename = f'rep_cp-{carbon_price:.0f}.pickle'

        # Check if model has already been solved
        if (not overwrite) and (filename in os.listdir(output_dir)):
            print(f'Already solved: {filename}')
            return

        # Construct hash for case ID
        case_id = self.get_hash(params)

        # Save hash and associated parameters
        self.save_hash(case_id, params, output_dir)

        # Start timer for model run
        t_start = time.time()

        self.algorithm_logger('run_rep_case',
                              'Starting case with params: ' + str(params))

        # Results to extract
        result_keys = [
            'x_c', 'p', 'p_V', 'p_in', 'p_out', 'q', 'p_L', 'baseline',
            'permit_price', 'YEAR_EMISSIONS', 'YEAR_EMISSIONS_INTENSITY',
            'YEAR_SCHEME_REVENUE', 'TOTAL_SCHEME_REVENUE', 'C_MC', 'ETA',
            'DELTA', 'RHO', 'EMISSIONS_RATE',
            'YEAR_SCHEME_EMISSIONS_INTENSITY',
            'YEAR_CUMULATIVE_SCHEME_REVENUE', 'OBJECTIVE'
        ]

        # Run carbon tax case
        self.algorithm_logger('run_rep_case', 'Starting carbon tax case solve')
        m, status = self.run_primal_fixed_policy(start, end, scenarios,
                                                 permit_prices, baselines)
        log_infeasible_constraints(m)
        self.algorithm_logger('run_rep_case', 'Finished carbon tax case solve')

        # Model results
        carbon_tax_results = {
            k: self.extract_result(m, k)
            for k in result_keys
        }

        # Add dual variable from power balance constraint
        carbon_tax_results['PRICES'] = {
            k: m.dual[m.POWER_BALANCE[k]]
            for k in m.POWER_BALANCE.keys()
        }

        # Update baselines so they = emissions intensity of output from participating generators
        baselines = carbon_tax_results['YEAR_SCHEME_EMISSIONS_INTENSITY']

        # Container for iteration results
        i_results = dict()

        # Iteration counter
        counter = 1

        # Initialise iteration input to carbon tax scenario results (used to check stopping criterion)
        i_input = carbon_tax_results

        while True:
            # Re-run model with new baselines
            self.algorithm_logger(
                'run_rep_case', f'Starting solve for REP iteration={counter}')
            m, status = self.run_primal_fixed_policy(start, end, scenarios,
                                                     permit_prices, baselines)
            log_infeasible_constraints(m)
            self.algorithm_logger(
                'run_rep_case', f'Finished solved for REP iteration={counter}')

            # Model results
            i_output = {k: self.extract_result(m, k) for k in result_keys}

            # Get dual variable values from power balance constraint
            i_output['PRICES'] = {
                k: m.dual[m.POWER_BALANCE[k]]
                for k in m.POWER_BALANCE.keys()
            }

            # Add results to iteration results container
            i_results[counter] = copy.deepcopy(i_output)

            # Check max absolute capacity difference between successive iterations
            max_capacity_difference = self.get_successive_iteration_difference(
                i_input, i_output, 'x_c')
            print(
                f'{counter}: Maximum capacity difference = {max_capacity_difference} MW'
            )

            # Max absolute baseline difference between successive iterations
            max_baseline_difference = self.get_successive_iteration_difference(
                i_input, i_output, 'baseline')
            print(
                f'{counter}: Maximum baseline difference = {max_baseline_difference} tCO2/MWh'
            )

            # If max absolute difference between successive iterations is sufficiently small stop iterating
            if max_baseline_difference < 0.05:
                break

            # If iteration limit exceeded
            elif counter > 9:
                message = f'Max iterations exceeded. Exiting loop.'
                print(message)
                self.algorithm_logger('run_rep_case', message)
                break

            # Update iteration inputs (used to check stopping criterion in next iteration)
            i_input = copy.deepcopy(i_output)

            # Update baselines to be used in next iteration
            baselines = i_output['YEAR_SCHEME_EMISSIONS_INTENSITY']

            # Update iteration counter
            counter += 1

        # Combine results into single dictionary
        results = {
            'stage_1_carbon_tax': carbon_tax_results,
            'stage_2_rep': i_results
        }

        # Save results
        self.save_results(results, output_dir, filename)

        # Dictionary to be returned by method
        output = {'results': results, 'model': m, 'status': status}
        self.algorithm_logger('run_rep_case', f'Finished REP case')

        # Total number of iterations processed
        total_iterations = max(i_results.keys())

        # Save summary of the solution time
        solution_summary = {
            'case_id': case_id,
            'mode': params['mode'],
            'carbon_price': carbon_price,
            'total_solution_time': time.time() - t_start,
            'total_iterations': total_iterations,
            'max_capacity_difference': max_capacity_difference,
            'max_baseline_difference': max_baseline_difference
        }

        self.save_solution_summary(solution_summary, output_dir)

        message = 'Finished REP case: ' + str(solution_summary)
        self.algorithm_logger('run_rep_case', message)

        return output
Exemplo n.º 18
0
    m.fs.costing.cost_process()

    #  m.fs.crystallizer.k_param = 0.06
    # solving
    m.fs.crystallizer.initialize(outlvl=idaeslog.DEBUG)
    assert_units_consistent(m)  # check that units are consistent
    assert (
        degrees_of_freedom(m) == 0
    )  # check that the degrees of freedom are what we expect
    solver = get_solver()
    # solver = SolverFactory('ipopt')
    # solver.options = {'tol': 1e-8, 'nlp_scaling_method': 'user-scaling', 'halt_on_ampl_error': 'yes'}
    results = solver.solve(m, tee=True, symbolic_solver_labels=True)
    output = StringIO()
    with LoggingIntercept(output, "pyomo.util.infeasible", logging.INFO):
        log_infeasible_constraints(m)
    print(output.getvalue().splitlines())
    assert results.solver.termination_condition == TerminationCondition.optimal
    # m.fs.crystallizer.display()

    m.fs.crystallizer.report()

    # assert False
    ##########################################
    # # Case 2: Fix crystallizer yield
    ##########################################
    print("\n--- Case 2 ---")
    # m.fs.crystallizer.T_crystallization.unfix()
    m.fs.crystallizer.solids.flow_mass_phase_comp[0, "Sol", "NaCl"].unfix()
    m.fs.crystallizer.crystallization_yield["NaCl"].fix(0.7)
Exemplo n.º 19
0
    def _process_solver_results(self, model):
        """
        Method to post process results from 'solve_model' method
        :param model: solved model
        :return: dictionary of solver results
        """

        from pyomo.environ import Set, RealSet, RangeSet, Param, Var

        # Write solution to stdout/file
        if self.write_solution and (
                str(self.solver_results.solver.Status) in ['ok']
                or str(self.solver_results.solver.Termination_condition)
                in ['maxTimeLimit']):

            if self.write_solution_to_stdout:
                # Write solution to screen
                self.solver_results.write()
            else:
                pass

            # Write solution to file named <model_name>/DD_MM_YY_HH_MM_xx.json
            # Create (if it does not exist) the '_results_store' folder
            results_store_folder = path.join('_results_store',
                                             self.__model_name_str, '')
            if not path.exists(results_store_folder):
                makedirs(results_store_folder)

            if self.__pyomo_version <= '5.7.1':
                model.solutions.store_to(
                    self.solver_results)  # define solutions storage folder
            else:
                pass
            self.__current_datetime_str = datetime.now().strftime(
                "%d_%m_%y_%H_%M_")
            file_suffix = 0
            # Results filename
            if self.__model_name_str == 'Unknown' or len(
                    self.__model_name_str) <= 10:
                result_filename = self.__model_name_str + self.__current_datetime_str + str(
                    file_suffix) + ".json"
            else:
                result_filename = self.__model_name_str[:4] + '..' + self.__model_name_str[-4:] + \
                                  self.__current_datetime_str + str(file_suffix) + ".json"
            while path.exists(results_store_folder + result_filename):
                file_suffix += 1
                result_filename = self.__current_datetime_str + str(
                    file_suffix) + ".json"
            result_filename = self.__current_datetime_str + str(
                file_suffix) + ".json"
            self.solver_results.write(filename=results_store_folder +
                                      result_filename,
                                      format="json")
        else:
            pass

        # Create dictionary to for solver statistics and solution
        final_result = dict()
        # Include the default solver results from opt_solver.solve & current state of model
        final_result['solver_results_def'] = self.solver_results
        final_result[
            'model'] = model  # copy.deepcopy(model)   # include all model attributes

        # _include solver statistics
        acceptable_termination_conditions = [
            'maxTimeLimit', 'maxIterations', 'locallyOptimal',
            'globallyOptimal', 'optimal', 'other'
        ]
        if str(self.solver_results.solver.Status) == 'ok' or (
                str(self.solver_results.solver.Status) == 'aborted'
                and str(self.solver_results.solver.Termination_condition)
                in acceptable_termination_conditions):
            final_result['solver'] = dict(
            )  # Create dictionary for solver statistics
            final_result['solver'] = {
                'status':
                str(self.solver_results.solver.Status),
                'solver_message':
                str(self.solver_results.solver.Message),
                'termination_condition':
                str(self.solver_results.solver.Termination_condition)
            }
            try:
                final_result['solver'][
                    'wall_time'] = self.solver_results.solver.wall_time
            except AttributeError:
                final_result['solver']['wall_time'] = None

            try:
                final_result['solver'][
                    'wall_time'] = self.solver_results.solver.wall_time
            except AttributeError:
                final_result['solver']['wall_time'] = None

            try:
                final_result['solver'][
                    'cpu_time'] = self.solver_results.solver.time
            except AttributeError:
                final_result['solver']['cpu_time'] = None

            try:
                if self.solver_results.problem.Upper_bound == 0 and self.solver_results.problem.Lower_bound == 0:
                    final_result['solver']['gap'] = 0
                elif self.solver_results.problem.Upper_bound == 0:
                    final_result['solver']['gap'] = abs(
                        round(self.solver_results.problem.Lower_bound, 2))
                else:
                    final_result['solver']['gap'] = abs(round(
                        (self.solver_results.problem.Upper_bound - self.solver_results.problem.Lower_bound) \
                        * 100 / self.solver_results.problem.Upper_bound, 2))
            except AttributeError:
                final_result['solver']['gap'] = None

            # Check state of available solution
            if self.__pyomo_version < '5.7.1':
                try:
                    for key, value in final_result['solver_results_def'][
                            'Solution'][0]['Objective'].items():
                        objective_value = value['Value']
                    final_result['solution_status'] = True
                except:
                    final_result['solution_status'] = False
                    objective_value = 'Unk'
            else:
                try:
                    objective_value = model.solutions.solutions[0]._entry[
                        'objective'][list(
                            model.solutions.solutions[0]._entry['objective'].
                            keys())[0]][1]['Value']
                    final_result['solution_status'] = True
                except:
                    final_result['solution_status'] = False
                    objective_value = 'Unk'

            if self.return_solution and final_result['solution_status']:
                # True: include values of all model objects in 'final_result'
                # write list of sets, parameters and variables
                final_result['sets_list'] = [
                    str(i) for i in chain(model.component_objects(Set),
                                          model.component_objects(RealSet),
                                          model.component_objects(RangeSet))
                    if (re.split("_", str(i))[-1] != 'index')
                    if (re.split("_", str(i))[-1] != 'domain')
                ]
                final_result['parameters_list'] = [
                    str(i) for i in model.component_objects(Param)
                ]
                final_result['variables_list'] = [
                    str(i) for i in model.component_objects(Var)
                ]

                # Populate final results for sets, parameters and variables
                # Create method to return array
                def indexed_value_extract(index, object):
                    return array([value for value in object[index].value])

                # Sets
                final_result['sets'] = dict()
                for set in final_result['sets_list']:
                    set_object = getattr(model, str(set))
                    final_result['sets'][set] = array(
                        list(set_object))  # save array of set elements

                # Parameters
                final_result['parameters'] = dict()
                if self.verbosity:
                    print('\nProcessing parameters . . . ')
                else:
                    pass
                for par in final_result['parameters_list']:
                    if self.verbosity:
                        print(par, ' ', end="")
                    else:
                        pass
                    par_object = getattr(model, str(par))
                    par_object_dim = par_object.dim(
                    )  # get dimension of parameter
                    if par_object_dim == 0:
                        final_result['parameters'][par] = par_object.value
                    elif par_object_dim == 1:
                        final_result['parameters'][par] = array(
                            [value for value in par_object.values()])
                    else:
                        try:
                            par_set_list = self.__get_set_list(par_object)
                            par_set_lens = [
                                len(getattr(model, str(set)))
                                for set in par_set_list
                            ]
                        except AttributeError:
                            par_set_list = [str(par_object._index.name)]
                            temp_par_set = getattr(model, par_set_list[0])
                            if temp_par_set.dimen == 1:
                                par_set_lens = [len(temp_par_set)]
                            else:
                                par_set_lens = [
                                    len(set) for set in
                                    self.__get_set_list_alt(temp_par_set)
                                ]

                        # print(par_set_lens)
                        final_result['parameters'][par] = zeros(
                            shape=par_set_lens, dtype=float)
                        if par_object_dim == 2:
                            if len(par_set_list) == par_object_dim:
                                for ind_i, i in enumerate(
                                        getattr(model, str(par_set_list[0]))):
                                    for ind_j, j in enumerate(
                                            getattr(model,
                                                    str(par_set_list[1]))):
                                        final_result['parameters'][par][ind_i][
                                            ind_j] = par_object[i, j]
                            elif len(par_set_list) == 1:
                                for set in par_set_list:
                                    for ind, (i, j) in enumerate(
                                            getattr(model, str(set))):
                                        # print(type(final_result['parameters'][par]),final_result['parameters'][par])
                                        # print(i,j,final_result['parameters'][par][i-1][j-1])
                                        # print(par_set_lens)
                                        # print(par_set_list)
                                        # print(par_object_dim)
                                        if self.__pyomo_version < '5.7':  # FIXME: Better way to do this?
                                            final_result['parameters'][par][
                                                i - 1][j - 1] = par_object[i,
                                                                           j]
                                        else:
                                            final_result['parameters'][par][
                                                ind] = par_object[i, j]
                            else:
                                pass

                        else:
                            pass  # FIXME 3-dimensional variables are not considered yet

                # Variables
                final_result['variables'] = dict()
                # Include objective functionv value
                final_result['variables']['Objective'] = objective_value
                if self.verbosity:
                    print('\nProcessing results of variables . . . ')
                else:
                    pass
                for variable in final_result['variables_list']:
                    try:
                        if self.verbosity:
                            print(variable, ' ', end="")
                        else:
                            pass
                        variable_object = getattr(model, str(variable))
                        variable_object_dim = variable_object.dim(
                        )  # get dimension of variable
                        if variable_object_dim == 0:
                            final_result['variables'][
                                variable] = variable_object.value
                        elif variable_object_dim == 1:
                            final_result['variables'][variable] = array([
                                value.value
                                for value in variable_object.values()
                            ])
                        else:
                            try:
                                variable_set_list = self.__get_set_list(
                                    variable_object)
                                variable_set_lens = [
                                    len(getattr(model, str(set)))
                                    for set in variable_set_list
                                ]
                            except AttributeError:
                                variable_set_list = [
                                    str(variable_object._index.name)
                                ]
                                temp_variable_set = getattr(
                                    model, variable_set_list[0])
                                if temp_variable_set.dimen == 1:
                                    variable_set_lens = [
                                        len(temp_variable_set)
                                    ]
                                else:
                                    variable_set_lens = [
                                        len(set)
                                        for set in self.__get_set_list_alt(
                                            temp_variable_set)
                                    ]

                            # print(variable_set_lens)
                            final_result['variables'][variable] = zeros(
                                shape=variable_set_lens, dtype=float)
                            if variable_object_dim == 2:
                                if len(variable_set_list
                                       ) == variable_object_dim:
                                    for ind_i, i in enumerate(
                                            getattr(
                                                model,
                                                str(variable_set_list[0]))):
                                        for ind_j, j in enumerate(
                                                getattr(
                                                    model,
                                                    str(variable_set_list[1]))
                                        ):
                                            final_result['variables'][
                                                variable][ind_i][
                                                    ind_j] = variable_object[
                                                        i, j].value
                                elif len(variable_set_list) == 1:
                                    for set in variable_set_list:
                                        for ind, (i, j) in enumerate(
                                                getattr(model, str(set))):
                                            # print(type(final_result['variables'][variable]),final_result['variables'][variable])
                                            # print(i,j,final_result['variables'][variable][i-1][j-1])
                                            if self.__pyomo_version < '5.7':  # FIXME: Better way to do this?
                                                final_result['variables'][
                                                    variable][i - 1][
                                                        j -
                                                        1] = variable_object[
                                                            i, j].value
                                            else:
                                                final_result['variables'][
                                                    variable][
                                                        ind] = variable_object[
                                                            i, j].value
                                else:
                                    pass

                            else:
                                pass  # FIXME 3-dimensional variables are not considered yet

                    except AttributeError:
                        pass

                print('\n')

            else:  # if solver_status != 'ok' or amongst acceptable termination conditions
                if self.debug_mode:
                    if self.verbose_debug_mode:  # Print troublesome constraints
                        from pyomo.util.infeasible import log_infeasible_constraints
                        log_infeasible_constraints(model)
                    else:
                        pass
                    self.__psmsg('An optimal solution could not be processed'
                                 )  # leave program running to debug
                else:
                    self.__pemsg('An optimal solution could not be processed')

        else:  # if solver_status != ok
            self.__pemsg('An optimal solution was NOT found')

        return final_result
Exemplo n.º 20
0
    def run_bau_case(self, params, output_dir, overwrite=False):
        """Run business-as-usual case"""

        # Case filename
        filename = 'bau_case.pickle'

        # Check if case exists
        if (not overwrite) and (filename in os.listdir(output_dir)):
            print(f'Already solved: {filename}')
            return

        # Construct hash for case
        case_id = self.get_hash(params)

        # Save case params and associated hash
        self.save_hash(case_id, params, output_dir)

        # Extract case parameters for model
        start, end, scenarios = params['start'], params['end'], params[
            'scenarios']

        # Start timer for case run
        t_start = time.time()

        message = f"""Starting case: first_year={start}, final_year={end}, scenarios_per_year={scenarios}"""
        self.algorithm_logger('run_bau_case', message)

        # Permit prices and emissions intensity baselines for BAU case (all 0)
        permit_prices = {y: float(0) for y in range(start, end + 1)}
        baselines = {y: float(0) for y in range(start, end + 1)}

        # Run model
        self.algorithm_logger('run_bau_case', 'Starting solve')
        m, status = self.run_primal_fixed_policy(start, end, scenarios,
                                                 permit_prices, baselines)
        log_infeasible_constraints(m)
        self.algorithm_logger('run_bau_case', 'Finished solve')

        # Results to extract
        result_keys = [
            'x_c', 'p', 'p_V', 'p_in', 'p_out', 'p_L', 'baseline',
            'permit_price', 'YEAR_EMISSIONS', 'YEAR_EMISSIONS_INTENSITY',
            'YEAR_SCHEME_REVENUE', 'TOTAL_SCHEME_REVENUE', 'C_MC', 'ETA',
            'DELTA', 'RHO', 'EMISSIONS_RATE', 'OBJECTIVE'
        ]

        # Model results
        results = {k: self.extract_result(m, k) for k in result_keys}

        # Add dual variable from power balance constraint
        results['PRICES'] = {
            k: m.dual[m.POWER_BALANCE[k]]
            for k in m.POWER_BALANCE.keys()
        }

        # Save results
        self.save_results(results, output_dir, filename)

        # Combine output in dictionary. To be returned by method.
        output = {'results': results, 'model': m, 'status': status}

        # Solution summary
        solution_summary = {
            'case_id': case_id,
            'mode': params['mode'],
            'total_solution_time': time.time() - t_start
        }
        self.save_solution_summary(solution_summary, output_dir)

        self.algorithm_logger(
            'run_bau_case',
            f'Finished BAU case: case_id={case_id}, total_solution_time={time.time() - t_start}s'
        )

        return output