public void Restore(LinearProgram linearProgram, double[] originalCoeficients, int[] originalIndices)
        {
            var newObjective = new double[linearProgram.ObjectiveCoefficients.Length];

            for (var i = 1; i < originalIndices.Length; i++)
            {
                var originalIndice = originalIndices[i];
                var originalCoef   = originalCoeficients[i];

                if (linearProgram.NonBasicIndices.Contains(originalIndice))
                {
                    var index = Array.FindIndex(linearProgram.NonBasicIndices, n => n == originalIndice);
                    var ttmp  = new double[linearProgram.ObjectiveCoefficients.Length];
                    ttmp[index] = originalCoef;
                    AddArray(newObjective, ttmp);
                }
                else
                {
                    var index = Array.FindIndex(linearProgram.BasicIndices, b => b == originalIndice);

                    var tmp = new double[linearProgram.ObjectiveCoefficients.Length];
                    linearProgram.Coefficients[index].CopyTo(tmp, 0);

                    AddArray(newObjective, tmp, originalCoef);
                }
            }

            linearProgram.ObjectiveCoefficients = newObjective;
        }
コード例 #2
0
        public LinearProgamSolution Solve(LinearProgram linearProgram)
        {
            //check if needs initialization
            bool needsInit = linearProgram.Coefficients.Any(c => c[0] < 0);

            if (needsInit)
            {
                //solve dual
                var dual    = _mapPrimalToDual.Map(linearProgram);
                var dualSol = SolveSingle(dual);

                //todo: check if feasbile
                if (dualSol.SolutionType != LinearProgramSolutionType.Solved)
                {
                    return(new LinearProgamSolution(0, 0, LinearProgramSolutionType.Infeasible));
                }

                //map back to primal
                var primal = _mapDualToPrimal.Map(dual);

                //restore objective
                _restoreObjective.Restore(primal, dual.OriginalObjectiveCoefficients, dual.OriginalNonBasicIndices);

                //solve
                var primalSol = SolveSingle(primal);
                return(primalSol);
            }
            else
            {
                return(SolveSingle(linearProgram));
            }
        }
コード例 #3
0
        private LinearProgamSolution SolveSingle(LinearProgram linearProgram)
        {
            var pivotCount = 0;

            while (true)
            {
                //do this until no entering, or stop if unbounded
                _analyze.Analyze(linearProgram);

                //no entering, must be solved
                if (_analyze.Entering == 0)
                {
                    break;
                }

                //if unbounded
                if (_analyze.Leaving == 0)
                {
                    return(new LinearProgamSolution(0, 0, LinearProgramSolutionType.Unbounded));
                }

                //if here, we can pivot
                ++pivotCount;

                _pivotor.Pivot(_analyze.Entering, _analyze.Leaving, linearProgram);
            }

            return(new LinearProgamSolution(linearProgram.ObjectiveValue, pivotCount, LinearProgramSolutionType.Solved));
        }
コード例 #4
0
        private int GetEntering(LinearProgram linearProgram)
        {
            var objectiveCoefficients = linearProgram.ObjectiveCoefficients;
            var nonbasic = linearProgram.NonBasicIndices;
            var n        = linearProgram.N;

            //pick entering var (coeff > 0)
            var enteringPos = int.MaxValue;

            for (var j = 1; j <= n; j++)
            {
                if (objectiveCoefficients[j] > 0.0)
                {
                    if (enteringPos == int.MaxValue ||
                        nonbasic[j] < nonbasic[enteringPos])
                    {
                        enteringPos = j;
                    }
                }
            }

            if (enteringPos == int.MaxValue)
            {
                return(0);
            }

            _enteringPos = enteringPos;
            return(nonbasic[enteringPos]);
        }
コード例 #5
0
        public void Analyze(LinearProgram linearProgram)
        {
            Entering = GetEntering(linearProgram);
            //if unbounded
            if (Entering == 0)
            {
                return;
            }

            Leaving = GetLeaving(linearProgram);
        }
        public LinearProgram Read(string fileName)
        {
            var lp = new LinearProgram();

            var lines = File.ReadAllLines(fileName);

            var sizeVars = GetInts(lines[0]);

            lp.M = sizeVars[0];
            lp.N = sizeVars[1];

            var basic = GetInts(lines[1]);

            lp.BasicIndices = new int[basic.Length + 1];
            basic.CopyTo(lp.BasicIndices, 1);

            var nonBasic = GetInts(lines[2]);

            lp.NonBasicIndices = new int[nonBasic.Length + 1];
            nonBasic.CopyTo(lp.NonBasicIndices, 1);

            var bVars = GetDoubles(lines[3]);

            lp.Coefficients = new double[bVars.Length + 1][];

            int m = 0;

            for (int i = 4; i < lines.Length; i++)
            {
                var values = GetDoubles(lines[i]);

                if (i == lines.Length - 1)
                {
                    lp.ObjectiveCoefficients = values;
                }
                else
                {
                    if (m == 0)
                    {
                        lp.Coefficients[m] = new double[values.Length + 1];
                    }
                    ++m;
                    lp.Coefficients[m]    = new double[values.Length + 1];
                    lp.Coefficients[m][0] = bVars[m - 1];
                    values.CopyTo(lp.Coefficients[m], 1);
                }
            }

            return(lp);
        }
