AnyLogic离散事件仿真EOQ模型总成本函数求根问题及实现方法
Hey there! Let's tackle your problem head-on. The short answer is: Yes, you absolutely can calculate the optimal (root) total inventory cost using only events, parameters, and variables in AnyLogic. The issue you're seeing—cost staying the same despite parameter changes—usually comes down to missing links between your parameters, simulation logic, and cost calculation. Here's a step-by-step breakdown to fix this and implement the optimization:
1. First, Fix the Cost Calculation Dependency
The most likely reason your cost isn't updating is that your inventorycost() function isn't dynamically tied to your changing parameters. Let's fix that:
- Define your key optimization parameter (like order quantity
Q) as a global parameter in your Root agent (not hardcoded in the function). - Rewrite your
inventorycost()function to directly reference this parameter. For example, if using the standard EOQ formula:
If you're calculating cost via simulation events (not just the formula), ensure all cost-tracking variables (likereturn (root.annualDemand / root.Q) * root.orderingCost + (root.Q / 2) * root.holdingCost + root.annualDemand * root.unitCost;totalOrderCost,totalHoldingCost) are updated using the global parameter values during runtime.
2. Add a Simulation Reset Event
Every time you change your parameter, you need to reset the simulation state to avoid carrying over old data. Create a Reset Event in your Root agent:
- Set its trigger to "Manual" (you'll call it when needed).
- In the event's action, reset all critical variables:
// Reset inventory state currentInventory = initialInventory; // Reset cost trackers totalOrderCost = 0; totalHoldingCost = 0; // Reset simulation time getEngine().reset(); - This ensures every parameter change starts with a clean simulation slate.
3. Build a Simulation Execution Pipeline
You need a way to trigger the reset, run the simulation, and capture the final cost. Use a chain of events:
- Reset & Start Event: When triggered, first call your reset event, then start the simulation:
resetEvent.execute(); getEngine().start(); - Simulation End Event: Set this event to trigger when your simulation reaches its end time (e.g.,
time() >= 365for a 1-year model). In its action:// Calculate total cost from tracked values root.totalInventoryCost = root.totalOrderCost + root.totalHoldingCost; // Stop the simulation getEngine().stop(); - Now your
inventorycost()function can simply returnroot.totalInventoryCostinstead of calculating it directly.
4. Implement the "Root-Finding" (Optimization) Logic
To find the parameter that minimizes total cost, use an iterative event loop:
- Add these global variables to your Root agent:
currentQ: The order quantity you're testing right nowstepQ: The increment/decrement for testing valuesminTotalCost: Tracks the lowest cost found so faroptimalQ: Tracks the order quantity that gives the lowest cost
- Create an Optimization Iteration Event with a manual trigger. In its action:
// Set the current test parameter root.Q = root.currentQ; // Run the simulation to get the cost resetAndStartEvent.execute(); // Wait for simulation to finish (adjust delay based on your model runtime) delay(1, TimeUnit.DAYS); // Compare costs and update optimal values if (root.totalInventoryCost < root.minTotalCost) { root.minTotalCost = root.totalInventoryCost; root.optimalQ = root.currentQ; } // Move to next test value root.currentQ += root.stepQ; // Stop iteration if we've tested all values (e.g., currentQ > maxQ) if (root.currentQ > root.maxQ) { this.cancel(); traceln("Optimal Q found: " + root.optimalQ + " with total cost: " + root.minTotalCost); } else { // Schedule next iteration this.schedule(1); } - Pro tip: For faster convergence, use a binary search approach instead of linear steps once you've narrowed down a range of Q values.
Common Pitfalls to Avoid
- Hardcoded values: Never use fixed numbers in your cost calculation—always reference global parameters/variables.
- Incomplete resets: Forgetting to reset cost trackers or inventory state will lead to stale data.
- Not waiting for simulation to finish: Make sure your iteration event waits until the simulation ends before comparing costs (use delays or check
getEngine().isRunning()).
内容的提问来源于stack exchange,提问作者Thomy

