/// <summary> /// Auxilia a acçáo em cadeia. /// </summary> /// <param name="startNode">O nó de início.</param> private void InnerChainReaction(TransportationMatrixTreeNode startNode) { var currentNode = startNode.Next; if (currentNode == null) { return; } var minimumAllocation = this.resultMatrix[currentNode.Line, currentNode.Column]; var toRemoveNode = currentNode; currentNode = currentNode.Next; bool status = false; while (currentNode != null) { if (status) { var temp = resultMatrix[currentNode.Line, currentNode.Column]; if (temp < minimumAllocation) { minimumAllocation = temp; toRemoveNode = currentNode; } } currentNode = currentNode.Next; status = !status; } currentNode = startNode; while (currentNode != null) { resultMatrix[currentNode.Line, currentNode.Column] += minimumAllocation; currentNode = currentNode.Next; resultMatrix[currentNode.Line, currentNode.Column] -= minimumAllocation; currentNode = currentNode.Next; } resultMatrix[toRemoveNode.Line, toRemoveNode.Column] = -1; resultMatrix[startNode.Line, startNode.Column] = minimumAllocation; }
/// <summary> /// Aplica a acção em cadeia. /// </summary> /// <returns>Verdadeiro caso uma alteração tenha sido processada e falso caso contrário.</returns> /// <exception cref="MathematicsException">Em caso de erro interno.</exception> private bool ChainReaction() { double minimumCost = 0; int chosenLine = -1; int chosenColumn = -1; for (int i = 0; i < this.supplyNumber; ++i) { for (int j = 0; j < this.demandNumber; ++j) { double temporary = this.transportationCost[i, j] - u[i] - v[j]; if (temporary < minimumCost) { minimumCost = temporary; chosenLine = i; chosenColumn = j; } } } if (chosenLine == -1 || chosenColumn == -1) { return(false); } bool[] isRowEliminated = new bool[this.supplyNumber]; bool[] isColumnEliminated = new bool[this.demandNumber]; Queue <TransportationMatrixTreeNode> nodeQueue = new Queue <TransportationMatrixTreeNode>(); var startNode = new TransportationMatrixTreeNode() { Line = chosenLine, Column = chosenColumn }; for (int i = 0; i < this.demandNumber; ++i) { if (this.resultMatrix[chosenLine, i] != -1 && i != chosenColumn) { nodeQueue.Enqueue(new TransportationMatrixTreeNode() { Line = chosenLine, Column = i, }); } } isRowEliminated[chosenLine] = true; while (nodeQueue.Count != 0) { var currentNode = nodeQueue.Dequeue(); if (!isRowEliminated[currentNode.Line]) { for (int i = 0; i < this.demandNumber; ++i) { if (currentNode.Line == startNode.Line && i == startNode.Column) { startNode.Next = currentNode; this.InnerChainReaction(startNode); return(true); } if (this.resultMatrix[currentNode.Line, i] != -1 && i != currentNode.Column && !isColumnEliminated[i]) { if (!nodeQueue.Any(n => n.Line == currentNode.Line && n.Column == i)) { nodeQueue.Enqueue(new TransportationMatrixTreeNode() { Line = currentNode.Line, Column = i, Next = currentNode }); } } } isRowEliminated[currentNode.Line] = true; } if (!isColumnEliminated[currentNode.Column]) { for (int i = 0; i < this.supplyNumber; ++i) { if (i == startNode.Line && currentNode.Column == startNode.Column) { startNode.Next = currentNode; this.InnerChainReaction(startNode); return(true); } if (this.resultMatrix[i, currentNode.Column] != -1 && i != currentNode.Line && !isRowEliminated[i]) { if (!nodeQueue.Any(n => n.Line == i && n.Column == currentNode.Column)) { nodeQueue.Enqueue(new TransportationMatrixTreeNode() { Line = i, Column = currentNode.Column, Next = currentNode }); } } } isColumnEliminated[currentNode.Column] = true; } } throw new MathematicsException("An error occured while processing chain reacion."); }