77 lines
2.1 KiB
Rust
77 lines
2.1 KiB
Rust
use eframe::emath::Numeric;
|
|
use rand::{random, random_range};
|
|
use crate::algo::Board;
|
|
use crate::algo::misc::{initializeBoard, isOnDiagonal, swapRandomQueensOnce};
|
|
|
|
pub(super) fn calculateEnergy(b: &Board) -> f64 {
|
|
let mut conflictsCount = 0usize;
|
|
for i1 in 0..b.len() {
|
|
for i2 in (i1 + 1)..b.len() {
|
|
if isOnDiagonal((i1, b[i1]), (i2, b[i2])) {
|
|
conflictsCount += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return conflictsCount.to_f64()
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
struct State {
|
|
board: Board,
|
|
energy: f64
|
|
}
|
|
|
|
pub struct AnnealingConfig {
|
|
pub initialTemperature: f64,
|
|
pub targetTemperature: f64,
|
|
pub cooldownCoefficient: f64,
|
|
pub iterationsPerAge: usize
|
|
}
|
|
|
|
pub(crate) fn simulateAnnealing(len: usize, config: &AnnealingConfig) -> Board {
|
|
assert!(config.targetTemperature < config.initialTemperature);
|
|
assert!((0f64..1f64).contains(&config.cooldownCoefficient));
|
|
|
|
let mut currentState = State {
|
|
board: Board::alloc(len),
|
|
energy: f64::INFINITY
|
|
};
|
|
initializeBoard(&mut currentState.board);
|
|
currentState.energy = calculateEnergy(¤tState.board);
|
|
|
|
let mut bestState = currentState.clone();
|
|
|
|
let mut currentTemperature = config.initialTemperature;
|
|
|
|
while currentTemperature > config.targetTemperature {
|
|
|
|
for _ in 0..config.iterationsPerAge {
|
|
let mut newState = currentState.clone();
|
|
swapRandomQueensOnce(&mut newState.board);
|
|
newState.energy = calculateEnergy(&newState.board);
|
|
|
|
if newState.energy <= currentState.energy {
|
|
currentState = newState
|
|
} else {
|
|
let test = random::<f64>();
|
|
let delta = newState.energy - currentState.energy;
|
|
let calc = (-delta/test).exp();
|
|
|
|
if calc > test {
|
|
currentState = newState
|
|
} else {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if currentState.energy < bestState.energy {
|
|
bestState = currentState.clone();
|
|
}
|
|
}
|
|
|
|
currentTemperature *= config.cooldownCoefficient;
|
|
}
|
|
|
|
return bestState.board;
|
|
} |