Неправильные результаты с Microsoft solver foundation
I have an issue with Microsoft solver foundation. It is a little hard to explain, so I will try to describe the issue to the best of my abilities: The goal of the code is to get the optimum selection of air filters to filter a given airflow. The constraint is that the optimum selection of filters does not exceed a given width. There are three filters to choose from. Each model of filter has a value of airflow and width. For instance: Objetive airflow: 19000 Maximum width: 2236 Filters: Filter X: Airflow = 5100, width=592 Filter Y: Airflow = 4250, width=490 Filter Z: Airflow = 2550, width=287 The solution would be to get the number of filters type X, Y and Z so that we get as close to the airflow goal, but without exceeding the maximum width: 19000 – (X * 5100 + Y * 4250 + Z * 2550) MINIMIZE THIS X * 592 + Y * 490 + Z * 287 <= 2236 CONSTRAINT THis is the code I've benn working on:
Что я уже пробовал:
Это код, который у меня сейчас есть:
Sub OPT_3_FILTROS(ByVal REF_filtros As List(Of String), ByVal Q_filtros As List(Of Double), ByVal W_filtros As List(Of Double), ByVal W_util As Integer, ByVal Q_nominal As Integer, ByRef lista_solucion As List(Of Single), ByRef tipo As List(Of String)) Dim solver = SolverContext.GetContext() Dim model = solver.CreateModel() '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ ' 1: DECISIONES: "decisions" Dim X As New Decision(Domain.IntegerNonnegative, "decision_1") Dim Y As New Decision(Domain.IntegerNonnegative, "decision_2") Dim Z As New Decision(Domain.IntegerNonnegative, "decision_3") model.AddDecisions(X, Y, Z) '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ ' 2: OBJETIVOS: "goal" model.AddGoal("Goal_0", GoalKind.Minimize, Q_nominal - (Q_filtros(0) * X + Q_filtros(1) * Y + Q_filtros(2) * Z)) '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ ' 3: RESTRICCIONES: "constraints" model.AddConstraint("C_1", X * W_filtros(0) + Y * W_filtros(1) + Z * W_filtros(2) <= W_util) '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ ' 4: RESOLVEMOS: "solve" Dim solution = solver.Solve(New ConstraintProgrammingDirective()) '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ ' 5: OBTENEMOS RESULTADOS: "solve" Dim temp As String = "" While (solution.Quality <> SolverQuality.Infeasible) lista_solucion.Add(X.GetDouble) lista_solucion.Add(Y.GetDouble) lista_solucion.Add(Z.GetDouble) tipo.Add(solution.Quality.ToString()) solution.GetNext() End While solver.ClearModel() End Sub
In the list "lista_solucion" I get the results of the optimization. And, as you can see in the code above, I get all optimum solutions, not just one. If I run this code, I get the following results: lista_solucion={0,1,6,1,1,4} This means that there are two optimum solutions: 0 X filters + 1 Y filters + 6 Z filters 1 X filters + 1 Y filters + 4 Z filters Both solutions obtain this airflow: 0x5100 + 1x4250 + 6x2550 = 19550 1x5100 + 1x4250 + 4x2550 = 19550 So, we have a +550 deviation from goal airflow (19000) All seems legit. The problem here is that I have checked that this is not the optimal solution: If I add this new constraint, that basically means that the solution must not exceed 102% of the goal airflow: model.AddConstraint("C_2", X * Q_filtros(0) + Y * Q_filtros(1) + Z * Q_filtros(2) <= 1.02*19000) This time I get the following solutions: lista_solucion={0,2,4,1,2,2,2,2,0} This means that there are three optimum solutions this time: 0 X filters + 2 Y filters + 4 Z filters 1 X filters + 2 Y filters + 2 Z filters 2 X filters + 2 Y filters + 0 Z filters All solutions obtain this airflow: 0x5100 + 2x4250 + 4x2550 = 18700 1x5100 + 2x4250 + 2x2550 = 18700 2x5100 + 2x4250 + 0x2550 = 18700 So, we have a -300 deviation from goal airflow (19000) Obviously, a -300 difference is lower than a +500 difference. What is happening here? Why does it optimize by excess rather that to the closest value to goal?
Charly Nasic
Я думаю, что все было бы решено, если бы я мог использовать абсолютные значения в цели... но, по-видимому, это невозможно?
Кто-нибудь знает способ использовать абсолютное значение в цели?
Charly Nasic
Ладно, на всякий случай, если кто-то вмешается в это дело:
Чтобы добавить цель или ограничение с абсолютным значением, вы не можете использовать math. abs()
Вместо этого вы должны использовать model. abs()
Например:
model.AddGoal("Goal_0", GoalKind.Minimize, model.Abs(Q_nominal - Q_filtros(0) * X - Q_filtros(1) * Y - Q_filtros(2) * Z))
Использование model.abs() решает проблему оптимизации, проблема теперь заключается в том, что, помимо того, что время выполнения процедуры оптимизации взлетело до небес, несколько раз я получаю противоречивые результаты... или вообще никаких результатов.