コード例 #7
0
        public void Pivot(int entering, int leaving, LinearProgram linearProgram)
        {
            var enteringPos = Array.FindIndex(linearProgram.NonBasicIndices, i => i == entering);
            var leavingPos  = Array.FindIndex(linearProgram.BasicIndices, i => i == leaving);

            var a = linearProgram.ObjectiveCoefficients;
            var b = linearProgram.Coefficients[leavingPos];

            var m = a[enteringPos];
            var n = b[enteringPos];

            var objValue = a[0] + m * b[0] / -n;

            linearProgram.ObjectiveCoefficients[0] = objValue;
        }
コード例 #8
0
        public void Pivot(int entering, int leaving, LinearProgram linearProgram)
        {
            var enteringPos = Array.FindIndex(linearProgram.NonBasicIndices, i => i == entering);
            var leavingPos  = Array.FindIndex(linearProgram.BasicIndices, i => i == leaving);

            var a = linearProgram.ObjectiveCoefficients;
            var b = linearProgram.Coefficients[leavingPos];

            //update leaving row:
            // - calculate new coefficients
            var n = b[enteringPos];

            b[enteringPos] = -1.0;
            var multiplier = 1 / -n;

            MultiplyArray(b, multiplier);

            //update other rows
            for (var i = 1; i < linearProgram.Coefficients.Length; i++)
            {
                //already updated leaving row
                if (i == leavingPos)
                {
                    continue;
                }
                //the row to update
                var bb = linearProgram.Coefficients[i];
                //the coefficient in this row
                var c = bb[enteringPos];
                //reset coefficient for array addition
                bb[enteringPos] = 0.0;

                AddArray(bb, b, c);
            }

            //update objective row
            var oc = a[enteringPos];

            a[enteringPos] = 0;
            AddArray(a, b, oc);

            //update basic / non-basic indices
            linearProgram.BasicIndices[leavingPos]     = entering;
            linearProgram.NonBasicIndices[enteringPos] = leaving;
        }
コード例 #9
0
        private int GetLeaving(LinearProgram linearProgram)
        {
            var coefficients = linearProgram.Coefficients;
            var m            = linearProgram.M;
            var basic        = linearProgram.BasicIndices;
            var enteringPos  = _enteringPos;

            //pick leaving var (coeff <= 0, value within constraints)
            var leavingPos   = int.MaxValue;
            var leavingValue = double.MaxValue;

            for (var i = 1; i <= m; i++)
            {
                var c = coefficients[i][enteringPos];
                if (c < 0)
                {
                    var value = coefficients[i][0] / -c;

                    if (value < leavingValue)
                    {
                        leavingValue = value;
                        leavingPos   = i;
                    }
                    else if (Math.Abs(value - leavingValue) < .00001)
                    {
                        if (basic[i] < basic[leavingPos])
                        {
                            leavingPos = i;
                        }
                    }
                }
            }

            if (leavingPos == int.MaxValue)
            {
                return(0);
            }
            return(basic[leavingPos]);
        }
コード例 #10
0
        //[Line 1] m n
        //[Line 2] B1 B2 ... Bm [the list of basic indices m integers]
        //[Line 3] N1 N2 ... Nn [the list of non-basic indices n integers]
        //[Line 4] b1 .. bm (m floating point numbers)
        //[Line 5] a11 ... a1n (first row coefficients. See dictionary notation above.)
        //....
        //[Line m+4] am1 ... amn (mth row coefficients. See dictionary notation above.)
        //[Line m+5] z0 c1 .. cn (objective coefficients (n+1 floating point numbers))

        public DualLinearProgram Map(LinearProgram primal)
        {
            var dual = new DualLinearProgram();

            dual.M = primal.N;
            dual.N = primal.M;
            dual.OriginalObjectiveCoefficients = primal.ObjectiveCoefficients;
            dual.OriginalNonBasicIndices       = primal.NonBasicIndices;

            dual.BasicIndices    = new int[primal.NonBasicIndices.Length];
            dual.NonBasicIndices = new int[primal.BasicIndices.Length];

            dual.Coefficients = new double[primal.Coefficients[0].Length][];

            dual.ObjectiveCoefficients = new double[primal.BasicIndices.Length];

            //map primal coefficients to dual coefficients
            var a = primal.Coefficients.Length;

            for (var i = 0; i < dual.Coefficients.Length; i++)
            {
                dual.Coefficients[i] = new double[a];//empty row for 1-based indexes
                if (i == 0)
                {
                    continue;
                }

                for (var k = 1; k < primal.Coefficients.Length; k++)
                {
                    dual.Coefficients[i][k] = -primal.Coefficients[k][i];
                }
            }

            //map 1 to dual coefficients b-value
            for (var i = 1; i < primal.ObjectiveCoefficients.Length; i++)
            {
                dual.Coefficients[i][0] = 1;
            }

            //map primal b values to dual objective coefficients
            for (var i = 1; i < primal.Coefficients.Length; i++)
            {
                dual.ObjectiveCoefficients[i] = -primal.Coefficients[i][0];
            }

            //set basic / non basic indices
            var y = 0;

            for (var i = 1; i < dual.BasicIndices.Length; i++)
            {
                dual.BasicIndices[i] = ++y;
            }
            for (var i = 1; i < dual.NonBasicIndices.Length; i++)
            {
                dual.NonBasicIndices[i] = ++y;
            }

            //set complements
            dual.Complements    = new int[2][];
            dual.Complements[0] = primal.NonBasicIndices.Skip(1).Concat(primal.BasicIndices.Skip(1)).ToArray();
            dual.Complements[1] = dual.NonBasicIndices.Skip(1).Concat(dual.BasicIndices.Skip(1)).ToArray();

            return(dual);
        }