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"); }
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"); }
// // 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; }