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: A' x = a B x >= b This routine solves the quadratic programming optimization problem minimize f(x) = 0.5 x' D x - d' x x optionally constrained by: A' x = a B x >= b .... more docs to come .... }); pp_add_exported('', 'qp_orig'); pp_addpm({At=>'Bot'},<<'EOD'); sub qp_orig { my ($Dmat, $dvec, $Amat, $bvec, $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( ! defined $bvec ){ # if b is undef, create it $bvec = zeros($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 bvec are incompatible!") if $q != $bvec->nelem; # Check A is [_ x q] croak("Value of meq is invalid!") if ($meq > $q) || ($meq < 0 ); my $iact = zeros($q); # Store which constraints are active my $nact = pdl(0); # Store number of active constraints my $r = $n < $q ? $n : $q; # Used to size work space my $sol = zeros($n->sclr); # Store the solution [n] my $lagr = zeros($q->sclr); # Store the Lagranges for the constraints my $crval= pdl(0); # Value at min my $work = zeros((2*$n+$r*($r+5)/2+2*$q+1)->sclr); # Work space my $iter = zeros(2); # Store info about interations my $ierr = pdl(0); # Input: 1=Factorized; Output: error flag my $res = qpgen2( $Dmat->copy, $dvec->copy, $n, $n, $sol, $lagr, $crval, $Amat->transpose->copy, $bvec->copy, $n, $q, $meq, $iact, $nact, $iter, $work, $ierr ); croak "qp: constraints are inconsistent, no solution!" if $ierr->sclr == 1; croak "qp: matrix D in quadratic function is not positive definite!" if $ierr->sclr == 2; croak "qp: some problem with mininization" if $ierr->sclr; return { x => $sol, lagr => $lagr, crval => $crval, iact => $iact, nact => $nact, iter => $iter, ierr => $ierr, }; # TODO: process/return the results # # From R implementation: # # list(solution=res1$sol, # value=res1$crval, # unconstrained.solution=res1$dvec, # iterations=res1$iter, # Lagrangian = res1$lagr, # iact=res1$iact[1:res1$nact]) } EOD pp_add_exported('', 'qp'); pp_addpm({At=>'Bot'},<<'EOD'); sub qp { my ($Dmat, $dvec, $Amat, $avec, $Bmat, $bvec) = @_; my $n = pdl $Dmat->dim(1); # D is an [n x n] matrix my $q = pdl $Amat->dim(0) + $Bmat->dim(0); # A is an [n x q] matrix if( ! defined $bvec ){ # if b is undef, create it $bvec = zeros($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("Bmat and dvec are incompatible!") if $n != $Bmat->dim(1); # Check B is [n x _] croak("Amat and avec are incompatible!") if $Amat->dim(0) != $avec->nelem; # Check A is [_ x q] croak("Bmat and bvec are incompatible!") if $Bmat->dim(0) != $bvec->nelem; # Check B is [_ x q] my $iact = zeros($q); # Store which constraints are active my $nact = pdl(0); # Store number of active constraints my $r = $n < $q ? $n : $q; # Used to size work space my $sol = zeros($n->sclr); # Store the solution [n] my $lagr = zeros($q->sclr); # Store the Lagranges for the constraints my $crval= pdl(0); # Value at min my $work = zeros((2*$n+$r*($r+5)/2+2*$q+1)->sclr); # Work space my $iter = zeros(2); # Store info about interations my $ierr = pdl(0); # Input: 1=Factorized; Output: error flag my $A = $Amat->glue( 0, $Bmat )->copy; my $a = $avec->glue( 0, $bvec )->copy; # ->flat? my $meq = $Amat->dim(0); print "\$A' = ", $A->transpose; print "\$a = ", $a; print "n = $n"; print "q = $q"; print "meq = $meq"; print "\n"; my $res = qpgen2( $Dmat->copy, $dvec->copy, $n, $n, $sol, $lagr, $crval, $A->transpose, $a, $n, $q, $meq, $iact, $nact, $iter, $work, $ierr ); croak "qp: constraints are inconsistent, no solution!" if $ierr->sclr == 1; croak "qp: matrix D in quadratic function is not positive definite!" if $ierr->sclr == 2; croak "qp: some problem with mininization" if $ierr->sclr; return { x => $sol, lagr => $lagr, crval => $crval, iact => $iact, nact => $nact, iter => $iter, ierr => $ierr, }; # TODO: process/return the results # # From R implementation: # # list(solution=res1$sol, # value=res1$crval, # unconstrained.solution=res1$dvec, # iterations=res1$iter, # Lagrangian = res1$lagr, # iact=res1$iact[1:res1$nact]) } EOD pp_addpm({At=>'Bot'},<<'EOD'); SEE ALSO PDL, PDL::Opt::NonLinear BUGS Please report any bugs or suggestions at AUTHOR Mark Grimes, COPYRIGHT AND LICENSE This software is copyright (c) 2013 by Mark Grimes, . This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.