# anneal method Null safety

Future<List<num>> anneal(
1. MarkovChainLength markov,
2. {bool isRecursive = false,
3. num ratio = 0.5,
4. bool isVerbose = false}
)

Starts the simulated annealing process and returns the best solution found.

• isRecursive: Flag used to call the method recursively if the algorithm converges towards a local minimum. (The algorithm keeps track of the lowest energy values previously visited.)
• ratio: Factor reducing the length of the initial temperature sequence during recursive calls. The parameter is used to model repeated annealing cycles with decreasing initial temperature.
• Note: `0.0 < ratio < 1.0`.

## Implementation

``````Future<List<num>> anneal(
MarkovChainLength markov, {
bool isRecursive = false,
num ratio = 0.5,
bool isVerbose = false,
}) async {
/// Initialize parameters:
final temperatures = await this.temperatures;
final perturbationMagnitudes = await this.perturbationMagnitudes;
final grid = await this.grid;
num dE = 0;

if (_recursionCounter == 0) {
_t = temperatures.first;
_deltaPosition = perturbationMagnitudes.first;
_currentGrid = grid.first;
prepareLog();
recordLog();
}

// During the first iteration _ratio = 1.0 and i = 0.
final _ratio = pow(ratio.abs(), _recursionCounter);
var i = (temperatures.length * (1.0 - _ratio)).toInt();

if (_recursionCounter > 0 && isVerbose) {
print('Restarted annealing at:');
print('  temperature: \${temperatures[i]},');
print('  position: \$_currentMinPosition, ');
print('  energy: \$_currentMinEnergy');
}
++_recursionCounter;

// Outer iteration loop.
for (i; i < temperatures.length; i++) {
_t = temperatures[i];
_deltaPosition = perturbationMagnitudes[i];
_currentGrid = grid[i];

// Inner iteration loop.
for (var j = 0; j < markov(_t, _currentGrid); j++) {
// Choose next random point and calculate energy difference.
dE = _field.perturb(
_currentMinPosition,
_deltaPosition,
grid: _currentGrid,
) -
_currentMinEnergy;

if (dE < 0) {
_currentMinEnergy = _field.value;
_currentMinPosition = _field.position;
_acceptanceProbability = 1.0;
} else {
_acceptanceProbability = exp(-dE / _t);
if (_acceptanceProbability > Interval.random.nextDouble()) {
_currentMinEnergy = _field.value;
_currentMinPosition = _field.position;
}
}
recordLog();
}

}
if (globalMinEnergy < _currentMinEnergy) {
if (isVerbose) {
print('------------------------------------------------');
print('E_min_global(\$globalMinPosition) = \$globalMinEnergy ');
print('E_min(\$_currentMinPosition) = \$_currentMinEnergy!');
print('Returning global minimum solution!');
print('');
}
_currentMinPosition = globalMinPosition;
_currentMinEnergy = globalMinEnergy;
if (isRecursive) {
_currentMinPosition = await anneal(
markov,
isRecursive: isRecursive,
ratio: ratio,
);
}
}
return _currentMinPosition;
}``````