You’re probably a researcher or grad student interested in power system optimization.
But where Minpower really shines is when you want to add a constraint like load shedding, or even add a model of an electric vehicle aggregator. Or run a wind farm profitability study where UC is just another procedure that you need in a long chain of analysis. When you want to do research.
Because Minpower is written in Python, the code is easy to read and write. Because Minpower is open source you can use models other people have written and create your own.
Minpower doesn’t have a true API - it has been developed primarily as a research tool. But that doesn’t mean you can’t take only the pieces you need out of it. You can import any function (or class) into your own script, e.g.:from minpower.solve import create_problem
and then call it, e.g.:create_problem(power_system=my_ERCOT_iso_model, times=year_2010_hourly_times)
Checking out how Minpower’s testing utilities work is one way to see how you can programmatically create/change/solve/test problems.
Constraints can be added to existing power system components with a very simple syntax. Within the create_constraints() method (e.g. create_constraints()), simply call add_constraint(). This method takes a name for the constraint, a time the constraint is in reference to (if applicable), and an expression. As an example, the maximum power limit is set for a generator by
class Generator(OptimizationObject): #other methods here def create_constraints(self,times): for time in times: #add other constraints here expression = self.power(time)<=self.status(time)*self.Pmax self.add_constraint('max gen power', time, expression) return self.all_constraints(times)
The power system components in Minpower are object oriented models and are also all Check out :mod:`powersystems for examples of existing models. To define your own, simply inherit the OptimizationObject class and follow its template:
- __init__() creates a new object of that class and sets its parameters
- init_optimization() is called within __init__() and sets up an empty structure for optimization variables, constraints, and objective components
- create_variables() sets up the optimization variables
- create_constraints() sets up the optimization constraints
- create_objective() defines a objective cost component (if any)
- __str__() defines a unique string representing the object
Below is an example of the basic structure for an EV aggregator model:
class EV_aggregator(OptimizationObject): """an example model of an electric vehicle aggregator""" def __init__( self, number_cars=10, per_car_capacity=50, index=None ): """create a new aggregator object""" update_attributes(self,locals()) #load in inputs self.init_optimization() def create_variables(times): """create the aggregator's optimization variables for each time here""" return self.all_variables(times) def create_objective(time): """define the aggregator's cost function here""" return self.objective def create_constraints(): """define the aggregator's optimization constraints here""" return self.all_constraint(times) #some more methods for the aggregator def __str__(self): """a unique identifier for the aggregator""" return 'agg_'+self.index