---
title: "Using different or custom root solvers in `geex`"
author: "Bradley Saul"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Root solvers in geex}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, echo = FALSE, message = FALSE, warning=FALSE}
library(geex)
```

## Choice of `rootFUN`

By default, `geex` uses the [`rootSolve::multiroot`](https://cran.r-project.org/package=rootSolve) function for finding roots of a set of estimating equations when `compute_roots = TRUE` in `m_estimate()`. However, a user can choose a different root find find algorithm via the `root_control` argument.

For example, consider the following `estFUN` which is Huber's estimator for the center of symmetric distributions [@stefanski2002; example 6]. This example was chosen because it has a single root, so that the `stats::uniroot` function can be used to find the roots.
```{r SB6_estFUN, echo = TRUE}
myefun <- function(data, k = 1.5){
  function(theta){
    x <- data$Y1 - theta[1]
    if(abs(x) <= k) x else sign(x) * k
  }
}
```

Internally, `estFUN` is used to build $G_m = \sum_{i = 1}^m  \psi(O_i, \theta)$ or in psuedo-code `f = sum(inner_estFUN(theta))`. `f` is passed to the root finding function along with options in the `root_control` arguments. For example,  `multiroot` requires `f` and `start` (starting values for the algorithm: 

```{r multiroot_example, echo = TRUE, message=FALSE}
multiroot_results <- m_estimate(
  estFUN = myefun, 
  data  = geexex,
  root_control = setup_root_control(start = 3))
```

The `stats::uniroot` function, however, requires the arguments `f` and `interval` (or `lower` and `upper`)

```{r uniroot_example, echo = TRUE, message=FALSE}
uniroot_results <- m_estimate(
  estFUN = myefun, 
  data  = geexex,
  root_control = setup_root_control(stats::uniroot, interval = c(0, 10)))
```

Comparing results:

```{r compare_results}
roots(multiroot_results) - roots(uniroot_results)
```

They are basically the same, but this may not be true depending `f` and the options given to the root finder.


## Building a custom root finder

All that is necessary for `rootFUN` is a function where:

* the *first* argument is the function whose roots are sought
* the output is a named list where the root estimates can be identified by the `rootFUN_object` argument in `m_estimate`. For example, both `uniroot` and `multiroot` return a list where the root estimates are in the item named "roots". The default is `rootFUN_object = 'roots'`, so this option works for both `uniroot` and `multiroot`. 
