0

制約のある非線形最適化の問題があります。ソルバー アドインを使用して Microsoft Excel で解決できますが、C# で再現するのに問題があります。

Microsoft Solver Foundation dll をインストールしました

これは、次のコードを適用した例です: http://msdn.microsoft.com/en-us/library/gg261758(v=vs.93).aspx?cs-save-lang=1&cs-lang=csharp#コード スニペット 3

基本的に、私のコードには、RHO と NU という 2 つのパラメーターがあります。二乗和を最小化する最適値を取得する必要があります。RHO には 1 つの値しかなく、NU には 1 つの値しかないので、コードに RHO[s] と NU[s] を入れるのが間違っていることはわかっていますが、それらを RHO と NU に置き換えるとエラーが発生します。

もう 1 つの問題は、この例では、コードが「目標」タイプの「燃料」と呼ばれる 1 つの最適な変数を探すことです。私の場合、最適化する必要がある変数が 2 つあります。

明らかに、プログラムは最後の行で壊れており、「伝播する解決策はありません」と書かれています。

私のコードを修正する方法を知っている人はいますか?? どんな助けでも大歓迎です!

これは私のコードです:

    class Segment
    {
        public double Strike { get; set; }
        public double VolImp { get; set; }
        public double _Rho_ { get; set; }
        public double _Nu_ { get; set; }
        public double _Alpha_ { get; set; }
    }



       Segment[] segmentData = new Segment[] { 
            new Segment { Strike = 5, VolImp = 53.2608},
            new Segment { Strike = 10, VolImp = 48.3773},
            new Segment { Strike = 20, VolImp = 43.8949},
            new Segment { Strike = 30, VolImp = 40.9367},
            new Segment { Strike = 40, VolImp = 38.891},
            new Segment { Strike = 50, VolImp = 37.417},
            new Segment { Strike = 60, VolImp = 36.2838},
            new Segment { Strike = 70, VolImp = 35.3713},
            new Segment { Strike = 80, VolImp = 34.6192},
            new Segment { Strike = 90, VolImp = 33.9774},
            new Segment { Strike = 100, VolImp = 33.4359},
            new Segment { Strike = 110, VolImp = 32.9747},
            new Segment { Strike = 120, VolImp = 32.5635},
            new Segment { Strike = 130, VolImp = 32.2025},
            new Segment { Strike = 140, VolImp = 31.8917},
            new Segment { Strike = 150, VolImp = 31.6209},
            new Segment { Strike = 160, VolImp = 31.3702},
            new Segment { Strike = 170, VolImp = 31.1596},
            new Segment { Strike = 180, VolImp = 30.9591},
       };


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



        // Parameters
        Set segments = new Set(Domain.Integer, "segments");

        Parameter RHO = new Parameter(Domain.Real, "RHO", segments);
        RHO.SetBinding(segmentData, "_Rho_", "Strike");

        Parameter NU = new Parameter(Domain.RealNonnegative, "NU", segments);
        NU.SetBinding(segmentData, "_Nu_", "Strike");

        Parameter ALPHA = new Parameter(Domain.RealNonnegative, "ALPHA", segments);
        ALPHA.SetBinding(segmentData, "_Alpha_", "Strike");

        Parameter MyStrike = new Parameter(Domain.RealNonnegative, "MyStrike", segments);
        MyStrike.SetBinding(segmentData, "Strike", "Strike");

        Parameter MyImpVol = new Parameter(Domain.RealNonnegative, "MyImpVol", segments);
        MyImpVol.SetBinding(segmentData, "VolImp", "Strike");

        model.AddParameters(RHO, NU, ALPHA, MyStrike, MyImpVol);


        //Constraints
        model.AddConstraint("rho_bound", Model.ForEach(segments, s => (-1 <= RHO[s] <= 1))) ;
        model.AddConstraint("nu_bound", Model.ForEach(segments, s => (0 <= NU[s]) )) ;
        model.AddConstraint("alpha_bound", Model.ForEach(segments, s => (0 < ALPHA[s]))) ;

        double Forward = 100 ;

        //Goal
        Goal Mygoal = model.AddGoal("Mygoal", GoalKind.Minimize, Model.Sum(Model.ForEach(segments, s => Model.Power((MyImpVol[s] - (ALPHA[s] * (NU[s] / ALPHA[s] * Model.Log(Forward / MyStrike[s])) * (Model.Log((Model.Sqrt(1 - 2 * RHO[s] * (NU[s] / ALPHA[s] * Model.Log(Forward / MyStrike[s])) + Model.Power((NU[s] / ALPHA[s] * Model.Log(Forward / MyStrike[s])), 2)) + (NU[s] / ALPHA[s] * Model.Log(Forward / MyStrike[s])) - RHO[s]) / (1 - RHO[s]))) * (1 + (0.25 * RHO[s] * NU[s] * ALPHA[s] + (2 - 3 * RHO[s] * RHO[s]) / 24 * NU[s] * NU[s]) * 6.46407))), 2)))) ;


        //solve
        context.Solve();
        context.PropagateDecisions();
4

0 に答える 0