void OnEnable()
    {
        frameCounter      = 0;
        allNodesGenerated = false;

        node = new List <SystemNode>();
        float[] prod = new float[1]; prod[0] = +1f;
        node.Add(new SystemNode(new Vector3(0, 0, 1), prod, 1f));
        prod = new float[1]; prod[0] = -0.4f;
        node.Add(new SystemNode(new Vector3(-0.6f, 0, 0), prod, 1f));
        prod = new float[1]; prod[0] = -0.6f;
        node.Add(new SystemNode(new Vector3(+0.6f, 0, 0), prod, 1f));
        for (int a = 0; a < node.Count; a++)
        {
            for (int b = 0; b < node.Count; b++)
            {
                if (b != a)
                {
                    node[a].AddDistanceEdge(new DistanceEdge(node[b], (node[a].pos - node[b].pos).magnitude));
                }
            }
        }

        LinearProgrammingSolution solution = LinearProgramming.MinimumCostFlow(node);

        // Interpret analysis results
        for (int i = 0; i < solution.source.Count; i++)
        {
            solution.source[i].AddResourceEdge(new ResourceEdge(solution.target[i], solution.magnitude[i]));
        }
    }
    /*
     * A linear programming problem is in STANDARD FORM if it seeks to MAXIMISE the objective
     * function z = c1x1 + c2x2 + ... + cnxn subject to the constraints:
     * a11x1 + a12x2 + ... + a1nxn <= b1
     * a21x1 + a22x2 + ... + a2nxn <= b2
     *  ...     ...    ...    ...    ...
     * am1x1 + am2x2 + ... + amnxn <= bm
     * where xi >= 0 and bi >= 0.
     * After adding slack variables, the corresponding system of CONSTRAINT EQUATIONS is:
     * a11x1 + a12x2 + ... + a1nxn + s1           = b1
     * a21x1 + a22x2 + ... + a2nxn      + s2      = b2
     *  ...     ...    ...    ...                  ...
     * am1x1 + am2x2 + ... + amnxn           + sm = bm
     * where si >= 0.
     */

    /*
     * Note that for a linear programming problem in standard form, the objective is to be
     * maximised, not minimised.
     */

    /* A BASIC SOLUTION of a linear programming problem in standard form is a solution
     * (x1, x2, ..., xn, s1, s2, ..., sm) of the constraint equations in which AT MOST m variables
     * are nonzero - the variables that are nonzero are called BASIC VARIABLES. A basic solution
     * for which all variables are nonnegative is called a BASIC FEASIBLE SOLUTION.
     */

    /*
     * The simplex method is carried out by performing elementary row operations on a matrix that
     * we call the SIMPLEX TABLEAU. This tableau consists of the augmented matrix corresponding
     * to the constraint equations together with the coefficients of the objective function written
     * in the form
     * -c1x1 - c2x2 - ... - cnxn + (0)s1 + (0)s2 + ... + (0)sm + z = 0
     * In the tableau, it is customary to omit the coefficient of z. For instance, the simplex
     * tableau for the linear programming problem
     * z = 4x1 + 6x2       objective function
     * x1, x2 >= 0         constraint
     * -x1 + x2 + s1 = 11  constraint
     * x1 + x2 + s2 = 27   constraint
     * 2x1 + 5x2 + s3 = 90 constraint
     * is as follows.
     */

    /*
     * x1   x2   s1   s2   s3   b   basic variables
     * -1   +1   +1    0    0   11   s1
     * +1   +1    0   +1    0   27   s2
     * +2   +5    0    0   +1   90   s3
     * ---------------------------
     * -4   -6    0    0    0    0 <-- current z-value
     */

    public static LinearProgrammingSolution MinimumCostFlow(List <SystemNode> systemNode)
    {
        Debug.Log("Performing minimum-cost flow analysis.");

        // Take a copy of the network
        //List<SystemNode> copy = new List<SystemNode>();
        //foreach (SystemNode n in systemNode) copy.Add(n.TakeCopy());

        Debug.Log("Network copy taken.");

        int nSurrogate = Surrogate(systemNode);

        Debug.Log(nSurrogate + " surrogate nodes inserted.");

        // Count the number of nodes and edges
        int numNodes = 0;
        int numEdges = 0;

        foreach (SystemNode n in systemNode)
        {
            numNodes++;
            foreach (DistanceEdge d in n.distance)
            {
                numEdges++;
            }
        }

        Debug.Log("Number of nodes: " + numNodes);
        Debug.Log("Number of edges: " + numEdges);

        //float[,] tableau = BuildMatrix(copy, numNodes, numEdges);
        float[,] matrix = BuildMatrix(systemNode, numNodes, numEdges);

        Debug.Log("Augmented matrix constructed.");

        //PrintTableau(matrix);

        float[] rawResult = Minimise(matrix);

        // Interpret result
        float[] flows = new float[numEdges];
        float   cost  = rawResult[rawResult.Length - 1];

        for (int i = 0; i < numEdges; i++)
        {
            int index = rawResult.Length - numEdges - 1 + i;
            flows[i] = rawResult[index];
        }

        // Record resource flow edge data
        List <SystemNode> source    = new List <SystemNode>();
        List <Node>       target    = new List <Node>();
        List <float>      magnitude = new List <float>();
        int nodeIndex = -1;
        int edgeIndex = -1;

        foreach (SystemNode n in systemNode)
        {
            nodeIndex++;
            foreach (DistanceEdge d in n.distance)
            {
                edgeIndex++;
                if (flows[edgeIndex] > 0)
                {
                    if (!n.surrogate && !d.target.surrogate)
                    {
                        source.Add(n);
                        target.Add(d.target);
                        magnitude.Add(flows[edgeIndex]);
                    }
                }
            }
        }

        // Build solution
        LinearProgrammingSolution solution = new LinearProgrammingSolution(source, target, magnitude);

        // Destroy surrogate nodes
        List <int> surrogateIndex = new List <int>();

        for (int i = 0; i < systemNode.Count; i++)
        {
            if (systemNode[i].surrogate)
            {
                surrogateIndex.Add(i);
            }
        }
        //for (int i = 0; i < surrogateIndex.Count; i++)
        //{
        //    int j = surrogateIndex.Count - 1 - i;
        //    systemNode.RemoveAt(j);
        //}

        // Return the solution
        return(solution);
    }