<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged pulp</title>
<link>https://coderlegion.com/tag/pulp</link>
<description>Powered by Question2Answer</description>
<item>
<title>S&amp;OP Engineering IV: Scaling to Enterprise (Multi-SKU &amp; Bottlenecks)</title>
<link>https://coderlegion.com/14033/sop-engineering-iv-scaling-to-enterprise-multi-sku-bottlenecks</link>
<description>&lt;p&gt;Your MVP works. One product, one model, one perfect plan. Congratulations: you just solved the easiest problem in Supply Chain.&lt;/p&gt;
&lt;p&gt;Now add 3 products sharing the same factory. Product A needs 14,000 units in July. Product C needs 13,000 that same month. Your factory produces 15,000. &lt;strong&gt;Who gets shorted?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If your answer is &quot;we'll figure it out in Thursday's meeting,&quot; your company has an engineering problem, not a management one.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Executive Summary:&lt;/strong&gt; In chapters &lt;a rel=&quot;nofollow&quot; href=&quot;https://datalaria.com/en/posts/sop_engineering-data-hygiene/&quot;&gt;1&lt;/a&gt;, &lt;a rel=&quot;nofollow&quot; href=&quot;https://datalaria.com/en/posts/sop-engineering-part2-forecasting/&quot;&gt;2&lt;/a&gt; and &lt;a rel=&quot;nofollow&quot; href=&quot;https://datalaria.com/en/posts/sop-engineering-part3-optimization/&quot;&gt;3&lt;/a&gt; we built a working MVP for a single product. In this Chapter 4, we break it. We inject 3 years of history with 3 SKUs of radically different demand profiles (Core, Intermittent, and Seasonal), parallelize Prophet model training with MLOps, and build a unified Linear Programming model where products &lt;em&gt;compete mathematically&lt;/em&gt; for limited factory capacity. Welcome to Theory of Constraints executed in code.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;the-fatal-error-optimizing-in-silos&quot;&gt;The Fatal Error: Optimizing in Silos&lt;/h3&gt;
&lt;p&gt;The biggest sin in Supply Chain Planning isn't using dirty data (we fixed that in &lt;a rel=&quot;nofollow&quot; href=&quot;https://datalaria.com/en/posts/sop_engineering-data-hygiene/&quot;&gt;Chapter 1&lt;/a&gt;). It's &lt;strong&gt;optimizing each product as if the factory were infinite&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Imagine three product managers, each with their optimized Excel:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SKU-001 Manager (Core): &quot;I need to produce 6,000/month. Already calculated.&quot;&lt;/li&gt;
&lt;li&gt;SKU-002 Manager (Spare Part): &quot;I only need 15/month. No big deal.&quot;&lt;/li&gt;
&lt;li&gt;SKU-003 Manager (Seasonal): &quot;In July I need 14,000. Non-negotiable.&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sum: 6,000 + 15 + 14,000 = &lt;strong&gt;20,015 units&lt;/strong&gt;. Your factory produces 15,000. Each manager is right individually. Collectively, it's a collapse.&lt;/p&gt;
&lt;p&gt;This is what Eli Goldratt described in &lt;em&gt;The Goal&lt;/em&gt; as &lt;strong&gt;Theory of Constraints&lt;/strong&gt;: the system is not optimized by summing local optima. It's optimized by identifying the bottleneck and letting mathematics allocate the resources.&lt;/p&gt;
&lt;h3 id=&quot;stress-test-the-3-profiles-that-break-your-mvp&quot;&gt;Stress-Test: The 3 Profiles That Break Your MVP&lt;/h3&gt;
&lt;p&gt;To validate the Enterprise architecture, we generated a 3-year dataset (2023-2025) with three SKUs designed to break any naïve model:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;SKU &lt;/th&gt;&lt;th&gt;Profile &lt;/th&gt;&lt;th&gt;Average Demand &lt;/th&gt;&lt;th&gt;Trap&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;SKU-001&lt;/strong&gt; &lt;/td&gt;&lt;td&gt;Core Product &lt;/td&gt;&lt;td&gt;~200/day &lt;/td&gt;&lt;td&gt;High variance + 3x Black Friday&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;SKU-002&lt;/strong&gt; &lt;/td&gt;&lt;td&gt;Intermittent Spare &lt;/td&gt;&lt;td&gt;~0.6/day &lt;/td&gt;&lt;td&gt;70% zero-demand days&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;strong&gt;SKU-003&lt;/strong&gt; &lt;/td&gt;&lt;td&gt;Seasonal Summer &lt;/td&gt;&lt;td&gt;~250/day &lt;/td&gt;&lt;td&gt;500+ peaks in July, zero in winter&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;We injected real ERP noise: outliers (x50), corrupted dates, nulls, negatives. This isn't a toy tutorial. It's what comes out of a production SAP on any given Tuesday.&lt;/p&gt;
&lt;h3 id=&quot;mlops-parallelizing-the-forecasting&quot;&gt;MLOps: Parallelizing the Forecasting&lt;/h3&gt;
&lt;p&gt;With a single product, training Prophet takes 2 seconds. With 50 SKUs in a &lt;code&gt;for&lt;/code&gt; loop, you wait 100 seconds. With 500, you go home.&lt;/p&gt;
&lt;p&gt;The solution is the same one production pipelines use: &lt;strong&gt;parallelization&lt;/strong&gt;. Each SKU is statistically independent, so each model can train on its own thread:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from concurrent.futures import ThreadPoolExecutor

