求解器得到决策中的最小值集

本文关键字:最小值 决策 | 更新日期: 2023-09-27 18:03:47

我正在运行一个代码,需要计算组成动物食品的成分的适当百分比。为了做到这一点,我使用了MS求解器基础。我设置了传递成分和营养素的最小值和最大值的模型(成分百分比会干扰营养素的多或少)。我需要把动物性食品的成本降到最低。这是我的代码。

  private Solution FormularRacao()
    {
        var ingredientesRacao = _formulacaoRacao.CarregarIngredientesNutrientesFormulacao(true);
        var nutrientes = _formulacaoRacao.CarregarIngredientesNutrientesFormulacao(false);
        var formulacao = _formulacaoRacao.CarregarFormulacao();
        SolverContext context = SolverContext.GetContext();
        context.ClearModel();
        Model model = context.CreateModel();
        var objetivo = new SumTermBuilder(ingredientesRacao.Count);
        var totalIngrediente = new SumTermBuilder(ingredientesRacao.Count);
        List<SumTermBuilder> listaTotalNutriente = new List<SumTermBuilder>();
        //Set decisions
        foreach (var item in ingredientesRacao)
        {
            item.Nome = TratarNome(item.Nome);
            Decision d = new Decision(Domain.RealRange(Convert.ToDouble(item.Minimo), Convert.ToDouble(item.Maximo)), "d_" + item.Nome);
            model.AddDecision(d);
            objetivo.Add(Model.Product(d, Convert.ToDouble(item.Custo)));
            totalIngrediente.Add(d);
            listaTotalNutriente.Add(new SumTermBuilder(nutrientes.Count));
        }
        var SomaIngrediente = totalIngrediente.ToTerm();
        //sum of decisions values must be equal 100
        model.AddConstraint("c_totalIngrediente", SomaIngrediente == 100);
        //totalIngrediente;
        model.AddGoal("racao", GoalKind.Minimize, objetivo.ToTerm());
        int indexIngrediente = 0;
        int indexNutriente = 0;
        //each ingredient contributes with nutrients
        //each nutrient has a min and max set            
        foreach (var ingredienteRacao in ingredientesRacao)
        {
            Ingrediente ingrediente = _formulacaoRacao.CarregarIngrediente(ingredienteRacao.Id);
            indexNutriente = 0;
            ingredienteRacao.Nome = TratarNome(ingredienteRacao.Nome);
            Decision d = model.Decisions.First(x => x.Name == "d_" + ingredienteRacao.Nome);
            foreach (var nutriente in nutrientes)
            {
                var valor = new object();
                if (nutriente.AminoacidoDigestivo.Equals("S"))
                {
                    var aminoacidoDigestivo = _formulacaoRacao.CarregarAminoacidoDigestivo(ingredienteRacao.Id);
                    valor = aminoacidoDigestivo.GetType().GetProperty(nutriente.Nome).GetValue(aminoacidoDigestivo, null);
                }
                else
                {
                    nutriente.Nome = TratarNomeNutriente(nutriente.Nome);
                    valor = ingrediente.GetType().GetProperty(nutriente.Nome).GetValue(ingrediente, null);
                }
                var proporcaoNutriente = Convert.ToDouble(valor.ToString()) * d;
                listaTotalNutriente[indexNutriente].Add(proporcaoNutriente / 100);
                if (indexIngrediente == ingredientesRacao.Count - 1) //last iteration
                {
                    var totalNutriente = listaTotalNutriente[indexNutriente].ToTerm();
                    if (nutriente.Minimo == nutriente.Maximo)
                       model.AddConstraint("c_" + nutriente.Nome, totalNutriente == Convert.ToDouble(nutriente.Maximo));                        
                    else
                        model.AddConstraint("c" + nutriente.Nome, Convert.ToDouble(nutriente.Minimo) <= totalNutriente <= Convert.ToDouble(nutriente.Maximo));                        
                }
                indexNutriente++;
            }
            indexIngrediente++;
        }            
        //saves the model
        TextWriter tw = new StreamWriter("Path'file.oml");
        context.SaveModel(FileFormat.OML, tw);
        tw.Close();
        //Imprime o modelo
        TextWriter txt = new StreamWriter("Path'file.txt");
        foreach (var item in model.Constraints.ToList())
        {
            txt.WriteLine(item.Name + ":  " + item.Expression);
            txt.WriteLine();
        }
        txt.Close();
        Solution solution = context.Solve();
        return solution;
    }

我得到的结果是它所设置的决策的最小值,这意味着没有找到解决方案。我的问题是:为什么求解器考虑决策中的最小值集,而不是为每个决策计算适当的值?

求解器得到决策中的最小值集

这是我在建模模型时的错误。代码运行良好。但它确实帮助我通过创建一个txt文件并添加所有约束来解决问题,所以我可以仔细检查我设置的约束,也可以创建一个模型文件(oml)并将其导入Excel,这样我就可以检查为解决模型而设置的所有约束。代码在我的问题中更新,所以如果你需要,你可以检查如何创建txt和oml文件。