/// <summary> /// metóda pre získanie zadania úlohy lineárneho programovania z okna /// </summary> /// <param name="variablesCount">počet premenných</param> /// <returns>zadanie úlohy lineárneho programovania</returns> public LPTreeBody GetTaskInput(int variablesCount) { LinearTaskInputWindow dlg = new LinearTaskInputWindow(variablesCount); bool? result = dlg.ShowDialog(); if (result == true) { myTaskType = dlg.TaskType; myTaskFunction = (Equation)dlg.CriterialFunction.Clone(); myTaskConditions = (EquationsCollection)dlg.ConditionFunctions; LPTreeBody tree = new LPTreeBody(dlg.CriterialFunction, dlg.ConditionFunctions, dlg.TaskType); return tree; } return null; }
/// <summary> /// metóda pre pridanie rovnice - ohraničenia /// </summary> /// <param name="theEquation">ohraničenie</param> public void InsertEquation(Equation theEquation) { myConditions.Add(theEquation); }
private int myVariablesCount = 0; //pocet premennych #endregion Fields #region Constructors /// <summary> /// konštruktor /// </summary> /// <param name="theType">typ úlohy</param> /// <param name="theFunction">kriteriálna funkcia</param> public Simplex(LinearTypes theType, Equation theFunction) { myFunction = theFunction; myVariablesCount = myFunction.LeftSide.Count; myType = theType; }
/// <summary> /// metóda pre transformáciu problému do kanonického tvaru /// </summary> public void TransformToCanonicalForm() { // Zmena problemu na maximalizacny. if (myType == LinearTypes.Minimalization) { myType = LinearTypes.Maximalization; myFunction.Multiply(-1); } // Zmena nerovnosti na rovnosti. myConditions.RemoveInequality(); myTempFunction = myConditions.HelpFunction; // Zmena koeficientov na pravej strane na nezaporne. foreach (Equation item in myConditions) { if (item.RightSide < 0) { item.Multiply(-1); } } // Doplnenie 0 do kriteriálnej funkcie for (int i = 0; i < myConditions[0].LeftSide.Count - myVariablesCount; i++) { myFunction.AddVariable(0); } }
/// <summary> /// metóda pre riešenie úlohy simplexovou metódou /// </summary> /// <returns>riešenie</returns> public Solution Solve() { TransformToCanonicalForm(); myFunction.Multiply(-1); //transformacia krit. fcie do tvaru z-ax-...=0 myTempFunction = myConditions.HelpFunction; if (myTempFunction.LeftSide.Count > 0) { if (IsSolveWithHelpFunction() == false) { return null; } } while (!IsOptimal()) //test optimality { int minIndex = FindIndexOfMinimalCoefInFunction(); //vyhladanie min prvku v spodnom riadku PivotResult pivotResult = FindPivot(minIndex); //urcenie pivota + jeho polohy if (pivotResult == null) { return null; } Equation pivotEq = myConditions[pivotResult.Index]; //vyber ohranicenia, v ktorom je pivot foreach (Equation item in myConditions) //prenasobenie ohraniceni - eliminacia na 0 { if (item != pivotEq) { item.Combine(pivotEq, -item.LeftSide[minIndex] / pivotResult.Pivot); } } myFunction.Combine(pivotEq, -myFunction.LeftSide[minIndex] / pivotResult.Pivot); //prenasobenie kf - eliminacia na 0 pivotEq.Multiply((double)1 / pivotResult.Pivot); //prenasobenie ohranicenia, v ktorom je pivot jeho prvratenou hodnotou - eliminacia na 1 } Solution solution = RetrieveSolution(myVariablesCount); return solution; }
/// <summary> /// konštruktor /// </summary> /// <param name="function">kriteriálna funkcia</param> /// <param name="conditions">ohraničenia</param> /// <param name="type">typ úlohy lineárneho programovania</param> public LPTreeBody(Equation function, EquationsCollection conditions, LinearTypes type) { myRoot = new LPTreeItem(function, type, conditions); myUnprocessedItems.Add(myRoot); }
/// <summary> /// metóda pre vytvorenie kópie objektu /// </summary> /// <returns>kópia objektu</returns> public object Clone() { Equation eq = new Equation(new double[] { }, myType.Clone().ToString(), myRightSide); foreach (double item in myLeftSide) { eq.AddVariable(item); } return eq; }
/// <summary> /// metóda pre súčet dvoch rovníc /// </summary> /// <param name="theEquation">rovnica, ktorá má byť pripočítaná k pôvodnej rovnici</param> /// <param name="theFactor">koeficient, ktorým je potrebné pripočítavanú rovnicu vynásobiť</param> public void Combine(Equation theEquation, double theFactor) { //premenná pre uloženie počtu premenných na ľavej strane int leftSideLength = theEquation.LeftSide.Count > this.LeftSide.Count ? theEquation.LeftSide.Count : this.LeftSide.Count; for (int i = 0; i < leftSideLength; i++) { double secondValue = 0; if (i < theEquation.LeftSide.Count) { secondValue = theEquation.LeftSide[i] * theFactor; } if (i < this.LeftSide.Count) { this.LeftSide[i] += secondValue; } } this.myRightSide += theFactor * theEquation.RightSide; }
/// <summary> /// konštuktor /// </summary> /// <param name="function">kriteriálna funkcia</param> /// <param name="type">typ úlohy lineárneho programovaina</param> /// <param name="conditions">ohraničenia</param> public LPTreeItem(Equation function, LinearTypes type, EquationsCollection conditions) { myConditions = conditions; myFunction = function; myType = type; myFunctionBackup = (Equation)function.Clone(); foreach (Equation item in conditions) { myConditionsBackup.Add((Equation)item.Clone()); } Simplex simplex = new Simplex(myType, myFunction); simplex.InsertEquations(myConditions); Solution solution = simplex.Solve(); myNodeSolution = solution; if (solution != null) { myHasSolution = true; double val = double.MinValue; int index = -1; for (int i = 0; i < solution.Count; i++) { if (Math.Abs(Math.Round(solution[i]) - solution[i]) > 0.000005) { val = solution[i]; index = i; break; } } // Ak nie je nájdené riešenie celočíselné: if (val > double.MinValue + 0.000005) { int left = (int)Math.Floor(val); int right = (int)Math.Ceiling(val); // príprava ľavej strany ohraničenia List<double> leftSide = new List<double>(); for (int i = 0; i < myFunctionBackup.LeftSide.Count; i++) { if (i == index) { leftSide.Add(1); } else { leftSide.Add(0); } } // príprava ohraničenia pre ľavého syna EquationsCollection leftConditions = (EquationsCollection)myConditionsBackup.Clone(); leftConditions.Add(new Equation(leftSide, "<=", left)); // príprava ohraničenia pre pravého syna EquationsCollection rightConditions = (EquationsCollection)myConditionsBackup.Clone(); rightConditions.Add(new Equation(leftSide, ">=", right)); // vytvorenie potomkov myLeftChild = new LPTreeItem((Equation)myFunctionBackup.Clone(), myType, (EquationsCollection)leftConditions.Clone()); myRightChild = new LPTreeItem((Equation)myFunctionBackup.Clone(), myType, (EquationsCollection)rightConditions.Clone()); myUpperBound = myFunction.RightSide; } else { // Ak je nájdené riešenie celočíselné: myLowerBound = (int)myFunction.RightSide; myUpperBound = (int)myFunction.RightSide; myIsFinalNode = true; } } }
/// <summary> /// metóda pre výpočet dolnej medze /// </summary> /// <param name="function">kriteriálna funkcia</param> /// <param name="solution">riešenie bez zaokrúhlenia</param> /// <returns>dolná medza daného uzla</returns> public double CountLowerBound(Equation function, Solution solution) { double lowerBoundFromRounding = 0; Solution roundedSolution = new Solution(); foreach (double i in solution) { roundedSolution.Add(Math.Round(i)); } foreach (double i in solution) { foreach (double j in function.LeftSide) { if (solution.IndexOf(i)==function.LeftSide.IndexOf(j)) { lowerBoundFromRounding += j * i; } } } return lowerBoundFromRounding; }