Mark Grimes > PDL-Opt-QP-0.26_10 > PDL::Opt::QP

PDL-Opt-QP-0.26_10.tar.gz

Dependencies

Annotate this POD

# CPAN RT

 Open 0
View/Report Bugs
Module Version: 0.26_10   Source   Latest Release: PDL-Opt-QP-0.26

# NAME

PDL::Opt::QP - Quadratic programming solver for PDL

# SYNOPSIS

```    use PDL;
use PDL::NiceSlice;
use PDL::Opt::QP;

my \$mu   = pdl(q[ 0.0427 0.0015 0.0285 ])->transpose; # [ n x 1 ]
my \$mu_0 = 0.0427;
my \$dmat = pdl q[ 0.0100 0.0018 0.0011 ;
0.0018 0.0109 0.0026 ;
0.0011 0.0026 0.0199 ];
my \$dvec = zeros(3);
my \$amat = \$mu->glue( 0, ones( 1, 3 ) )->copy;
my \$bvec = pdl(\$mu_0)->glue( 1, ones(1) )->flat;
my \$meq  = pdl(2);

my \$sol = qp( \$dmat, \$dvec, \$amat, \$bvec, \$meq );
say "Solution: ", \$sol->{x};```

# DESCRIPTION

This routine uses Goldfarb/Idnani algorithm to solve the following minimization problem:

```           minimize  f(x) = 0.5 * x' D x  -  d' x
x

optionally constrained by:

Aeq'  x  = a_eq
Aneq  x >= b_neq```

This routine solves the quadratic programming optimization problem

```           minimize  f(x) = 0.5 x' D x  -  d' x
x

optionally constrained by:

Aeq'  x  = a_eq
Aneq  x >= b_neq```

.... more docs to come .... });

sub qp_orig { my (\$Dmat, \$dvec, \$Amat, \$avec, \$meq) = @_;

```  my \$n = pdl \$Dmat->dim(1);    # D is an [n x n] matrix
my \$q = pdl \$Amat->dim(0);    # A is an [n x q] matrix

if( \$avec->isnull ){ \$avec = zeros(1,\$q); }

croak("Dmat is not square!")
if \$n != \$Dmat->dim(0);               # Check D is [n x n]
croak("Dmat and dvec are incompatible!")
if \$n != \$dvec->nelem;                # Check d is [n]
croak("Amat and dvec are incompatible!")
if \$n != \$Amat->dim(1);               # Check A is [n x _]
croak("Amat and avec are incompatible!")
if \$q != \$avec->nelem;                # Check A is [_ x q]
croak("Value of meq is invalid!")
if (\$meq > \$q) || (\$meq < 0 );

#  Pars => 'dmat(m,m); dvec(m);
#      [o]sol(m); [o]lagr(q); [o]crval();
#      amat(m,q); bvec(q); int meq();
#      int [o]iact(q); int [o]nact();
#      int [o]iter(s=2); [t] work(z); int [o]ierr();

my ( \$sol, \$lagr, \$crval, \$iact, \$nact, \$iter, \$ierr ) = qpgen2(
\$Dmat->copy, \$dvec->copy,
\$Amat->transpose->copy,
\$avec->copy,
\$meq,
);

croak "qp: constraints are inconsistent, no solution!"
if any(\$ierr == 1);
croak "qp: matrix D in quadratic function is not positive definite!"
if any(\$ierr == 2);
croak "qp: some problem with mininization" if any(\$ierr);

return {
x     => \$sol,
lagr  => \$lagr,
crval => \$crval,
iact  => \$iact,
nact  => \$nact,
iter  => \$iter,
ierr  => \$ierr,
};```

} EOD

