0

I am trying to solve a supply chain problem using optimisation and linear programming.

I am not a optimisation expert and I am having trouble formulating a solution using variables, constraints and goals.

It is only a proof of concept, and I have tried Microsoft Solver Foundation and Optano to create a demonstration.

I need to deliver products to customers. I deliver on fixed days. I need to make sure the customer has minimum agreed stock level per day on their shelves.

The customer does a stock check once a week, and tells me the starting stock level for each product for the week. The average daily usage for each product is a known parameter.

So far, so good. I have a solution for this. This next requirement is where I am stuck.

For logistical reasons, the supplier would prefer each delivery to have roughly the same total quantity of products.

The stock level can drop below the usual agreed stock level on exceptional days. As a minimum it must be the average daily usage and by the end of the week the total amount delivered must be the agreed stock level for the week.

I have tried a number of experiments based on articles I have read and examples I have explored. I have not found a way to formulate the constraints and objectives to solve the requirement to equally distribute the quantities delivered each day.

I imagine this is a fairly common supply chain problem, I would really (really) appreciate some guidance?

UPDATE: This is the basic implementation using Microsoft Solver Foundation (solver services API). I am not tied to MSF. It calculates the quantity delivered each day and the amount of stock expected on the shelf at the end of each day.

SolverContext context = SolverContext.GetContext();
Model model = context.CreateModel();

// these are the quantities to be delivered each day
Decision qMon = new Decision(Domain.IntegerNonnegative, "monQuantity");
Decision qTue = new Decision(Domain.IntegerNonnegative, "tueQuantity");
Decision qWed = new Decision(Domain.IntegerNonnegative, "wedQuantity");
Decision qThu = new Decision(Domain.IntegerNonnegative, "thuQuantity");
Decision qFri = new Decision(Domain.IntegerNonnegative, "friQuantity");
Decision qSat = new Decision(Domain.IntegerNonnegative, "satQuantity");
Decision qSun = new Decision(Domain.IntegerNonnegative, "sunQuantity");

// these are the expected quantities to be found on the shelf
//at the end of each day
Decision sMon = new Decision(Domain.IntegerNonnegative, "monStock");
Decision sTue = new Decision(Domain.IntegerNonnegative, "tueStock");
Decision sWed = new Decision(Domain.IntegerNonnegative, "wedStock");
Decision sThu = new Decision(Domain.IntegerNonnegative, "thuStock");
Decision sFri = new Decision(Domain.IntegerNonnegative, "friStock");
Decision sSat = new Decision(Domain.IntegerNonnegative, "satStock");
Decision sSun = new Decision(Domain.IntegerNonnegative, "sunStock");
model.AddDecisions(qMon, qTue, qWed, qThu, qFri, qSat, qSun);
model.AddDecisions(sMon, sTue, sWed, sThu, sFri, sSat, sSun);

// this is the quantity from the stock count 
var initialCount = 0;
// this is the average quantity used per day
var averageUsage = 10;

// the stock level must be greater than agreed minimum (150)
model.AddConstraints("stock",
    150 <= sMon, 150 <= sTue,
    150 <= sWed, 150 <= sThu,
    150 <= sFri, 150 <= sSat,
    150 <= sSun);

// apply constraint to calculate the stock left on the shelf
// use supply/demand formula
// a special rule for monday using the inital stock take
// the remaining days rely on stock left over from previous day 
model.AddConstraint("initialStock",
    sMon + averageUsage == qMon + initialCount);

model.AddConstraints("restStock",
    sTue + averageUsage == qTue + sMon,
    sWed + averageUsage == qWed + sTue,
    sThu + averageUsage == qThu + sWed,
    sFri + averageUsage == qFri + sThu,
    sSat + averageUsage == qSat + sFri,
    sSun + averageUsage == qSun + sSat
);

model.AddGoal("minimiseDeliveries", 
    GoalKind.Minimize, 
    qMon + qTue + qWed + qThu + qFri + qSat + qSun);

Solution solution = context.Solve(new SimplexDirective());

// a couple of checks that we found an optimal solution
Assert.Equal(SolverQuality.Optimal, solution.Quality);

Assert.True(sSun.GetDouble() >= 150);

I hope this gives more context to my problem.

David
  • 13
  • 2
  • 1
    Too broad! There is only text, no mathematical-model (of your partially solved tasked). It can't be answered like that. We don't even know what quantity of products mean in your model (so recommendations like: minimize norm of diffs to mean (not LP) are just guessings). – sascha Nov 19 '17 at 13:43
  • Sorry to be too general. Novice mistake, not mathematical. Quantity of product is the number of containers containing each product. It doesn't have to be a LP solution, I have been reading about minimizing norm of diffs but wasn't sure how to go about that using Microsoft Solver Foundation. I suggested LP because I am a novice and am trying to keep it as simple if possible. – David Nov 19 '17 at 15:02

1 Answers1

1

Some notes:

  • Microsoft Solver Foundation has been discontinued years ago. If this is more than a one-off model, you may want to look at another tool.
  • Typically we use indexing for a number of related variables (like an array). A whole bunch of scalar variables and equations can become tedious very quickly.
  • Penalizing deviations from a single value can be modeled with slacks. E.g. BaselineDeliver + Over[t] - Under[t] (with Over[t],Under[t]>=0). Then add a term in the objective penalty * sum (Over[t]+Under[t]).
  • It often helps to write down the mathematical optimization model before starting coding. Sometimes starting with a piece of paper instead of a computer screen is a good idea.
Erwin Kalvelagen
  • 15,677
  • 2
  • 14
  • 39
  • Thanks Erwin for the tips. I understand about MSF. I will update my algorithm and give it a go. What alternative to MSF would you recommend that is .Net c# based (and free/open source)? – David Nov 20 '17 at 10:20
  • MSF was never free or open source (except for a "demo" version with limited number of variables and constraints). Many of the commercial LP/MIP solvers have .NET interfaces (some have free "demo" or "community" versions). – Erwin Kalvelagen Nov 20 '17 at 14:12
  • Hi Erwin. Sorry for being a dumbo, but I am struggling to make this work. Can you please expand on what you mean by BaselineDeliver + Over[t] - Under[t]. I understand (I think) that this should be an equality, so what would be on the right hand side on the equation to turn it into a constraint? – David Nov 20 '17 at 14:26
  • `q[t] = BaselineDeliver + Over[t] - Under[t]` where `q[t]` is quantity delivered at day `t`. I was hoping that was obvious. – Erwin Kalvelagen Nov 20 '17 at 14:33
  • Sorry Erwin, when you are dealing with a dumbo, nothing is obvious. You have really given me what I need though, and I really appreciate your help (and patience)!! – David Nov 20 '17 at 14:51