0

I'm currently working on trying to optimise a battery schedule system. The schedule is created once a day for the entire day with a half hour granularity, this means i need to create a schedule for the 48 periods. The battery can operate in 3 different modes, meaning I have a search space of 3^48. The schedule is optimised to maximise the savings made by the battery. I have a programme that can evaluate the saving of a current schedule, and savings is what i'm trying to optimise for.

Can someone point me in the right direction of what algorithm or process i should use to solve this problem? I know brut force method wont work due to the huge search space. An option i've started looking into is Genetic Algorithms to try and find a local maximum and seemingly ignore the huge search space, but I don't want to spend a week implementing something that will end up not working.

It's worth noting that I can create logic that can get a decent schedule but it's very hard to create a schedule through logic that could beat or get close to manual schedule building. This is why i thought GA could be a good approach as i can give it a good starting point.

Optimisation is possible because our users have varying electricity costs throughout the day, and all users have solar generation so we want to take advantage of this free power. My evaluation programme takes in the forecasted power generation, forecasted solar generation, electricity prices, and battery schedule.

battery modes:

  • charge: charges the battery from grid or excess solar
  • discharge: discharges the battery to meet user load
  • normal: if there is excess solar charge, if there is user load discharge

Example of schedules:

first schedule:

[{"state":"charge","start":"00:00:00","end":"00:30:00"},
{"state":"disable","start":"00:30:00","end":"01:30:00"},
{"state":"charge","start":"01:30:00","end":"02:00:00"},
{"state":"normal","start":"02:00:00","end":"05:00:00"},
{"state":"charge","start":"05:00:00","end":"06:00:00"},
{"state":"normal","start":"06:00:00","end":"10:00:00"},
{"state":"charge","start":"10:00:00","end":"13:00:00"},
{"state":"normal","start":"13:00:00","end":"22:00:00"}]
savings: $10.2

final schedule:

[{"state":"disable","start":"00:00:00","end":"05:30:00"},
{"state":"charge","start":"05:30:00","end":"07:30:00"},
{"state":"normal","start":"07:30:00","end":"17:00:00"},
{"state":"charge","start":"17:00:00","end":"18:00:00"},
{"state":"normal","start":"18:00:00","end":"22:00:00"},
{"state":"disable","start":"22:00:00","end":"00:00:00"}]

savings: $15.9

I've tried brut force search but due to the search space size this isn't practical.

  • I'd consider writing this as a Linear Program, likely a MILP (Mixed Integer LP) because you will likely have integer values. If you've never done any LP work, there will be a learning curve and you might need a textbook or minimally some online tutorials... there are several. Similar concepts to constraint modeling suggested in other answer. – AirSquid Jun 09 '23 at 14:42
  • Here are some similar questions for knowledge/inspiration: https://stackoverflow.com/questions/71494297/python-pulp-linear-optimisation-for-off-grid-pv-and-battery-system/71501812#71501812 https://stackoverflow.com/questions/73610201/pyomo-battery-optimisation-if-condition/73612192#73612192 – AirSquid Jun 09 '23 at 14:42

1 Answers1

0

I would recommend you to play with constraint modeling approach, e.g. take a look into https://www.minizinc.org/.

You could try encoding your problem as a mixed-integer task. First, you introduce a variable for each point of time that correspond to one of 3 states. Second, you introduce vector of costs to have a system in a particular state, e.g. having a battery at NORM costs 0.50 cents, at DISABLE it's 0.0 (I worked with minizinc AGES ago, so consider the following as a pseudo-code, not as the exact approach):

var 0..1: t0_disabled;
var 0..1: t0_norm;
var 0..1: t0_charge;

var 0..1: t1_disabled;
# ...

float: cost_norm = 0.5;
float: cost_disabled = 0.0;
# ...

Then, you might add constraints, for example, prohibit moving from DISABLE state directly to CHARGE, if it makes any sense. One important constraint could be target charge level or something like that - otherwise keeping a battery disabled all the time is optimal, since such solution has 0 cost.

Define your optimization objective:

solve minimize (t0_disabled * cost_disabled) + (t0_norm * ...);

Later you could model more complex cost model with, for example, different costs for switching between states: DISABLE -> NORM might be more expensive compared to CHARGE -> NORM.

And that should be it! For details take a look here: https://www.minizinc.org/doc-2.7.4/en/part_1_overview.html

On top of that, if you would manage to introduce significant amount of constraints coming for your expert knowledge, you could switch from solve minimize to solve satisfy. The benefit is faster solving time (no guarantees on that, but it often IS the case), however, it would return any feasible solution and it might be not globally optimal, just good enough for you.

CaptainTrunky
  • 1,562
  • 2
  • 15
  • 23