def process_sku(sku, df_sku, months, country_code):
    &quot;&quot;&quot;Worker: trains Prophet for one SKU.&quot;&quot;&quot;
    predictor = ProphetPredictor(df_sku, sku_name=sku)
    predictor.preprocess_daily_aggregation()
    predictor.train_model(country_code=country_code)
    return predictor.generate_forecast(months=months)

with ThreadPoolExecutor(max_workers=3) as executor:
    futures = {
        executor.submit(process_sku, sku, df, 12, &quot;ES&quot;): sku
        for sku, df in sku_dataframes.items()
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;3 Prophet models, 3 seconds. Not 6. Three. If you add 50 SKUs like any mid-sized company has, the difference between sequential and parallel is the difference between an operational pipeline and a script nobody wants to run.&lt;/p&gt;
&lt;h4 id=&quot;negative-clipping-the-business-rule-prophet-ignores&quot;&gt;Negative Clipping: The Business Rule Prophet Ignores&lt;/h4&gt;
&lt;p&gt;Prophet can generate negative predictions. Mathematically it makes sense (the regression doesn't know demand can't be -12 units). Operationally it's a disaster.&lt;/p&gt;
&lt;p&gt;Our &lt;code&gt;forecasting_engine_v2.py&lt;/code&gt; applies a &lt;strong&gt;Negative Clipping&lt;/strong&gt; post-prediction:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# Business Rule: Demand cannot be negative
for col in [&quot;yhat&quot;, &quot;yhat_lower&quot;, &quot;yhat_upper&quot;]:
    self.forecast[col] = self.forecast[col].clip(lower=0)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One line. One fewer production bug. This is what separates MLOps from &quot;Machine Learning in a Jupyter Notebook.&quot;&lt;/p&gt;
&lt;h4 id=&quot;fault-tolerance-one-sku-doesn-t-kill-the-pipeline&quot;&gt;Fault Tolerance: One SKU Doesn't Kill the Pipeline&lt;/h4&gt;
&lt;p&gt;What happens if SKU-002 has only 10 records and Prophet fails? In an amateur script, the entire pipeline dies. In an Enterprise system:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;sku_name, forecast_df, error = future.result()
if error:
    print(f&quot;[!!] {sku_name}: FAILED - {error}&quot;)
    result[&quot;skus_failed&quot;] += 1
else:
    forecasts.append(forecast_df)
    result[&quot;skus_success&quot;] += 1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The 2 healthy SKUs finish their work. The failed one gets logged. This is the difference between a script and a &lt;strong&gt;system&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id=&quot;the-mathematics-of-bottlenecks-unified-pulp-model&quot;&gt;The Mathematics of Bottlenecks: Unified PuLP Model&lt;/h3&gt;
&lt;p&gt;Here's the intellectual core of the entire chapter. In &lt;a rel=&quot;nofollow&quot; href=&quot;https://datalaria.com/en/posts/sop-engineering-part3-optimization/&quot;&gt;Chapter 3&lt;/a&gt; we optimized one product. Now we create a &lt;strong&gt;single LP model&lt;/strong&gt; where all SKUs coexist:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# ── MULTI-DIMENSIONAL decision variables ──
production[sku][t]  # How much to produce of SKU s in period t
inventory[sku][t]   # Inventory of SKU s at end of period t

# ── Objective Function: TOTAL system cost ──
problem += lpSum(
    prod_cost[sku] * production[sku][t]
    + hold_cost[sku] * inventory[sku][t]
    for sku in skus for t in range(T)
), &quot;Total_System_Cost&quot;

# ── THE KEY CONSTRAINT: Shared Capacity ──
for t in range(T):
    problem += (
        lpSum(production[sku][t] for sku in skus) &amp;lt;= SHARED_MAX_CAPACITY,
        f&quot;SharedCapacity_t{t}&quot;
    )
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Read that last constraint. It's a single line of code, but it contains &lt;strong&gt;Goldratt's entire Theory of Constraints encoded&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;lpSum(production[sku][t] for sku in skus) &amp;lt;= 15,000&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;You're telling the machine: &quot;The factory produces at most 15,000 units per month. I don't care if it's 15,000 of SKU-001 or 7,500 of each. You decide the allocation that minimizes total system cost.&quot;&lt;/p&gt;
&lt;p&gt;And the solver decides. No meetings. No politics. No &quot;we always prioritize the big client.&quot; Mathematics.&lt;/p&gt;
&lt;h3 id=&quot;the-result-intelligent-capacity-allocation&quot;&gt;The Result: Intelligent Capacity Allocation&lt;/h3&gt;
&lt;p&gt;Our solver with real Supabase data:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;  SKU-001: demand=70,879 | prod=70,579 | avg_inv=5,754 | cost=855,394 EUR
  SKU-002: demand=143   | prod=128   | avg_inv=6     | cost=6,775 EUR
  SKU-003: demand=84,298 | prod=84,098 | avg_inv=115   | cost=1,265,970 EUR

  Total production cost:       1,973,660 EUR
  Total holding cost:            154,479 EUR
  ** TOTAL SYSTEM COST:        2,128,139 EUR **
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Observe the decisions the algorithm made:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SKU-001&lt;/strong&gt; (prod_cost=€10, hold_cost=€2): Cheap to store. The solver produces ahead during cheap months and stockpiles inventory (avg 5,754 units). Intelligent pre-build.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SKU-002&lt;/strong&gt; (prod_cost=€50, hold_cost=€5): Expensive part. Strict just-in-time production (avg_inv=6 units). Doesn't stockpile a single extra piece.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SKU-003&lt;/strong&gt; (seasonal): Minimum inventory at safety stock. Produces exactly what it needs each month, following the seasonal wave.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;No human with Excel can calculate this with 3 products and 13 months. And they definitely can't recalculate it every week when the forecast changes.&lt;/p&gt;
&lt;h3 id=&quot;the-ah-ha-moment-the-bottleneck-visualized&quot;&gt;The Ah-Ha Moment: The Bottleneck Visualized&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://datalaria.com/en/posts/sop-engineering-part4-enterprise/pulp_multisku_capacity_en.png&quot; alt=&quot;Multi-SKU shared production capacity: the red line marks the factory limit&quot;&gt;&lt;br&gt;
&lt;em&gt;Look at the summer months. Combined demand from the 3 SKUs exceeds factory capacity (red line). What does the algorithm do? Instead of breaking stock, it decides to advance production of the cheapest-to-store SKU (SKU-001) to spring, freeing factory space for the critical seasonal product (SKU-003) in summer. This is Theory of Constraints executed by a machine.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you look at the chart, it seems like SKU-002 (spare parts) doesn't exist. But it's there. It represents 0.1% of the factory's volume, but in manual management, it usually consumes 20% of the planner's mental time due to its high volatility. By delegating this to a Linear Programming model, the system manages large volumes and the long tail simultaneously without stress.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;open-kitchen-break-the-system&quot;&gt;Open Kitchen: Break the System&lt;/h3&gt;
&lt;p&gt;I distrust theories that can't be put into practice. I've prepared a new Enterprise Google Colab where you can run the most revealing experiment of the entire series:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Lower the &lt;code&gt;SHARED_MAX_CAPACITY&lt;/code&gt; variable to 12,000.&lt;/strong&gt; Watch the solver start juggling: it sacrifices SKU-001 inventory to prioritize SKU-003 in July. Lower it to 10,000 and you'll see the model declare &lt;code&gt;INFEASIBLE&lt;/code&gt; — the factory literally cannot meet demand even with the best possible planning. That's your inflection point for investing in capacity expansion.&lt;/p&gt;
&lt;p&gt; &lt;strong&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://colab.research.google.com/drive/1fBun7rDVGWN7XQGeSUbffm9VuhtTN9Bo?usp=sharing&quot;&gt;Open the Multi-SKU Enterprise Google Colab&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Change the maximum factory capacity, modify holding costs, add a fourth SKU. Do engineering, not faith.&lt;/p&gt;
&lt;h3 id=&quot;the-full-chain-from-mvp-to-enterprise&quot;&gt;The Full Chain: From MVP to Enterprise&lt;/h3&gt;
&lt;p&gt;With this fourth chapter, we've scaled a single-product prototype to a Multi-SKU Enterprise architecture:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://datalaria.com/en/posts/sop-engineering-part4-enterprise/architecture.png&quot; alt=&quot;Multi-SKU architecture&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;next-step-the-autonomous-brain&quot;&gt;Next Step: The Autonomous Brain&lt;/h3&gt;
&lt;p&gt;Our Supabase database now has the perfect master plan. Three products, thirteen months, every unit assigned to the optimal month considering costs, seasonality, and physical capacity.&lt;/p&gt;
&lt;p&gt;But databases don't send emails to suppliers. They don't negotiate with plant directors. They don't generate purchase orders at 6am on Monday.&lt;/p&gt;
&lt;p&gt;In &lt;strong&gt;Chapter 5 (Grand Finale)&lt;/strong&gt;, we'll connect this plan to &lt;strong&gt;AI Agents&lt;/strong&gt; (CrewAI) to execute operations autonomously. The algorithm decides how much to buy. The agent executes the purchase. The human... supervises.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;The difference between a company that plans and one that optimizes is a mathematical model between its data and its decisions. And between its decisions and its actions, an autonomous agent.&lt;/p&gt;
&lt;/blockquote&gt;
</description>
<category>Tutorials</category>
<guid isPermaLink="true">https://coderlegion.com/14033/sop-engineering-iv-scaling-to-enterprise-multi-sku-bottlenecks</guid>
<pubDate>Mon, 06 Apr 2026 05:55:15 +0000</pubDate>
</item>
<item>
<title>S&amp;OP Engineering III: The End of Excel (Linear Programming for Supply Planning)</title>
<link>https://coderlegion.com/13794/sop-engineering-iii-the-end-of-excel-linear-programming-for-supply-planning</link>
<description>&lt;p&gt;&quot;We always want 4 weeks of coverage.&quot; This phrase, repeated like a mantra in every S&amp;amp;OP meeting on the planet, is financially toxic.&lt;/p&gt;
&lt;p&gt;Why? Because it's a &lt;strong&gt;fixed rule applied to a dynamic system&lt;/strong&gt;. If your demand in January is 200 units and in July is 20, you're forcing yourself to maintain 800 and 80 units respectively &quot;just in case.&quot; January falls short. July immobilizes capital for no reason.&lt;/p&gt;
&lt;p&gt;The alternative isn't more sophisticated intuition. It's &lt;strong&gt;mathematics&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Executive Summary:&lt;/strong&gt; In this chapter, we connect the probabilistic forecast from &lt;a rel=&quot;nofollow&quot; href=&quot;https://datalaria.com/en/posts/sop-engineering-part2-forecasting/&quot;&gt;Chapter 2&lt;/a&gt; with a Linear Programming engine (PuLP) that calculates the exact production plan minimizing total cost (production + storage) while respecting Safety Stock constraints. We move from passive prediction to active prescription.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;from-forecast-to-decision-architecture&quot;&gt;From Forecast to Decision: Architecture&lt;/h3&gt;
&lt;p&gt;In &lt;a rel=&quot;nofollow&quot; href=&quot;https://datalaria.com/en/posts/sop_engineering-data-hygiene/&quot;&gt;Chapter 1&lt;/a&gt; we cleaned the signal. In &lt;a rel=&quot;nofollow&quot; href=&quot;https://datalaria.com/en/posts/sop-engineering-part2-forecasting/&quot;&gt;Chapter 2&lt;/a&gt; we predicted demand. Now we take the step Excel can't: &lt;strong&gt;optimize&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Our pipeline on GitHub connects to Supabase, reads the &lt;code&gt;demand_forecasts&lt;/code&gt; table (the future we predicted), and generates a new &lt;code&gt;supply_plans&lt;/code&gt; table. The system has evolved from &lt;strong&gt;descriptive&lt;/strong&gt; (what happened?) to &lt;strong&gt;predictive&lt;/strong&gt; (what will happen?) and now to &lt;strong&gt;prescriptive&lt;/strong&gt; (what should I do?).&lt;/p&gt;
&lt;p&gt;This is Operations Research. The same discipline that optimizes airline routes, military logistics, and global supply chains. And we run it with 50 lines of Python.&lt;/p&gt;
&lt;h3 id=&quot;the-mathematics-of-business&quot;&gt;The Mathematics of Business&lt;/h3&gt;
&lt;p&gt;We're not going to hide the equations. They're the heart of the decision. Here's the core fragment from our &lt;code&gt;SupplyOptimizer&lt;/code&gt; class:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# Objective Function: Minimize total cost
problem += pulp.lpSum(
    production_cost * production[t] + holding_cost * inventory[t]
    for t in range(T)
), &quot;Total_Cost&quot;

# Constraint: Inventory Balance (Conservation of Mass)
for t in range(T):
    prev_inv = initial_inventory if t == 0 else inventory[t - 1]
    problem += (
        inventory[t] == prev_inv + production[t] - demand[t],
        f&quot;Balance_t{t}&quot;
    )

# Constraint: Safety Stock (Risk Policy)
for t in range(T):
    problem += (
        inventory[t] &amp;gt;= safety_stock,
        f&quot;SafetyStock_t{t}&quot;
    )
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Three engineering decisions worth explaining:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Objective Function&lt;/strong&gt; doesn't seek &quot;lots of stock&quot; or &quot;high production.&quot; It seeks the &lt;strong&gt;minimum financial cost&lt;/strong&gt;: the equilibrium between manufacturing (expensive) and storing (also expensive). The solver automatically finds the exact point where the combined cost is minimal.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Mass Balance&lt;/strong&gt; is a physical constraint: you can't sell what you don't have. Today's inventory equals yesterday's, plus what you produce today, minus what you sell. No magic. The equations forbid cheating.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Safety Stock&lt;/strong&gt; is the risk policy: never let inventory drop below a safety minimum. In our case, 1.5 months of average demand. The system calculates this, not a spreadsheet with a number pulled from thin air.&lt;/p&gt;
&lt;h3 id=&quot;the-master-plan-from-algorithm-to-business-decision&quot;&gt;The Master Plan: From Algorithm to Business Decision&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://datalaria.com/en/posts/sop-engineering-part3-optimization/pulp_optimization_plan.png&quot; alt=&quot;Master Production Schedule optimized with PuLP: production, inventory, and Safety Stock by month&quot;&gt;&lt;br&gt;
&lt;em&gt;This is what the Operations Director needs to see. The algorithm doesn't produce uniformly: if it detects a massive demand spike in one period, it decides to &quot;pre-build&quot; inventory in preceding months to flatten the production load. If Holding Cost is high, it keeps the warehouse empty and manufactures Just-in-Time. Excel doesn't do this on its own; mathematics does.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The result from our solver with test data:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Production cost:&lt;/strong&gt; €1,680&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Storage cost:&lt;/strong&gt; €540&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Total optimized cost:&lt;/strong&gt; €2,220&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This number is not an estimate. It's the &lt;strong&gt;provable global minimum&lt;/strong&gt; given the constraints. If someone proposes a cheaper plan with the same parameters, they're violating a constraint.&lt;/p&gt;
&lt;h3 id=&quot;open-kitchen-play-with-the-solver&quot;&gt;Open Kitchen: Play with the Solver&lt;/h3&gt;
&lt;p&gt;I distrust theories that can't be put into practice. That's why I've prepared a Google Colab where you can run the optimizer on a snapshot of our real data.&lt;/p&gt;
&lt;p&gt;The most revealing experiment: &lt;strong&gt;change &lt;code&gt;holding_cost&lt;/code&gt; to an extremely high value&lt;/strong&gt; (e.g., €50/unit). Watch how the algorithm automatically decides to manufacture Just-in-Time and keep the warehouse practically empty. Then lower the production cost and watch it prefer to produce in bulk and store. Mathematics adapts. Excel's fixed rules don't.&lt;/p&gt;
&lt;p&gt; &lt;strong&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://colab.research.google.com/drive/1fF9DY-eHL13G0AFg_geNxQ6duEMOWy4N?usp=sharing&quot;&gt;Open the Interactive Google Colab&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Modify the costs, capacity constraints, Safety Stock. Do engineering, not faith.&lt;/p&gt;
&lt;h3 id=&quot;the-complete-chain-from-data-to-decisions&quot;&gt;The Complete Chain: From Data to Decisions&lt;/h3&gt;
&lt;p&gt;With this third chapter, we've built an end-to-end S&amp;amp;OP system that goes from a dirty ERP CSV to an optimal production plan:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://datalaria.com/en/posts/sop-engineering-part3-optimization/architecture.png&quot; alt=&quot;architecture&quot;&gt;&lt;/p&gt;
&lt;h3 id=&quot;next-step-scaling-to-enterprise&quot;&gt;Next Step: Scaling to Enterprise&lt;/h3&gt;
&lt;p&gt;We now have the perfect plan in our database. But only for one product. What happens when you add 3 SKUs sharing the same factory?&lt;/p&gt;
&lt;p&gt;In &lt;a rel=&quot;nofollow&quot; href=&quot;https://datalaria.com/en/posts/sop-engineering-part4-enterprise/&quot;&gt;Chapter 4&lt;/a&gt; we break the MVP: we inject multi-product data with radically different profiles, parallelize the forecasting with &lt;strong&gt;MLOps&lt;/strong&gt;, and build a unified Linear Programming model where products &lt;em&gt;compete mathematically&lt;/em&gt; for shared production capacity.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;The difference between an Operations Director who plans and one who optimizes is an objective function between their intuition and reality.&lt;/p&gt;
&lt;/blockquote&gt;
</description>
<category>Tutorials</category>
<guid isPermaLink="true">https://coderlegion.com/13794/sop-engineering-iii-the-end-of-excel-linear-programming-for-supply-planning</guid>
<pubDate>Wed, 01 Apr 2026 06:01:26 +0000</pubDate>
</item>
</channel>
</rss>