// cg differential function along a restricted set of eigenvectors.
//
// There will be one coordinate for each eigenvector.
cg differential function along a restricted set of eigenvectors.
There will be one coordinate for each eigenvector.
cg differential function along a restricted set of eigenvectors . There will be one coordinate for each eigenvector .
fn constrained_diff_fn<'a>(
    // operates on 3N coords
    flat_3n_diff_fn: &'a mut DynCgDiffFn<'a>,
    // K values, K <= 3N
    flat_init_pos: &'a [f64],
    // K eigenvectors
    flat_evs: &'a [&[f64]],
) -> Box<DynCgDiffFn<'a>>
{
    struct Adapter<'b> {
        flat_init_pos: &'b [f64],
        flat_3n_diff_fn: &'b mut DynCgDiffFn<'b>,
        flat_evs: &'b [&'b [f64]],
    }
    impl<'b> cg::DiffFn for Adapter<'b> {
        type Error = failure::Error;
        fn compute(&mut self, coeffs: &[f64]) -> FailResult<(f64, Vec<f64>)>
        {Ok({
            let Adapter { flat_init_pos, flat_3n_diff_fn, flat_evs } = self;
            // This is dead simple.
            // The kth element of the new gradient is the slope along the kth ev.
            // The change in position is a sum over contributions from each ev.
            // These relationships have a simple expression in terms of
            //   the matrix whose columns are the selected eigenvectors.
            // (though the following is transposed for our row-centric formalism)
            let flat_pos = flat_constrained_position(flat_init_pos, coeffs, flat_evs);
            let (value, flat_grad) = flat_3n_diff_fn.compute(&flat_pos)?;
            let grad = dot_mat_vec_dumb(flat_evs, &flat_grad);
            (value, grad)
        })}
        fn check(&mut self, coeffs: &[f64]) -> FailResult<()> {
            let Adapter { flat_init_pos, flat_3n_diff_fn, flat_evs } = self;
            let flat_pos = flat_constrained_position(flat_init_pos, coeffs, flat_evs);
            flat_3n_diff_fn.check(&flat_pos)
        }
    }
    Box::new(Adapter { flat_init_pos, flat_3n_diff_fn, flat_evs })
}
fn constrained_diff_fn < ' a > ( // operates on 3N coords flat_3n_diff_fn : & ' a mut DynCgDiffFn < ' a > , // K values, K <= 3N flat_init_pos : & ' a [ f64 ] , // K eigenvectors flat_evs : & ' a [ & [ f64 ] ] , ) -> Box < DynCgDiffFn < ' a > > { struct Adapter < ' b > { flat_init_pos : & ' b [ f64 ] , flat_3n_diff_fn : & ' b mut DynCgDiffFn < ' b > , flat_evs : & ' b [ & ' b [ f64 ] ] , } impl < ' b > cg :: DiffFn for Adapter < ' b > { type Error = failure :: Error ; fn compute ( & mut self , coeffs : & [ f64 ] ) -> FailResult < ( f64 , Vec < f64 > ) > { Ok ( { let Adapter { flat_init_pos , flat_3n_diff_fn , flat_evs } = self ; // This is dead simple. // The kth element of the new gradient is the slope along the kth ev. // The change in position is a sum over contributions from each ev. // These relationships have a simple expression in terms of //   the matrix whose columns are the selected eigenvectors. // (though the following is transposed for our row-centric formalism) let flat_pos = flat_constrained_position ( flat_init_pos , coeffs , flat_evs ) ; let ( value , flat_grad ) = flat_3n_diff_fn . compute ( & flat_pos ) ? ; let grad = dot_mat_vec_dumb ( flat_evs , & flat_grad ) ; ( value , grad ) } ) } fn check ( & mut self , coeffs : & [ f64 ] ) -> FailResult < ( ) > { let Adapter { flat_init_pos , flat_3n_diff_fn , flat_evs } = self ; let flat_pos = flat_constrained_position ( flat_init_pos , coeffs , flat_evs ) ; flat_3n_diff_fn . check ( & flat_pos ) } } Box :: new ( Adapter { flat_init_pos , flat_3n_diff_fn , flat_evs } ) }
cg differential function along a restricted set of eigenvectors.
cg differential function along a restricted set of eigenvectors .
flat_3n_diff_fn
&'a mut DynCgDiffFn<'a>
flat_init_pos
&'a [f64]
flat_evs
&'a [&[f64]]