class LeapfrogIntegrator {

    public LeapfrogState step(LeapfrogState fromState, final ProbabilisticModelWithGradient logProbGradientCalculator, final double timeStep) {

        final double halfTimeStep = timeStep / 2.0;

        Map<VariableReference, DoubleTensor> nextMomentum = stepMomentum(halfTimeStep, fromState.getMomentum(), fromState.getGradient());

        Map<VariableReference, DoubleTensor> nextVelocity = potential.getVelocity(nextMomentum);

        Map<VariableReference, DoubleTensor> nextPosition = stepPosition(timeStep, nextVelocity, fromState.getPosition());

        Map<? extends VariableReference, DoubleTensor> nextPositionGradient = logProbGradientCalculator.logProbGradients(nextPosition);
        final double nextPositionLogProb = logProbGradientCalculator.logProb();

        nextMomentum = stepMomentum(halfTimeStep, nextMomentum, nextPositionGradient);

        return new LeapfrogState(nextPosition, nextMomentum, nextPositionGradient, nextPositionLogProb, potential);
    }

}