Ejemplo n.º 1
0
 public GLPK(int a, int b)
 {
     this.a = a;
     this.b = b;
     lp = glp_create_prob();
     //Col 1 is x, Col 2 is y
     glp_add_rows(lp, 1);
     glp_add_cols(lp, 2);
     glp_set_col_bnds(lp, 1, GLP_FR, 0.0, 0.0);
     glp_set_col_bnds(lp, 2, GLP_FR, 0.0, 0.0);
     glp_set_col_kind(lp, 1, GLP_IV);
     glp_set_col_kind(lp, 2, GLP_IV);
     //Row 1 is a*x + b*y
     ConstraintMatrix CM = new ConstraintMatrix();
     CM.ia[1]=1; CM.ja[1]=1; CM.ar[1]=a;
     CM.ia[2]=1; CM.ja[2]=2; CM.ar[2]=b;
     glp_load_matrix(lp, 2, CM.ia, CM.ja, CM.ar);
     Console.WriteLine("Hello Nigel");
 }
Ejemplo n.º 2
0
    public GLPK(int a, int b)
    {
        this.a = a;
        this.b = b;
        lp     = glp_create_prob();
        //Col 1 is x, Col 2 is y
        glp_add_rows(lp, 1);
        glp_add_cols(lp, 2);
        glp_set_col_bnds(lp, 1, GLP_FR, 0.0, 0.0);
        glp_set_col_bnds(lp, 2, GLP_FR, 0.0, 0.0);
        glp_set_col_kind(lp, 1, GLP_IV);
        glp_set_col_kind(lp, 2, GLP_IV);
        //Row 1 is a*x + b*y
        ConstraintMatrix CM = new ConstraintMatrix();

        CM.ia[1] = 1; CM.ja[1] = 1; CM.ar[1] = a;
        CM.ia[2] = 1; CM.ja[2] = 2; CM.ar[2] = b;
        glp_load_matrix(lp, 2, CM.ia, CM.ja, CM.ar);
        Console.WriteLine("Hello Nigel");
    }
