#![allow(
clippy::pedantic,
clippy::unnecessary_wraps,
clippy::needless_range_loop,
clippy::useless_vec,
clippy::needless_collect,
clippy::too_many_arguments,
clippy::field_reassign_with_default
)]
#![allow(unused_must_use)]
#[cfg(feature = "fujitsu")]
use quantrs2_anneal::{
fujitsu::{FujitsuAnnealingParams, FujitsuClient, GuidanceConfig},
ising::IsingModel,
qubo::{QuboBuilder, QuboFormulation},
simulator::{AnnealingParams, QuantumAnnealingSimulator},
};
use scirs2_core::random::prelude::*;
use std::time::Instant;
#[cfg(feature = "fujitsu")]
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== Fujitsu Digital Annealer Demo ===\n");
if !quantrs2_anneal::is_fujitsu_available() {
println!("Fujitsu Digital Annealer not available.");
println!("Please set FUJITSU_DAU_API_KEY and FUJITSU_DAU_ENDPOINT environment variables.");
return Ok(());
}
let client = quantrs2_anneal::fujitsu::from_env()?;
println!("Example 1: MaxCut Problem");
let model = create_maxcut_instance(20)?;
let mut params = FujitsuAnnealingParams::default();
params.number_iterations = Some(20_000_000);
params.number_runs = Some(32);
params.time_limit_sec = Some(30);
let start = Instant::now();
let fujitsu_result = client.solve_ising(&model, params.clone()).await?;
let fujitsu_time = start.elapsed();
println!("Fujitsu Digital Annealer results:");
println!(" Best energy: {:.4}", fujitsu_result.best_energy);
println!(" Time: {fujitsu_time:.2?}");
println!(" Info: {}", fujitsu_result.info);
println!("\nLocal simulation for comparison:");
let sim_params = AnnealingParams {
num_sweeps: 10000,
num_repetitions: 10,
..Default::default()
};
let mut simulator = QuantumAnnealingSimulator::new(sim_params)?;
let start = Instant::now();
let sim_result = simulator.solve(&model)?;
let sim_time = start.elapsed();
println!(" Best energy: {:.4}", sim_result.best_energy);
println!(" Time: {sim_time:.2?}");
let speedup = sim_time.as_secs_f64() / fujitsu_time.as_secs_f64();
println!("\nFujitsu speedup: {speedup:.1}x");
println!(
"\n{}Example 2: Guidance Mode{}",
"=".repeat(10),
"=".repeat(10)
);
let initial_solution = sim_result.best_spins.clone();
params.guidance_config = Some(GuidanceConfig {
enabled: true,
initial_solution: Some(initial_solution),
guidance_strength: 0.5,
});
let start = Instant::now();
let guided_result = client.solve_ising(&model, params).await?;
let guided_time = start.elapsed();
println!("Guided optimization results:");
println!(" Best energy: {:.4}", guided_result.best_energy);
println!(" Time: {guided_time:.2?}");
println!(
" Improvement: {:.4}",
sim_result.best_energy - guided_result.best_energy
);
println!(
"\n{}Example 3: QUBO Problem{}",
"=".repeat(10),
"=".repeat(10)
);
let qubo = create_portfolio_optimization(15)?;
let params = FujitsuAnnealingParams {
number_iterations: Some(30_000_000),
number_runs: Some(64),
temperature_mode: Some("ADAPTIVE".to_string()),
..Default::default()
};
let start = Instant::now();
let qubo_model = qubo.build();
let qubo_solution = client.solve_qubo(&qubo_model, params).await?;
let qubo_time = start.elapsed();
println!("Portfolio optimization results:");
println!(" Solution: {qubo_solution:?}");
println!(" Time: {qubo_time:.2?}");
let selected_count = qubo_solution.iter().filter(|&&x| x).count();
println!(
" Assets selected: {}/{}",
selected_count,
qubo_solution.len()
);
Ok(())
}
#[cfg(feature = "fujitsu")]
fn create_maxcut_instance(n: usize) -> Result<IsingModel, Box<dyn std::error::Error>> {
let mut model = IsingModel::new(n);
for i in 0..n {
for j in (i + 1)..n {
if thread_rng().random::<f64>() < 0.4 {
model.set_coupling(i, j, -1.0)?;
}
}
}
Ok(model)
}
#[cfg(feature = "fujitsu")]
fn create_portfolio_optimization(
n_assets: usize,
) -> Result<QuboBuilder, Box<dyn std::error::Error>> {
let mut builder = QuboBuilder::new();
let returns: Vec<f64> = (0..n_assets)
.map(|_| thread_rng().random::<f64>() * 0.1)
.collect();
let risks: Vec<f64> = (0..n_assets)
.map(|_| thread_rng().random::<f64>() * 0.05)
.collect();
let vars: Vec<_> = (0..n_assets)
.map(|i| builder.add_variable(format!("asset_{i}")).unwrap())
.collect();
let lambda = 2.0;
for i in 0..n_assets {
builder.set_linear_term(&vars[i], -returns[i] + lambda * risks[i])?;
}
let k = n_assets / 3;
builder.set_constraint_weight(10.0)?;
builder.constrain_sum_equal(&vars, k as f64)?;
for i in 0..n_assets {
for j in (i + 1)..n_assets {
if thread_rng().random::<f64>() < 0.2 {
let correlation = thread_rng().random::<f64>() * 0.1;
builder.set_quadratic_term(&vars[i], &vars[j], lambda * correlation)?;
}
}
}
Ok(builder)
}
#[cfg(not(feature = "fujitsu"))]
fn main() {
println!("This example requires the 'fujitsu' feature to be enabled.");
println!("Run with: cargo run --example fujitsu_example --features fujitsu");
}