Gluglug is the big biofuel company in DS City. They want to optimize their production. You have known how to do that since your very first linear programming class. Or have you?
You sit across from a Gluglug manager in worn-out, cuffed pants. While you are contemplating what life choices ended you up sitting in this dusty office that, contrary to the manager's pants, has seen better days, you vaguely take in his words.
"Gluglug produces two types of ethanol blends, E-Standard (x1) and E-Premium (x2), sold in tons. The profit is $250 per ton for E-Standard and $300 per ton for E-Premium.
Our production is limited by three resources:
- Labor Hours: A total of 2,500 hours per month are available for fermentation and distillation. E-Standard requires 24 minutes per ton. E-Premium is made with a new organic catalyst. On average, it requires 36 minutes per ton to make E-Premium.
- Corn Supply: We receive 14,000 tons of corn each month. E-Standard requires 3 tons of corn for every ton of fuel, while E-Premium requires 2.5 tons.
- Carrier Capacity: On average, there are enough fuel trucks to transport 6,350 cubic meters of product away from the refinery. E-Standard and E-Premium both require 1.27 cubic meters per ton."
You quickly make out that these folks make more than ten million per year in profit. You are thinking, "I wonder how much they are paying their managers. Can he really not afford new pants?"
He leans in closer: "We need you to determine the production quantities of E-Standard and E-Premium that maximize our total profit!" His smile shows the deepest level of confidence in you.
Of course, the very first problem your OR prof ever showed you was a linear program (LP) that looked exactly like this. Sometimes life can be so easy.

But of course, whenever life is easy, already in the next moment it isn't.
"The thing is, though, when we produce E-Premium, that catalyst I mentioned? Well, it does not always work the same. On average, we need 36 minutes, but if we use this stuff as is, then the actual time varies with a gamma distribution. Standard deviation is also 36 minutes. I measured it myself!"
The words "gamma distribution" coming from a man in cuffed pants are almost too much to handle.
"Now, we figured out that there is another component that we can add to this catalyst that will reduce its variance in time needed to ferment E-Premium. The thing is, preprocessing the catalyst takes a long time, so we have to do that upfront, before we know the catalyst's efficiency. Only when we start production do we know how much time it will actually take. Then it is just a matter of solving a simple LP."
You look at Mr. Cuffed with wide eyes. Did he just say 'LP'?
"You didn't think it was that easy, did you?!" His elbow in your ribs, you manage just a faint "No, of course not."
"We figured out that if we add this component, it lowers the deviation from the expected 36 minutes proportionally to how much we use. If we add ten tons of this component to the catalyst, then there is no more variance. If we add nothing, the standard deviation is 36 minutes. And if we use, say, five tons, then the standard deviation is 18 minutes. We do not want to add too much; this component costs $470 per ton. That is a lot of money."
His finger in the air, you think, "Yeah, for $470 you can buy twenty more pairs of those pants. Or three nice ones."
He goes on: "Also, it is not entirely clear if we should use it at all. After all, this component also makes a super-efficient catalyst a bit less efficient. It really only lowers the variance."
He smiles. "You young fellows, you are all so smart with all the AI and stuff you come up with." It is a good thing that he cannot read your mind right now. And that is not just because of your opinion of his pants.
"Oh, one more thing, before you go to work. The fuel trucks do not belong to us. So we rely on our carriers to transport our finished product. Their capacity varies normally with a standard deviation of 20%, or 1,270 cubic meters. At least we know how much they can transport before we start production. Now, we can enter a contract that will guarantee us a capacity of at least 5,200 cubic meters. But that would cost us $30,000 per month just for the guarantee."
A hard slap on your shoulders jolts you from your thoughts. "Now to work! I will check back in an hour to see what you come up with. Now I have some fermenting to do. I am an oil man, you know."
As the door falls shut behind him, you sort your thoughts. The optimal choices for my production levels will fall out of an LP once we observe how fast the catalyst works and we know what carrier capacity we have. Both of these values will be affected by our decisions of how much of that component we buy and if we go for the carrier capacity guarantee or not.


A formulation, at least. But is it the right one? And how do you solve this? What would you recommend Gluglug to do? How much of that variance-dampening component should they buy? And should they go for the carrier capacity guarantee?

If you could find a good expected-case solution for Gluglug, do not forget to assess risk.

The recommendation is for Gluglug to purchase the carrier guarantee and 7.13 tons of that variance-dampening component. The final production quantities then depend on the realized efficiency of the catalyst and the availability of trucks. On average, we expect to produce 1,315 tons of E-Standard and 3,474 tons of E-Premium for an expected profit of $1.3375 million per month.
This recommendation will likely surprise, as it is not the course of action that maximizes expected profits. To do that, we should pass on the carrier guarantee and only buy 3.91 tons of the variance-dampening component. This would result in $1.3473 million profit.
But it would also mean that our average profit in the bottom 5% of scenarios drops dramatically by almost half a million, down to $860,431. Our proposed solution, in contrast, has a CVaR-5% of $1.0839 million. The picture below illustrates the probability densities for the two different solutions.

So for about $10K we can buy insurance that we will make $150K more on average under adverse conditions. Well worth it, we think, especially as Gluglug's managers are so very frugal.
The Seeker model below solves this problem.
env = skr.Env("license.sio", stochastic=True)
env.set_stochastic_parameters(100000, 0.85)
# decision variables
x = [env.continuous(0,10), env.categorical(0,1)]
profit = env.convert([250, 300])
# nested stochastic LP
matrix = env.convert([[0.4,0.6],
[3,2.5],
[1.27,1.27]])
matrix[0][1] = 0.6 - ( 0.6 - env.gamma(0.6,1,100)) * (10 - x[0])/10
ressources = env.convert([0,2500, 0, 14000, 0, 6350])
h = ressources[5]+ressources[5]*env.normal(0,0.2)
ressources[5] = env.max([h, x[1]*5200])
variable_bounds = env.convert([0, 5000, 0, 5000])
LP = env.lp(profit,variable_bounds,ressources,matrix,True)
quality = LP.get_objective()
exp_quality = env.aggregate_mean(quality)
# outer Seeker objective
obj = -470*x[0] - 30000*x[1] + quality
exp_obj = env.aggregate_mean(obj)
cvar = env.aggregate_cvar(obj, 0.05, False)
# maximize expected profit
env.set_report(1, [exp_obj, exp_quality, x[0], x[1], cvar],
["total", "quality", "damper", "limit", "cvar"])
env.maximize(exp_obj, 30)
# reoptimize for risk
env.multi_objective([exp_obj, cvar], [1300000, 850000],
[1340000, 1100000], [True, True], 30)
# report
print("final profit", exp_obj.get_value())
print(env.get_number_evaluations())
env.end()