Ejemplo n.º 3
0
        //
        // This routine uses the Goldfarb/Idnani algorithm to solve the
        // following minimization problem:
        //
        //       minimize 1/2 * x^T D x + d^T x
        //       where   A1 x  = b1
        //               A2 x >= b2
        //
        // the matrix D is assumed to be positive definite.  Especially,
        // w.l.o.g. D is assumed to be symmetric. This is slightly different
        // from the original implementation by Berwin A. Turlach.
        //
        // Input parameter:
        // dmat   nxn matrix, the matrix D from above (dp)
        //        *** WILL BE DESTROYED ON EXIT ***
        //        The user has two possibilities:
        //        a) Give D (ierr=0), in this case we use routines from LINPACK
        //           to decompose D.
        //        b) To get the algorithm started we need R^-1, where D=R^TR.
        //           So if it is cheaper to calculate R^-1 in another way (D may
        //           be a band matrix) then with the general routine, the user
        //           may pass R^{-1}.  Indicated by ierr not equal to zero.
        // dvec   nx1 vector, the vector d from above (dp)
        //        *** WILL BE DESTROYED ON EXIT ***
        //        contains on exit the solution to the initial, i.e.,
        //        unconstrained problem
        // fddmat scalar, the leading dimension of the matrix dmat
        // n      the dimension of dmat and dvec (int)
        // amat   nxq matrix, the matrix A from above (dp) [ A=(A1 A2) ]
        //        *** ENTRIES CORRESPONDING TO EQUALITY CONSTRAINTS MAY HAVE
        //            CHANGED SIGNES ON EXIT ***
        // bvec   qx1 vector, the vector of constants b in the constraints (dp)
        //        [ b = (b1^T b2^T)^T ]
        //        *** ENTRIES CORRESPONDING TO EQUALITY CONSTRAINTS MAY HAVE
        //            CHANGED SIGNES ON EXIT ***
        // fdamat the first dimension of amat as declared in the calling program.
        //        fdamat >= n !!
        // q      int, the number of constraints.
        // meq    int, the number of equality constraints, 0 <= meq <= q.
        // ierr   int, code for the status of the matrix D:
        //           ierr =  0, we have to decompose D
        //           ierr != 0, D is already decomposed into D=R^TR and we were
        //                      given R^{-1}.
        //
        // Output parameter:
        // sol   nx1 the final solution (x in the notation above)
        // crval scalar, the value of the criterion at the minimum
        // iact  qx1 vector, the constraints which are active in the final
        //       fit (int)
        // nact  scalar, the number of constraints active in the final fit (int)
        // iter  2x1 vector, first component gives the number of "main"
        //       iterations, the second one says how many constraints were
        //        deleted after they became active
        //  ierr  int, error code on exit, if
        //          ierr = 0, no problems
        //          ierr = 1, the minimization problem has no solution
        //          ierr = 2, problems with decomposing D, in this case sol
        //                     contains garbage!!
        //
        //  Working space:
        //  work  vector with length at least 2n+r*(r+5)/2 + 2q +1
        //        where r=min(n,q)
        //
        private void qpgen2(double[,] dmat, double[] dvec, int[] iact, out int nact, ref int ierr)
        {
            var n    = NumberOfVariables;
            var q    = NumberOfConstraints;
            var meq  = NumberOfEqualities;
            var amat = (double[, ])ConstraintMatrix.Clone();
            var bvec = (double[])constraintValues.Clone();
            var sol  = Solution;

            int    l1;
            double gc, gs, tt, sum;

            double f = 0;

            nact = 0;
            // Store the initial dvec to calculate below the
            //  unconstrained minima of the critical value.

            Array.Clear(iwzv, 0, iwzv.Length);
            Array.Clear(iwrv, 0, iwrv.Length);
            Array.Clear(iwuv, 0, iwuv.Length);
            Array.Clear(iwrm, 0, iwrm.Length);
            Array.Clear(iwsv, 0, iwsv.Length);
            Array.Clear(iwnbv, 0, iwnbv.Length);

            for (var i = 0; i < dvec.Length; i++)
            {
                work[i] = dvec[i];
            }

            for (var i = 0; i < iact.Length; i++)
            {
                iact[i] = -1;
            }
            // Get the initial solution
            if (ierr == 0)
            {
                // L'L = chol(D)
                var success = dpofa(dmat);

                if (!success)
                {
                    ierr = 2;
                    return;
                }

                // L*x = d
                dposl(dmat, dvec);

                // D = inv(L)
                dpori(dmat);
            }
            else
            {
                // Matrix D is already factorized, so we have to multiply d first with
                // R^-T and then with R^-1.  R^-1 is stored in the upper half of the
                // array dmat.

                for (var j = 0; j < sol.Length; j++)
                {
                    sol[j] = 0.0;

                    for (var i = 0; i < j; i++)
                    {
                        sol[j] += dmat[j, i] * dvec[i];
                    }
                }

                for (var j = 0; j < dvec.Length; j++)
                {
                    dvec[j] = 0.0;

                    for (var i = j; i < sol.Length; i++)
                    {
                        dvec[j] += dmat[i, j] * sol[i];
                    }
                }
            }

            // Set upper triangular of dmat to zero, store dvec in sol and
            //   calculate value of the criterion at unconstrained minima

            f = 0.0;

            // calculate some constants, i.e., from which index on
            // the different quantities are stored in the work matrix

            for (var j = 0; j < sol.Length; j++)
            {
                sol[j]  = dvec[j];
                f      += work[j] * sol[j];
                work[j] = 0.0;

                for (var i = j + 1; i < n; i++)
                {
                    dmat[j, i] = 0.0;
                }
            }

            f    = -f / 2.0;
            ierr = 0;
            // calculate the norm of each column of the A matrix

            for (var i = 0; i < iwnbv.Length; i++)
            {
                sum = 0.0;
                for (var j = 0; j < n; j++)
                {
                    sum += amat[i, j] * amat[i, j];
                }

                iwnbv[i] = Math.Sqrt(sum);
            }

            nact       = 0;
            Iterations = 0;
            Deletions  = 0;
L50:        // start a new iteration

            if (Token.IsCancellationRequested)
            {
                return;
            }

            Iterations++;

            if (MaxIterations > 0 && Iterations > MaxIterations)
            {
                return;
            }

            // calculate all constraints and check which are still violated
            // for the equality constraints we have to check whether the normal
            // vector has to be negated (as well as bvec in that case)

            var l = 0;

            for (var i = 0; i < bvec.Length; i++)
            {
                sum = -bvec[i];

                for (var j = 0; j < sol.Length; j++)
                {
                    sum += amat[i, j] * sol[j];
                }

                if (Math.Abs(sum) < Constants.DoubleEpsilon)
                {
                    sum = 0.0;
                }

                if (double.IsNaN(sum))
                {
                    sum = 0.0;
                }

                if (i >= meq)
                {
                    // this is an inequality constraint
                    iwsv[l] = sum;
                }
                else
                {
                    // this is an equality constraint
                    iwsv[l] = -Math.Abs(sum);

                    if (sum > 0.0)
                    {
                        for (var j = 0; j < n; j++)
                        {
                            amat[i, j] = -amat[i, j];
                        }
                        bvec[i] = -bvec[i];
                    }
                }

                l++;
            }

            // as safeguard against rounding errors set
            // already active constraints explicitly to zero

            for (var i = 0; i < nact; i++)
            {
                iwsv[iact[i]] = 0.0;
            }

            // We weight each violation by the number of non-zero elements in the
            // corresponding row of A. then we choose the violated constraint which
            // has maximal absolute value, i.e., the minimum. By obvious commenting
            // and uncommenting we can choose the strategy to take always the first
            // constraint which is violated. ;-)

            var nvl  = -1;
            var temp = 0.0;

            for (var i = 0; i < iwnbv.Length; i++)
            {
                var w   = temp * iwnbv[i];
                var tol = constraintTolerances[i];

                if (iwsv[i] < w - tol)
                {
                    nvl  = i;
                    temp = iwsv[i] / iwnbv[i];
                }

                // if (work(iwsv+i) .LT. 0.d0) then
                //     nvl = i
                //     goto 72
                // endif
            }

            if (nvl == -1)
            {
                return;
            }
L55:

            // calculate d=J^Tn^+ where n^+ is the normal vector of the violated
            // constraint. J is stored in dmat in this implementation!!
            // if we drop a constraint, we have to jump back here.

            for (var i = 0; i < work.Length; i++)
            {
                sum = 0.0;
                for (var j = 0; j < n; j++)
                {
                    sum += dmat[i, j] * amat[nvl, j];
                }

                work[i] = sum;
            }

            // Now calculate z = J_2 d_2 ...

            for (var i = 0; i < iwzv.Length; i++)
            {
                iwzv[i] = 0.0;
            }

            for (var j = nact; j < work.Length; j++)
            {
                for (var i = 0; i < iwzv.Length; i++)
                {
                    iwzv[i] += dmat[j, i] * work[j];
                }
            }

            // ... and r = R^{-1} d_1, check also if r has positive elements
            // (among the entries corresponding to inequalities constraints).

            l1 = 0;
            var    it1   = 0;
            double t1    = 0;
            var    t1inf = true;

            for (var i = nact - 1; i >= 0; i--)
            {
                sum = work[i];
                l   = (i + 1) * (i + 4) / 2 - 1;
                l1  = l - i - 1;

                for (var j = i + 1; j < nact; j++)
                {
                    sum -= iwrm[l] * iwrv[j];
                    l   += j + 1;
                }

                sum /= iwrm[l1];

                iwrv[i] = sum;

                if (iact[i] < meq)
                {
                    continue;
                }

                if (sum <= 0.0)
                {
                    continue;
                }

                if (double.IsNaN(sum))
                {
                    continue;
                }

                t1inf = false;
                it1   = i + 1;
            }
            // if r has positive elements, find the partial step length t1, which is
            // the maximum step in dual space without violating dual feasibility.
            // it1 stores in which component t1, the min of u/r, occurs.

            if (!t1inf)
            {
                t1 = iwuv[it1 - 1] / iwrv[it1 - 1];

                for (var i = 0; i < nact; i++)
                {
                    if (iact[i] < meq)
                    {
                        continue;
                    }

                    if (iwrv[i] <= 0.0)
                    {
                        continue;
                    }

                    temp = iwuv[i] / iwrv[i];

                    if (temp < t1)
                    {
                        t1  = temp;
                        it1 = i + 1;
                    }
                }
            }
            // test if the z vector is equal to zero

            sum = 0.0;
            for (var i = 0; i < iwzv.Length; i++)
            {
                sum += iwzv[i] * iwzv[i];
            }

            if (Math.Abs(sum) <= Constants.DoubleEpsilon)
            {
                // No step in primal space such that the new constraint becomes
                // feasible. Take step in dual space and drop a constant.

                if (t1inf)
                {
                    // No step in dual space possible
                    // either, problem is not solvable
                    ierr = 1;
                    return;
                }
                // we take a partial step in dual space and drop constraint it1,
                // that is, we drop the it1-th active constraint.
                // then we continue at step 2(a) (marked by label 55)

                for (var i = 0; i < nact; i++)
                {
                    iwuv[i] -= t1 * iwrv[i];
                }

                iwuv[nact] += t1;
                goto L700;
            }
            // compute full step length t2, minimum step in primal space such that
            // the constraint becomes feasible.
            // keep sum (which is z^Tn^+) to update crval below!

            sum = 0.0;
            for (var i = 0; i < iwzv.Length; i++)
            {
                sum += iwzv[i] * amat[nvl, i];
            }

            tt = -iwsv[nvl] / sum;
            var t2min = true;

            if (!t1inf)
            {
                if (t1 < tt)
                {
                    tt    = t1;
                    t2min = false;
                }
            }

            // take step in primal and dual space
            for (var i = 0; i < sol.Length; i++)
            {
                sol[i] += tt * iwzv[i];
            }

            f += tt * sum * (tt / 2.0 + iwuv[nact]);

            for (var i = 0; i < nact; i++)
            {
                iwuv[i] -= tt * iwrv[i];
            }

            iwuv[nact] += tt;

            // if it was a full step, then we check whether further constraints are
            // violated otherwise we can drop the current constraint and iterate once
            // more

            if (t2min)
            {
                // we took a full step. Thus add constraint nvl to the list of active
                // constraints and update J and R

                iact[nact++] = nvl;
                // to update R we have to put the first nact-1 components of the d vector
                // into column (nact) of R

                l = (nact - 1) * nact / 2;
                for (var i = 0; i < nact - 1; i++, l++)
                {
                    iwrm[l] = work[i];
                }

                // if now nact=n, then we just have to add the last element to the new
                // row of R.

                // Otherwise we use Givens transformations to turn the vector d(nact:n)
                // into a multiple of the first unit vector. That multiple goes into the
                // last element of the new row of R and J is accordingly updated by the
                // Givens transformations.

                if (nact == n)
                {
                    iwrm[l] = work[n - 1];
                }
                else
                {
                    for (var i = n - 1; i >= nact; i--)
                    {
                        // We have to find the Givens rotation which will reduce the element
                        // (l1) of d to zero. If it is already zero we don't have to do anything,
                        // except of decreasing l1

                        if (work[i] == 0.0)
                        {
                            continue;
                        }

                        gc   = Math.Max(Math.Abs(work[i - 1]), Math.Abs(work[i]));
                        gs   = Math.Min(Math.Abs(work[i - 1]), Math.Abs(work[i]));
                        temp = Special.Sign(gc * Math.Sqrt(1.0 + gs * gs / (gc * gc)), work[i - 1]);
                        gc   = work[i - 1] / temp;
                        gs   = work[i] / temp;

                        // The Givens rotation is done with the matrix (gc gs, gs -gc). If
                        // gc is one, then element (i) of d is zero compared with element
                        // (l1-1). Hence we don't have to do anything. If gc is zero, then
                        // we just have to switch column (i) and column (i-1) of J. Since
                        // we only switch columns in J, we have to be careful how we update
                        // d depending on the sign of gs. Otherwise we have to apply the
                        // Givens rotation to these columns. The i-1 element of d has to be
                        // updated to temp.

                        if (gc == 1.0)
                        {
                            continue;
                        }

                        if (gc == 0.0)
                        {
                            work[i - 1] = gs * temp;

                            for (var j = 0; j < n; j++)
                            {
                                temp           = dmat[i - 1, j];
                                dmat[i - 1, j] = dmat[i, j];
                                dmat[i, j]     = temp;
                            }
                        }
                        else
                        {
                            work[i - 1] = temp;
                            var nu = gs / (gc + 1.0);

                            for (var j = 0; j < n; j++)
                            {
                                temp           = gc * dmat[i - 1, j] + gs * dmat[i, j];
                                dmat[i, j]     = nu * (dmat[i - 1, j] + temp) - dmat[i, j];
                                dmat[i - 1, j] = temp;
                            }
                        }
                    }

                    // l is still pointing to element (nact,nact) of
                    // the matrix R. So store d(nact) in R(nact,nact)
                    iwrm[l] = work[nact - 1];
                }
            }
            else
            {
                // We took a partial step in dual space. Thus drop constraint it1,
                // that is, we drop the it1-th active constraint. Then we continue
                // at step 2(a) (marked by label 55) but since the fit changed, we
                // have to recalculate now "how much" the fit violates the chosen
                // constraint now.

                sum = -bvec[nvl];

                for (var j = 0; j < sol.Length; j++)
                {
                    sum += sol[j] * amat[nvl, j];
                }

                if (nvl + 1 > meq)
                {
                    iwsv[nvl] = sum;
                }
                else
                {
                    iwsv[nvl] = -Math.Abs(sum);

                    if (sum > 0.0)
                    {
                        for (var j = 0; j < n; j++)
                        {
                            amat[nvl, j] = -amat[nvl, j];
                        }

                        bvec[nvl] = -bvec[nvl];
                    }
                }

                goto L700;
            }

            goto L50;
L700:       // Drop constraint it1

            // if it1 = nact it is only necessary
            // to update the vector u and nact

            if (it1 == nact)
            {
                goto L799;
            }
L797:       // After updating one row of R (column of J) we will also come back here

            // We have to find the Givens rotation which will reduce the element
            // (it1+1,it1+1) of R to zero. If it is already zero we don't have to
            // do anything except of updating u, iact, and shifting column (it1+1)
            // of R to column (it1). Then l  will point to element (1,it1+1) of R
            // and l1 will point to element (it1+1,it1+1) of R.

            l  = it1 * (it1 + 1) / 2;
            l1 = l + it1;

            if (iwrm[l1] == 0.0)
            {
                goto L798;
            }

            gc   = Math.Max(Math.Abs(iwrm[l1 - 1]), Math.Abs(iwrm[l1]));
            gs   = Math.Min(Math.Abs(iwrm[l1 - 1]), Math.Abs(iwrm[l1]));
            temp = Special.Sign(gc * Math.Sqrt(1.0 + gs * gs / (gc * gc)), iwrm[l1 - 1]);
            gc   = iwrm[l1 - 1] / temp;
            gs   = iwrm[l1] / temp;
            // The Givens rotation is done with the matrix (gc gs, gs -gc). If gc is
            // one, then element (it1+1,it1+1) of R is zero compared with element
            // (it1,it1+1). Hence we don't have to do anything. if gc is zero, then
            // we just have to switch row (it1) and row (it1+1) of R and column (it1)
            // and column (it1+1) of J. Since we switch rows in R and columns in J,
            // we can ignore the sign of gs. Otherwise we have to apply the Givens
            // rotation to these rows/columns.

            if (gc == 1.0)
            {
                goto L798;
            }

            if (gc == 0.0)
            {
                for (var i = it1; i < nact; i++)
                {
                    temp         = iwrm[l1 - 1];
                    iwrm[l1 - 1] = iwrm[l1];
                    iwrm[l1]     = temp;
                    l1          += i + 1;
                }

                for (var i = 0; i < n; i++)
                {
                    temp             = dmat[it1 - 1, i];
                    dmat[it1 - 1, i] = dmat[it1, i];
                    dmat[it1, i]     = temp;
                }
            }
            else
            {
                var nu = gs / (gc + 1.0);

                for (var i = it1; i < nact; i++)
                {
                    temp         = gc * iwrm[l1 - 1] + gs * iwrm[l1];
                    iwrm[l1]     = nu * (iwrm[l1 - 1] + temp) - iwrm[l1];
                    iwrm[l1 - 1] = temp;
                    l1          += i + 1;
                }

                for (var i = 0; i < n; i++)
                {
                    temp             = gc * dmat[it1 - 1, i] + gs * dmat[it1, i];
                    dmat[it1, i]     = nu * (dmat[it1 - 1, i] + temp) - dmat[it1, i];
                    dmat[it1 - 1, i] = temp;
                }
            }

L798:

            // shift column (it1+1) of R to column (it1) (that is, the first it1
            // elements). The position of element (1,it1+1) of R was calculated
            // above and stored in l.

            l1 = l - it1;
            for (var i = 0; i < it1; i++, l++, l1++)
            {
                iwrm[l1] = iwrm[l];
            }

            // update vector u and iact as necessary
            // Continue with updating the matrices J and R

            iwuv[it1 - 1] = iwuv[it1];
            iact[it1 - 1] = iact[it1];
            it1++;

            if (it1 < nact)
            {
                goto L797;
            }

L799:

            iwuv[nact - 1] = iwuv[nact];
            iwuv[nact]     = 0.0;
            iact[nact - 1] = -1;

            nact--;
            Deletions++;

            goto L55;
        }