sub qp { my (\$Dmat, \$dvec, %args) = @_;

```  my \$col   = 0;
my \$row   = 1;
my \$stack = 2;

my \$n = pdl \$Dmat->dim(\$row);    # D is an [n x n] matrix
my \$s = pdl \$Dmat->dim(\$stack);  # ... of \$s stacked problems

# Default handling for A_eq and A_neq
my \$A_eq  = exists \$args{A_eq}  ? \$args{A_eq}  : zeroes(0, \$n);
my \$A_neq = exists \$args{A_neq} ? \$args{A_neq} : zeroes(0, \$n);

my \$m = pdl \$A_eq->dim(\$col);    # A is an [n x m] matrix
my \$p = pdl \$A_neq->dim(\$col);   # A is an [n x p] matrix

# Default handling for a_eq and a_neq
# These have to be [?x1] matrixes to ensure threading works if glue,
# otherwise they are relicated not just attached.
my \$a_eq  = exists \$args{a_eq}  ? \$args{a_eq}  : zeroes(1, \$m);
my \$a_neq = exists \$args{a_neq} ? \$args{a_neq} : zeroes(1, \$p);

check_dimmensions( 'Dmat', \$Dmat, \$n, \$n, \$s );
check_dimmensions( 'dvec', \$dvec, \$n, \$s );
check_dimmensions( 'A_eq', \$A_eq, \$m, \$n, \$s );
check_dimmensions( 'a_eq', \$a_eq, \$m, \$s );
check_dimmensions( 'A_neq', \$A_neq, \$p, \$n, \$s );

if( \$p == 0 ){ # If a_neq has zero elems (per stack), then it will be [0x1]
check_dimmensions( 'a_neq', \$a_neq, 1, \$p, \$s );
} else {       # otherwise it will be a [p] vector
check_dimmensions( 'a_neq', \$a_neq, \$p, \$s );
}

# Combine _eq and _neq, use meq to specifiy number of equality constratins
my \$A = \$A_eq->glue( 0, \$A_neq );
my \$a = \$a_eq->glue( 0, \$a_neq );
my \$meq = \$A_eq->dim(\$col);

#  Pars => 'dmat(m,m); dvec(m);
#      [o]sol(m); [o]lagr(q); [o]crval();
#      amat(m,q); bvec(q); int meq();
#      int [o]iact(q); int [o]nact();
#      int [o]iter(s=2); [t] work(z); int [io]ierr();

my ( \$sol, \$lagr, \$crval, \$iact, \$nact, \$iter, \$ierr ) = qpgen2(
\$Dmat->copy, \$dvec->copy,
\$A->transpose->copy,
\$a->copy,
\$meq,
);

croak "qp: constraints are inconsistent, no solution!"
if any(\$ierr == 1);
croak "qp: matrix D in quadratic function is not positive definite!"
if any(\$ierr == 2);
croak "qp: some problem with mininization" if any(\$ierr);

return {
x     => \$sol,
lagr  => \$lagr,
crval => \$crval,
iact  => \$iact,
nact  => \$nact,
iter  => \$iter,
ierr  => \$ierr,
};```

}

sub check_dimmensions { my (\$name, \$pdl, @dims) = @_;

```    pop @dims if \$dims[-1] == 1;    # remove last dim if a dimension of 1
my \$got      = pdl \$pdl->dims;
my \$expected = pdl @dims;

croak( sprintf( "dimmension check failed for %s (is %s)\nexpected [%s]\n%s",
\$name, \$pdl->info, join(',',@dims), qp_usage() )
) unless all \$got == \$expected;
}```

sub qp_usage { return q{ usage: qp( Dmat [n x n], dvec [n], A_eq => [n x m], a_eq => [m], a_neq => [n x p], a_neq => [p] ) where A_eq and a_eq are the equality constraints and A_neq and a_neq are the inequality constraints (>=) All inputs can add one addition dimmension to "stack" multiple Optimization problems. The returned solution (x) will have stack dimmensions. }; } });

# BUGS

Please report any bugs or suggestions at http://rt.cpan.org/

# AUTHOR

Mark Grimes, <mgrimes@cpan.org>