在 AnyLogic 多目标优化中引用 Non-Decision/Non-Optimization 个变量

Referencing Non-Decision/Non-Optimization Variables in AnyLogic MultiObjective Optimization

TLDR:希望从 OptQuest 解决方案中提取非决策变量的值,或者找到一个可行的解决方法来获取此信息。

我目前在 AnyLogic 中 运行 进行加权多 objective 优化(自定义)实验,处理分销渠道中制造商、分销商和零售商的利润。 我的决策变量是每个成员的再订货点 (r) 和再订货数量 (Q)。我的objective是渠道的利润(root.MultObjs)和零售商的利润(root.RObj)。


try {
    // Create Engine, initialize random number generator:
    Engine engine = createEngine();
    engine.setStartTime(0.0);
    engine.setTimeUnit(DAY);
    // Set stop time:
    engine.setStopTime( 365 );

    // ***Create optimization variable***   
    
    
    final COptQuestDiscreteVariable Rr = new COptQuestDiscreteVariable();
    Rr.SetLowerBound(100);
    Rr.SetUpperBound(3000);
    Rr.SetStepSize(100);
    final COptQuestDiscreteVariable RQ = new COptQuestDiscreteVariable();
    RQ.SetLowerBound(100);
    RQ.SetUpperBound(3000);
    RQ.SetStepSize(100);
    final COptQuestDiscreteVariable Dr = new COptQuestDiscreteVariable();
    Dr.SetLowerBound(100);
    Dr.SetUpperBound(10000);
    Dr.SetStepSize(100);
    final COptQuestDiscreteVariable DQ = new COptQuestDiscreteVariable();
    DQ.SetLowerBound(100);
    DQ.SetUpperBound(10000);
    DQ.SetStepSize(100);
    final COptQuestDiscreteVariable Mr = new COptQuestDiscreteVariable();
    Mr.SetLowerBound(100);
    Mr.SetUpperBound(15000);
    Mr.SetStepSize(100);
    final COptQuestDiscreteVariable MQ = new COptQuestDiscreteVariable();
    MQ.SetLowerBound(100);
    MQ.SetUpperBound(15000);
    MQ.SetStepSize(100);
    
    
    // add parameters
    
    final COptQuestContinuousVariable R_Inv = new COptQuestContinuousVariable();

    // ***Create objectives***
    final COptQuestObjective obj1 = new COptQuestUserControlledObjective(); //Retailer
    obj1.SetMaximize();
    final COptQuestObjective obj2 = new COptQuestUserControlledObjective(); //Chain
    obj2.SetMaximize();
    
    
    //weighted coefficients starts here

    final COptQuestWeightedMultiObjective weightedMultiObjective = new COptQuestWeightedMultiObjective();
    weightedMultiObjective.AddObjective(obj1,0);
    weightedMultiObjective.AddObjective(obj2,1);
        
    //set requirements
    COptQuestUpperRequirement ReqROverstock= new COptQuestUpperRequirement(0);
    COptQuestUpperRequirement ReqDOverstock= new COptQuestUpperRequirement(0);
    COptQuestUpperRequirement ReqMOverstock= new COptQuestUpperRequirement(0);
        
    // Create optimization engine
    final COptQuestOptimization opt = ExperimentOptimization.createOptimization(engine, new OptimizationCallback() 
    {
    
        @Override
        public void evaluate(COptQuestOptimization optimization,
                COptQuestSolution solution, Engine engine) 
        {
                
            // Create new root object:
            Main root = new Main( engine, null, null );
    
            // Setup parameters of root object here
                
            //set default values of vars
            root.setParametersToDefaultValues();
            
            //set decision variables
            //***left side model*** ***right side*** optimization
            root.Rr = (int)solution.GetVariableValue(Rr);
            root.RQ = (int)solution.GetVariableValue(RQ);
            root.Dr = (int)solution.GetVariableValue(Dr);
            root.DQ = (int)solution.GetVariableValue(DQ);
            root.Mr = (int)solution.GetVariableValue(Mr);
            root.MQ = (int)solution.GetVariableValue(MQ);
            
        
            
            // Prepare Engine for simulation:
            root.getDefaultRandomGenerator().setSeed(1);
            engine.start( root );
            
            // Start simulation in fast mode:
            engine.runFast();
            // Process results of simulation here
            
            //***left side method expression*** ***right side model objective****
            solution.SetObjectiveValue( obj1, root.RObj );
            solution.SetObjectiveValue( obj2, root.MultObjs );

            
            //set requirements here 
            solution.SetRequirementValue(ReqROverstock,root.ROverstock);
            solution.SetRequirementValue(ReqDOverstock,root.DOverstock);
            solution.SetRequirementValue(ReqMOverstock,root.MOverstock);
        
            // Destroy the model:
            engine.stop();
        }
            
    });
    
        
        // ***Setup optimization engine***
        
        //add decision variables
        opt.AddVariable(Rr);
        opt.AddVariable(RQ); 
        opt.AddVariable(Dr);
        opt.AddVariable(DQ); 
        opt.AddVariable(Mr);
        opt.AddVariable(MQ); 
        

        // add constraints 
        opt.AddRequirement(ReqROverstock);
        opt.AddRequirement(ReqDOverstock);
        opt.AddRequirement(ReqMOverstock);
        
        // add objective
        opt.AddObjective(weightedMultiObjective);

        
        // Set the number of iterations to run
        opt.SetMaximumIterations(500);
        
        // Perform optimization
        opt.Optimize();
        
    //setup for printout
    traceln(" Lambda : Param Rr : Param RQ : Param Dr : Param DQ : Param Mr : Param MQ: :    Best obj1(R)   :   Best obj2(Chain)   :  DProfit : MProfit : feasible?");
    traceln("-----------------------------------------------------------------------------------------------------------------------------------------------------------");
        
        double nLambda=10; //sets resolution of weighted multi-objective search
        for (int i=0; i <=nLambda; i++)
        {
            double lweight=i/nLambda;
            weightedMultiObjective.SetObjectiveCoefficient(obj1, lweight);
            weightedMultiObjective.SetObjectiveCoefficient(obj2, (1- lweight));
            
            opt.Recalculate();

            COptQuestSolution bestSolution = opt.GetBestSolution(); 
            //COptQuestSolution currentSolution=opt.GetIterationSolution(500);
            
            // Output results
            traceln(String.format("  %1.2f : %7.2f : %8.2f : %8.2f : %8.2f : %8.2f : %8.2f : %8.2f : %8.2f : %8.2f : %8.2f : %8s",
            lweight, bestSolution.GetVariableValue(Rr),bestSolution.GetVariableValue(RQ), 
            bestSolution.GetVariableValue(Dr),bestSolution.GetVariableValue(DQ),,
            bestSolution.GetVariableValue(Mr),bestSolution.GetVariableValue(MQ),
            
            bestSolution.GetObjectiveValue(obj1),
            bestSolution.GetObjectiveValue(obj2), 
            null,
            null,
            bestSolution.IsFeasible()));

        }
} 

catch (COptQuestException e) {
    traceln(e.Description());
}

我通过 OptQuest 文档选择了自己的方式,并设法获得了一个可执行模型,该模型在实验结束时打印我的决策变量和 objectives。我真正想做的是从最优解中提取非决策变量(root.RBackOrderCost、root.RCarryingCost)的实例,并将它们包含在输出中。我 运行 遇到的问题是 OptQuestSolution Class 似乎只关心决策变量的输入和 objective 的输出,到我们已经弄清楚了,引擎已经被破坏了,所以我不能只从根目录中提取一个值。 我扔了几个冰雹玛丽无济于事:

  1. 我试图创建一个虚拟决策变量(甚至是一个虚拟 objective)来在引擎被销毁之前将值存储在其中,但这没有用。
  2. 我还尝试将模拟回调中的变量值存储到回调外部的数组中。也不走运。

不幸的是,没有简单的方法让 COptQuestSolution 携带额外的变量。我之前这样做的方法是在 root 对象被销毁之前保存额外的信息。要做到这一点:

  1. evaluate
  2. 之外创建一个 Map<Integer, Map<String, Double>> extraVars
  3. 然后在调用 engine.stop() 之前在 evaluate 方法中填充 extraVars 使用 solution.getIteration 作为键