JWS C Library
C language utility library
dynamics.c
Go to the documentation of this file.
00001 /*
00002  * This work is licensed under a Creative Commons 
00003  * Attribution-Noncommercial-Share Alike 3.0 United States License.
00004  * 
00005  *    http://creativecommons.org/licenses/by-nc-sa/3.0/us/
00006  * 
00007  * You are free:
00008  * 
00009  *    to Share - to copy, distribute, display, and perform the work
00010  *    to Remix - to make derivative works
00011  * 
00012  * Under the following conditions:
00013  * 
00014  *    Attribution. You must attribute the work in the manner specified by the
00015  *    author or licensor (but not in any way that suggests that they endorse you
00016  *    or your use of the work).
00017  * 
00018  *    Noncommercial. You may not use this work for commercial purposes.
00019  * 
00020  *    Share Alike. If you alter, transform, or build upon this work, you may
00021  *    distribute the resulting work only under the same or similar license to
00022  *    this one.
00023  * 
00024  * For any reuse or distribution, you must make clear to others the license
00025  * terms of this work. The best way to do this is by including this header.
00026  * 
00027  * Any of the above conditions can be waived if you get permission from the
00028  * copyright holder.
00029  * 
00030  * Apart from the remix rights granted under this license, nothing in this
00031  * license impairs or restricts the author's moral rights.
00032  */
00033 
00034 
00047 #include <jwsc/config.h>
00048 
00049 #include <stdlib.h>
00050 #include <stdio.h>
00051 #include <inttypes.h>
00052 #include <math.h>
00053 #include <assert.h>
00054 
00055 #include "jwsc/base/error.h"
00056 #include "jwsc/base/limits.h"
00057 #include "jwsc/vector/vector.h"
00058 #include "jwsc/vector/vector_math.h"
00059 #include "jwsc/vector/vector_io.h"
00060 #include "jwsc/matrix/matrix.h"
00061 #include "jwsc/prob/pdf.h"
00062 #include "jwsc/prob/mv_pdf.h"
00063 #include "jwsc/stat/dynamics.h"
00064 
00065 
00096 Error* stochastic_dynamics_1_d
00097 (
00098     uint32_t iterations,
00099     double   delta_t,
00100     double   alpha,
00101     uint32_t kick,
00102     void*    params,
00103     void     (*get_pt_from_params)(Vector_d** p_out, const void* params),
00104     Error*   (*grad_energy_func)(Vector_d** grad_out, void* params),
00105     Error*   (*accept_sample)(const Vector_d* sample, const Vector_d* momenta, void* params)
00106 )
00107 {
00108     uint32_t D;
00109 
00110     Vector_d* p = NULL;
00111     Vector_d* delta_t_v = NULL;
00112     Error*    err;
00113 
00114     get_pt_from_params(&p, params);
00115     D = p->num_elts;
00116 
00117     create_init_vector_d(&delta_t_v, D, delta_t);
00118 
00119     err = stochastic_dynamics_2_d(iterations, delta_t_v, alpha, kick, params,
00120             get_pt_from_params, grad_energy_func, accept_sample);
00121 
00122     free_vector_d(p);
00123     free_vector_d(delta_t_v);
00124 
00125     return err;
00126 }
00127 
00128 
00151 Error* stochastic_dynamics_2_d
00152 (
00153     uint32_t        iterations,
00154     const Vector_d* delta_t,
00155     double          alpha,
00156     uint32_t        kick,
00157     void*           params,
00158     void            (*get_pt_from_params)(Vector_d** p_out, const void* params),
00159     Error*          (*grad_energy_func)(Vector_d** grad_out, void* params),
00160     Error*          (*accept_sample)(const Vector_d* sample, const Vector_d* momenta, void* params)
00161 )
00162 {
00163     uint32_t i;
00164     uint32_t d, D;
00165 
00166     Vector_d* g  = NULL;
00167     Vector_d* p  = NULL;
00168     Vector_d* p_stoch  = NULL;
00169     Vector_d* pp = NULL;
00170     Vector_d* q  = NULL;
00171     Vector_d* gauss = NULL;
00172     Error*    err;
00173 
00174     get_pt_from_params(&q, params);
00175     D = q->num_elts;
00176 
00177     sample_standard_mv_gaussian_pdf_d(&p, D);
00178 
00179     if ((err = grad_energy_func(&g, params)))
00180     {
00181         free_vector_d(g);
00182         free_vector_d(p);
00183         free_vector_d(q);
00184         free_vector_d(gauss);
00185         return err;
00186     }
00187     for (d = 0; d < D; d++)
00188     {
00189         g->elts[ d ] *= 0.5 * delta_t->elts[ d ];
00190     }
00191     subtract_vectors_d(&p, p, g);
00192     copy_vector_d(&p_stoch, p);
00193 
00194     for (i = 0; i < iterations; i++)
00195     {
00196         if (kick > 0 && ((i+1) % kick == 0))
00197         {
00198             copy_vector_d(&p_stoch, p);
00199         }
00200 
00201         copy_vector_d(&pp, p_stoch);
00202         for (d = 0; d < D; d++)
00203         {
00204             pp->elts[ d ] *= delta_t->elts[ d ];
00205         }
00206         add_vectors_d(&q, q, pp);
00207 
00208         if ((err = accept_sample(q, p_stoch, params)))
00209         {
00210             free_vector_d(g);
00211             free_vector_d(p);
00212             free_vector_d(p_stoch);
00213             free_vector_d(pp);
00214             free_vector_d(q);
00215             free_vector_d(gauss);
00216             return err;
00217         }
00218 
00219         /* The params might range limit the point, so get it again. */
00220         get_pt_from_params(&q, params);
00221 
00222         if ((err = grad_energy_func(&g, params)))
00223         {
00224             free_vector_d(g);
00225             free_vector_d(p);
00226             free_vector_d(p_stoch);
00227             free_vector_d(pp);
00228             free_vector_d(q);
00229             free_vector_d(gauss);
00230             return err;
00231         }
00232         for (d = 0; d < D; d++)
00233         {
00234             g->elts[ d ] *= delta_t->elts[ d ];
00235         }
00236         subtract_vectors_d(&p, p, g);
00237         subtract_vectors_d(&p_stoch, p_stoch, g);
00238 
00239         multiply_vector_by_scalar_d(&p_stoch, p_stoch, alpha);
00240         sample_standard_mv_gaussian_pdf_d(&gauss, D);
00241         multiply_vector_by_scalar_d(&gauss, gauss, sqrt(1 - alpha*alpha));
00242         add_vectors_d(&p_stoch, p_stoch, gauss);
00243     }
00244 
00245     // Ignore the last half-step update of the momenta.
00246 
00247     free_vector_d(g);
00248     free_vector_d(p);
00249     free_vector_d(p_stoch);
00250     free_vector_d(pp);
00251     free_vector_d(q);
00252     free_vector_d(gauss);
00253 
00254     return NULL;
00255 }
00256 
00300 Error* hybrid_monte_carlo_1_d
00301 (
00302     uint32_t iterations,
00303     uint32_t leap_iter,
00304     double   delta_t,
00305     double   alpha,
00306     uint32_t kick,
00307     void*    params,
00308     void     (*get_pt_from_params)(Vector_d** p_out, const void* params),
00309     Error*   (*set_params_from_pt)(const Vector_d* p, void* params),
00310     Error*   (*energy_func)(double* energy_out, void* params),
00311     Error*   (*grad_energy_func)(Vector_d** grad_out, void* params),
00312     Error*   (*accept_sample)(const Vector_d* sample, const Vector_d* momenta, void* params),
00313     Error*   (*reject_sample)(const Vector_d* sample, const Vector_d* momenta, void* params)
00314 )
00315 {
00316     uint32_t D;
00317 
00318     Vector_d* p = NULL;
00319     Vector_d* delta_t_v = NULL;
00320     Error*    err;
00321 
00322     get_pt_from_params(&p, params);
00323     D = p->num_elts;
00324 
00325     create_init_vector_d(&delta_t_v, D, delta_t);
00326 
00327     err = hybrid_monte_carlo_2_d(iterations, leap_iter, delta_t_v, alpha,
00328             kick, params, get_pt_from_params, set_params_from_pt, energy_func,
00329             grad_energy_func, accept_sample, reject_sample);
00330 
00331     free_vector_d(p);
00332     free_vector_d(delta_t_v);
00333 
00334     return err;
00335 }
00336 
00367 Error* hybrid_monte_carlo_2_d
00368 (
00369     uint32_t        iterations,
00370     uint32_t        leap_iter,
00371     const Vector_d* delta_t,
00372     double          alpha,
00373     uint32_t        kick,
00374     void*           params,
00375     void            (*get_pt_from_params)(Vector_d** p_out, const void* params),
00376     Error*          (*set_params_from_pt)(const Vector_d* p, void* params),
00377     Error*          (*energy_func)(double* energy_out, void* params),
00378     Error*          (*grad_energy_func)(Vector_d** grad_out, void* params),
00379     Error*          (*accept_sample)(const Vector_d* sample, const Vector_d* momenta, void* params),
00380     Error*          (*reject_sample)(const Vector_d* sample, const Vector_d* momenta, void* params)
00381 )
00382 {
00383     uint32_t i, l;
00384     uint32_t d, D;
00385     double   lambda;
00386     double   E, K;
00387     double   E_prop, K_prop;
00388     double   log_alpha;
00389     double   log_u;
00390 
00391     Vector_d* g = NULL;
00392     Vector_d* p = NULL;
00393     Vector_d* p_stoch = NULL;
00394     Vector_d* p_prop = NULL;
00395     Vector_d* p_stoch_prop = NULL;
00396     Vector_d* pp_prop = NULL;
00397     Vector_d* q = NULL;
00398     Vector_d* q_prop = NULL;
00399     Vector_d* gauss = NULL;
00400     Vector_d* delta_t_0 = NULL;
00401     Error*    err;
00402 
00403     get_pt_from_params(&q, params);
00404     D = q->num_elts;
00405 
00406     sample_standard_mv_gaussian_pdf_d(&p, D);
00407 
00408     if ((err = energy_func(&E, params)))
00409     {
00410         free_vector_d(p);
00411         free_vector_d(q);
00412         return err;
00413     }
00414 
00415     copy_vector_d(&p_stoch, p);
00416     calc_vector_dot_prod_d(&K, p, p);
00417     K *= 0.5;
00418 
00419     copy_vector_d(&delta_t_0, delta_t);
00420 
00421     for (i = 0; i < iterations; i++)
00422     {
00423         copy_vector_d(&q_prop, q);
00424         copy_vector_d(&p_prop, p);
00425         copy_vector_d(&p_stoch_prop, p_stoch);
00426 
00427         lambda = (sample_uniform_pdf_d(0, 1) < 0.5) ? -1 : 1;
00428         for (d = 0; d < D; d++)
00429         {
00430             delta_t->elts[ d ] = delta_t_0->elts[ d ] * lambda;
00431         }
00432 
00433         if ((err = grad_energy_func(&g, params)))
00434         {
00435             free_vector_d(g);
00436             free_vector_d(p); free_vector_d(p_prop); free_vector_d(pp_prop);
00437             free_vector_d(p_stoch); free_vector_d(p_stoch_prop);
00438             free_vector_d(q); free_vector_d(q_prop);
00439             free_vector_d(gauss);
00440             free_vector_d(delta_t_0);
00441             return err;
00442         }
00443         for (d = 0; d < D; d++)
00444         {
00445             g->elts[ d ] *= 0.5*delta_t->elts[ d ];
00446         }
00447         subtract_vectors_d(&p_prop, p_prop, g);
00448         subtract_vectors_d(&p_stoch_prop, p_stoch_prop, g);
00449 
00450         for (l = 0; l < leap_iter; l++)
00451         {
00452             copy_vector_d(&pp_prop, p_stoch_prop);
00453             for (d = 0; d < D; d++)
00454             {
00455                 pp_prop->elts[ d ] *= delta_t->elts[ d ];
00456             }
00457             add_vectors_d(&q_prop, q_prop, pp_prop);
00458 
00459             if ((err = set_params_from_pt(q_prop, params)) ||
00460                 (err = grad_energy_func(&g, params)))
00461             {
00462                 assert(set_params_from_pt(q, params) == NULL);
00463                 free_vector_d(g);
00464                 free_vector_d(p); free_vector_d(p_prop); free_vector_d(pp_prop);
00465                 free_vector_d(p_stoch); free_vector_d(p_stoch_prop);
00466                 free_vector_d(q); free_vector_d(q_prop);
00467                 free_vector_d(gauss);
00468                 free_vector_d(delta_t_0);
00469                 return err;
00470             }
00471 
00472             /* The params might range limit the point, so get it again. */
00473             get_pt_from_params(&q_prop, params);
00474 
00475             for (d = 0; d < D; d++)
00476             {
00477                 g->elts[ d ] *= delta_t->elts[ d ];
00478             }
00479             subtract_vectors_d(&p_prop, p_prop, g);
00480             subtract_vectors_d(&p_stoch_prop, p_stoch_prop, g);
00481 
00482             multiply_vector_by_scalar_d(&p_stoch_prop, p_stoch_prop, alpha);
00483             sample_standard_mv_gaussian_pdf_d(&gauss, D);
00484             multiply_vector_by_scalar_d(&gauss, gauss, sqrt(1 - alpha*alpha));
00485             add_vectors_d(&p_stoch_prop, p_stoch_prop, gauss);
00486         }
00487 
00488         if ((err = energy_func(&E_prop, params)) ||
00489             (err = set_params_from_pt(q, params)))
00490         {
00491             free_vector_d(g);
00492             free_vector_d(p); free_vector_d(p_prop); free_vector_d(pp_prop);
00493             free_vector_d(p_stoch); free_vector_d(p_stoch_prop);
00494             free_vector_d(q); free_vector_d(q_prop);
00495             free_vector_d(gauss);
00496             free_vector_d(delta_t_0);
00497             return err;
00498         }
00499 
00500         calc_vector_dot_prod_d(&K_prop, p_stoch_prop, p_stoch_prop);
00501         K_prop *= 0.5;
00502 
00503         log_alpha = - E_prop - K_prop + E + K;
00504         log_u     = log(sample_uniform_pdf_d(JWSC_MIN_LOG_ARG, 1.0));
00505 
00506         if (log_u <= log_alpha)
00507         {
00508             copy_vector_d(&q, q_prop);
00509             copy_vector_d(&p, p_prop);
00510             copy_vector_d(&p_stoch, p_stoch_prop);
00511 
00512             if ((err = accept_sample(q, p_stoch, params)))
00513             {
00514                 free_vector_d(g);
00515                 free_vector_d(p); free_vector_d(p_prop); free_vector_d(pp_prop);
00516                 free_vector_d(p_stoch); free_vector_d(p_stoch_prop);
00517                 free_vector_d(q); free_vector_d(q_prop);
00518                 free_vector_d(gauss);
00519                 free_vector_d(delta_t_0);
00520                 return err;
00521             }
00522 
00523             /* The params might range limit the point, so get it again. */
00524             get_pt_from_params(&q, params);
00525 
00526             E = E_prop;
00527 
00528             if (kick > 0 && ((i+1) % kick == 0))
00529             {
00530                 copy_vector_d(&p_stoch, p);
00531                 calc_vector_dot_prod_d(&K, p_stoch, p_stoch);
00532                 K *= 0.5;
00533             }
00534             else
00535             {
00536                 K = K_prop;
00537             }
00538         }
00539         else if (reject_sample)
00540         {
00541             if ((err = reject_sample(q_prop, p_stoch_prop, params)))
00542             {
00543                 free_vector_d(g);
00544                 free_vector_d(p); free_vector_d(p_prop); free_vector_d(pp_prop);
00545                 free_vector_d(p_stoch); free_vector_d(p_stoch_prop);
00546                 free_vector_d(q); free_vector_d(q_prop);
00547                 free_vector_d(gauss);
00548                 free_vector_d(delta_t_0);
00549                 return err;
00550             }
00551         }
00552     }
00553 
00554     free_vector_d(g);
00555     free_vector_d(p);
00556     free_vector_d(p_stoch);
00557     free_vector_d(p_prop);
00558     free_vector_d(p_stoch_prop);
00559     free_vector_d(pp_prop);
00560     free_vector_d(q);
00561     free_vector_d(q_prop);
00562     free_vector_d(gauss);
00563     free_vector_d(delta_t_0);
00564 
00565     return NULL;
00566 }
00567 
00597 Error* langevin_1_f
00598 (
00599     uint32_t iterations,
00600     float    delta_t,
00601     void*    params,
00602     void     (*get_pt_from_params)(Vector_f** p_out, const void* params),
00603     Error*   (*grad_energy_func)(Vector_f** grad_out, void* params),
00604     Error*   (*accept_sample)(const Vector_f* sample, void* params)
00605 )
00606 {
00607     uint32_t D;
00608 
00609     Vector_f* p = NULL;
00610     Vector_f* delta_t_v = NULL;
00611     Error*    err;
00612 
00613     get_pt_from_params(&p, params);
00614     D = p->num_elts;
00615 
00616     create_init_vector_f(&delta_t_v, D, delta_t);
00617 
00618     err = langevin_2_f(iterations, delta_t_v, params, get_pt_from_params,
00619             grad_energy_func, accept_sample);
00620 
00621     free_vector_f(p);
00622     free_vector_f(delta_t_v);
00623 
00624     return err;
00625 }
00626 
00644 Error* langevin_2_f
00645 (
00646     uint32_t        iterations,
00647     const Vector_f* delta_t,
00648     void*           params,
00649     void            (*get_pt_from_params)(Vector_f** p_out, const void* params),
00650     Error*          (*grad_energy_func)(Vector_f** grad_out, void* params),
00651     Error*          (*accept_sample)(const Vector_f* sample, void* params)
00652 )
00653 {
00654     uint32_t i;
00655     uint32_t n;
00656     float    dx;
00657     float    dt;
00658     float    gauss;
00659 
00660     Vector_f* g = NULL;
00661     Vector_f* s = NULL;
00662     Error*    err;
00663 
00664     for (i = 0; i < iterations; i++)
00665     {
00666         if ((err = grad_energy_func(&g, params)))
00667         {
00668             free_vector_f(g);
00669             free_vector_f(s);
00670             return err;
00671         }
00672 
00673         get_pt_from_params(&s, params);
00674 
00675         assert(s->num_elts == g->num_elts);
00676         assert(s->num_elts == delta_t->num_elts);
00677 
00678         for (n = 0; n < s->num_elts; n++)
00679         {
00680             dx    = g->elts[ n ];
00681             dt    = delta_t->elts[ n ];
00682             gauss = sample_standard_gaussian_pdf_f(-6.0, 6.0);
00683             s->elts[ n ] -= dt*(0.5*dt*dx + gauss);
00684         }
00685 
00686         if ((err = accept_sample(s, params)))
00687         {
00688             free_vector_f(g);
00689             free_vector_f(s);
00690             return err;
00691         }
00692     }
00693 
00694     free_vector_f(g);
00695     free_vector_f(s);
00696 
00697     return NULL;
00698 }
00699 
00717 Error* langevin_1_d
00718 (
00719     uint32_t iterations,
00720     double   delta_t,
00721     void*    params,
00722     void     (*get_pt_from_params)(Vector_d** p_out, const void* params),
00723     Error*   (*grad_energy_func)(Vector_d** grad_out, void* params),
00724     Error*   (*accept_sample)(const Vector_d* sample, void* params)
00725 )
00726 {
00727     uint32_t D;
00728 
00729     Vector_d* p = NULL;
00730     Vector_d* delta_t_v = NULL;
00731     Error*    err;
00732 
00733     get_pt_from_params(&p, params);
00734     D = p->num_elts;
00735 
00736     create_init_vector_d(&delta_t_v, D, delta_t);
00737 
00738     err = langevin_2_d(iterations, delta_t_v, params, get_pt_from_params,
00739             grad_energy_func, accept_sample);
00740 
00741     free_vector_d(p);
00742     free_vector_d(delta_t_v);
00743 
00744     return err;
00745 }
00746 
00764 Error* langevin_2_d
00765 (
00766     uint32_t        iterations,
00767     const Vector_d* delta_t,
00768     void*           params,
00769     void            (*get_pt_from_params)(Vector_d** p_out, const void* params),
00770     Error*          (*grad_energy_func)(Vector_d** grad_out, void* params),
00771     Error*          (*accept_sample)(const Vector_d* sample, void* params)
00772 )
00773 {
00774     uint32_t i;
00775     uint32_t n;
00776     double   dx;
00777     double   dt;
00778     double   gauss;
00779 
00780     Vector_d* g = NULL;
00781     Vector_d* s = NULL;
00782     Error*    err;
00783 
00784     for (i = 0; i < iterations; i++)
00785     {
00786         if ((err = grad_energy_func(&g, params)))
00787         {
00788             free_vector_d(g);
00789             free_vector_d(s);
00790             return err;
00791         }
00792 
00793         get_pt_from_params(&s, params);
00794 
00795         assert(s->num_elts == g->num_elts);
00796         assert(s->num_elts == delta_t->num_elts);
00797 
00798         for (n = 0; n < s->num_elts; n++)
00799         {
00800             dx    = g->elts[ n ];
00801             dt    = delta_t->elts[ n ];
00802             gauss = sample_standard_gaussian_pdf_d(-6.0, 6.0);
00803             s->elts[ n ] -= dt*(0.5*dt*dx + gauss);
00804         }
00805 
00806         if ((err = accept_sample(s, params)))
00807         {
00808             free_vector_d(g);
00809             free_vector_d(s);
00810             return err;
00811         }
00812     }
00813 
00814     free_vector_d(g);
00815     free_vector_d(s);
00816 
00817     return NULL;
00818 }
00819 
00832 static Error* hyperdynamics_hessian_eigenvalue_f
00833 (
00834     float*          e_out, 
00835     const Vector_f* v,
00836     float           eta, 
00837     void*           params,
00838     void            (*get_pt_from_params)(Vector_f**, const void*),
00839     Error*          (*set_params_from_pt)(const Vector_f*, void*),
00840     Error*          (*energy_func)(float*, void*)
00841 )
00842 {
00843     float a, b, c;
00844 
00845     Vector_f* eta_v   = NULL;
00846     Vector_f* p       = NULL;
00847     Vector_f* q       = NULL;
00848     Error*    err;
00849 
00850     get_pt_from_params(&p, params);
00851 
00852     multiply_vector_by_scalar_f(&eta_v, v, eta);
00853 
00854     assert(add_vectors_f(&q, p, eta_v) == NULL);
00855 
00856     if ((err = set_params_from_pt(q, params)) ||
00857         (err = energy_func(&a, params)))
00858     {
00859         assert(set_params_from_pt(p, params) == NULL);
00860         free_vector_f(eta_v);
00861         free_vector_f(p); free_vector_f(q);
00862         return err;
00863     }
00864 
00865     assert(subtract_vectors_f(&q, p, eta_v) == NULL);
00866 
00867     if ((err = set_params_from_pt(q, params)) ||
00868         (err = energy_func(&b, params)))
00869     {
00870         assert(set_params_from_pt(p, params) == NULL);
00871         free_vector_f(eta_v);
00872         free_vector_f(p); free_vector_f(q);
00873         return err;
00874     }
00875 
00876     assert(set_params_from_pt(p, params) == NULL);
00877 
00878     if ((err = energy_func(&c, params)))
00879     {
00880         free_vector_f(eta_v);
00881         free_vector_f(p); free_vector_f(q);
00882         return err;
00883     }
00884 
00885     *e_out = (a + b - 2.0*c) / (eta*eta);
00886 
00887     free_vector_f(eta_v);
00888     free_vector_f(p);
00889     free_vector_f(q);
00890 
00891     return NULL;
00892 }
00893 
00894 static Error* hyperdynamics_hessian_eigenvalue_d
00895 (
00896     double*         e_out, 
00897     const Vector_d* v,
00898     double          eta, 
00899     void*           params,
00900     void            (*get_pt_from_params)(Vector_d**, const void*),
00901     Error*          (*set_params_from_pt)(const Vector_d*, void*),
00902     Error*          (*energy_func)(double*, void*)
00903 )
00904 {
00905     double a, b, c;
00906 
00907     Vector_d* eta_v   = NULL;
00908     Vector_d* p       = NULL;
00909     Vector_d* q       = NULL;
00910     Error*    err;
00911 
00912     get_pt_from_params(&p, params);
00913 
00914     multiply_vector_by_scalar_d(&eta_v, v, eta);
00915 
00916     assert(add_vectors_d(&q, p, eta_v) == NULL);
00917 
00918     if ((err = set_params_from_pt(q, params)) ||
00919         (err = energy_func(&a, params)))
00920     {
00921         assert(set_params_from_pt(p, params) == NULL);
00922         free_vector_d(eta_v);
00923         free_vector_d(p); free_vector_d(q);
00924         return err;
00925     }
00926 
00927     assert(subtract_vectors_d(&q, p, eta_v) == NULL);
00928 
00929     if ((err = set_params_from_pt(q, params)) ||
00930         (err = energy_func(&b, params)))
00931     {
00932         assert(set_params_from_pt(p, params) == NULL);
00933         free_vector_d(eta_v);
00934         free_vector_d(p); free_vector_d(q);
00935         return err;
00936     }
00937 
00938     assert(set_params_from_pt(p, params) == NULL);
00939 
00940     if ((err = energy_func(&c, params)))
00941     {
00942         free_vector_d(eta_v);
00943         free_vector_d(p); free_vector_d(q);
00944         return err;
00945     }
00946 
00947     *e_out = (a + b - 2.0*c) / (eta*eta);
00948 
00949     free_vector_d(eta_v);
00950     free_vector_d(p);
00951     free_vector_d(q);
00952 
00953     return NULL;
00954 }
00955 
00968 static Error* hyperdynamics_hessian_eigenvector_f
00969 (
00970     Vector_f**      v_out, 
00971     float           eta, 
00972     float           gamma,
00973     void*           params,
00974     void            (*get_pt_from_params)(Vector_f**, const void*),
00975     Error*          (*set_params_from_pt)(const Vector_f*, void*),
00976     Error*          (*energy_func)(float*, void*),
00977     Error*          (*grad_energy_func)(Vector_f**, void*)
00978 )
00979 {
00980     uint32_t n;
00981     uint32_t N;
00982     uint8_t  done;
00983 
00984     float    e;
00985     float    delta_e;
00986     float    g;
00987     float    e_dv_dp;
00988     float    e_dv_prev_dp;
00989     float    beta;
00990 
00991     Vector_f* v;
00992     Vector_f* v_cp    = NULL;
00993     Vector_f* delta_v = NULL;
00994     Vector_f* eta_v   = NULL;
00995     Vector_f* p       = NULL;
00996     Vector_f* q       = NULL;
00997     Vector_f* a       = NULL;
00998     Vector_f* b       = NULL;
00999     Error*    err     = NULL;
01000     Vector_f* e_dv    = NULL;
01001     Vector_f* e_dv_prev = NULL;
01002     Vector_f* e_dv_diff = NULL;
01003 
01004     get_pt_from_params(&p, params);
01005     N = p->num_elts;
01006 
01007     create_vector_f(v_out, N);
01008     v = *v_out;
01009 
01010     e    = 1.0e+10;
01011     done = 0;
01012 
01013     while (!done)
01014     {
01015         get_pt_from_params(&p, params);
01016 
01017         multiply_vector_by_scalar_f(&eta_v, v, eta);
01018 
01019         assert(add_vectors_f(&q, p, eta_v) == NULL);
01020 
01021         if ((err = set_params_from_pt(q, params)) ||
01022             (err = grad_energy_func(&a, params)))
01023         {
01024             assert(set_params_from_pt(p, params) == NULL);
01025             break;
01026         }
01027 
01028         assert(subtract_vectors_f(&q, p, eta_v) == NULL);
01029 
01030         if ((err = set_params_from_pt(q, params)) ||
01031             (err = grad_energy_func(&b, params)))
01032         {
01033             assert(set_params_from_pt(p, params) == NULL);
01034             break;
01035         }
01036 
01037         assert(set_params_from_pt(p, params) == NULL);
01038 
01039         assert(copy_vector_f(&delta_v, v) == NULL);
01040 
01041         assert(subtract_vectors_f(&e_dv, a, b) == NULL);
01042         multiply_vector_by_scalar_f(&e_dv, e_dv, 1 / eta);
01043 
01044         if (!e_dv_prev)
01045         {
01046             copy_vector_f(&e_dv_prev, e_dv);
01047             calc_vector_dot_prod_f(&e_dv_prev_dp, e_dv_prev, e_dv_prev);
01048         }
01049 
01050         subtract_vectors_f(&e_dv_diff, e_dv, e_dv_prev);
01051         calc_vector_dot_prod_f(&e_dv_dp, e_dv, e_dv_diff);
01052 
01053         beta = (e_dv_prev_dp > 0) && (e_dv_dp / e_dv_prev_dp) > 0 
01054             ? e_dv_dp / e_dv_prev_dp : 0;
01055 
01056         multiply_vector_by_scalar_f(&e_dv_prev, e_dv_prev, beta);
01057         add_vectors_f(&e_dv, e_dv, e_dv_prev);
01058 
01059         g       = gamma;
01060         delta_e = e;
01061         done    = 0;
01062 
01063         while (!done)
01064         {
01065             copy_vector_f(&v_cp, v);
01066 
01067             for (n = 0; n < N; n++)
01068             {
01069                 v_cp->elts[ n ] -= g * e_dv->elts[ n ];
01070             }
01071             normalize_vector_mag_f(&v_cp, v_cp);
01072 
01073             if ((err = hyperdynamics_hessian_eigenvalue_f(&e, v_cp, eta, 
01074                             params, get_pt_from_params, set_params_from_pt, 
01075                             energy_func)))
01076             {
01077                 break;
01078             }
01079 
01080             // TEMP
01081             //fprintf(stdout, "e1 : %10.3e %10.3e %10.3e\n", 
01082             //        e, (delta_e - e), g);
01083 
01084             g *= 0.5;
01085 
01086             if (g < 1.0e-16 || (delta_e - e) >= 0)
01087             {
01088                 done = 1;
01089             }
01090         }
01091         if (err) 
01092         {
01093             break;
01094         }
01095 
01096         copy_vector_f(&v, v_cp);
01097 
01098         delta_e -= e;
01099 
01100         done = 1;
01101         for (n = 0; n < N; n++)
01102         {
01103             delta_v->elts[ n ] 
01104                 = (fabs(fabs(delta_v->elts[ n ]) - fabs(v->elts[ n ])) < 1.0e-6)
01105                 ?  fabs(fabs(delta_v->elts[ n ]) - fabs(v->elts[ n ]))
01106                 :  fabs(delta_v->elts[ n ] - v->elts[ n ]);
01107 
01108             done = (done && (delta_v->elts[ n ] <= 1.0e-6));
01109         }
01110 
01111         // TEMP
01112         //fprintf(stdout, "dv : ");
01113         //write_formatted_vector_fp_f(delta_v, "%10.3e", stdout);
01114         //fprintf(stdout, "v  : ");
01115         //write_formatted_vector_fp_f(v, "%10.3e", stdout);
01116 
01117         copy_vector_f(&e_dv_prev, e_dv);
01118         calc_vector_dot_prod_f(&e_dv_prev_dp, e_dv_prev, e_dv_prev);
01119     }
01120 
01121     free_vector_f(v_cp);
01122     free_vector_f(delta_v);
01123     free_vector_f(eta_v);
01124     free_vector_f(p);
01125     free_vector_f(q);
01126     free_vector_f(a);
01127     free_vector_f(b);
01128     free_vector_f(e_dv);
01129     free_vector_f(e_dv_prev);
01130     free_vector_f(e_dv_diff);
01131 
01132     if (err)
01133     {
01134         free_vector_f(*v_out); *v_out = NULL;
01135     }
01136 
01137     return err;
01138 }
01139 
01140 static Error* hyperdynamics_hessian_eigenvector_d
01141 (
01142     Vector_d**      v_out, 
01143     double          eta, 
01144     double          gamma,
01145     void*           params,
01146     void            (*get_pt_from_params)(Vector_d**, const void*),
01147     Error*          (*set_params_from_pt)(const Vector_d*, void*),
01148     Error*          (*energy_func)(double*, void*),
01149     Error*          (*grad_energy_func)(Vector_d**, void*)
01150 )
01151 {
01152     uint32_t n;
01153     uint32_t N;
01154     uint8_t  done;
01155 
01156     double   e;
01157     double   delta_e;
01158     double   g;
01159     double   e_dv_dp;
01160     double   e_dv_prev_dp;
01161     double   beta;
01162 
01163     Vector_d* v;
01164     Vector_d* v_cp    = NULL;
01165     Vector_d* delta_v = NULL;
01166     Vector_d* eta_v   = NULL;
01167     Vector_d* p       = NULL;
01168     Vector_d* q       = NULL;
01169     Vector_d* a       = NULL;
01170     Vector_d* b       = NULL;
01171     Error*    err     = NULL;
01172     Vector_d* e_dv    = NULL;
01173     Vector_d* e_dv_prev = NULL;
01174     Vector_d* e_dv_diff = NULL;
01175 
01176     get_pt_from_params(&p, params);
01177     N = p->num_elts;
01178 
01179     create_vector_d(v_out, N);
01180     v = *v_out;
01181 
01182     e    = 1.0e+10;
01183     done = 0;
01184 
01185     while (!done)
01186     {
01187         get_pt_from_params(&p, params);
01188 
01189         multiply_vector_by_scalar_d(&eta_v, v, eta);
01190 
01191         assert(add_vectors_d(&q, p, eta_v) == NULL);
01192 
01193         if ((err = set_params_from_pt(q, params)) ||
01194             (err = grad_energy_func(&a, params)))
01195         {
01196             assert(set_params_from_pt(p, params) == NULL);
01197             break;
01198         }
01199 
01200         assert(subtract_vectors_d(&q, p, eta_v) == NULL);
01201 
01202         if ((err = set_params_from_pt(q, params)) ||
01203             (err = grad_energy_func(&b, params)))
01204         {
01205             assert(set_params_from_pt(p, params) == NULL);
01206             break;
01207         }
01208 
01209         assert(set_params_from_pt(p, params) == NULL);
01210 
01211         assert(copy_vector_d(&delta_v, v) == NULL);
01212 
01213         assert(subtract_vectors_d(&e_dv, a, b) == NULL);
01214         multiply_vector_by_scalar_d(&e_dv, e_dv, 1 / eta);
01215 
01216         if (!e_dv_prev)
01217         {
01218             copy_vector_d(&e_dv_prev, e_dv);
01219             calc_vector_dot_prod_d(&e_dv_prev_dp, e_dv_prev, e_dv_prev);
01220         }
01221 
01222         subtract_vectors_d(&e_dv_diff, e_dv, e_dv_prev);
01223         calc_vector_dot_prod_d(&e_dv_dp, e_dv, e_dv_diff);
01224 
01225         beta = (e_dv_prev_dp > 0) && (e_dv_dp / e_dv_prev_dp) > 0 
01226             ? e_dv_dp / e_dv_prev_dp : 0;
01227 
01228         multiply_vector_by_scalar_d(&e_dv_prev, e_dv_prev, beta);
01229         add_vectors_d(&e_dv, e_dv, e_dv_prev);
01230 
01231         g       = gamma;
01232         delta_e = e;
01233         done    = 0;
01234 
01235         while (!done)
01236         {
01237             copy_vector_d(&v_cp, v);
01238 
01239             for (n = 0; n < N; n++)
01240             {
01241                 v_cp->elts[ n ] -= g * e_dv->elts[ n ];
01242             }
01243             normalize_vector_mag_d(&v_cp, v_cp);
01244 
01245             if ((err = hyperdynamics_hessian_eigenvalue_d(&e, v_cp, eta, 
01246                             params, get_pt_from_params, set_params_from_pt, 
01247                             energy_func)))
01248             {
01249                 break;
01250             }
01251 
01252             // TEMP
01253             //fprintf(stdout, "e1 : %10.3e %10.3e %10.3e\n", 
01254             //        e, (delta_e - e), g);
01255 
01256             g *= 0.5;
01257 
01258             if (g < 1.0e-128 || (delta_e - e) >= 0)
01259             {
01260                 done = 1;
01261             }
01262         }
01263         if (err) 
01264         {
01265             break;
01266         }
01267 
01268         copy_vector_d(&v, v_cp);
01269 
01270         delta_e -= e;
01271 
01272         done = 1;
01273         for (n = 0; n < N; n++)
01274         {
01275             delta_v->elts[ n ] 
01276                 = (fabs(fabs(delta_v->elts[ n ]) - fabs(v->elts[ n ])) < 1.0e-8)
01277                 ?  fabs(fabs(delta_v->elts[ n ]) - fabs(v->elts[ n ]))
01278                 :  fabs(delta_v->elts[ n ] - v->elts[ n ]);
01279 
01280             done = (done && (delta_v->elts[ n ] <= 1.0e-8));
01281         }
01282 
01283         // TEMP
01284         //fprintf(stdout, "dv : ");
01285         //write_formatted_vector_fp_d(delta_v, "%10.3e", stdout);
01286         //fprintf(stdout, "v  : ");
01287         //write_formatted_vector_fp_d(v, "%10.3e", stdout);
01288 
01289         copy_vector_d(&e_dv_prev, e_dv);
01290         calc_vector_dot_prod_d(&e_dv_prev_dp, e_dv_prev, e_dv_prev);
01291     }
01292 
01293     free_vector_d(v_cp);
01294     free_vector_d(delta_v);
01295     free_vector_d(eta_v);
01296     free_vector_d(p);
01297     free_vector_d(q);
01298     free_vector_d(a);
01299     free_vector_d(b);
01300     free_vector_d(e_dv);
01301     free_vector_d(e_dv_prev);
01302     free_vector_d(e_dv_diff);
01303 
01304     if (err)
01305     {
01306         free_vector_d(*v_out); *v_out = NULL;
01307     }
01308 
01309     return err;
01310 }
01311 
01325 static Error* hyperdynamics_dx_hessian_eigenvalue_f
01326 (
01327     Vector_f**      e_dx_out, 
01328     const Vector_f* v,
01329     float           eta, 
01330     void*           params,
01331     void            (*get_pt_from_params)(Vector_f**, const void*),
01332     Error*          (*set_params_from_pt)(const Vector_f*, void*),
01333     Error*          (*grad_energy_func)(Vector_f**, void*)
01334 )
01335 {
01336     uint32_t n;
01337     uint32_t N;
01338 
01339     Vector_f* eta_v   = NULL;
01340     Vector_f* a       = NULL;
01341     Vector_f* b       = NULL;
01342     Vector_f* c       = NULL;
01343     Vector_f* p       = NULL;
01344     Vector_f* q       = NULL;
01345     Error*    err;
01346 
01347     get_pt_from_params(&p, params);
01348     N = p->num_elts;
01349 
01350     multiply_vector_by_scalar_f(&eta_v, v, eta);
01351 
01352     assert(add_vectors_f(&q, p, eta_v) == NULL);
01353 
01354     if ((err = set_params_from_pt(q, params)) ||
01355         (err = grad_energy_func(&a, params)))
01356     {
01357         assert(set_params_from_pt(p, params) == NULL);
01358         free_vector_f(eta_v);
01359         free_vector_f(p); free_vector_f(q);
01360         free_vector_f(a); free_vector_f(b); free_vector_f(c);
01361         free_vector_f(*e_dx_out); *e_dx_out = NULL;
01362         return err;
01363     }
01364 
01365     assert(subtract_vectors_f(&q, p, eta_v) == NULL);
01366 
01367     if ((err = set_params_from_pt(q, params)) ||
01368         (err = grad_energy_func(&b, params)))
01369     {
01370         assert(set_params_from_pt(p, params) == NULL);
01371         free_vector_f(eta_v);
01372         free_vector_f(p); free_vector_f(q);
01373         free_vector_f(a); free_vector_f(b); free_vector_f(c);
01374         free_vector_f(*e_dx_out); *e_dx_out = NULL;
01375         return err;
01376     }
01377 
01378     assert(set_params_from_pt(p, params) == NULL);
01379 
01380     if ((err = grad_energy_func(&c, params)))
01381     {
01382         free_vector_f(eta_v);
01383         free_vector_f(p); free_vector_f(q);
01384         free_vector_f(a); free_vector_f(b); free_vector_f(c);
01385         free_vector_f(*e_dx_out); *e_dx_out = NULL;
01386         return err;
01387     }
01388 
01389     create_vector_f(e_dx_out, N);
01390     for (n = 0; n < N; n++)
01391     {
01392         (*e_dx_out)->elts[ n ] = (a->elts[n] + b->elts[n] - 2.0*c->elts[n]) / 
01393                                  (eta*eta);
01394     }
01395 
01396     free_vector_f(eta_v);
01397     free_vector_f(p);
01398     free_vector_f(q);
01399     free_vector_f(a);
01400     free_vector_f(b);
01401     free_vector_f(c);
01402 
01403     return NULL;
01404 }
01405 
01406 static Error* hyperdynamics_dx_hessian_eigenvalue_d
01407 (
01408     Vector_d**      e_dx_out, 
01409     const Vector_d* v,
01410     double          eta, 
01411     void*           params,
01412     void            (*get_pt_from_params)(Vector_d**, const void*),
01413     Error*          (*set_params_from_pt)(const Vector_d*, void*),
01414     Error*          (*grad_energy_func)(Vector_d**, void*)
01415 )
01416 {
01417     uint32_t n;
01418     uint32_t N;
01419 
01420     Vector_d* eta_v   = NULL;
01421     Vector_d* a       = NULL;
01422     Vector_d* b       = NULL;
01423     Vector_d* c       = NULL;
01424     Vector_d* p       = NULL;
01425     Vector_d* q       = NULL;
01426     Error*    err;
01427 
01428     get_pt_from_params(&p, params);
01429     N = p->num_elts;
01430 
01431     multiply_vector_by_scalar_d(&eta_v, v, eta);
01432 
01433     assert(add_vectors_d(&q, p, eta_v) == NULL);
01434 
01435     if ((err = set_params_from_pt(q, params)) ||
01436         (err = grad_energy_func(&a, params)))
01437     {
01438         assert(set_params_from_pt(p, params) == NULL);
01439         free_vector_d(eta_v);
01440         free_vector_d(p); free_vector_d(q);
01441         free_vector_d(a); free_vector_d(b); free_vector_d(c);
01442         free_vector_d(*e_dx_out); *e_dx_out = NULL;
01443         return err;
01444     }
01445 
01446     assert(subtract_vectors_d(&q, p, eta_v) == NULL);
01447 
01448     if ((err = set_params_from_pt(q, params)) ||
01449         (err = grad_energy_func(&b, params)))
01450     {
01451         assert(set_params_from_pt(p, params) == NULL);
01452         free_vector_d(eta_v);
01453         free_vector_d(p); free_vector_d(q);
01454         free_vector_d(a); free_vector_d(b); free_vector_d(c);
01455         free_vector_d(*e_dx_out); *e_dx_out = NULL;
01456         return err;
01457     }
01458 
01459     if ((err = set_params_from_pt(p, params)) ||
01460         (err = grad_energy_func(&c, params)))
01461     {
01462         assert(set_params_from_pt(p, params) == NULL);
01463         free_vector_d(eta_v);
01464         free_vector_d(p); free_vector_d(q);
01465         free_vector_d(a); free_vector_d(b); free_vector_d(c);
01466         free_vector_d(*e_dx_out); *e_dx_out = NULL;
01467         return err;
01468     }
01469 
01470     create_vector_d(e_dx_out, N);
01471     for (n = 0; n < N; n++)
01472     {
01473         (*e_dx_out)->elts[ n ] = (a->elts[n] + b->elts[n] - 2.0*c->elts[n]) / 
01474                                  (eta*eta);
01475     }
01476 
01477     free_vector_d(eta_v);
01478     free_vector_d(p);
01479     free_vector_d(q);
01480     free_vector_d(a);
01481     free_vector_d(b);
01482     free_vector_d(c);
01483 
01484     return NULL;
01485 }
01486 
01500 static Error* hyperdynamics_hessgrad_eigenvalue_f
01501 (
01502     float*          e_out,
01503     float           lambda,
01504     const Vector_f* v,
01505     float           eta, 
01506     void*           params,
01507     void            (*get_pt_from_params)(Vector_f**, const void*),
01508     Error*          (*set_params_from_pt)(const Vector_f*, void*),
01509     Error*          (*energy_func)(float*, void*),
01510     uint8_t         positive
01511 )
01512 {
01513     float e;
01514     float a, b;
01515 
01516     Vector_f* eta_v = NULL;
01517     Vector_f* p     = NULL;
01518     Vector_f* q     = NULL;
01519     Error*    err;
01520 
01521     if ((err = hyperdynamics_hessian_eigenvalue_f(&e, v, eta, params,
01522                     get_pt_from_params, set_params_from_pt, energy_func)))
01523     {
01524         free_vector_f(eta_v);
01525         free_vector_f(p);
01526         free_vector_f(q);
01527         return err;
01528     }
01529 
01530     get_pt_from_params(&p, params);
01531 
01532     multiply_vector_by_scalar_f(&eta_v, v, eta);
01533 
01534     assert(add_vectors_f(&q, p, eta_v) == NULL);
01535 
01536     if ((err = set_params_from_pt(q, params)) ||
01537         (err = energy_func(&a, params)))
01538     {
01539         assert(set_params_from_pt(p, params) == NULL);
01540         free_vector_f(eta_v);
01541         free_vector_f(p);
01542         free_vector_f(q);
01543         return err;
01544     }
01545 
01546     assert(subtract_vectors_f(&q, p, eta_v) == NULL);
01547 
01548     if ((err = set_params_from_pt(q, params)) ||
01549         (err = energy_func(&b, params)))
01550     {
01551         assert(set_params_from_pt(p, params) == NULL);
01552         free_vector_f(eta_v);
01553         free_vector_f(p);
01554         free_vector_f(q);
01555         return err;
01556     }
01557 
01558     assert(set_params_from_pt(p, params) == NULL);
01559 
01560     if (positive)
01561     {
01562         e += (0.25*lambda / (eta*eta)) * (a - b) * (a - b);
01563     }
01564     else
01565     {
01566         e -= (0.25*lambda / (eta*eta)) * (a - b) * (a - b);
01567     }
01568 
01569     *e_out = e;
01570 
01571     free_vector_f(eta_v);
01572     free_vector_f(p);
01573     free_vector_f(q);
01574 
01575     return NULL;
01576 }
01577 
01578 static Error* hyperdynamics_hessgrad_eigenvalue_d
01579 (
01580     double*         e_out,
01581     double          lambda,
01582     const Vector_d* v,
01583     double          eta, 
01584     void*           params,
01585     void            (*get_pt_from_params)(Vector_d**, const void*),
01586     Error*          (*set_params_from_pt)(const Vector_d*, void*),
01587     Error*          (*energy_func)(double*, void*),
01588     uint8_t         positive
01589 )
01590 {
01591     double e;
01592     double a, b;
01593 
01594     Vector_d* eta_v = NULL;
01595     Vector_d* p     = NULL;
01596     Vector_d* q     = NULL;
01597     Error*    err;
01598 
01599     if ((err = hyperdynamics_hessian_eigenvalue_d(&e, v, eta, params,
01600                     get_pt_from_params, set_params_from_pt, energy_func)))
01601     {
01602         free_vector_d(eta_v);
01603         free_vector_d(p);
01604         free_vector_d(q);
01605         return err;
01606     }
01607 
01608     get_pt_from_params(&p, params);
01609 
01610     multiply_vector_by_scalar_d(&eta_v, v, eta);
01611 
01612     assert(add_vectors_d(&q, p, eta_v) == NULL);
01613 
01614     if ((err = set_params_from_pt(q, params)) ||
01615         (err = energy_func(&a, params)))
01616     {
01617         assert(set_params_from_pt(p, params) == NULL);
01618         free_vector_d(eta_v);
01619         free_vector_d(p);
01620         free_vector_d(q);
01621         return err;
01622     }
01623 
01624     assert(subtract_vectors_d(&q, p, eta_v) == NULL);
01625 
01626     if ((err = set_params_from_pt(q, params)) ||
01627         (err = energy_func(&b, params)))
01628     {
01629         assert(set_params_from_pt(p, params) == NULL);
01630         free_vector_d(eta_v);
01631         free_vector_d(p);
01632         free_vector_d(q);
01633         return err;
01634     }
01635 
01636     assert(set_params_from_pt(p, params) == NULL);
01637 
01638     if (positive)
01639     {
01640         e += (0.25*lambda / (eta*eta)) * (a - b) * (a - b);
01641     }
01642     else
01643     {
01644         e -= (0.25*lambda / (eta*eta)) * (a - b) * (a - b);
01645     }
01646 
01647     *e_out = e;
01648 
01649     free_vector_d(eta_v);
01650     free_vector_d(p);
01651     free_vector_d(q);
01652 
01653     return NULL;
01654 }
01655 
01669 static Error* hyperdynamics_proj_hessian_eigenvector_f
01670 (
01671     float* g1p_out,
01672     float  e_pos,
01673     float  e_neg,
01674     float  lambda
01675 )
01676 {
01677     double d;
01678 
01679     assert(fabs(lambda) > 1.0e-8);
01680 
01681     d = (e_pos - e_neg) / lambda;
01682     //assert(d > 0);
01683     if (d < 1.0e-8)
01684     {
01685         d = 1.0e-8;
01686     }
01687 
01688     *g1p_out = sqrt(0.5 * d);
01689 
01690     return NULL;
01691 }
01692 
01693 static Error* hyperdynamics_proj_hessian_eigenvector_d
01694 (
01695     double* g1p_out,
01696     double  e_pos,
01697     double  e_neg,
01698     double  lambda
01699 )
01700 {
01701     double d;
01702 
01703     assert(fabs(lambda) > 1.0e-8);
01704 
01705     d = (e_pos - e_neg) / lambda;
01706     //assert(d > 0);
01707     if (d < 1.0e-8)
01708     {
01709         d = 1.0e-8;
01710     }
01711 
01712     *g1p_out = sqrt(0.5 * d);
01713 
01714     return NULL;
01715 }
01716 
01730 static Error* hyperdynamics_hessgrad_eigenvector_f
01731 (
01732     float*          lambda_out,
01733     Vector_f**      v_pos_out,
01734     Vector_f**      v_neg_out,
01735     float           eta, 
01736     float           gamma,
01737     void*           params,
01738     void            (*get_pt_from_params)(Vector_f**, const void*),
01739     Error*          (*set_params_from_pt)(const Vector_f*, void*),
01740     Error*          (*energy_func)(float*, void*),
01741     Error*          (*grad_energy_func)(Vector_f**, void*)
01742 )
01743 {
01744     uint32_t n;
01745     uint32_t N;
01746     uint8_t  done;
01747     float    g1p;
01748     float    lambda;
01749     float    lambda_cp;
01750     float    e_pos;
01751     float    e_neg;
01752     float    e_pos_dlambda;
01753     float    e_neg_dlambda;
01754     float    e_pos_dlambda_diff;
01755     float    e_neg_dlambda_diff;
01756     float    e_pos_dlambda_prev;
01757     float    e_neg_dlambda_prev;
01758     float    c, d;
01759     float    delta_g1p;
01760     float    delta_e;
01761     float    delta_lambda;
01762     float    g;
01763     float    e_pos_dv_dp;
01764     float    e_neg_dv_dp;
01765     float    e_pos_dv_prev_dp;
01766     float    e_neg_dv_prev_dp;
01767     float    e_pos_dlambda_dp;
01768     float    e_neg_dlambda_dp;
01769     float    e_pos_dlambda_prev_dp;
01770     float    e_neg_dlambda_prev_dp;
01771     float    e_pos_dv_beta;
01772     float    e_neg_dv_beta;
01773     float    e_pos_dlambda_beta;
01774     float    e_neg_dlambda_beta;
01775 
01776     Vector_f* v_pos;
01777     Vector_f* v_neg;
01778     Vector_f* v_pos_cp    = NULL;
01779     Vector_f* v_neg_cp    = NULL;
01780     Vector_f* delta_v_pos = NULL;
01781     Vector_f* delta_v_neg = NULL;
01782     Vector_f* eta_v       = NULL;
01783     Vector_f* e_pos_dv    = NULL;
01784     Vector_f* e_neg_dv    = NULL;
01785     Vector_f* e_pos_dv_diff = NULL;
01786     Vector_f* e_neg_dv_diff = NULL;
01787     Vector_f* e_pos_dv_prev = NULL;
01788     Vector_f* e_neg_dv_prev = NULL;
01789     Vector_f* p           = NULL;
01790     Vector_f* q           = NULL;
01791     Vector_f* a           = NULL;
01792     Vector_f* b           = NULL;
01793     Error*    err         = NULL;
01794 
01795     get_pt_from_params(&p, params);
01796     N = p->num_elts;
01797 
01798     create_vector_f(v_pos_out, N);
01799     v_pos = *v_pos_out;
01800 
01801     create_vector_f(v_neg_out, N);
01802     v_neg = *v_neg_out;
01803 
01804     create_vector_f(&e_pos_dv, N);
01805     create_vector_f(&e_neg_dv, N);
01806 
01807     lambda = *lambda_out;
01808 
01809     /* May not be the best initialization for these. */
01810     g1p   = 0;
01811     e_pos = 0;
01812     e_neg = 0;
01813 
01814     done = 0;
01815 
01816     while (!done)
01817     {
01818         get_pt_from_params(&p, params);
01819 
01820         /* Positive lambda */
01821         multiply_vector_by_scalar_f(&eta_v, v_pos, eta);
01822 
01823         assert(add_vectors_f(&q, p, eta_v) == NULL);
01824 
01825         if ((err = set_params_from_pt(q, params)) ||
01826             (err = grad_energy_func(&a, params)) ||
01827             (err = energy_func(&c, params)))
01828         {
01829             assert(set_params_from_pt(p, params) == NULL);
01830             break;
01831         }
01832 
01833         assert(subtract_vectors_f(&q, p, eta_v) == NULL);
01834 
01835         if ((err = set_params_from_pt(q, params)) ||
01836             (err = grad_energy_func(&b, params)) ||
01837             (err = energy_func(&d, params)))
01838         {
01839             assert(set_params_from_pt(p, params) == NULL);
01840             break;
01841         }
01842 
01843         for (n = 0; n < N; n++)
01844         {
01845             e_pos_dv->elts[n] = (a->elts[n] - b->elts[n]) / eta +
01846                                 (0.5*lambda / eta) *
01847                                 (c - d) * (a->elts[n] + b->elts[n]);
01848         }
01849         e_pos_dlambda = (0.5*(c - d) / eta) * (0.5*(c - d) / eta);
01850 
01851         if (!e_pos_dv_prev)
01852         {
01853             copy_vector_f(&e_pos_dv_prev, e_pos_dv);
01854             calc_vector_dot_prod_f(&e_pos_dv_prev_dp, e_pos_dv_prev, 
01855                     e_pos_dv_prev);
01856             e_pos_dlambda_prev = e_pos_dlambda;
01857             e_pos_dlambda_prev_dp = e_pos_dlambda_prev * e_pos_dlambda_prev;
01858         }
01859 
01860         subtract_vectors_f(&e_pos_dv_diff, e_pos_dv, e_pos_dv_prev);
01861         calc_vector_dot_prod_f(&e_pos_dv_dp, e_pos_dv, e_pos_dv_diff);
01862 
01863         e_pos_dlambda_diff = e_pos_dlambda - e_pos_dlambda_prev;
01864         e_pos_dlambda_dp = e_pos_dlambda * e_pos_dlambda_diff;
01865 
01866         e_pos_dv_beta = 
01867             (e_pos_dv_prev_dp > 0) && (e_pos_dv_dp / e_pos_dv_prev_dp) > 0 
01868             ? e_pos_dv_dp / e_pos_dv_prev_dp : 0;
01869 
01870         e_pos_dlambda_beta = (e_pos_dlambda_prev_dp > 0) && 
01871             (e_pos_dlambda_dp / e_pos_dlambda_prev_dp) > 0 
01872             ? e_pos_dlambda_dp / e_pos_dlambda_prev_dp : 0;
01873 
01874         multiply_vector_by_scalar_f(&e_pos_dv_prev, e_pos_dv_prev, 
01875                 e_pos_dv_beta);
01876         add_vectors_f(&e_pos_dv, e_pos_dv, e_pos_dv_prev);
01877 
01878         e_pos_dlambda += e_pos_dlambda_beta * e_pos_dlambda_prev;
01879 
01880 
01881         /* Negative lambda */
01882         multiply_vector_by_scalar_f(&eta_v, v_neg, eta);
01883 
01884         assert(add_vectors_f(&q, p, eta_v) == NULL);
01885 
01886         if ((err = set_params_from_pt(q, params)) ||
01887             (err = grad_energy_func(&a, params)) ||
01888             (err = energy_func(&c, params)))
01889         {
01890             assert(set_params_from_pt(p, params) == NULL);
01891             break;
01892         }
01893 
01894         assert(subtract_vectors_f(&q, p, eta_v) == NULL);
01895 
01896         if ((err = set_params_from_pt(q, params)) ||
01897             (err = grad_energy_func(&b, params)) ||
01898             (err = energy_func(&d, params)))
01899         {
01900             assert(set_params_from_pt(p, params) == NULL);
01901             break;
01902         }
01903 
01904         for (n = 0; n < N; n++)
01905         {
01906             e_neg_dv->elts[n] = (a->elts[n] - b->elts[n]) / eta -
01907                                 (0.5*lambda / eta) *
01908                                 (c - d) * (a->elts[n] + b->elts[n]);
01909         }
01910         e_neg_dlambda = -1.0 * (0.5*(c - d) / eta) * (0.5*(c - d) / eta);
01911 
01912         if (!e_neg_dv_prev)
01913         {
01914             copy_vector_f(&e_neg_dv_prev, e_neg_dv);
01915             calc_vector_dot_prod_f(&e_neg_dv_prev_dp, e_neg_dv_prev, 
01916                     e_neg_dv_prev);
01917             e_neg_dlambda_prev = e_neg_dlambda;
01918             e_neg_dlambda_prev_dp = e_neg_dlambda_prev * e_neg_dlambda_prev;
01919         }
01920 
01921         subtract_vectors_f(&e_neg_dv_diff, e_neg_dv, e_neg_dv_prev);
01922         calc_vector_dot_prod_f(&e_neg_dv_dp, e_neg_dv, e_neg_dv_diff);
01923 
01924         e_neg_dlambda_diff = e_neg_dlambda - e_neg_dlambda_prev;
01925         e_neg_dlambda_dp = e_neg_dlambda * e_neg_dlambda_diff;
01926 
01927         e_neg_dv_beta = 
01928             (e_neg_dv_prev_dp > 0) && (e_neg_dv_dp / e_neg_dv_prev_dp) > 0 
01929             ? e_neg_dv_dp / e_neg_dv_prev_dp : 0;
01930 
01931         e_neg_dlambda_beta = (e_neg_dlambda_prev_dp > 0) && 
01932             (e_neg_dlambda_dp / e_neg_dlambda_prev_dp) > 0 
01933             ? e_neg_dlambda_dp / e_neg_dlambda_prev_dp : 0;
01934 
01935         multiply_vector_by_scalar_f(&e_neg_dv_prev, e_neg_dv_prev, 
01936                 e_neg_dv_beta);
01937         add_vectors_f(&e_neg_dv, e_neg_dv, e_neg_dv_prev);
01938 
01939         e_neg_dlambda += e_neg_dlambda_beta * e_neg_dlambda_prev;
01940 
01941 
01942         assert(set_params_from_pt(p, params) == NULL);
01943 
01944 
01945         assert(copy_vector_f(&delta_v_pos, v_pos) == NULL);
01946         assert(copy_vector_f(&delta_v_neg, v_neg) == NULL);
01947         delta_g1p    = g1p;
01948         delta_lambda = lambda;
01949         delta_e      = e_pos + e_neg;
01950         done         = 0;
01951         g            = gamma;
01952 
01953         while (!done)
01954         {
01955             lambda_cp = lambda;
01956 
01957             lambda_cp -= g * e_pos_dlambda;
01958             lambda_cp -= g * e_neg_dlambda;
01959 
01960             copy_vector_f(&v_pos_cp, v_pos);
01961             copy_vector_f(&v_neg_cp, v_neg);
01962 
01963             for (n = 0; n < N; n++)
01964             {
01965                 v_pos_cp->elts[ n ] -= g * e_pos_dv->elts[ n ];
01966                 v_neg_cp->elts[ n ] -= g * e_neg_dv->elts[ n ];
01967             }
01968             normalize_vector_mag_f(&v_pos_cp, v_pos_cp);
01969             normalize_vector_mag_f(&v_neg_cp, v_neg_cp);
01970 
01971             if ((err = hyperdynamics_hessgrad_eigenvalue_f(&e_pos, lambda_cp, 
01972                             v_pos_cp, eta, params, get_pt_from_params, 
01973                             set_params_from_pt, energy_func, 1)) ||
01974                 (err = hyperdynamics_hessgrad_eigenvalue_f(&e_neg, lambda_cp, 
01975                             v_neg_cp, eta, params, get_pt_from_params, 
01976                             set_params_from_pt, energy_func, 0)))
01977             {
01978                 break;
01979             }
01980 
01981             // TEMP
01982             //fprintf(stdout, "g1p: %10.3e %10.3e %10.3e %10.3e\n", 
01983             //        e_pos, e_neg, (delta_e - (e_pos+e_neg)), g);
01984 
01985             g *= 0.5;
01986 
01987             if (g < 1.0e-16 || (delta_e - (e_pos+e_neg)) >= 0)
01988             {
01989                 done = 1;
01990             }
01991         }
01992         if (err) 
01993         {
01994             break;
01995         }
01996         lambda = lambda_cp;
01997 
01998         copy_vector_f(&v_pos, v_pos_cp);
01999         copy_vector_f(&v_neg, v_neg_cp);
02000 
02001         delta_lambda = fabs(delta_lambda - lambda);
02002         delta_e = fabs(delta_e - (e_pos + e_neg));
02003 
02004         hyperdynamics_proj_hessian_eigenvector_f(&g1p, e_pos, e_neg, lambda);
02005         delta_g1p = fabs(delta_g1p - g1p);
02006 
02007         done = 1;
02008         for (n = 0; n < N; n++)
02009         {
02010             delta_v_pos->elts[ n ] 
02011                 = (fabs(fabs(delta_v_pos->elts[ n ]) - 
02012                    fabs(v_pos->elts[ n ])) < 1.0e-6)
02013                 ?  fabs(fabs(delta_v_pos->elts[ n ]) - fabs(v_pos->elts[ n ]))
02014                 :  fabs(delta_v_pos->elts[ n ] - v_pos->elts[ n ]);
02015 
02016             delta_v_neg->elts[ n ] 
02017                 = (fabs(fabs(delta_v_neg->elts[ n ]) - 
02018                    fabs(v_neg->elts[ n ])) < 1.0e-6)
02019                 ?  fabs(fabs(delta_v_neg->elts[ n ]) - fabs(v_neg->elts[ n ]))
02020                 :  fabs(delta_v_neg->elts[ n ] - v_neg->elts[ n ]);
02021 
02022             done = (done && (delta_v_pos->elts[ n ] <= 1.0e-6)
02023                          && (delta_v_neg->elts[ n ] <= 1.0e-6));
02024         }
02025         done = (done && (delta_lambda <= 1.0e-6));
02026         done = (done || (delta_g1p <= 1.0e-4));
02027 
02028         copy_vector_f(&e_pos_dv_prev, e_pos_dv);
02029         calc_vector_dot_prod_f(&e_pos_dv_prev_dp, e_pos_dv_prev, e_pos_dv_prev);
02030 
02031         e_pos_dlambda_prev = e_pos_dlambda;
02032         e_pos_dlambda_prev_dp = e_pos_dlambda_prev * e_pos_dlambda_prev;
02033 
02034         copy_vector_f(&e_neg_dv_prev, e_neg_dv);
02035         calc_vector_dot_prod_f(&e_neg_dv_prev_dp, e_neg_dv_prev, e_neg_dv_prev);
02036 
02037         e_neg_dlambda_prev = e_neg_dlambda;
02038         e_neg_dlambda_prev_dp = e_neg_dlambda_prev * e_neg_dlambda_prev;
02039     }
02040 
02041     *lambda_out = lambda;
02042 
02043     free_vector_f(v_pos_cp);
02044     free_vector_f(v_neg_cp);
02045     free_vector_f(delta_v_pos);
02046     free_vector_f(delta_v_neg);
02047     free_vector_f(eta_v);
02048     free_vector_f(e_pos_dv);
02049     free_vector_f(e_neg_dv);
02050     free_vector_f(e_pos_dv_diff);
02051     free_vector_f(e_neg_dv_diff);
02052     free_vector_f(e_pos_dv_prev);
02053     free_vector_f(e_neg_dv_prev);
02054     free_vector_f(p);
02055     free_vector_f(q);
02056     free_vector_f(a);
02057     free_vector_f(b);
02058 
02059     if (err)
02060     {
02061         free_vector_f(*v_pos_out); *v_pos_out = NULL;
02062         free_vector_f(*v_neg_out); *v_neg_out = NULL;
02063     }
02064 
02065     return err;
02066 }
02067 
02068 static Error* hyperdynamics_hessgrad_eigenvector_d
02069 (
02070     double*         lambda_out,
02071     Vector_d**      v_pos_out,
02072     Vector_d**      v_neg_out,
02073     double          eta, 
02074     double          gamma,
02075     void*           params,
02076     void            (*get_pt_from_params)(Vector_d**, const void*),
02077     Error*          (*set_params_from_pt)(const Vector_d*, void*),
02078     Error*          (*energy_func)(double*, void*),
02079     Error*          (*grad_energy_func)(Vector_d**, void*)
02080 )
02081 {
02082     uint32_t n;
02083     uint32_t N;
02084     uint8_t  done;
02085     double   g1p;
02086     double   lambda;
02087     double   lambda_cp;
02088     double   e_pos;
02089     double   e_neg;
02090     double   e_pos_dlambda;
02091     double   e_neg_dlambda;
02092     double   e_pos_dlambda_diff;
02093     double   e_neg_dlambda_diff;
02094     double   e_pos_dlambda_prev;
02095     double   e_neg_dlambda_prev;
02096     double   c, d;
02097     double   delta_g1p;
02098     double   delta_e;
02099     double   delta_lambda;
02100     double   g;
02101     double   e_pos_dv_dp;
02102     double   e_neg_dv_dp;
02103     double   e_pos_dv_prev_dp;
02104     double   e_neg_dv_prev_dp;
02105     double   e_pos_dlambda_dp;
02106     double   e_neg_dlambda_dp;
02107     double   e_pos_dlambda_prev_dp;
02108     double   e_neg_dlambda_prev_dp;
02109     double   e_pos_dv_beta;
02110     double   e_neg_dv_beta;
02111     double   e_pos_dlambda_beta;
02112     double   e_neg_dlambda_beta;
02113 
02114     Vector_d* v_pos;
02115     Vector_d* v_neg;
02116     Vector_d* v_pos_cp    = NULL;
02117     Vector_d* v_neg_cp    = NULL;
02118     Vector_d* delta_v_pos = NULL;
02119     Vector_d* delta_v_neg = NULL;
02120     Vector_d* eta_v       = NULL;
02121     Vector_d* e_pos_dv    = NULL;
02122     Vector_d* e_neg_dv    = NULL;
02123     Vector_d* e_pos_dv_diff = NULL;
02124     Vector_d* e_neg_dv_diff = NULL;
02125     Vector_d* e_pos_dv_prev = NULL;
02126     Vector_d* e_neg_dv_prev = NULL;
02127     Vector_d* p           = NULL;
02128     Vector_d* q           = NULL;
02129     Vector_d* a           = NULL;
02130     Vector_d* b           = NULL;
02131     Error*    err         = NULL;
02132 
02133     get_pt_from_params(&p, params);
02134     N = p->num_elts;
02135 
02136     create_vector_d(v_pos_out, N);
02137     v_pos = *v_pos_out;
02138 
02139     create_vector_d(v_neg_out, N);
02140     v_neg = *v_neg_out;
02141 
02142     create_vector_d(&e_pos_dv, N);
02143     create_vector_d(&e_neg_dv, N);
02144 
02145     lambda = *lambda_out;
02146 
02147     /* May not be the best initialization for these. */
02148     e_pos = 0;
02149     e_neg = 0;
02150     g1p   = 0;
02151 
02152     done = 0;
02153 
02154     while (!done)
02155     {
02156         get_pt_from_params(&p, params);
02157 
02158         /* Positive lambda */
02159         multiply_vector_by_scalar_d(&eta_v, v_pos, eta);
02160 
02161         assert(add_vectors_d(&q, p, eta_v) == NULL);
02162 
02163         if ((err = set_params_from_pt(q, params)) ||
02164             (err = grad_energy_func(&a, params)) ||
02165             (err = energy_func(&c, params)))
02166         {
02167             assert(set_params_from_pt(p, params) == NULL);
02168             break;
02169         }
02170 
02171         assert(subtract_vectors_d(&q, p, eta_v) == NULL);
02172 
02173         if ((err = set_params_from_pt(q, params)) ||
02174             (err = grad_energy_func(&b, params)) ||
02175             (err = energy_func(&d, params)))
02176         {
02177             assert(set_params_from_pt(p, params) == NULL);
02178             break;
02179         }
02180 
02181         for (n = 0; n < N; n++)
02182         {
02183             e_pos_dv->elts[n] = (a->elts[n] - b->elts[n]) / eta +
02184                                 (0.5*lambda / eta) *
02185                                 (c - d) * (a->elts[n] + b->elts[n]);
02186         }
02187         e_pos_dlambda = (0.5*(c - d) / eta) * (0.5*(c - d) / eta);
02188 
02189         if (!e_pos_dv_prev)
02190         {
02191             copy_vector_d(&e_pos_dv_prev, e_pos_dv);
02192             calc_vector_dot_prod_d(&e_pos_dv_prev_dp, e_pos_dv_prev, 
02193                     e_pos_dv_prev);
02194             e_pos_dlambda_prev = e_pos_dlambda;
02195             e_pos_dlambda_prev_dp = e_pos_dlambda_prev * e_pos_dlambda_prev;
02196         }
02197 
02198         subtract_vectors_d(&e_pos_dv_diff, e_pos_dv, e_pos_dv_prev);
02199         calc_vector_dot_prod_d(&e_pos_dv_dp, e_pos_dv, e_pos_dv_diff);
02200 
02201         e_pos_dlambda_diff = e_pos_dlambda - e_pos_dlambda_prev;
02202         e_pos_dlambda_dp = e_pos_dlambda * e_pos_dlambda_diff;
02203 
02204         e_pos_dv_beta = 
02205             (e_pos_dv_prev_dp > 0) && (e_pos_dv_dp / e_pos_dv_prev_dp) > 0 
02206             ? e_pos_dv_dp / e_pos_dv_prev_dp : 0;
02207 
02208         e_pos_dlambda_beta = (e_pos_dlambda_prev_dp > 0) && 
02209             (e_pos_dlambda_dp / e_pos_dlambda_prev_dp) > 0 
02210             ? e_pos_dlambda_dp / e_pos_dlambda_prev_dp : 0;
02211 
02212         multiply_vector_by_scalar_d(&e_pos_dv_prev, e_pos_dv_prev, 
02213                 e_pos_dv_beta);
02214         add_vectors_d(&e_pos_dv, e_pos_dv, e_pos_dv_prev);
02215 
02216         e_pos_dlambda += e_pos_dlambda_beta * e_pos_dlambda_prev;
02217 
02218 
02219         /* Negative lambda */
02220         multiply_vector_by_scalar_d(&eta_v, v_neg, eta);
02221 
02222         assert(add_vectors_d(&q, p, eta_v) == NULL);
02223 
02224         if ((err = set_params_from_pt(q, params)) ||
02225             (err = grad_energy_func(&a, params)) ||
02226             (err = energy_func(&c, params)))
02227         {
02228             assert(set_params_from_pt(p, params) == NULL);
02229             break;
02230         }
02231 
02232         assert(subtract_vectors_d(&q, p, eta_v) == NULL);
02233 
02234         if ((err = set_params_from_pt(q, params)) ||
02235             (err = grad_energy_func(&b, params)) ||
02236             (err = energy_func(&d, params)))
02237         {
02238             assert(set_params_from_pt(p, params) == NULL);
02239             break;
02240         }
02241 
02242         for (n = 0; n < N; n++)
02243         {
02244             e_neg_dv->elts[n] = (a->elts[n] - b->elts[n]) / eta -
02245                                 (0.5*lambda / eta) *
02246                                 (c - d) * (a->elts[n] + b->elts[n]);
02247         }
02248         e_neg_dlambda = -1.0 * (0.5*(c - d) / eta) * (0.5*(c - d) / eta);
02249 
02250         if (!e_neg_dv_prev)
02251         {
02252             copy_vector_d(&e_neg_dv_prev, e_neg_dv);
02253             calc_vector_dot_prod_d(&e_neg_dv_prev_dp, e_neg_dv_prev, 
02254                     e_neg_dv_prev);
02255             e_neg_dlambda_prev = e_neg_dlambda;
02256             e_neg_dlambda_prev_dp = e_neg_dlambda_prev * e_neg_dlambda_prev;
02257         }
02258 
02259         subtract_vectors_d(&e_neg_dv_diff, e_neg_dv, e_neg_dv_prev);
02260         calc_vector_dot_prod_d(&e_neg_dv_dp, e_neg_dv, e_neg_dv_diff);
02261 
02262         e_neg_dlambda_diff = e_neg_dlambda - e_neg_dlambda_prev;
02263         e_neg_dlambda_dp = e_neg_dlambda * e_neg_dlambda_diff;
02264 
02265         e_neg_dv_beta = 
02266             (e_neg_dv_prev_dp > 0) && (e_neg_dv_dp / e_neg_dv_prev_dp) > 0 
02267             ? e_neg_dv_dp / e_neg_dv_prev_dp : 0;
02268 
02269         e_neg_dlambda_beta = (e_neg_dlambda_prev_dp > 0) && 
02270             (e_neg_dlambda_dp / e_neg_dlambda_prev_dp) > 0 
02271             ? e_neg_dlambda_dp / e_neg_dlambda_prev_dp : 0;
02272 
02273         multiply_vector_by_scalar_d(&e_neg_dv_prev, e_neg_dv_prev, 
02274                 e_neg_dv_beta);
02275         add_vectors_d(&e_neg_dv, e_neg_dv, e_neg_dv_prev);
02276 
02277         e_neg_dlambda += e_neg_dlambda_beta * e_neg_dlambda_prev;
02278 
02279 
02280         assert(set_params_from_pt(p, params) == NULL);
02281 
02282 
02283         assert(copy_vector_d(&delta_v_pos, v_pos) == NULL);
02284         assert(copy_vector_d(&delta_v_neg, v_neg) == NULL);
02285         delta_g1p    = g1p;
02286         delta_lambda = lambda;
02287         delta_e      = e_pos + e_neg;
02288         done         = 0;
02289         g            = gamma;
02290 
02291         while (!done)
02292         {
02293             lambda_cp = lambda;
02294 
02295             lambda_cp -= g * e_pos_dlambda;
02296             lambda_cp -= g * e_neg_dlambda;
02297 
02298             copy_vector_d(&v_pos_cp, v_pos);
02299             copy_vector_d(&v_neg_cp, v_neg);
02300 
02301             for (n = 0; n < N; n++)
02302             {
02303                 v_pos_cp->elts[ n ] -= g * e_pos_dv->elts[ n ];
02304                 v_neg_cp->elts[ n ] -= g * e_neg_dv->elts[ n ];
02305             }
02306             normalize_vector_mag_d(&v_pos_cp, v_pos_cp);
02307             normalize_vector_mag_d(&v_neg_cp, v_neg_cp);
02308 
02309             if ((err = hyperdynamics_hessgrad_eigenvalue_d(&e_pos, lambda_cp, 
02310                             v_pos_cp, eta, params, get_pt_from_params, 
02311                             set_params_from_pt, energy_func, 1)) ||
02312                 (err = hyperdynamics_hessgrad_eigenvalue_d(&e_neg, lambda_cp, 
02313                             v_neg_cp, eta, params, get_pt_from_params, 
02314                             set_params_from_pt, energy_func, 0)))
02315             {
02316                 break;
02317             }
02318 
02319             g *= 0.5;
02320 
02321             if (g < 1.0e-128 || (delta_e - (e_pos+e_neg)) >= 0)
02322             {
02323                 done = 1;
02324             }
02325         }
02326         if (err) 
02327         {
02328             break;
02329         }
02330         lambda = lambda_cp;
02331 
02332         copy_vector_d(&v_pos, v_pos_cp);
02333         copy_vector_d(&v_neg, v_neg_cp);
02334 
02335         delta_lambda = fabs(delta_lambda - lambda);
02336         delta_e = fabs(delta_e - (e_pos + e_neg));
02337 
02338         hyperdynamics_proj_hessian_eigenvector_d(&g1p, e_pos, e_neg, lambda);
02339         delta_g1p = fabs(delta_g1p - g1p);
02340 
02341         done = 1;
02342         for (n = 0; n < N; n++)
02343         {
02344             delta_v_pos->elts[ n ] 
02345                 = (fabs(fabs(delta_v_pos->elts[ n ]) - 
02346                    fabs(v_pos->elts[ n ])) < 1.0e-8)
02347                 ?  fabs(fabs(delta_v_pos->elts[ n ]) - fabs(v_pos->elts[ n ]))
02348                 :  fabs(delta_v_pos->elts[ n ] - v_pos->elts[ n ]);
02349 
02350             delta_v_neg->elts[ n ] 
02351                 = (fabs(fabs(delta_v_neg->elts[ n ]) - 
02352                    fabs(v_neg->elts[ n ])) < 1.0e-8)
02353                 ?  fabs(fabs(delta_v_neg->elts[ n ]) - fabs(v_neg->elts[ n ]))
02354                 :  fabs(delta_v_neg->elts[ n ] - v_neg->elts[ n ]);
02355 
02356             done = (done && (delta_v_pos->elts[ n ] <= 1.0e-8)
02357                          && (delta_v_neg->elts[ n ] <= 1.0e-8));
02358         }
02359         done = (done && (delta_lambda <= 1.0e-8));
02360         done = (done || (delta_g1p <= 1.0e-4));
02361 
02362         copy_vector_d(&e_pos_dv_prev, e_pos_dv);
02363         calc_vector_dot_prod_d(&e_pos_dv_prev_dp, e_pos_dv_prev, e_pos_dv_prev);
02364 
02365         e_pos_dlambda_prev = e_pos_dlambda;
02366         e_pos_dlambda_prev_dp = e_pos_dlambda_prev * e_pos_dlambda_prev;
02367 
02368         copy_vector_d(&e_neg_dv_prev, e_neg_dv);
02369         calc_vector_dot_prod_d(&e_neg_dv_prev_dp, e_neg_dv_prev, e_neg_dv_prev);
02370 
02371         e_neg_dlambda_prev = e_neg_dlambda;
02372         e_neg_dlambda_prev_dp = e_neg_dlambda_prev * e_neg_dlambda_prev;
02373     }
02374 
02375     *lambda_out = lambda;
02376 
02377     free_vector_d(v_pos_cp);
02378     free_vector_d(v_neg_cp);
02379     free_vector_d(delta_v_pos);
02380     free_vector_d(delta_v_neg);
02381     free_vector_d(eta_v);
02382     free_vector_d(e_pos_dv);
02383     free_vector_d(e_neg_dv);
02384     free_vector_d(e_pos_dv_diff);
02385     free_vector_d(e_neg_dv_diff);
02386     free_vector_d(e_pos_dv_prev);
02387     free_vector_d(e_neg_dv_prev);
02388     free_vector_d(p);
02389     free_vector_d(q);
02390     free_vector_d(a);
02391     free_vector_d(b);
02392 
02393     if (err)
02394     {
02395         free_vector_d(*v_pos_out); *v_pos_out = NULL;
02396         free_vector_d(*v_neg_out); *v_neg_out = NULL;
02397     }
02398 
02399     return err;
02400 }
02401 
02415 static Error* hyperdynamics_dx_hessgrad_eigenvalue_f
02416 (
02417     Vector_f**      e_lambda_dx_out, 
02418     float           lambda, 
02419     const Vector_f* v, 
02420     float           eta, 
02421     void*           params,
02422     void            (*get_pt_from_params)(Vector_f**, const void*),
02423     Error*          (*set_params_from_pt)(const Vector_f*, void*),
02424     Error*          (*energy_func)(float*, void*),
02425     Error*          (*grad_energy_func)(Vector_f**, void*),
02426     uint8_t         positive
02427 )
02428 {
02429     uint32_t n;
02430     uint32_t N;
02431     float    a, b;
02432 
02433     Vector_f* e_lambda_dx;
02434     Vector_f* e_dx  = NULL;
02435     Vector_f* eta_v = NULL;
02436     Vector_f* p     = NULL;
02437     Vector_f* q     = NULL;
02438     Vector_f* c     = NULL;
02439     Vector_f* d     = NULL;
02440     Error*    err;
02441 
02442     if ((err = hyperdynamics_dx_hessian_eigenvalue_f(&e_dx, v, eta, params,
02443                     get_pt_from_params, set_params_from_pt, grad_energy_func)))
02444     {
02445         return err;
02446     }
02447 
02448     get_pt_from_params(&p, params);
02449     N = p->num_elts;
02450 
02451     multiply_vector_by_scalar_f(&eta_v, v, eta);
02452 
02453     assert(add_vectors_f(&q, p, eta_v) == NULL);
02454 
02455     if ((err = set_params_from_pt(q, params)) ||
02456         (err = energy_func(&a, params)) ||
02457         (err = grad_energy_func(&c, params)))
02458     {
02459         assert(set_params_from_pt(p, params) == NULL);
02460         free_vector_f(e_dx);
02461         free_vector_f(eta_v);
02462         free_vector_f(p); free_vector_f(q);
02463         free_vector_f(c); free_vector_f(d);
02464         return err;
02465     }
02466 
02467     assert(subtract_vectors_f(&q, p, eta_v) == NULL);
02468 
02469     if ((err = set_params_from_pt(q, params)) ||
02470         (err = energy_func(&b, params)) ||
02471         (err = grad_energy_func(&d, params)))
02472     {
02473         assert(set_params_from_pt(p, params) == NULL);
02474         free_vector_f(e_dx);
02475         free_vector_f(eta_v);
02476         free_vector_f(p); free_vector_f(q);
02477         free_vector_f(c); free_vector_f(d);
02478         return err;
02479     }
02480 
02481     assert(set_params_from_pt(p, params) == NULL);
02482 
02483     create_vector_f(e_lambda_dx_out, N);
02484     e_lambda_dx = *e_lambda_dx_out;
02485     for (n = 0; n < N; n++)
02486     {
02487         e_lambda_dx->elts[ n ] = e_dx->elts[ n ];
02488 
02489         if (positive)
02490         {
02491             e_lambda_dx->elts[ n ] += 0.5*lambda * (a - b) * 
02492                                       (c->elts[n] - d->elts[n]) / (eta*eta);
02493         }
02494         else
02495         {
02496             e_lambda_dx->elts[ n ] -= 0.5*lambda * (a - b) * 
02497                                       (c->elts[n] - d->elts[n]) / (eta*eta);
02498         }
02499     }
02500 
02501     free_vector_f(e_dx);
02502     free_vector_f(eta_v);
02503     free_vector_f(p);
02504     free_vector_f(q);
02505     free_vector_f(c);
02506     free_vector_f(d);
02507 
02508     return NULL;
02509 }
02510 
02511 static Error* hyperdynamics_dx_hessgrad_eigenvalue_d
02512 (
02513     Vector_d**      e_lambda_dx_out, 
02514     double          lambda, 
02515     const Vector_d* v, 
02516     double          eta, 
02517     void*           params,
02518     void            (*get_pt_from_params)(Vector_d**, const void*),
02519     Error*          (*set_params_from_pt)(const Vector_d*, void*),
02520     Error*          (*energy_func)(double*, void*),
02521     Error*          (*grad_energy_func)(Vector_d**, void*),
02522     uint8_t         positive
02523 )
02524 {
02525     uint32_t n;
02526     uint32_t N;
02527     double   a, b;
02528 
02529     Vector_d* e_lambda_dx;
02530     Vector_d* e_dx  = NULL;
02531     Vector_d* eta_v = NULL;
02532     Vector_d* p     = NULL;
02533     Vector_d* q     = NULL;
02534     Vector_d* c     = NULL;
02535     Vector_d* d     = NULL;
02536     Error*    err;
02537 
02538     if ((err = hyperdynamics_dx_hessian_eigenvalue_d(&e_dx, v, eta, params,
02539                     get_pt_from_params, set_params_from_pt, grad_energy_func)))
02540     {
02541         return err;
02542     }
02543 
02544     get_pt_from_params(&p, params);
02545     N = p->num_elts;
02546 
02547     multiply_vector_by_scalar_d(&eta_v, v, eta);
02548 
02549     assert(add_vectors_d(&q, p, eta_v) == NULL);
02550 
02551     if ((err = set_params_from_pt(q, params)) ||
02552         (err = energy_func(&a, params)) ||
02553         (err = grad_energy_func(&c, params)))
02554     {
02555         assert(set_params_from_pt(p, params) == NULL);
02556         free_vector_d(e_dx);
02557         free_vector_d(eta_v);
02558         free_vector_d(p); free_vector_d(q);
02559         free_vector_d(c); free_vector_d(d);
02560         return err;
02561     }
02562 
02563     assert(subtract_vectors_d(&q, p, eta_v) == NULL);
02564 
02565     if ((err = set_params_from_pt(q, params)) ||
02566         (err = energy_func(&b, params)) ||
02567         (err = grad_energy_func(&d, params)))
02568     {
02569         assert(set_params_from_pt(p, params) == NULL);
02570         free_vector_d(e_dx);
02571         free_vector_d(eta_v);
02572         free_vector_d(p); free_vector_d(q);
02573         free_vector_d(c); free_vector_d(d);
02574         return err;
02575     }
02576 
02577     assert(set_params_from_pt(p, params) == NULL);
02578 
02579     create_vector_d(e_lambda_dx_out, N);
02580     e_lambda_dx = *e_lambda_dx_out;
02581     for (n = 0; n < N; n++)
02582     {
02583         e_lambda_dx->elts[ n ] = e_dx->elts[ n ];
02584 
02585         if (positive)
02586         {
02587             e_lambda_dx->elts[ n ] += 0.5*lambda * (a - b) * 
02588                                       (c->elts[n] - d->elts[n]) / (eta*eta);
02589         }
02590         else
02591         {
02592             e_lambda_dx->elts[ n ] -= 0.5*lambda * (a - b) * 
02593                                       (c->elts[n] - d->elts[n]) / (eta*eta);
02594         }
02595     }
02596 
02597     free_vector_d(e_dx);
02598     free_vector_d(eta_v);
02599     free_vector_d(p);
02600     free_vector_d(q);
02601     free_vector_d(c);
02602     free_vector_d(d);
02603 
02604     return NULL;
02605 }
02606 
02620 static Error* hyperdynamics_dx_proj_hessian_eigenvector_f
02621 (
02622     Vector_f**      g1p_dx_out,
02623     const Vector_f* e_pos_dx,
02624     const Vector_f* e_neg_dx,
02625     float           g1p,
02626     float           lambda
02627 )
02628 {
02629     uint32_t n;
02630     uint32_t N;
02631 
02632     N = e_pos_dx->num_elts;
02633     create_vector_f(g1p_dx_out, N);
02634 
02635     for (n = 0; n < N; n++)
02636     {
02637         (*g1p_dx_out)->elts[ n ] = (e_pos_dx->elts[n] - e_neg_dx->elts[n]) /
02638                                    (g1p*4.0*lambda);
02639     }
02640 
02641     return NULL;
02642 }
02643 
02644 static Error* hyperdynamics_dx_proj_hessian_eigenvector_d
02645 (
02646     Vector_d**      g1p_dx_out,
02647     const Vector_d* e_pos_dx,
02648     const Vector_d* e_neg_dx,
02649     double          g1p,
02650     double          lambda
02651 )
02652 {
02653     uint32_t n;
02654     uint32_t N;
02655 
02656     N = e_pos_dx->num_elts;
02657     create_vector_d(g1p_dx_out, N);
02658 
02659     for (n = 0; n < N; n++)
02660     {
02661         (*g1p_dx_out)->elts[ n ] = (e_pos_dx->elts[n] - e_neg_dx->elts[n]) /
02662                                    (g1p*4.0*lambda);
02663     }
02664 
02665     return NULL;
02666 }
02667 
02710 Error* langevin_hyperdynamics_1_f
02711 (
02712     uint32_t iterations,
02713     float    delta_t,
02714     float    gamma,
02715     float    eta,
02716     float    h,
02717     float    d,
02718     void*    params,
02719     void     (*get_pt_from_params)(Vector_f** p_out, const void* params),
02720     Error*   (*set_params_from_pt)(const Vector_f* p, void* params),
02721     Error*   (*energy_func)(float* energy_out, void* params),
02722     Error*   (*grad_energy_func)(Vector_f** grad_out, void* params),
02723     Error*   (*accept_sample)(const Vector_f* sample, void* params, float energy_bias)
02724 )
02725 {
02726     uint32_t D;
02727 
02728     Vector_f* p = NULL;
02729     Vector_f* delta_t_v = NULL;
02730     Error*    err;
02731 
02732     get_pt_from_params(&p, params);
02733     D = p->num_elts;
02734 
02735     create_init_vector_f(&delta_t_v, D, delta_t);
02736 
02737     err = langevin_hyperdynamics_2_f(iterations, delta_t_v, gamma, eta, h, d,
02738             params, get_pt_from_params, set_params_from_pt, energy_func,
02739             grad_energy_func, accept_sample);
02740 
02741     free_vector_f(p);
02742     free_vector_f(delta_t_v);
02743 
02744     return err;
02745 }
02746 
02776 Error* langevin_hyperdynamics_2_f
02777 (
02778     uint32_t        iterations,
02779     const Vector_f* delta_t,
02780     float           gamma,
02781     float           eta,
02782     float           h,
02783     float           d,
02784     void*           params,
02785     void            (*get_pt_from_params)(Vector_f** p_out, const void* params),
02786     Error*          (*set_params_from_pt)(const Vector_f* p, void* params),
02787     Error*          (*energy_func)(float* energy_out, void* params),
02788     Error*          (*grad_energy_func)(Vector_f** grad_out, void* params),
02789     Error*          (*accept_sample)(const Vector_f* sample, void* params, float energy_bias)
02790 )
02791 {
02792     uint32_t i;
02793     uint32_t n;
02794     uint32_t N;
02795     float    gauss;
02796     float    lambda;
02797     float    e;
02798     float    e_pos;
02799     float    e_neg;
02800     float    g1p;
02801     float    Vb;
02802     float    Vb_dx;
02803     float    dt;
02804 
02805     Vector_f* p        = NULL;
02806     Vector_f* v        = NULL;
02807     Vector_f* v_pos    = NULL;
02808     Vector_f* v_neg    = NULL;
02809     Vector_f* e_dx     = NULL;
02810     Vector_f* e_pos_dx = NULL;
02811     Vector_f* e_neg_dx = NULL;
02812     Vector_f* g1p_dx   = NULL;
02813     Vector_f* V_dx     = NULL;
02814     Error*    err      = NULL;
02815 
02816     get_pt_from_params(&p, params);
02817     N = p->num_elts;
02818 
02819     /* Randomly initialize lambda and the eigenvectors. */
02820     create_random_vector_f(&v, N, -1, 1);
02821     normalize_vector_mag_f(&v, v);
02822 
02823     create_random_vector_f(&v_pos, N, -1, 1);
02824     normalize_vector_mag_f(&v_pos, v_pos);
02825 
02826     create_random_vector_f(&v_neg, N, -1, 1);
02827     normalize_vector_mag_f(&v_neg, v_neg);
02828 
02829     lambda = sample_uniform_pdf_f(-1.0e3, 1.0e3);
02830 
02831     for (i = 0; i < iterations; i++)
02832     {
02833         if ((err = hyperdynamics_hessian_eigenvector_f(&v, eta, gamma, 
02834                         params, get_pt_from_params, set_params_from_pt, 
02835                         energy_func, grad_energy_func)))
02836         {
02837             break;
02838         }
02839 
02840         if ((err = hyperdynamics_hessian_eigenvalue_f(&e, v, eta, params,
02841                         get_pt_from_params, set_params_from_pt, energy_func)))
02842         {
02843             break;
02844         }
02845 
02846         if ((err = hyperdynamics_dx_hessian_eigenvalue_f(&e_dx, v, eta, params,
02847                         get_pt_from_params, set_params_from_pt, 
02848                         grad_energy_func)))
02849         {
02850             break;
02851         }
02852 
02853         if ((err = hyperdynamics_hessgrad_eigenvector_f(&lambda, &v_pos, &v_neg,
02854                         eta, gamma, params, get_pt_from_params, 
02855                         set_params_from_pt, energy_func, grad_energy_func)))
02856         {
02857             break;
02858         }
02859 
02860         if ((err = hyperdynamics_hessgrad_eigenvalue_f(&e_pos, lambda, v_pos,
02861                         eta, params, get_pt_from_params, set_params_from_pt, 
02862                         energy_func, 1)))
02863         {
02864             break;
02865         }
02866 
02867         if ((err = hyperdynamics_hessgrad_eigenvalue_f(&e_neg, lambda, v_neg,
02868                         eta, params, get_pt_from_params, set_params_from_pt, 
02869                         energy_func, 0)))
02870         {
02871             break;
02872         }
02873 
02874         if ((err = hyperdynamics_dx_hessgrad_eigenvalue_f(&e_pos_dx, lambda, 
02875                         v_pos, eta, params, get_pt_from_params, 
02876                         set_params_from_pt, energy_func, grad_energy_func, 1)))
02877         {
02878             break;
02879         }
02880 
02881         if ((err = hyperdynamics_dx_hessgrad_eigenvalue_f(&e_neg_dx, lambda, 
02882                         v_neg, eta, params, get_pt_from_params, 
02883                         set_params_from_pt, energy_func, grad_energy_func, 0)))
02884         {
02885             break;
02886         }
02887 
02888         if ((err = hyperdynamics_proj_hessian_eigenvector_f(&g1p, e_pos, e_neg, 
02889                         lambda)))
02890         {
02891             break;
02892         }
02893 
02894         if ((err = hyperdynamics_dx_proj_hessian_eigenvector_f(&g1p_dx, 
02895                         e_pos_dx, e_neg_dx, g1p, lambda)))
02896         {
02897             break;
02898         }
02899 
02900         if ((err = grad_energy_func(&V_dx, params)))
02901         {
02902             break;
02903         }
02904 
02905         get_pt_from_params(&p, params);
02906 
02907         Vb = 0.5*h * (1 + e / sqrt(e*e + g1p*g1p/(d*d)));
02908 
02909         for (n = 0; n < N; n++)
02910         {
02911             Vb_dx = (h / (2*sqrt((e*e) + ((g1p*g1p)/(d*d))))) * 
02912                     (e_dx->elts[n] - e*(e*e_dx->elts[n] + 
02913                                         (g1p/(d*d))*g1p_dx->elts[n]) / 
02914                      (e*e + (g1p*g1p)/(d*d)));
02915 
02916             dt    = delta_t->elts[ n ];
02917             gauss = sample_standard_gaussian_pdf_f(-6.0, 6.0);
02918 
02919             p->elts[ n ] -= dt*(0.5*dt*(V_dx->elts[n]+Vb_dx) + gauss);
02920         }
02921 
02922         if ((err = accept_sample(p, params, Vb)))
02923         {
02924             break;
02925         }
02926     }
02927 
02928     free_vector_f(p);
02929     free_vector_f(v);
02930     free_vector_f(v_pos);
02931     free_vector_f(v_neg);
02932     free_vector_f(e_dx);
02933     free_vector_f(e_pos_dx);
02934     free_vector_f(e_neg_dx);
02935     free_vector_f(g1p_dx);
02936     free_vector_f(V_dx);
02937 
02938     return err;
02939 }
02940 
02969 Error* langevin_hyperdynamics_1_d
02970 (
02971     uint32_t iterations,
02972     double   delta_t,
02973     double   gamma,
02974     double   eta,
02975     double   h,
02976     double   d,
02977     void*    params,
02978     void     (*get_pt_from_params)(Vector_d** p_out, const void* params),
02979     Error*   (*set_params_from_pt)(const Vector_d* p, void* params),
02980     Error*   (*energy_func)(double* energy_out, void* params),
02981     Error*   (*grad_energy_func)(Vector_d** grad_out, void* params),
02982     Error*   (*accept_sample)(const Vector_d* sample, void* params, double energy_bias)
02983 )
02984 {
02985     uint32_t D;
02986 
02987     Vector_d* p = NULL;
02988     Vector_d* delta_t_v = NULL;
02989     Error*    err;
02990 
02991     get_pt_from_params(&p, params);
02992     D = p->num_elts;
02993 
02994     create_init_vector_d(&delta_t_v, D, delta_t);
02995 
02996     err = langevin_hyperdynamics_2_d(iterations, delta_t_v, gamma, eta, h, d,
02997             params, get_pt_from_params, set_params_from_pt, energy_func,
02998             grad_energy_func, accept_sample);
02999 
03000     free_vector_d(p);
03001     free_vector_d(delta_t_v);
03002 
03003     return err;
03004 }
03005 
03034 Error* langevin_hyperdynamics_2_d
03035 (
03036     uint32_t        iterations,
03037     const Vector_d* delta_t,
03038     double          gamma,
03039     double          eta,
03040     double          h,
03041     double          d,
03042     void*           params,
03043     void            (*get_pt_from_params)(Vector_d** p_out, const void* params),
03044     Error*          (*set_params_from_pt)(const Vector_d* p, void* params),
03045     Error*          (*energy_func)(double* energy_out, void* params),
03046     Error*          (*grad_energy_func)(Vector_d** grad_out, void* params),
03047     Error*          (*accept_sample)(const Vector_d* sample, void* params, double energy_bias)
03048 )
03049 {
03050     uint32_t i;
03051     uint32_t n;
03052     uint32_t N;
03053     double   gauss;
03054     double   lambda;
03055     double   e;
03056     double   e_pos;
03057     double   e_neg;
03058     double   g1p;
03059     double   Vb;
03060     double   Vb_dx;
03061     double   dt;
03062 
03063     Vector_d* p        = NULL;
03064     Vector_d* v        = NULL;
03065     Vector_d* v_pos    = NULL;
03066     Vector_d* v_neg    = NULL;
03067     Vector_d* e_dx     = NULL;
03068     Vector_d* e_pos_dx = NULL;
03069     Vector_d* e_neg_dx = NULL;
03070     Vector_d* g1p_dx   = NULL;
03071     Vector_d* V_dx     = NULL;
03072     Error*    err      = NULL;
03073 
03074     get_pt_from_params(&p, params);
03075     N = p->num_elts;
03076 
03077     /* Randomly initialize lambda and the eigenvectors. */
03078     create_random_vector_d(&v, N, -1, 1);
03079     normalize_vector_mag_d(&v, v);
03080 
03081     create_random_vector_d(&v_pos, N, -1, 1);
03082     normalize_vector_mag_d(&v_pos, v_pos);
03083 
03084     create_random_vector_d(&v_neg, N, -1, 1);
03085     normalize_vector_mag_d(&v_neg, v_neg);
03086 
03087     lambda = sample_uniform_pdf_d(-1.0e3, 1.0e3);
03088 
03089     for (i = 0; i < iterations; i++)
03090     {
03091         if ((err = hyperdynamics_hessian_eigenvector_d(&v, eta, gamma, 
03092                         params, get_pt_from_params, set_params_from_pt, 
03093                         energy_func, grad_energy_func)))
03094         {
03095             break;
03096         }
03097 
03098         if ((err = hyperdynamics_hessian_eigenvalue_d(&e, v, eta, params,
03099                         get_pt_from_params, set_params_from_pt, energy_func)))
03100         {
03101             break;
03102         }
03103 
03104         if ((err = hyperdynamics_dx_hessian_eigenvalue_d(&e_dx, v, eta, params,
03105                         get_pt_from_params, set_params_from_pt, 
03106                         grad_energy_func)))
03107         {
03108             break;
03109         }
03110 
03111         if ((err = hyperdynamics_hessgrad_eigenvector_d(&lambda, &v_pos, &v_neg,
03112                         eta, gamma, params, get_pt_from_params, 
03113                         set_params_from_pt, energy_func, grad_energy_func)))
03114         {
03115             break;
03116         }
03117 
03118         if ((err = hyperdynamics_hessgrad_eigenvalue_d(&e_pos, lambda, v_pos,
03119                         eta, params, get_pt_from_params, set_params_from_pt, 
03120                         energy_func, 1)))
03121         {
03122             break;
03123         }
03124 
03125         if ((err = hyperdynamics_hessgrad_eigenvalue_d(&e_neg, lambda, v_neg,
03126                         eta, params, get_pt_from_params, set_params_from_pt, 
03127                         energy_func, 0)))
03128         {
03129             break;
03130         }
03131 
03132         if ((err = hyperdynamics_dx_hessgrad_eigenvalue_d(&e_pos_dx, lambda, 
03133                         v_pos, eta, params, get_pt_from_params, 
03134                         set_params_from_pt, energy_func, grad_energy_func, 1)))
03135         {
03136             break;
03137         }
03138 
03139         if ((err = hyperdynamics_dx_hessgrad_eigenvalue_d(&e_neg_dx, lambda, 
03140                         v_neg, eta, params, get_pt_from_params, 
03141                         set_params_from_pt, energy_func, grad_energy_func, 0)))
03142         {
03143             break;
03144         }
03145 
03146         if ((err = hyperdynamics_proj_hessian_eigenvector_d(&g1p, e_pos, e_neg, 
03147                         lambda)))
03148         {
03149             break;
03150         }
03151 
03152         if ((err = hyperdynamics_dx_proj_hessian_eigenvector_d(&g1p_dx, 
03153                         e_pos_dx, e_neg_dx, g1p, lambda)))
03154         {
03155             break;
03156         }
03157 
03158         if ((err = grad_energy_func(&V_dx, params)))
03159         {
03160             break;
03161         }
03162 
03163         get_pt_from_params(&p, params);
03164 
03165         Vb = 0.5*h * (1 + e / sqrt(e*e + g1p*g1p/(d*d)));
03166 
03167         for (n = 0; n < N; n++)
03168         {
03169             Vb_dx = (h / (2*sqrt((e*e) + ((g1p*g1p)/(d*d))))) * 
03170                     (e_dx->elts[n] - e*(e*e_dx->elts[n] + 
03171                                         (g1p/(d*d))*g1p_dx->elts[n]) / 
03172                      (e*e + (g1p*g1p)/(d*d)));
03173 
03174             dt    = delta_t->elts[ n ];
03175             gauss = sample_standard_gaussian_pdf_d(-6.0, 6.0);
03176 
03177             p->elts[ n ] -= dt*(0.5*dt*(V_dx->elts[n]+Vb_dx) + gauss);
03178         }
03179 
03180         if ((err = accept_sample(p, params, Vb)))
03181         {
03182             break;
03183         }
03184     }
03185 
03186     free_vector_d(p);
03187     free_vector_d(v);
03188     free_vector_d(v_pos);
03189     free_vector_d(v_neg);
03190     free_vector_d(e_dx);
03191     free_vector_d(e_pos_dx);
03192     free_vector_d(e_neg_dx);
03193     free_vector_d(g1p_dx);
03194     free_vector_d(V_dx);
03195 
03196     return err;
03197 }
03198