Estimation overhaul
This version presents a major overhaul in the ability estimation module. I decided to revisit the theory behind finding extrema of unimodal functions without the use of derivatives (which is the case of the log-likelihood used to estimate the most likely abilities for examinees during a CAT, given their response patterns) and bumped into [this amazing playlist](https://www.youtube.com/playlist?list=PLb0Tx2oJWuYIXLHAjQgko2fZtJ_NxnV-x) by osveliz.
New estimator implementations
From that playlist, I have implemented the following methods for finding the maxima of the log-likelihood function:
- [ternary search](https://github.com/douglasrizzo/catsim/blob/f12b10f7add54741f7e1ee5c512bd984638c8a4c/catsim/estimation.py#L236-L271)
- [dichotomous search](https://github.com/douglasrizzo/catsim/blob/f12b10f7add54741f7e1ee5c512bd984638c8a4c/catsim/estimation.py#L236-L271)
- [fibonacci search](https://github.com/douglasrizzo/catsim/blob/f12b10f7add54741f7e1ee5c512bd984638c8a4c/catsim/estimation.py#L273-L315)
- [golden-section search](https://github.com/douglasrizzo/catsim/blob/f12b10f7add54741f7e1ee5c512bd984638c8a4c/catsim/estimation.py#L317-L348)
New estimators from SciPy
I also found out that all minimization methods implemented in [`scipy.optimize.minimize_scalar`](https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize_scalar.html) work really well in catsim, so [I have also made those available in the estimation module](https://github.com/douglasrizzo/catsim/blob/f12b10f7add54741f7e1ee5c512bd984638c8a4c/catsim/estimation.py#L157-L167).
Better results
These changes have introduced a small but noticeable speedup in simulation times, since many of the new methods tend to evaluate the log-likelihood function fewer times than the older estimators present in catsim. In particular, all of the new methods are more theoretically sound than the `HillClimbingEstimator` as well as 5 to 10 times faster than the `DifferentialEvolutionEstimator`.
Breaking changes
Due to that, I have decided to retire the `DifferentialEvolutionEstimator` and joined all estimators [(including the `HillClimbingEstimator`)](https://github.com/douglasrizzo/catsim/blob/f12b10f7add54741f7e1ee5c512bd984638c8a4c/catsim/estimation.py#L174-L234) into a new [`NumericalSearchEstimator` class](https://github.com/douglasrizzo/catsim/blob/f12b10f7add54741f7e1ee5c512bd984638c8a4c/catsim/estimation.py#L11).
Instantiating the new estimators
For the old hill-clibing estimation method:
py
estimator = NumericalSearchEstimator("hillclimbing")
For the four new estimators implemented into catsim::
py
estimator = NumericalSearchEstimator("ternary")
estimator = NumericalSearchEstimator("dichotomous")
estimator = NumericalSearchEstimator("fibonacci")
estimator = NumericalSearchEstimator("golden2")
For the three estimators from `scipy.optimize.minimize_scalar()`:
py
estimator = NumericalSearchEstimator("brent")
estimator = NumericalSearchEstimator("bounded")
estimator = NumericalSearchEstimator("golden")
Closing remarks
If everything goes right with the new GitHub Actions I've implemented, the documentation will be updated shortly. The examples in the README as well as the documentation website will have all information regarding the new estimators. After the documentation update, you find a comparison among the new estimation methods [here](https://douglasrizzo.com.br/catsim/estimation.html#comparison-between-estimators).