2次計画問題(QP)を解くためのOctave関数

2次計画問題(QP)を解くためのOctave関数

標準形の2次計画問題

        minimize   z = 0.5x'Qx + c'x
        subject to Ax = b, x >= 0

を解くためのOctave関数を紹介します.

拡張シンプレックス法(Dantzig and Van de Panne)によるプログラム

qp.m の中で lp.m を呼んでいます.その他 simplex.mpivot.m が必要です.lp.msimplex.mpivot.m については 線形計画問題のページ を参照してください.

例題(参考文献[1],p.191)

octave:1> A = [1 2 1 0;
> 1 1 0 1]
A =

  1  2  1  0
  1  1  0  1

octave:2> b = [7;5]
b =

  7
  5

octave:3> Q = [1 0.5 0 0;
> 0.5 1 0 0;
> 0 0 0 0;
> 0 0 0 0]
Q =

  1.00000  0.50000  0.00000  0.00000
  0.50000  1.00000  0.00000  0.00000
  0.00000  0.00000  0.00000  0.00000
  0.00000  0.00000  0.00000  0.00000

octave:4> c = -[10;11;0;0]
c =

  -10
  -11
   -0
   -0

octave:5> [x,zmin,is_bounded,sol] = qp(Q,c,A,b)
x =

  3
  2
  0
  0

zmin = -42.500
is_bounded = 1
sol = 1

qp.m

function [optx,zmin,is_bounded,sol] = qp(Q,c,A,b)
% [optx,zmin,is_bounded,sol] = qp(Q,c,A,b)
% This program solves the standard quadratic programming problem:
%   minimize    z = 0.5x'Qx + c'x 
%   subject to  Ax = b, x >= 0
% using the algorithm of Dantzig and Van de Panne, a simplex-like method.
% optx: an optimal solution.
% zmin: the optimal value. 
% is_bounded: 1 if the solution is bounded; 0 if unbounded.
% sol: 1 if the problem is solvable; 0 if unsolvable.
%
% Actually the program solves the equivalent problem:
%   maximize    z = -0.5x'Cx + p'x 
%   subject to  Ax = b, x >= 0
% where C = Q, p = -c.
 

C = Q;
p = -c;
[n,m] = size(A);
c1 = zeros(m,1);
[optx,zmin,is_bounded,sol,basis] = lp(c1,A,b); % getting a feasible solution

if sol != 0

basis = sort(basis);  % indices of basis variables

% indices of nonbasis variables
nonbasis = 1:m;  
for i=basis
        nonbasis(i) = 0;
endfor
for i=m:-1:1
        if nonbasis(i) == 0
                nonbasis(i) = [];  
        endif
endfor
index = [basis nonbasis]; 
% rearrangement of the matrices according to the indices
for j = 1:m
        A0(:,j) = A(:,index(j)); 
        p0(j) = p(index(j));     
        Ctemp(:,j) = C(:,index(j));
endfor
C0 = zeros(m,m);
for i = 1:m
        C0(i,:) = Ctemp(index(i),:);
endfor

% making the initial simplex-like table
H = [eye(m,m) -A0' -C0 zeros(m,n) -p0';
     zeros(n,m) zeros(n,n) A0 eye(n,n) b];

for ip = 1:n
        jp = m+ip;
        H = pivot(H,ip,jp);
endfor
for i = 1:n
        ip = m+i;
        jp = m+n+i;
        H = pivot(H,ip,jp);
endfor
H(1:n,:) = [];
H(:,m+1:m+n) = [];
H(:,m+m+1:m+m+n) = []; 
n1 = m-n;
m2 = m+m;
m3 = m2+1;
basis = n+1:m;
basis = [basis [m+1:m+n]];
us = zeros(1,m);
xs = us;
for i=basis
        if i > m
                xs(i-m) = 1;
        else
                us(i) = 1;
        endif
endfor
opt = 0;

