So last week I wrote about using dynamic optimization to understand how we should optimally respond to the global covid-19 crisis. This week, I wanted to take a step back and talk about the python package that made that all possible. It is a nice little package called gekko. As an aside, make sure to check out gekko’s documentation. I haven’t been using gekko for very long; I just discovered it, but wow, what a useful package. However, Dynamic Optimization is something that I have known about for some time. And in all honesty, I hated the subject because solving problems was always a pain. You either had to solve analytically, or take some time to do some serious programming handstands to solve it numerically. Fortunately, gekko looks like the bomb-diggity when it comes to solving numerically, (define the model and press Go! ).
I was able to code up a problem in a little less than an hour and start playing with it. I even thought, hey, this cute little model might be a fun way to calculate the value of a statistical life from the current pandemic. Let’s lay that aside for a moment, though. I really want to focus on what this tool can do for you and your business.
The question that I want to consider for today is: “It was a cute way to play with an epidemiological model, what can dynamic optimization do for me and my business?”
It turns out, quite a lot actually. Let’s turn our attention to the entire idea of goals.
Every business has goals. Usually they are expressed in terms of some KPI at some given date. Have you ever thought about how do you plan to reach that goal by that date?
I think about that all the time. I want a plan. A goal is meaningless without the plan on how you are going to achieve it. At best without a plan it is merely an aspiration. At worst, it is ammunition to destroy you. So I think that it is important to start talking about what does a goal for a business look like, and how can dynamic optimization help you to develop a plan to achieve that goal.
So let me give you a quick detour. This program will show you how to make a plan that if executed, will move a cart with an inverted pendulum from one location to another. Here is the solution that it found:
This is a really cool example of how to use a program to solve dynamic optimization problems can work in a really intuitive visualization. I have to move from the start location to the objective location without dropping the ball within 8 seconds. In essence, you have a goal. Your goal is likely more complicated than this simple physics example.
However, if you can model your business goals you can use dynamic optimization to give you a plan on how to achieve that goal.
In fact, when I read The Martian, the character Rich Purnell was awarded the title of “steely eyed missle man” by the crew for essentially solving a dynamic optimization problem in that book. I won’t spoil it if you haven’t read the book or seen the movie. (The book was better). The goal was to get to Mars and back on the slimmest of margins for error to rescue the protagonist. That is obviously more complicated than our simple cart and pole problem, but that is the main idea. You can plan your trajectory.
So it all starts with the question, can model your trajectory for your goal. If you can model your trajectory, you can use dynamic optimization to figure out how to achieve your goals. I won’t go too deeply, here, but there are also methods for accounting for risk and uncertainty into these models as well. However, we will only look in the easier world of the deterministic goals.
Production Targets using Dynamic Optimization
So I’m going to talk about a goal which is a production target. Hopefully, by going concrete here, I don’t lose anyone who thinks that this won’t apply. This could be any metric that you care about. It could be links to a page, visits to a website, or it could be number of sales, etc. For concreteness, I am going with a production target goal. Remember, as long as you can model the dynamics of the goal, you can use this method to chart your path forward.
Let’s say that you have the goal of manufacturing some product, and that you need to deliver a certain number of products per time period, e.g. per month. The goal is to minimize the total cost of producing a certain number of your product. Essentially, the idea is to hit a production target in each time period, and keep costs as low as possible. This is kind of a contrived example. Following the same logic as my post last week, I won’t build out the mathematical model. I will however drop a ton of code.
import matplotlib.animation as animation import numpy as np from gekko import GEKKO import matplotlib.pyplot as plt %matplotlib inline m = GEKKO(remote=False) m.solver_options = ['max_iter 3000'] #The amount of time we will give to the process m.time = np.linspace(0,12,13) #Set Parameter Values A = m.Param(value = 5) #Technology Level beta = m.Param(value=0.5) #rate of technical substitution gamma = m.Param(value=20) #contractual obligation Pk = m.Param(value=100) #rental rate of capital Pl = m.Param(value=200) #wage rate t = m.Param(value=m.time) #time for discounting #Control variables L = m.CV(value=0,lb=0,ub=100) K = m.CV(value=0,lb=0,ub=100) #State variables Q = m.SV(value=0) #Defining the State Space Model m.Equation(Q.dt() == A*(K**beta)(L**(1-beta))-gamma) m.Equation(Q>=0) #Define the objective function m.Obj((Pk*K+Pl*L)m.exp(-(0.07/12)t)) m.fix(Q,pos=12,val=100000) m.options.IMODE = 6 m.solve()
So if you run that block of code, what you will end up with is this really cool optimized production target model. The basic idea is to say how many of the product should I make per time period to minimize my cost.
It turns out that the answer is to just produce exactly what you need to hit your production target. You have absolutely no incentive to produce more in any time period, and you simply can’t produce less than what you need to produce. So say, if you are contractually bound to produce a certain number of rolls of toilet paper per day/week/month etc. The rational thing to do is to just produce what you have to. So if the demand for toilet paper rolls explodes all of a sudden, because some stupid virus causes people to stay home. And so they can’t use the toilet at work, and because of that households start demanding about 40% more toilet paper there is a persistent shortage in the supply. Errm, and so yeah, I’m a little bit bitter about the current situation.
Honestly, it probably doesn’t have anything to do with hoarders though, so there is that.
A more real example
I did want to talk a little bit about how you can build a more realistic version of this production target model. Suppose that you had some sort of backlog at work. And your goal was to reduce that backlog. This was the case for me last year. Ultimately, we built a robot to take care of the backlog, but suppose for a moment that is not an option for you.
Your bonus goal is to reduce the backlog from 3000 units to 1500 units. The problem is that new work arrives all the time for you. In fact, you could assume that the work arrives at a near constant rate, let’s assume that it arrives at a rate of about 100 units of work per day.
You can work up to 8 hours a day, because let’s say you are an hourly employee that management will have a really hard time with you working overtime. So the question becomes what does my work schedule look like to hit my goal exactly?
Here is another super simple model to tell you.
import matplotlib.animation as animation import numpy as np from gekko import GEKKO import matplotlib.pyplot as plt %matplotlib inline m = GEKKO() m.solver_options = ['max_iter 3000'] #The amount of time we will give to the process m.time = np.linspace(0,260,261) #Set Parameter Values beta = m.Param(value=100) #rate of new work gamma = m.Param(value=16) #hourly rate of production t = m.Param(value=m.time) #time for discounting #Control variables L = m.CV(value=0,lb=0,ub=8) #State variables Q = m.SV(value=3000) #Defining the State Space Model m.Equation(Q.dt() == beta-gamma*L) m.Equation(Q>=0) #Define the objective function m.Obj((Q))#m.exp(-(0.07/365)t)) m.fix(Q,pos=260,val=1500) m.options.IMODE = 6 m.solve()
And if you print your work schedule that this produces you get the following chart.
This optimal work schedule seems to make sense intuitively, you work at maximum power until the backlog is taken care of. Literally, you take care of it. It is gone. You can do that with these parameters. Then you maintain at no backlog for the rest of the year. Take a two week vacation, and boom, you meet your goal.
But the operative phrase is “With these parameters”. If you tweak the parameters of this problem it is really easy to get to a point that is infeasible. That would be the power of these methods, you can go back to the management team and say that the goal they have set for you is infeasible, and here is the math to prove it.
This is not particularly helpful with this problem. You can use linear trends to figure out whether or not this example is feasible. With a slightly more complicated function you might not be able to easily tell whether it is feasible. You will seem like a genius, if you can connect to some important metric like cost as your objective function.