|
| 1 | +from amplpy import AMPL |
| 2 | +import pandas as pd |
| 3 | +import numpy as np |
| 4 | + |
| 5 | +# Unit Commitment data |
| 6 | +generators = ['G1', 'G2', 'G3', 'G4', 'G5', 'G6', 'G7'] |
| 7 | + |
| 8 | +# Generators data |
| 9 | +generators_data = pd.DataFrame({ |
| 10 | + 'min_output': [20, 30, 25, 15, 10, 40, 0], |
| 11 | + 'max_output': [100, 120, 90, 60, 50, 150, 30], |
| 12 | + 'ramp_up_limit': [40, 50, 30, 25, 20, 60, 10], |
| 13 | + 'ramp_down_limit': [40, 50, 30, 25, 20, 60, 10], |
| 14 | + 'linear_cost': [20, 16, 18, 22, 24, 14, 12], |
| 15 | + 'quadratic_cost': [0.04, 0.05, 0.06, 0.03, 0.04, 0.036, 0.1], |
| 16 | + 'startup_cost': [400, 300, 360, 200, 160, 600, 160], |
| 17 | + 'emission_rate': [0.7, 0.5, 0.6, 0.4, 0.3, 0.8, 0.0] |
| 18 | +}, index=generators) |
| 19 | + |
| 20 | +# Generate random demand |
| 21 | +num_time_periods = 24*2 |
| 22 | +time_periods = list(range(1, num_time_periods+1)) |
| 23 | + |
| 24 | +np.random.seed(None) |
| 25 | +base_demand = 150 + 40 * np.sin(np.linspace(0, 3*np.pi, num_time_periods)) |
| 26 | +noise = np.random.normal(0, 10, num_time_periods) |
| 27 | +demand = (base_demand + noise).clip(min=100).round().astype(int) |
| 28 | + |
| 29 | +# Optimization model and data |
| 30 | +ampl = AMPL() |
| 31 | +ampl.read('unit_commitment.mod') # This model should reflect renamed sets/vars/params |
| 32 | + |
| 33 | +ampl.set['TIME'] = time_periods |
| 34 | +ampl.set['GENERATORS'] = generators |
| 35 | +ampl.param['demand'] = demand |
| 36 | +ampl.set_data(generators_data, 'GENERATORS') |
| 37 | + |
| 38 | +# Hierarchical Multi-objective configuration |
| 39 | +# Higher priority first |
| 40 | +ampl.eval('let Total_Cost.objpriority := 2;') |
| 41 | +# Set 5% degradation tolerance for total cost |
| 42 | +ampl.eval('let Total_Cost.objreltol := 0.05;') |
| 43 | +# Second objective (less priority) |
| 44 | +ampl.eval('let Total_Emissions.objpriority := 1;') |
| 45 | + |
| 46 | +SOLVER='knitro' |
| 47 | +#SOLVER='gurobi' |
| 48 | +#SOLVER='xpress' |
| 49 | + |
| 50 | +max_seconds = 10 |
| 51 | + |
| 52 | +if SOLVER == 'knitro': |
| 53 | + ampl.solve(solver='mp2nl', |
| 54 | + knitro_options='maxtime='+str(max_seconds), |
| 55 | + verbose=True, |
| 56 | + mp2nl_options='solver=knitro obj:multi=2') |
| 57 | +else: |
| 58 | + ampl.solve(solver=SOLVER, |
| 59 | + mp_options='obj:multi=2 outlev=1 timelim='+str(max_seconds), |
| 60 | + verbose=True) |
| 61 | + |
| 62 | +is_committed = ampl.get_data('is_committed') |
| 63 | +produce = ampl.get_data('power_generated') |
| 64 | +startup = ampl.get_data('is_startup') |
| 65 | + |
| 66 | +# Flatten the dataframe values and count 1s and 0s |
| 67 | +values = is_committed.to_pandas().values.flatten() |
| 68 | +num_ones = (values == 1).sum() |
| 69 | +num_zeros = (values == 0).sum() |
| 70 | + |
| 71 | +print(f"Total ON periods (1s): {num_ones}") |
| 72 | +print(f"Total OFF periods (0s): {num_zeros}") |
| 73 | + |
| 74 | +print("=== Objective Values ===") |
| 75 | +total_cost = ampl.obj['Total_Cost'].value() |
| 76 | +total_emissions = ampl.obj['Total_Emissions'].value() |
| 77 | + |
| 78 | +print(f'Total cost: {total_cost:.2f}$') |
| 79 | +print(f'Total emissions: {total_emissions:.2f} tons CO₂') |
| 80 | + |
0 commit comments