# Generate a database of models using random search

This document details how to generate a database of parameters and metrics of some neuron or network model using the `xfind`

class.

Database searches have been shown to be an effective way of exploring the rich and high-dimensional parameter space of neuron models.

### Goal¶

Our goal in this exercise is to define some neuron model, and then randomly pick parameters and see if it generates action potentials. The goal is to create a large library of parameters and firing rates so we can quickly generate a long list of possible models that fire at some desired firing rate by looking it up in the database.

### Setting up the `xfind`

object¶

First, we create a xolotl object with the model we want to explore. Here, we will use built-in functions to generate a eight-conductance neuron model. We will also create an xfind object and put the xolotl object inside it.

```
p = xfind;
p.x = xolotl.examples.neurons.BurstingNeuron;
```

Now, let's define the parameters we want to explore and specify the bounds of the hypercube in parameter space we want to explore

```
p.ParameterNames = p.x.find('*gbar');
p.Upper = [1e3 200 200 10 500 1e3 10 1e3];
p.Lower = zeros(8,1);
```

Now we need to tell `xfind`

how to sample this space.
You are free to write your own sampling function, but for now
we can use a built-in sampling function that uniformly
randomly samples points within these bounds.

Note that if you write your own sampling function, it should
accept an `xfind`

object and should set the parameters of the
xolotl object inside it.

```
p.SampleFcn = @p.uniformRandom;
```

OK, now we have a way of uniformly and randomly sampling our
parameter space. What we need next is some function to
evaluate the model at sample points. Here, we are going to
use the built-in `measureFiringRate`

function, but you are
free to write and use your own. If you do, make sure your
function accepts a xolotl object and returns a vector of doubles as its
only output.

```
p.SimFcn = @xolotl.firingRate;
```

OK, we have now defined our `SampleFcn`

and our `SimFcn`

. There's one more piece: we don't really want to save all the
data that we get from our random sampler. For example, we don't really want to clog up our database with neurons that
never spike (you may want to, but for this example, we don't).

So we need to define a `DiscardFcn`

that tells `xfind`

when to save parameters and outputs from `SimFcn`

, and when to
skip them.

```
% we are using an anonymous function for this simple example
p.DiscardFcn = @(data) data <= 0;
```

That's it!

### Finding models¶

Now we are ready to find parameters. If you have the parallel computing toolbox installed, you can find models efficiently using all cores using

```
p.parallelSearch;
```

```
Starting workers...
Starting worker #8
Starting worker #7
Starting worker #6
Starting worker #5
Starting worker #4
Starting worker #3
Starting worker #2
Starting worker #1
```

Notice that control is returned immediately to you. That's because the heavy computation occurs in the background. To stop it, run:

```
cancel(p.workers)
```

### Looking at solutions¶

To look at the solutions that `xfind`

found, use:

```
[params,data]=p.gather;
```

`params`

will be a matrix of your parameters (in the order you defined `ParameterNames`

in) and `data`

will be a matrix of the outputs of your `SimFcn`

. In this case, there is only one output from `SimFcn`

, so `data`

is a vector.

### Under the hood¶

`xfind`

streams data to disk using binary files with extension `.xfind`

. The name of the file is the hash of the `xolotl`

model, so make sure you wipe these files (or move them) if you are changing your `SimFcn`

### What if you don't have the parallel computing toolbox?¶

The real power of this comes from finding models efficiently in parallel. However, if you don't have it, you can still use this with

```
p.simulate
```

instead of `p.parallelSearch`

but remember that you will have to manually crash it to stop (`Ctrl+C`

).