-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathquadprog.py
176 lines (132 loc) · 5.4 KB
/
quadprog.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
This module solves quadratic programs of the form
minimize in x: (-d^Tx + 1/2 x^T D x)
subject to: A^T >=b
where the matrix D is symmetric positive definite using the methods
of Goldfarb and Idnani (1982, 1983). The solvers are compiled Fortran routines
implemented by Berwin A. Turlach originally for the S-language. These solvers
were ported to the popular R package "quadprog" by Andreas Weingessel.
The module design follows closely the R implementation.
"""
import numpy as np
from pyquadprog import aind, qpgen1, qpgen2
class Solution:
'''A solution class for the result of a call to a quadprog solver.
Attributes:
solution: solution to the quadratic program
crval: scaler, value of the objetive function at the solution
unconstrained solution: nx1, global minimizer
iact: qx1, constraints active in the final iteration
nact: scalar, number of constraints active in the final iteration
iterations: 2x1, fist component is number of iterations;
the second the number of constraints deleted after they became active'''
def __init__(self, n, q):
self.iact = np.zeros(q)
self.nact = 0
self.solution = np.zeros(n)
self.unconstrained = np.zeros(n)
self.Lagrangian = np.zeros(q)
self.crval = 0
r = min(n,q)
self.work = np.zeros(int((2*n+r*(r+5.0)/2+2*q+1)))
self.iterations = np.zeros(2)
def __str__(self):
s = "Solution = " + self.solution.__str__()
return s
def solveCompactFormQP(Dmat, dvec, Amat, Aind, bvec, meq=0, factorized=False):
''' Solve a quadratic program using the active set methods of Goldfarb and Idnani (1982, 1983)
This methods solves a quadratic program of the form:
minimize in x: (-d^Tx + 1/2 x^T D x)
subject to: A^T >=b
where A is stored in a memory efficient form using the matrices Amat and Aind.
Arguments:
Dmat -- matrix D appearing in the quadratic form; when factorized = True, Dmat = R^{-1}
where D=R^T
dvec -- vector d appearing in the quadratic form
Amat -- matrix with amat[k,i] equal to the k-th non-zero element in column i of A.
Aind -- matrix with:
Aind[i,i] equal to the number of non-zero elements in column i of A
Aind[k,i] for k>1 equal to j if the (k-1)st non-zero element of A[:,i]
is A(i,j).
bvec -- the vector of constants in the inquality constraint
meq -- the first meq constraints of the inequality constraint will be treated as equalities
factorized -- when factorized is true, Dmat=R^{-1} where D = R^TR.
'''
n = Dmat.shape[0]
anrow, q = Amat.shape
if bvec is None:
bvec = np.zeros(q)
if n != Dmat.shape[1]:
raise ValueError("Dmat is not symmetric.")
if n != len(dvec):
raise ValueError("Dmat is not compatible with dvec.")
if meq>q or meq<0:
raise ValueError("meq is invalid.")
if anrow+1 != Aind.shape[0] or q!= Aind.shape[1] or q!= len(bvec):
raise ValueError("Amat, Aind, and bvec are incompatible!")
# check the indices for the input format.
Aindok = aind(Aind, q, n)
if Aindok==False:
raise ValueError("Aind contains illegal indexes.")
err = factorized
sol = Solution(n,q)
sol.solution, sol.crval, sol.iact, sol.nact, sol.iter, sol.work = qpgen1(
Dmat,
dvec,
Amat,
Aind,
bvec,
meq,
err)
if err == 1:
ValueError("constraints are inconsistent, no solution.")
if err == 2:
ValueError("matrix D in quadratic function is not positive definite!")
return(sol)
def solveQP(Dmat, dvec, Amat, bvec=None, meq=0, factorized=False):
''' Solve a quadratic program using the active set methods of Goldfarb and Idnani (1982, 1983)
This methods solves a quadratic program of the form:
minimize in x: (-d^Tx + 1/2 x^T D x)
subject to: A^T >=b
Arguments:
Dmat -- The matrix D appearing in the quadratic form; when factorized = True, Dmat = R^{-1}
where D=R^T
dvec -- vector appearing in the quadratic form
Amat -- matrix A appearing the constraint inquality
bvec -- the vector b of constants in the constraint inequality
meq -- the first meq (integer) constraints of the inequality constraint will be treated as equalities
factorized -- when factorized is true, Dmat=R^{-1} where D = R^TR.
'''
n = Dmat.shape[0]
q = Amat.shape[1]
if bvec is None:
bvec = np.zeros(q)
if n != Dmat.shape[1]:
raise ValueError("Dmat is not symmetric.")
if n != len(dvec):
raise ValueError("Dmat is not compatible with dvec.")
if n != Amat.shape[0]:
raise ValueError("Amat and dvec are not compatible.")
if q != len(bvec):
raise ValueError("Amat and bvec are incompatible.")
if meq>q or meq<0:
raise ValueError("meq is invalid.")
err = factorized
sol = Solution(n,q)
sol.solution, sol.crval, sol.iact, sol.nact, sol.iter, sol.work = qpgen2(
Dmat,
dvec,
Amat,
bvec,
meq,
err
)
if err == 1:
ValueError("constraints are inconsistent, no solution.")
if err == 2:
ValueError("matrix D in quadratic function is not positive definite!")
return(sol)
if __name__ == "__main__":
pass