Воспроизведение Excel Solver GRG Нелинейная оптимизация в Visual Basic .NET

Я пытаюсь воспроизвести следующую нелинейную оптимизацию Excel Solver GRG с использованием Microsoft Solver Foundation в VB.NET (цифры в этом примере упрощены):

  1. Цель: общий расход газа = 100000
  2. Переменная: скважина 1, дебит нефти
  3. Ограничения: 0 <= дебит скважины 1 <= 1000, дебит скважины 2 = 2000

Эта оптимизация подчиняется следующим отношениям:

  1. Скважина 1 Расход газа = Скважина 1 Расход нефти * 5
  2. Общий дебит газа = дебит скважины 1 + дебит скважины 2

Можно ли решить такую ​​проблему с помощью Solver Foundation? При попытке реализовать это я боролся с двумя вещами:

  1. Похоже, что модели Solver Foundation имеют только два GoalKind's: минимальный и максимальный. В моем случае я пытаюсь оптимизировать под конкретное значение. Есть какой-либо способ сделать это?
  2. Как мне определить вышеуказанные отношения? Я думаю, что последний будет определен как часть определения цели (например, model.AddGoal("total_gas_rate", GoalKind.[not sure what goes here], Well1PGasRate + Well2PGasRate), но как мне определить другой?

Спасибо!

2 ответа

Этот ответ касается только первой части вашего вопроса и концептуально, но, надеюсь, он будет полезен. Если вы пытаетесь оптимизировать для конкретного значения target и результат вашей функции output тогда вы можете попробовать что-то вроде этого псевдокода:

minimize(absolute_value(output/target-1))

По сути, это даст вам значение, которое достигает нуля, когда выход вашей функции приближается к целевому значению. Таким образом, вы все еще можете использовать механизм оптимизации, который минимизирует конечный результат вашей функции.

Ответ на С#:

          static void SolverGasRate()
    {
        Console.WriteLine("\nBegin Solver Gas Rate using Solver Context MSF\n");

        var solver = SolverContext.GetContext();
        var model = solver.CreateModel();

        var decisionWell1OilRate = new Decision(Domain.IntegerNonnegative, "Well1OilRate");
        model.AddDecision(decisionWell1OilRate);
        var decisionWell2GasRate = new Decision(Domain.IntegerNonnegative, "Well2GasRate");
        model.AddDecision(decisionWell2GasRate);

        Goal goal = model.AddGoal("Goal", GoalKind.Maximize, TotalGasRateTerm(decisionWell1OilRate, decisionWell2GasRate));

        model.AddConstraint("Objective", TotalGasRateTerm(decisionWell1OilRate, decisionWell2GasRate) <= 100000);
        model.AddConstraint("Constraint1", decisionWell1OilRate * 5 >= 0);
        model.AddConstraint("Constraint2", decisionWell1OilRate * 5 <= 1000);
        model.AddConstraint("Constraint3", decisionWell2GasRate <= 2000);

        var solution = solver.Solve();
        double Well1OilRate = decisionWell1OilRate.GetDouble();
        double Well2GasRate = decisionWell2GasRate.GetDouble();

        Console.WriteLine("Well1OilRate: " + (Well1OilRate).ToString());
        Console.WriteLine("Well1GasRate: " + (Well1OilRate*5).ToString());
        Console.WriteLine("Well2GasRate: " + (Well2GasRate).ToString());
        Console.WriteLine("TotalGasRate: " + TotalGasRate(Well1OilRate, Well2GasRate).ToString());

        Console.WriteLine("\nEnd Solver demo\n");
    }

    static Term TotalGasRateTerm(Decision decisionWell1OilRate, Decision decisionWell2GasRate)
    {
        return (decisionWell1OilRate * 5) + decisionWell2GasRate;
    }

    static double TotalGasRate(double Well1OilRate, double Well2GasRate)
    {
        return (Well1OilRate * 5) + Well2GasRate;
    }

Выход:

      Begin Solver Gas Rate using Solver Context MSF

Well1OilRate: 200
Well1GasRate: 1000
Well2GasRate: 2000
TotalGasRate: 3000

End Solver demo
Другие вопросы по тегам