-
Notifications
You must be signed in to change notification settings - Fork 4
optimize.py
optimize.py contains a single class called optimize which is used to generate an optimization object. The main methods of this class are described below.
Typically, the following lines of code are used to initiate, and execute the optimization, and retrieve results for further study.
from GBSOptimizer.optimize import optimize
# Create optimize object and initialize.
myOptimizationObject = optimize(<myOptimizationProjectName>, []) # empty second argument is place holder for later addition of other args
# Execute optimization
myOptimizationObject.doOptimization()
# Retrieve log of results. This can be analyzed to determine which iteration yielded the best result, and what the power and energy values for the EES were.
fitnessLog = myOptimizationLog.fl
__init__ is the constructor for the optimizer object and contains vital configuration and initial configurations tasks. An optimization object is created by calling myOptimizationObject = optimize('myProjectName', inputArgs), where myProjectName has to be identical to the project folder name in the GBSProjects folder, and inputArgs is a spare input argument to pass additional information as needed. It currently is unused, other than that it's contents is written to the global variable self.inputArgs which can be passed on and then unravelled in interfacing methods.
The __init__ method sets up key project parameters by reading optimizerConfig<myProjectName>.xml, which is required to be located in the ../../GBSProjects/<myProjectName>/InputData/Setup/ folder and needs to contain all tag described in optimizerConfig.xml. Based on this configuration, the base case is loaded. That is, a simulation run without energy storage online. This case is required to be available in <myProjectName>/InputData/TimeSeriesData/ProcessedData/.
From the base case, and based on the configuration of self.boundaryMethod optimization boundaries (min and max power and energy values for the energy storage system to consider) are determined by calling the interface in getOptimizationBoundaries.py.
Next, shorter time-series are calculated based on the configuration in self.dataReductionMethod by calling the getDataSubsets interface. The objective of this reduction is to work with shorter time series that provide a proxy for the overall dataset, but allow for quicker stepping through the iterations.
Lastly, __init__ calculates the fitness of the base case based on the method designated in self.optimizationObjective. The value, stored in self.basePerformance can be used as a benchmark for further optimization.
Note: it is not recommended to use self.basePerformance as direct benchmark for the results of the optimization run on shorter time-series. While trends relative to the base case may be discernible, absolute values may not be comparable. In the future, it would be recommended to calculate a proxy base case performance using the shorter time-series calculated in getDataSubsets and available in self.abbrevDatasets and self.abbrevDataWeights.
The doOptimization method has to be called to dispatch an optimization run. doOptimization itself is an interface method, that reads the value in self.searchMethod and dispatches the desired actual optimization method.
Currently only the an adapted hill climber method is implemented. Other methods should be considered while keeping in mind the significant run-time required per simulation (between 2 and 4 minutes per week of real-time at 1 Sample/second).
The hill climbing algorithm uses the history of fitness values, i.e., the renewable power penetration or fuel utilization, of its iterations to determine the direction in which to search for the next pairing of energy and power capacities. It does this until either, it has not found a better pairing for a set number of iterations (convergenceRepeatNum) or until a maximum number of iterations (maxIterNum) is reached. The history of the iterations is written to the object-wide variable fl (for fitnessLog) that can be accessed by the code that created the optimize object.