import libraries
from besos import eppy_funcs as ef
from besos.eplus_funcs import print_available_outputs
from besos.evaluator import EvaluatorEP
from besos.objectives import MeterReader, clear_outputs
from besos.optimizer import NSGAII
from besos.parameters import FieldSelector, Parameter, RangeDescriptor, wwr
from besos.problem import EPProblem, Problem
Objectives and Constraints¶
Evaluators
support two types of outputs: Objectives and Constraints.
These are both made using the MeterReader
and VariableReader
classes. The only difference is how they are used by the problem.
First we load the EnergyPlus example file, clear any output data and define some parameters.
building = ef.get_building()
clear_outputs(building)
inputs = [
wwr(),
Parameter(
FieldSelector(
class_name="Material",
object_name="Mass NonRes Wall Insulation",
field_name="Thickness",
),
RangeDescriptor(0.01, 0.99),
),
]
Objectives and constraints can be specified in various ways. + The most explicit is by calling the relevant constructor.
objectives = [
MeterReader(
key_name="Electricity:Facility", class_name="Output:Meter", frequency="Hourly"
)
]
EPProblem(outputs=objectives)
EPProblem(outputs=[MeterReader(class_name='Output:Meter', frequency='Hourly', func=<function sum_values at 0x7ff499d59c20>, key_name='Electricity:Facility')], minimize_outputs=[True], converters={'outputs': <class 'besos.objectives.MeterReader'>, 'constraints': <class 'besos.objectives.MeterReader'>})
- The most concise is a list of the
key_names
.
The constructor has defaults, so we can often omit class_name
and
frequency
. A list of key names will be automatically be converted by
EPProblem
. Meters and variables that do not have a frequency
specified will default to any frequency that is already used for that
output, or if none is used yet then they will use Hourly.
objectives = ["Electricity:Facility"]
EPProblem(outputs=objectives)
EPProblem(outputs=[MeterReader(class_name='Output:Meter', func=<function sum_values at 0x7ff499d59c20>, key_name='Electricity:Facility')], minimize_outputs=[True], converters={'outputs': <class 'besos.objectives.MeterReader'>, 'constraints': <class 'besos.objectives.MeterReader'>})
- Using
Problem
If we do not need the output-reading features of meters, we can use
Problem
instead of EPProblem
, and they will be converted to
Objective
objects which act as placeholders. EPProblem
converts
them to Meter:Reader
objects. Either of these conversions can be
overriden using the converters argument.
objectives = ["any", "names", "work"]
Problem(outputs=objectives)
Problem(outputs=[Objective(name='any'), Objective(name='names'), Objective(name='work')], minimize_outputs=[True, True, True], converters={'outputs': <class 'besos.IO_Objects.Objective'>, 'constraints': <class 'besos.IO_Objects.Objective'>})
- Specifying the aggregation function
The func
argument is used define how to aggregate the individual
time series results. By default, all measurements are summed. If we
wanted to instead minimize the variance, we can write our own aggrgation
function. Here we define two electricity objectives, the first summing
the hourly values and the second taking the variance.
def variance(result):
return result.data["Value"].var()
objectives = [
MeterReader("Electricity:Facility", name="Electricity Usage"),
MeterReader("Electricity:Facility", func=variance, name="Electricity Variance"),
]
When we want to specify the direction of optimisation, we can use
minmize_outputs
(defaults to true
for all objectives). Here we
say we want to search for a design that has: + low electricty use
(minimize objective 1 defined above) + high variability of electricity
use (maximize objective 2 defined above) + less than 800 kgCO2
(constraint)
evaluator = EvaluatorEP(
EPProblem(
inputs=inputs,
outputs=objectives,
minimize_outputs=[True, True],
constraints=["CO2:Facility"],
constraint_bounds=["<=800"],
),
building,
out_dir="outputdir",
)
# this cell runs the optimisation
results1 = NSGAII(evaluator, evaluations=1, population_size=10)
results1
Window to Wall Ratio | RangeDescriptor [0.01, 0.99] | Electricity Usage | Electricity Variance | CO2:Facility | violation | pareto-optimal | |
---|---|---|---|---|---|---|---|
0 | 0.314760 | 0.715944 | 1.748825e+09 | 7.021889e+14 | 687.526592 | 0 | False |
1 | 0.138244 | 0.045279 | 1.798338e+09 | 7.313313e+14 | 736.061818 | 0 | False |
2 | 0.810759 | 0.795599 | 1.746240e+09 | 7.001637e+14 | 685.921722 | 0 | True |
3 | 0.238819 | 0.185716 | 1.769438e+09 | 7.108890e+14 | 702.671833 | 0 | False |
4 | 0.791556 | 0.218705 | 1.766439e+09 | 7.095675e+14 | 699.363020 | 0 | False |
5 | 0.014021 | 0.677641 | 1.748894e+09 | 7.018043e+14 | 687.087382 | 0 | False |
6 | 0.554306 | 0.420160 | 1.756721e+09 | 7.047566e+14 | 691.789948 | 0 | False |
7 | 0.405387 | 0.449707 | 1.754975e+09 | 7.040729e+14 | 691.128415 | 0 | False |
8 | 0.368515 | 0.304489 | 1.761271e+09 | 7.068368e+14 | 695.123248 | 0 | False |
9 | 0.198858 | 0.124778 | 1.776774e+09 | 7.152380e+14 | 709.439930 | 0 | False |
results1.describe()
Window to Wall Ratio | RangeDescriptor [0.01, 0.99] | Electricity Usage | Electricity Variance | CO2:Facility | violation | |
---|---|---|---|---|---|---|
count | 10.000000 | 10.000000 | 1.000000e+01 | 1.000000e+01 | 10.000000 | 10.0 |
mean | 0.383522 | 0.393802 | 1.762791e+09 | 7.086849e+14 | 698.611391 | 0.0 |
std | 0.265697 | 0.263603 | 1.591286e+07 | 9.211768e+12 | 15.159307 | 0.0 |
min | 0.014021 | 0.045279 | 1.746240e+09 | 7.001637e+14 | 685.921722 | 0.0 |
25% | 0.208848 | 0.193963 | 1.750415e+09 | 7.026599e+14 | 688.427047 | 0.0 |
50% | 0.341637 | 0.362325 | 1.758996e+09 | 7.057967e+14 | 693.456598 | 0.0 |
75% | 0.517076 | 0.620658 | 1.768688e+09 | 7.105586e+14 | 701.844629 | 0.0 |
max | 0.810759 | 0.795599 | 1.798338e+09 | 7.313313e+14 | 736.061818 | 0.0 |
# this cell runs the optimisation
results2 = NSGAII(evaluator, evaluations=10, population_size=10)
results2
Window to Wall Ratio | RangeDescriptor [0.01, 0.99] | Electricity Usage | Electricity Variance | CO2:Facility | violation | pareto-optimal | |
---|---|---|---|---|---|---|---|
0 | 0.924697 | 0.188585 | 1.769064e+09 | 7.106604e+14 | 702.374777 | 0 | False |
1 | 0.768344 | 0.154239 | 1.772960e+09 | 7.128877e+14 | 706.067332 | 0 | False |
2 | 0.762573 | 0.520389 | 1.753550e+09 | 7.035887e+14 | 689.745844 | 0 | False |
3 | 0.651722 | 0.856427 | 1.744030e+09 | 6.988429e+14 | 685.317104 | 0 | True |
4 | 0.743798 | 0.825692 | 1.745299e+09 | 6.995130e+14 | 685.303142 | 0 | False |
5 | 0.376526 | 0.357123 | 1.758487e+09 | 7.054373e+14 | 694.428224 | 0 | False |
6 | 0.696219 | 0.335195 | 1.759149e+09 | 7.058099e+14 | 695.048911 | 0 | False |
7 | 0.890963 | 0.761254 | 1.746478e+09 | 6.999372e+14 | 685.945833 | 0 | False |
8 | 0.783504 | 0.737510 | 1.746514e+09 | 7.002857e+14 | 686.633076 | 0 | False |
9 | 0.080891 | 0.845379 | 1.744260e+09 | 6.989850e+14 | 685.438736 | 0 | False |
results2.describe()
Window to Wall Ratio | RangeDescriptor [0.01, 0.99] | Electricity Usage | Electricity Variance | CO2:Facility | violation | |
---|---|---|---|---|---|---|
count | 10.000000 | 10.000000 | 1.000000e+01 | 1.000000e+01 | 10.000000 | 10.0 |
mean | 0.667924 | 0.558179 | 1.753979e+09 | 7.035948e+14 | 691.630298 | 0.0 |
std | 0.254825 | 0.280424 | 1.062397e+07 | 5.048668e+12 | 7.619043 | 0.0 |
min | 0.080891 | 0.154239 | 1.744030e+09 | 6.988429e+14 | 685.303142 | 0.0 |
25% | 0.662846 | 0.340677 | 1.745594e+09 | 6.996191e+14 | 685.565511 | 0.0 |
50% | 0.753186 | 0.628949 | 1.750032e+09 | 7.019372e+14 | 688.189460 | 0.0 |
75% | 0.779714 | 0.809582 | 1.758983e+09 | 7.057168e+14 | 694.893740 | 0.0 |
max | 0.924697 | 0.856427 | 1.772960e+09 | 7.128877e+14 | 706.067332 | 0.0 |
Get available objectives¶
The user can use print_available_outputs to print out the available objectives for this building
building = ef.get_building(mode="idf")
print_available_outputs(building, name="facility", frequency="monthly")
['Electricity:Facility', 'Monthly']
['Gas:Facility', 'Monthly']
['CO2:Facility', 'Monthly']
['CO:Facility', 'Monthly']
['CH4:Facility', 'Monthly']
['NOx:Facility', 'Monthly']
['N2O:Facility', 'Monthly']
['SO2:Facility', 'Monthly']
['PM:Facility', 'Monthly']
['PM10:Facility', 'Monthly']
['PM2.5:Facility', 'Monthly']
['NH3:Facility', 'Monthly']
['NMVOC:Facility', 'Monthly']
['Hg:Facility', 'Monthly']
['Pb:Facility', 'Monthly']
['WaterEnvironmentalFactors:Facility', 'Monthly']
['Nuclear High:Facility', 'Monthly']
['Nuclear Low:Facility', 'Monthly']
['Carbon Equivalent:Facility', 'Monthly']