use crate::random::{
core::{seeded_rng, Random},
distributions::MultivariateNormal,
parallel::{ParallelRng, ThreadLocalRngPool},
};
use ::ndarray::{s, Array1, Array2, Array3, Axis};
use rand::{Rng, RngExt};
use rand_distr::{Distribution, Normal, Uniform};
use std::collections::HashMap;
use std::f64::consts::PI;
#[derive(Debug)]
pub struct QuantumInspiredEvolutionary {
population_size: usize,
dimension: usize,
quantum_population: Array3<f64>, classical_population: Array2<f64>,
rotation_angles: Array2<f64>,
generation: usize,
best_solution: Option<Array1<f64>>,
best_fitness: f64,
}
impl QuantumInspiredEvolutionary {
pub fn new(population_size: usize, dimension: usize) -> Self {
let mut quantum_pop = Array3::zeros((population_size, dimension, 2));
let initial_angle = PI / 4.0; for i in 0..population_size {
for j in 0..dimension {
quantum_pop[[i, j, 0]] = initial_angle.cos(); quantum_pop[[i, j, 1]] = initial_angle.sin(); }
}
Self {
population_size,
dimension,
quantum_population: quantum_pop,
classical_population: Array2::zeros((population_size, dimension)),
rotation_angles: Array2::zeros((population_size, dimension)),
generation: 0,
best_solution: None,
best_fitness: f64::NEG_INFINITY,
}
}
pub fn optimize<F>(
&mut self,
fitness_function: F,
max_generations: usize,
) -> Result<Array1<f64>, String>
where
F: Fn(&Array1<f64>) -> f64,
{
let mut rng = seeded_rng(42);
for generation in 0..max_generations {
self.generation = generation;
self.measure_quantum_population(&mut rng)?;
let fitness_values = self.evaluate_population(&fitness_function)?;
for (i, &fitness) in fitness_values.iter().enumerate() {
if fitness > self.best_fitness {
self.best_fitness = fitness;
self.best_solution = Some(self.classical_population.row(i).to_owned());
}
}
self.quantum_rotation(&fitness_values)?;
if generation % 10 == 0 {
self.quantum_interference()?;
}
if generation % 50 == 0 {
self.quantum_mutation(&mut rng)?;
}
if generation % 100 == 0 {
println!(
"Generation {}: Best fitness = {:.6}",
generation, self.best_fitness
);
}
}
self.best_solution
.clone()
.ok_or_else(|| "No solution found".to_string())
}
fn measure_quantum_population(
&mut self,
rng: &mut Random<rand::rngs::StdRng>,
) -> Result<(), String> {
for i in 0..self.population_size {
for j in 0..self.dimension {
let alpha = self.quantum_population[[i, j, 0]];
let beta = self.quantum_population[[i, j, 1]];
let prob_zero = alpha * alpha;
let measurement =
if rng.sample(Uniform::new(0.0, 1.0).expect("Operation failed")) < prob_zero {
0.0
} else {
1.0
};
self.classical_population[[i, j]] = measurement;
}
}
Ok(())
}
fn evaluate_population<F>(&self, fitness_function: &F) -> Result<Vec<f64>, String>
where
F: Fn(&Array1<f64>) -> f64,
{
let mut fitness_values = Vec::with_capacity(self.population_size);
for i in 0..self.population_size {
let individual = self.classical_population.row(i).to_owned();
let fitness = fitness_function(&individual);
fitness_values.push(fitness);
}
Ok(fitness_values)
}
fn quantum_rotation(&mut self, fitness_values: &[f64]) -> Result<(), String> {
let best_fitness = fitness_values
.iter()
.fold(f64::NEG_INFINITY, |a, &b| a.max(b));
let best_individual_idx = fitness_values
.iter()
.position(|&f| f == best_fitness)
.unwrap_or(0);
#[allow(clippy::needless_range_loop)]
for i in 0..self.population_size {
if i == best_individual_idx {
continue; }
let fitness_ratio = fitness_values[i] / best_fitness.max(1e-10);
let base_angle = 0.01 * PI * (1.0 - fitness_ratio);
for j in 0..self.dimension {
let current_alpha = self.quantum_population[[i, j, 0]];
let current_beta = self.quantum_population[[i, j, 1]];
let best_bit = self.classical_population[[best_individual_idx, j]];
let current_bit = self.classical_population[[i, j]];
let rotation_angle = if current_bit == best_bit {
0.0 } else {
if best_bit > current_bit {
base_angle
} else {
-base_angle
}
};
if rotation_angle.abs() > 1e-10 {
let cos_theta = rotation_angle.cos();
let sin_theta = rotation_angle.sin();
let new_alpha = cos_theta * current_alpha - sin_theta * current_beta;
let new_beta = sin_theta * current_alpha + cos_theta * current_beta;
self.quantum_population[[i, j, 0]] = new_alpha;
self.quantum_population[[i, j, 1]] = new_beta;
}
self.rotation_angles[[i, j]] = rotation_angle;
}
}
Ok(())
}
fn quantum_interference(&mut self) -> Result<(), String> {
for i in 0..self.population_size {
for j in (i + 1)..self.population_size {
let similarity = self.calculate_quantum_similarity(i, j)?;
if similarity > 0.8 {
for k in 0..self.dimension {
let alpha_i = self.quantum_population[[i, k, 0]];
let beta_i = self.quantum_population[[i, k, 1]];
let alpha_j = self.quantum_population[[j, k, 0]];
let beta_j = self.quantum_population[[j, k, 1]];
let new_alpha_i = 0.9 * alpha_i + 0.1 * alpha_j;
let new_beta_i = 0.9 * beta_i + 0.1 * beta_j;
let norm = (new_alpha_i * new_alpha_i + new_beta_i * new_beta_i).sqrt();
if norm > 1e-10 {
self.quantum_population[[i, k, 0]] = new_alpha_i / norm;
self.quantum_population[[i, k, 1]] = new_beta_i / norm;
}
}
}
}
}
Ok(())
}
fn calculate_quantum_similarity(&self, i: usize, j: usize) -> Result<f64, String> {
let mut similarity = 0.0;
for k in 0..self.dimension {
let alpha_i = self.quantum_population[[i, k, 0]];
let beta_i = self.quantum_population[[i, k, 1]];
let alpha_j = self.quantum_population[[j, k, 0]];
let beta_j = self.quantum_population[[j, k, 1]];
let fidelity = (alpha_i * alpha_j + beta_i * beta_j).abs();
similarity += fidelity;
}
Ok(similarity / self.dimension as f64)
}
fn quantum_mutation(&mut self, rng: &mut Random<rand::rngs::StdRng>) -> Result<(), String> {
let mutation_rate = 0.01;
let mutation_strength = 0.1;
for i in 0..self.population_size {
for j in 0..self.dimension {
if rng.sample(Uniform::new(0.0, 1.0).expect("Operation failed")) < mutation_rate {
let random_angle = rng.sample(
Uniform::new(-mutation_strength * PI, mutation_strength * PI)
.expect("Operation failed"),
);
let current_alpha = self.quantum_population[[i, j, 0]];
let current_beta = self.quantum_population[[i, j, 1]];
let cos_theta = random_angle.cos();
let sin_theta = random_angle.sin();
let new_alpha = cos_theta * current_alpha - sin_theta * current_beta;
let new_beta = sin_theta * current_alpha + cos_theta * current_beta;
self.quantum_population[[i, j, 0]] = new_alpha;
self.quantum_population[[i, j, 1]] = new_beta;
}
}
}
Ok(())
}
pub fn get_best_solution(&self) -> Option<&Array1<f64>> {
self.best_solution.as_ref()
}
pub fn get_best_fitness(&self) -> f64 {
self.best_fitness
}
}
#[derive(Debug)]
pub struct QuantumAmplitudeAmplification {
target_probability: f64,
optimal_iterations: usize,
oracle_calls: usize,
}
impl QuantumAmplitudeAmplification {
pub fn new(target_probability: f64) -> Self {
let optimal_iterations = ((PI / 4.0) / target_probability.sqrt().asin()).floor() as usize;
Self {
target_probability,
optimal_iterations,
oracle_calls: 0,
}
}
pub fn sample<F>(
&mut self,
oracle: F,
num_samples: usize,
seed: u64,
) -> Result<Vec<Array1<f64>>, String>
where
F: Fn(&Array1<f64>) -> bool, {
let mut rng = seeded_rng(seed);
let mut target_samples = Vec::new();
let dimension = 10;
let amplified_attempts = (num_samples as f64 / self.target_probability).ceil() as usize;
for _ in 0..amplified_attempts {
let mut state_amplitudes = Array2::zeros((1 << dimension.min(10), 2));
let amplitude = 1.0 / ((1 << dimension.min(10)) as f64).sqrt();
for i in 0..state_amplitudes.nrows() {
state_amplitudes[[i, 0]] = amplitude; state_amplitudes[[i, 1]] = 0.0; }
for _ in 0..self.optimal_iterations {
self.apply_oracle(&mut state_amplitudes, &oracle, dimension)?;
self.apply_diffusion(&mut state_amplitudes)?;
}
let measured_state =
self.measure_amplified_state(&state_amplitudes, dimension, &mut rng)?;
let sample = self.state_to_sample(&measured_state, dimension, &mut rng)?;
if oracle(&sample) {
target_samples.push(sample);
if target_samples.len() >= num_samples {
break;
}
}
}
Ok(target_samples)
}
fn apply_oracle<F>(
&mut self,
amplitudes: &mut Array2<f64>,
oracle: &F,
dimension: usize,
) -> Result<(), String>
where
F: Fn(&Array1<f64>) -> bool,
{
self.oracle_calls += 1;
for i in 0..amplitudes.nrows() {
let sample = self.index_to_sample(i, dimension)?;
if oracle(&sample) {
amplitudes[[i, 0]] = -amplitudes[[i, 0]]; amplitudes[[i, 1]] = -amplitudes[[i, 1]]; }
}
Ok(())
}
fn apply_diffusion(&self, amplitudes: &mut Array2<f64>) -> Result<(), String> {
let num_states = amplitudes.nrows();
let mut avg_real = 0.0;
let mut avg_imag = 0.0;
for i in 0..num_states {
avg_real += amplitudes[[i, 0]];
avg_imag += amplitudes[[i, 1]];
}
avg_real /= num_states as f64;
avg_imag /= num_states as f64;
for i in 0..num_states {
amplitudes[[i, 0]] = 2.0 * avg_real - amplitudes[[i, 0]];
amplitudes[[i, 1]] = 2.0 * avg_imag - amplitudes[[i, 1]];
}
Ok(())
}
fn measure_amplified_state(
&self,
amplitudes: &Array2<f64>,
dimension: usize,
rng: &mut Random<rand::rngs::StdRng>,
) -> Result<usize, String> {
let mut probabilities = Vec::with_capacity(amplitudes.nrows());
for i in 0..amplitudes.nrows() {
let real = amplitudes[[i, 0]];
let imag = amplitudes[[i, 1]];
let prob = real * real + imag * imag;
probabilities.push(prob);
}
let total_prob: f64 = probabilities.iter().sum();
if total_prob > 1e-10 {
for prob in &mut probabilities {
*prob /= total_prob;
}
}
let random_val = rng.sample(Uniform::new(0.0, 1.0).expect("Operation failed"));
let mut cumulative = 0.0;
for (i, &prob) in probabilities.iter().enumerate() {
cumulative += prob;
if random_val <= cumulative {
return Ok(i);
}
}
Ok(probabilities.len() - 1)
}
fn index_to_sample(&self, index: usize, dimension: usize) -> Result<Array1<f64>, String> {
let mut sample = Array1::zeros(dimension);
for i in 0..dimension.min(10) {
let bit = (index >> i) & 1;
sample[i] = bit as f64;
}
for i in 10..dimension {
sample[i] = ((index as f64) * (i as f64 + 1.0)).sin();
}
Ok(sample)
}
fn state_to_sample(
&self,
state_index: &usize,
dimension: usize,
rng: &mut Random<rand::rngs::StdRng>,
) -> Result<Array1<f64>, String> {
let mut sample = Array1::zeros(dimension);
for i in 0..dimension {
let base_value = ((*state_index as f64) * (i as f64 + 1.0) * 0.1).sin();
let noise = rng.sample(Normal::new(0.0, 0.1).expect("Operation failed"));
sample[i] = base_value + noise;
}
Ok(sample)
}
pub fn get_oracle_calls(&self) -> usize {
self.oracle_calls
}
}
#[derive(Debug)]
pub struct QuantumWalk {
dimension: usize,
position_amplitudes: Array2<f64>, coin_operator: Array2<f64>, step_size: f64,
coherence_time: usize,
}
impl QuantumWalk {
pub fn new(dimension: usize, coin_parameters: CoinParameters) -> Self {
let num_positions = 2_usize.pow(dimension.min(10) as u32);
let mut position_amplitudes = Array2::zeros((num_positions, 2));
let center = num_positions / 2;
position_amplitudes[[center, 0]] = 1.0;
let coin_operator = match coin_parameters {
CoinParameters::Hadamard => {
let mut coin = Array2::zeros((2, 2));
let inv_sqrt2 = 1.0 / 2.0_f64.sqrt();
coin[[0, 0]] = inv_sqrt2;
coin[[0, 1]] = inv_sqrt2;
coin[[1, 0]] = inv_sqrt2;
coin[[1, 1]] = -inv_sqrt2;
coin
}
CoinParameters::Rotation(angle) => {
let mut coin = Array2::zeros((2, 2));
coin[[0, 0]] = angle.cos();
coin[[0, 1]] = -angle.sin();
coin[[1, 0]] = angle.sin();
coin[[1, 1]] = angle.cos();
coin
}
CoinParameters::Custom(matrix) => matrix,
};
Self {
dimension,
position_amplitudes,
coin_operator,
step_size: 1.0,
coherence_time: 1000,
}
}
pub fn evolve(
&mut self,
num_steps: usize,
initial_state: Option<usize>,
) -> Result<Vec<usize>, String> {
if let Some(initial_pos) = initial_state {
self.position_amplitudes.fill(0.0);
if initial_pos < self.position_amplitudes.nrows() {
self.position_amplitudes[[initial_pos, 0]] = 1.0;
}
}
let mut trajectory = Vec::with_capacity(num_steps);
let mut rng = seeded_rng(42);
for step in 0..num_steps {
self.quantum_walk_step()?;
if step % 10 == 0 || step >= num_steps - 1 {
let measured_position = self.measure_position(&mut rng)?;
trajectory.push(measured_position);
}
if step > 0 && step % self.coherence_time == 0 {
self.apply_decoherence(&mut rng)?;
}
}
Ok(trajectory)
}
fn quantum_walk_step(&mut self) -> Result<(), String> {
let num_positions = self.position_amplitudes.nrows();
let mut new_amplitudes = Array2::zeros((num_positions, 2));
for pos in 0..num_positions {
let current_real = self.position_amplitudes[[pos, 0]];
let current_imag = self.position_amplitudes[[pos, 1]];
if current_real.abs() > 1e-10 || current_imag.abs() > 1e-10 {
let (left_real, left_imag, right_real, right_imag) =
self.apply_coin_operation(current_real, current_imag);
let left_pos = if pos > 0 { pos - 1 } else { num_positions - 1 };
let right_pos = (pos + 1) % num_positions;
new_amplitudes[[left_pos, 0]] += left_real;
new_amplitudes[[left_pos, 1]] += left_imag;
new_amplitudes[[right_pos, 0]] += right_real;
new_amplitudes[[right_pos, 1]] += right_imag;
}
}
self.position_amplitudes = new_amplitudes;
Ok(())
}
fn apply_coin_operation(&self, real: f64, imag: f64) -> (f64, f64, f64, f64) {
let left_real = self.coin_operator[[0, 0]] * real + self.coin_operator[[0, 1]] * imag;
let left_imag = self.coin_operator[[0, 0]] * imag - self.coin_operator[[0, 1]] * real;
let right_real = self.coin_operator[[1, 0]] * real + self.coin_operator[[1, 1]] * imag;
let right_imag = self.coin_operator[[1, 0]] * imag - self.coin_operator[[1, 1]] * real;
(left_real, left_imag, right_real, right_imag)
}
fn measure_position<R: Rng>(&self, rng: &mut Random<R>) -> Result<usize, String> {
let mut probabilities = Vec::with_capacity(self.position_amplitudes.nrows());
for i in 0..self.position_amplitudes.nrows() {
let real = self.position_amplitudes[[i, 0]];
let imag = self.position_amplitudes[[i, 1]];
let prob = real * real + imag * imag;
probabilities.push(prob);
}
let total_prob: f64 = probabilities.iter().sum();
if total_prob > 1e-10 {
for prob in &mut probabilities {
*prob /= total_prob;
}
}
let random_val = rng.sample(Uniform::new(0.0, 1.0).expect("Operation failed"));
let mut cumulative = 0.0;
for (i, &prob) in probabilities.iter().enumerate() {
cumulative += prob;
if random_val <= cumulative {
return Ok(i);
}
}
Ok(probabilities.len() - 1)
}
fn apply_decoherence<R: Rng>(&mut self, rng: &mut Random<R>) -> Result<(), String> {
let decoherence_strength = 0.1;
for i in 0..self.position_amplitudes.nrows() {
let phase_noise =
rng.sample(Normal::new(0.0, decoherence_strength).expect("Operation failed"));
let amplitude_noise =
rng.sample(Normal::new(0.0, decoherence_strength * 0.1).expect("Operation failed"));
let real = self.position_amplitudes[[i, 0]];
let imag = self.position_amplitudes[[i, 1]];
let new_real =
real * (1.0 + amplitude_noise) * phase_noise.cos() - imag * phase_noise.sin();
let new_imag =
real * phase_noise.sin() + imag * (1.0 + amplitude_noise) * phase_noise.cos();
self.position_amplitudes[[i, 0]] = new_real;
self.position_amplitudes[[i, 1]] = new_imag;
}
let mut total_prob = 0.0;
for i in 0..self.position_amplitudes.nrows() {
let real = self.position_amplitudes[[i, 0]];
let imag = self.position_amplitudes[[i, 1]];
total_prob += real * real + imag * imag;
}
if total_prob > 1e-10 {
let norm_factor = total_prob.sqrt();
for i in 0..self.position_amplitudes.nrows() {
self.position_amplitudes[[i, 0]] /= norm_factor;
self.position_amplitudes[[i, 1]] /= norm_factor;
}
}
Ok(())
}
pub fn get_probability_distribution(&self) -> Vec<f64> {
let mut probabilities = Vec::with_capacity(self.position_amplitudes.nrows());
for i in 0..self.position_amplitudes.nrows() {
let real = self.position_amplitudes[[i, 0]];
let imag = self.position_amplitudes[[i, 1]];
let prob = real * real + imag * imag;
probabilities.push(prob);
}
probabilities
}
}
#[derive(Debug, Clone)]
pub enum CoinParameters {
Hadamard, Rotation(f64), Custom(Array2<f64>), }
type EnergyFunction = Box<dyn Fn(&Array1<f64>) -> f64>;
pub struct QuantumInspiredAnnealing {
dimension: usize,
temperature_schedule: Vec<f64>,
quantum_tunneling_strength: f64,
current_state: Array1<f64>,
energy_function: Option<EnergyFunction>,
}
impl QuantumInspiredAnnealing {
pub fn new(
dimension: usize,
initial_temperature: f64,
final_temperature: f64,
num_steps: usize,
) -> Self {
let mut temperature_schedule = Vec::with_capacity(num_steps);
for i in 0..num_steps {
let t =
(final_temperature / initial_temperature).powf(i as f64 / (num_steps - 1) as f64);
temperature_schedule.push(initial_temperature * t);
}
Self {
dimension,
temperature_schedule,
quantum_tunneling_strength: 1.0,
current_state: Array1::zeros(dimension),
energy_function: None,
}
}
pub fn with_tunneling_strength(mut self, strength: f64) -> Self {
self.quantum_tunneling_strength = strength;
self
}
pub fn optimize<F>(
&mut self,
energy_function: F,
initial_state: Array1<f64>,
seed: u64,
) -> Result<Array1<f64>, String>
where
F: Fn(&Array1<f64>) -> f64,
{
self.current_state = initial_state;
let mut rng = seeded_rng(seed);
let mut best_state = self.current_state.clone();
let mut best_energy = energy_function(&best_state);
for (step, &temperature) in self.temperature_schedule.iter().enumerate() {
let tunneling_probability = self.quantum_tunneling_strength * temperature;
let proposal_state = if rng.sample(Uniform::new(0.0, 1.0).expect("Operation failed"))
< tunneling_probability
{
self.quantum_tunneling_move(&mut rng)?
} else {
self.thermal_move(temperature, &mut rng)?
};
let current_energy = energy_function(&self.current_state);
let proposal_energy = energy_function(&proposal_state);
let quantum_acceptance = self.quantum_acceptance_probability(
current_energy,
proposal_energy,
temperature,
tunneling_probability,
);
if rng.sample(Uniform::new(0.0, 1.0).expect("Operation failed")) < quantum_acceptance {
self.current_state = proposal_state;
if proposal_energy < best_energy {
best_energy = proposal_energy;
best_state = self.current_state.clone();
}
}
if step % 100 == 0 {
println!(
"Step {}: Temperature = {:.6}, Best energy = {:.6}",
step, temperature, best_energy
);
}
}
Ok(best_state)
}
fn quantum_tunneling_move<R: Rng>(&self, rng: &mut Random<R>) -> Result<Array1<f64>, String> {
let mut new_state = Array1::zeros(self.dimension);
let tunneling_scale = 2.0 * self.quantum_tunneling_strength;
for i in 0..self.dimension {
let tunneling_distance =
rng.sample(Normal::new(0.0, tunneling_scale).expect("Operation failed"));
new_state[i] = self.current_state[i] + tunneling_distance;
}
Ok(new_state)
}
fn thermal_move<R: Rng>(
&self,
temperature: f64,
rng: &mut Random<R>,
) -> Result<Array1<f64>, String> {
let mut new_state = self.current_state.clone();
let step_size = temperature.sqrt();
for i in 0..self.dimension {
let thermal_noise = rng.sample(Normal::new(0.0, step_size).expect("Operation failed"));
new_state[i] += thermal_noise;
}
Ok(new_state)
}
fn quantum_acceptance_probability(
&self,
current_energy: f64,
proposal_energy: f64,
temperature: f64,
tunneling_probability: f64,
) -> f64 {
let energy_diff = proposal_energy - current_energy;
if energy_diff <= 0.0 {
1.0
} else {
let classical_prob = (-energy_diff / temperature).exp();
let quantum_enhancement =
1.0 + tunneling_probability * (-energy_diff / (2.0 * temperature)).exp();
(classical_prob * quantum_enhancement).min(1.0)
}
}
pub fn get_current_state(&self) -> &Array1<f64> {
&self.current_state
}
}
#[cfg(test)]
mod tests {
use super::*;
use approx::assert_relative_eq;
#[test]
fn test_quantum_inspired_evolutionary() {
let mut qiea = QuantumInspiredEvolutionary::new(20, 5);
let solution = qiea
.optimize(|x| -x.iter().map(|xi| xi * xi).sum::<f64>(), 100)
.expect("Operation failed");
assert_eq!(solution.len(), 5);
for &val in solution.iter() {
assert!(val.abs() < 2.0);
}
}
#[test]
fn test_quantum_amplitude_amplification() {
let mut qaa = QuantumAmplitudeAmplification::new(0.1);
let oracle = |x: &Array1<f64>| x[0] > 0.5;
let samples = qaa.sample(oracle, 10, 42).expect("Operation failed");
for sample in &samples {
assert!(oracle(sample));
}
assert!(qaa.get_oracle_calls() < 100);
}
#[test]
fn test_quantum_walk() {
let mut qwalk = QuantumWalk::new(5, CoinParameters::Hadamard);
let trajectory = qwalk.evolve(50, Some(16)).expect("Operation failed");
assert!(!trajectory.is_empty());
let unique_positions: std::collections::HashSet<_> = trajectory.iter().collect();
assert!(unique_positions.len() > 1);
}
#[test]
fn test_quantum_annealing() {
let mut qa = QuantumInspiredAnnealing::new(2, 1.0, 0.01, 100);
let energy_function = |x: &Array1<f64>| (x[0] - 1.0).powi(2) + (x[1] - 1.0).powi(2);
let initial_state = Array1::from_vec(vec![0.0, 0.0]);
let solution = qa
.optimize(energy_function, initial_state, 42)
.expect("Operation failed");
assert_relative_eq!(solution[0], 1.0, epsilon = 0.5);
assert_relative_eq!(solution[1], 1.0, epsilon = 0.5);
}
#[test]
fn test_coin_parameters() {
let _hadamard_walk = QuantumWalk::new(3, CoinParameters::Hadamard);
let _rotation_walk = QuantumWalk::new(3, CoinParameters::Rotation(PI / 4.0));
let custom_coin =
Array2::from_shape_vec((2, 2), vec![0.8, 0.6, 0.6, -0.8]).expect("Operation failed");
let _custom_walk = QuantumWalk::new(3, CoinParameters::Custom(custom_coin));
}
}