while opt == 0
        if us*xs' == 0   % in standard case
        umin = 1; 
        ns = 0;
        for i = 1:m
                if basis(i) <= m
                        if H(i,m3) < umin
                                umin = H(i,m3);
                                ns = i;
                        endif
                endif
        endfor
        if umin >= 0
                %disp('opt')
                opt = 1;  % an optimal solution is obtained
        else
                k = basis(ns)+m;   % k:index to be in the basis.  basis(ns):index of candidate to be out the basis 
        endif
else            % in nonstandard case
        uxsum = us + xs;
        for i = 1:m
                if uxsum(i) == 0
                        k = i;
                        break;
                endif
        endfor
        for i = 1:m
                if basis(i) <= m
                        if uxsum(basis(i)) == 2
                                ns = i;
                                break;
                        endif
                endif
        endfor
end

if opt == 0
% finding index to be out the basis
amin = Inf;
i0 = 0;
if H(ns,k) != 0
        a = H(ns,m3)/H(ns,k);
        if (a >= 0) & (a < amin)
                amin = a;
                i0 = ns;
        endif
endif

for i = 1:m
        if basis(i) > m
                if H(i,k) != 0
                        a = H(i,m3)/H(i,k);
                        if (a >=0) & (a < amin)
                                amin = a;
                                i0 = i;
                        endif
                endif
        endif
endfor
% letting basis(i0) be out the basis and k in
if i0 == 0
        %disp('unbounded')
        opt = 1;
        is_bounded = 0; % unbounded solution
else
        basis(i0) = k;
        H = pivot(H,i0,k);
        
        us = zeros(1,m);
        xs = us;
        for i=basis
                if i > m
                        xs(i-m) = 1;
                else
                        us(i) = 1;
                endif
        endfor
endif

endif

endwhile

u = zeros(m,1);
x = u;
for i = 1:m
        if basis(i) > m
                x(basis(i)-m) = H(i,m3);
        else
                u(basis(i)) = H(i,m3);
        endif
endfor

for i = 1:m
        optx(index(i)) = x(i);
        optu(index(i)) = u(i);
endfor

zmin = 0.5*optx'*Q*optx + c'*optx;  % optimal value of z

endif

endfunction

The interior ellipsoidal trust region and barrier function algorithm によるプログラム

上記のWebサイトで公開されている Matlab 用関数で,Octave でも使えます.規模の大きな問題を比較的高速に解けます.

solqp.m と関連関数

qpsolver.zip

例題(参考文献[1],p.191)

octave:1> A = [1 2 1 0;
> 1 1 0 1]
A =

  1  2  1  0
  1  1  0  1

octave:2> b = [7;5]
b =

  7
  5

octave:3> Q = [1 0.5 0 0;
> 0.5 1 0 0;
> 0 0 0 0;
> 0 0 0 0]
Q =

  1.00000  0.50000  0.00000  0.00000
  0.50000  1.00000  0.00000  0.00000
  0.00000  0.00000  0.00000  0.00000
  0.00000  0.00000  0.00000  0.00000

octave:4> c = [-10;-11;0;0]
c =

  -10
  -11
    0
    0

octave:5> [x,y,obhis] = solqp(Q,A,b,c)
Search for a feasible point:
gap = 0
Search for an optimal solution:
obvalue = -31.988
obvalue = -41.816
lower = -42.863
obvalue = -42.468
obvalue = -42.495
lower = -42.505
obvalue = -42.500
obvalue = -42.500
A (local) optimal solution is found.
x =

   3.0000e+00
   2.0000e+00
   1.5917e-06
   8.5051e-06

y =

  -1.5001
  -4.4998

obhis =

  -31.988  -41.816  -42.468  -42.495  -42.500  -42.500
  
octave:6> zmin = 0.5*x'*Q*x + c'*x
zmin = -42.500

最終更新日:2004.5.27
戻る