Unity 在 while 循环(C#)(单纯形方法程序)上不断崩溃

问题描述 投票:0回答:1

我正在使用 Unity 用 C# 编写一个程序,以使用单纯形法找到线性规划问题的最佳解决方案,用于我的计算机科学课程。不幸的是,我对 C# 或 Unity 不太有经验,并且我的代码的一部分遇到了问题。

以下是针对某些上下文的线性规划的简短分解: (我仅针对具有两个变量的一级线性规划进行编码) 你有一个目标函数,你试图最大化它,例如P = 3x + 2y 该问题还存在许多限制条件,例如2x + y <= 18 or 3x + y <= 24 The most common method used to solve a problem like this is the simplex method, where all the values are stored in a table and then operated on until the optimal solutions for x and y are found (this website explains it a lot better: https://www.phpsimplex.com/en/simplex_method_example.htm#google_vignette)。

在我的项目中,执行单纯形方法的代码在多个 Unity 场景中执行。 在第一个场景中,从用户处获取问题的约束数量,并将每个约束本身的值存储到称为 simplexTable 的矩阵类 2D 浮点数组中。 simplexTable 的维度和元素使用 Player Prefs 类存储,以便可以从下一个场景访问它们。 在下一个场景中,用户输入问题的目标函数,并将 x 和 y 系数存储到 simplexTable 中。然后,他们单击“下一步”按钮,进入下一个场景。在这个场景中,我调用实际执行单纯形方法的方法,这个场景就是我的问题所在。

使用 Debug.Log 语句,我成功验证了该方法是否已被调用,并且 simplexMethod 中的数据已成功从 Player Prefs 中检索并恢复到 simplexTable 数组中 - 到这里一切都正常工作。

在此之后,我使用 while 循环,因为我只想在表格未最大化时继续应用单纯形方法(即尚未找到最佳解决方案),但每当代码到达这部分时,我的 Unity 编辑器应用程序就会冻结我必须强制退出它。我已经对这个问题做了一些研究,显然当你的代码有无限循环时它可能会发生,但我已经包含了一个在逻辑上合理的break语句,并且我在测试程序时输入的值应该给出一个允许打破循环的解决方案。可能是因为我的笔记本电脑很旧,只有 4GB RAM,但我不确定。

我已经粘贴了下面包含 while 循环的代码部分。

很抱歉给出了不好的解释,但如果有人可以提供帮助,我将非常感激。提前非常感谢!

我的代码:

bool maximised = false;//while the table is unmaximised
while (!maximised)
{
    Debug.Log("while loop started");
   
    int count = 0;
    float[] pivotValueArr = new float[numberOfConstraints + 4];
    float[] pivotColumn = new float[numberOfConstraints];
    float pivotValueCol;

    //iterates through each element in the objective row to check for negative values
    for (int ii = 0; ii < simplexTable.GetColumns(); ii++)
    {
       
        if (ii < simplexTable.GetColumns())
        {
            Debug.Log($"ii: {ii}, Rows: {simplexTable.GetRows()}, Columns: {simplexTable.GetColumns()}");

            if (simplexTable[0, ii] < 0)//IndexOutOfRangeException: Index was outside the bounds of the array
            {
                pivotValueArr[ii] = simplexTable[0, ii];
                count++;
            }
            else
            {
                pivotValueArr[ii] = 0;
            }

        }
        else
        {
            Debug.LogError($"Index out of bounds: ii={ii}, Columns={simplexTable.GetColumns()}");
        }
     
       

    }
   
    Debug.Log($"Loop execution: count = {count}, maximised = {maximised}");

    if (count == 0)
    {
        //maximised = true;
        Debug.Log("break actually gets called");
        break;
    }

    pivotValueCol = pivotValueArr.Min();
    int pivotValueIndex = Array.IndexOf(pivotValueArr, pivotValueArr.Min());

    for (int i = 0; i < numberOfConstraints; i++)
    {
        pivotColumn[i] = simplexTable[i, pivotValueIndex];
    }

    float[] ratioTestArr = new float[numberOfConstraints];
    ratioTestArr[0] = 0;

    for (int i = 1; i < pivotColumn.Length; i++)
    {
        if (simplexTable[i, pivotValueIndex] > 0)
        {
            ratioTestArr[i] = simplexTable[i, numberOfConstraints + 3] / simplexTable[i, pivotValueIndex];
        }                
    }

    int pivotRow = Array.IndexOf(ratioTestArr, ratioTestArr.Min());
    float pivotCell = simplexTable[pivotRow, pivotValueIndex];

    for (int i = 0; i < numberOfConstraints; i++)
    {

        if (i == pivotRow)
        {

            for (int j = 0; j <= numberOfConstraints + 3; j++)
            {
                simplexTable[i, j] = simplexTable[i, j] / pivotCell;
            }

        }

        else
        {
            simplexTable[i, pivotValueIndex] = 0;

            for (int j = 0; j <= numberOfConstraints + 3; j++)
            {

                if (j != pivotValueIndex)
                {
                    simplexTable[i, j] = simplexTable[i, j] - simplexTable[i, j] * (simplexTable[pivotRow, j] / pivotCell);
                }
            }
        }
    }

}

我尝试添加 Debug.Log 语句来识别错误,关闭所有其他应用程序(以防它们占用过多内存),并检查是否存在会导致循环无限执行的逻辑错误。

c# unity-game-engine optimization while-loop linear-programming
1个回答
0
投票

主线程中的While循环在完成之前不会释放任何资源。 所以解决方案是将循环放入协程中 并在每次迭代中添加延迟(yield return waitforendofframe())等

© www.soinside.com 2019 - 2024. All rights reserved.