# Serial Solver Execution
You may want to run the solver several times iteratively when evaluating performance. Also, some solvers are more likely to find a good solution by running several iterations with a short timeout than by running a single iteration with a long timeout.Amplify SDK allows running the same combinatorial optimization problem multiple times in a row with the same solver for such needs.
```{seealso}
[](parallel.md) may be more appropriate for obtaining statistics from multiple runs for formulation, solver performance studies, etc.
```
## Example of multiple runs
First, create a model and solver client as in a usual {py:func}`~amplify.solve` function execution.
```{testcode}
from amplify import VariableGenerator, one_hot, FixstarsClient, solve
from datetime import timedelta
gen = VariableGenerator()
q = gen.array("Binary", 3)
objective = q[0] * q[1] - q[2]
constraint = one_hot(q)
model = objective + constraint
client = FixstarsClient()
# client.token = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
client.parameters.timeout = timedelta(milliseconds=1000)
```
By passing an integer as the `num_solves` keyword argument to {py:func}`~amplify.solve`, the solver is executed iteratively for `num_solves` times.
```{testcode}
result = solve(model, client, num_solves=3)
```
As in a usual {py:func}`~amplify.solve` call, the solver returns an instance of the {py:class}`~amplify.Result` class. The return value contains the results of the num_solves iterations.
```{doctest}
>>> len(result)
3
```
Using the {py:class}`~amplify.Result.best` attribute, you can obtain the best solution among those returned by the `num_solves` runs.
```{doctest}
>>> print(f"objective = {result.best.objective}, q = {q.evaluate(result.best.values)}")
objective = -1.0, q = [0. 0. 1.]
```
## Fetching results
When {py:func}`~amplify.solve` is called with the `num_solves` keyword, the return value is an instance of the {py:class}`~amplify.Result` class, as usual.
The Amplify SDK determines the number of times of the solver executions by the {py:attr}`~amplify.Result.num_solves` attribute of the {py:class}`~amplify.Result` class. This attribute usually yields the same value as the value specified to {py:func}`~amplify.solve` as the `num_solves` keyword argument. Still, it may be less than the value specified as the `num_solves` keyword argument, if some of the solver runs, fail for some reason.
```{doctest}
>>> result.num_solves
3
```
Index or iteration access allows you to aggregate all the solutions the solver returns for the `num_solves` runs. By default, the Amplify SDK sorts them in order of preferred solution, and there is no distinction regarding the number of executions the solution was found.
```{doctest}
>>> print(f"objective = {result[0].objective}, q = {q.evaluate(result[0].values)}")
objective = -1.0, q = [0. 0. 1.]
```
Use the {py:attr}`~amplify.Result.split` property to get only the solutions returned by a particular run.
```{doctest}
>>> first_result = result.split[0] # extract only the part of the `result` that was obtained at the first run
>>> type(first_result)
>>> len(first_result)
1
>>> print(f"objective = {first_result.best.objective}, q = {q.evaluate(first_result.best.values)}")
objective = -1.0, q = [0. 0. 1.]
```
The following are included for each property of the {py:class}`~amplify.Result` object returned by {py:func}`~amplify.solve` when `num_solves` is specified, and the {py:attr}`~amplify.Result` object represents the result of the `i`-th run obtained by using the {py:attr}`~amplify.Result.split` property on it.
```{list-table}
:header-rows: 1
:width: 100%
:widths: 1 4 4
* - Property name
- {py:class}`~amplify.Result` returned by {py:func}`~amplify.solve`
- {py:class}`~amplify.Result` after applying {py:attr}`~amplify.Result.split`
* - {py:attr}`~amplify.Result.best`
- The best solution for the {py:attr}`~amplify.Result.num_solves` runs
- The best solution for the `i`-th run
* - {py:attr}`~amplify.Result.solutions`
- All solutions obtained for the {py:attr}`~amplify.Result.num_solves` runs
- All solutions obtained for the `i`-th run
* - {py:attr}`~amplify.Result.intermediate`
- Same as usual {py:func}`~amplify.solve` execution
- Same as usual {py:func}`~amplify.solve` execution
* - {py:attr}`~amplify.Result.embedding`
- Same as usual {py:func}`~amplify.solve` execution
- Same as usual {py:func}`~amplify.solve` execution
* - {py:attr}`~amplify.Result.client_result`
- Property obtained for the first run
- Property obtained for the `i`-th run
* - {py:attr}`~amplify.Result.execution_time`
- The sum of the {py:attr}`~amplify.Result.num_solves` runs
- Property obtained for the `i`-th run
* - {py:attr}`~amplify.Result.response_time`
- The sum of the {py:attr}`~amplify.Result.num_solves` runs
- Property obtained for the `i`-th run
* - {py:attr}`~amplify.Result.total_time`
- Time from the start to the end of {py:func}`~amplify.solve`
- Time used for the `i`-th run
```