#include "pso.h" #include #include #include #include template < typename Scalar, typename DerivedX, typename DerivedLB, typename DerivedUB> IGL_INLINE Scalar igl::pso( const std::function< Scalar (DerivedX &) > f, const Eigen::MatrixBase & LB, const Eigen::MatrixBase & UB, const int max_iters, const int population, DerivedX & X) { const Eigen::Array P = Eigen::Array::Zero(LB.size(),1); return igl::pso(f,LB,UB,P,max_iters,population,X); } template < typename Scalar, typename DerivedX, typename DerivedLB, typename DerivedUB, typename DerivedP> IGL_INLINE Scalar igl::pso( const std::function< Scalar (DerivedX &) > f, const Eigen::MatrixBase & LB, const Eigen::MatrixBase & UB, const Eigen::DenseBase & P, const int max_iters, const int population, DerivedX & X) { const int dim = LB.size(); assert(UB.size() == dim && "UB should match LB size"); assert(P.size() == dim && "P should match LB size"); typedef std::vector > VectorList; VectorList position(population); VectorList best_position(population); VectorList velocity(population); Eigen::Matrix best_f(population); // https://en.wikipedia.org/wiki/Particle_swarm_optimization#Algorithm // // g → X // p_i → best[i] // v_i → velocity[i] // x_i → position[i] Scalar min_f = std::numeric_limits::max(); for(int p=0;p UB(d)) { position[p](d) = UB(d); if(velocity[p](d) > 0.0) velocity[p](d) *= -1.0; } #else //#warning "trying no bounds on periodic" // // TODO: I'm not sure this is the right thing to do/enough. The // // velocities could be weird. Suppose the current "best" value is ε and // // the value is -ε and the "periodic bounds" [0,2π]. Moding will send // // the value to 2π-ε but the "velocity" term will now be huge pointing // // all the way from 2π-ε to ε. // // // // Q: Would it be enough to try (all combinations) of ±(UB-LB) before // // computing velocities to "best"s? In the example above, instead of // // // // v += best - p = ε - (2π-ε) = -2π+2ε // // // // you'd use // // // // v += / argmin |b - p| \ - p = (ε+2π)-(2π-ε) = 2ε // // | | // // \ b∈{best, best+2π, best-2π} / // // // // Though, for multivariate b,p,v this would seem to explode // // combinatorially. // // // // Maybe periodic things just shouldn't be bounded and we hope that the // // forces toward the current minima "regularize" them away from insane // // values. // if(P(d)) // { // position[p](d) = std::fmod(position[p](d)-LB(d),UB(d)-LB(d))+LB(d); // }else // { // position[p](d) = std::max(LB(d),std::min(UB(d),position[p](d))); // } position[p](d) = std::max(LB(d),std::min(UB(d),position[p](d))); #endif } const Scalar fp = f(position[p]); if(fp=max_iters) { break; } } return min_f; } #ifdef IGL_STATIC_LIBRARY template float igl::pso, Eigen::Matrix, Eigen::Matrix >(std::function&)>, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, int, int, Eigen::Matrix&); #endif