use cisat::{
AgentMethods, Cohort, CommunicationStyle, OperationalLearning, Parameters, Solution,
TeamMethods, TemperatureSchedule,
};
use indicatif::{HumanDuration, ProgressBar, ProgressStyle};
use std::time::Instant;
use structopt::StructOpt;
#[derive(StructOpt, Debug)]
#[structopt(author, name = "CISAT")]
struct Cli {
#[structopt(short, long)]
verbose: bool,
#[structopt(short = "R", long)]
parallel: bool,
#[structopt(short = "T", long, default_value = "10")]
teams: usize,
#[structopt(short = "P", long)]
problem: String,
#[structopt(short = "A", long, default_value = "3")]
agents: usize,
#[structopt(short = "I", long, default_value = "100")]
iter: usize,
#[structopt(short = "S", long, default_value = "Geometric")]
schedule: String,
#[structopt(short = "t", long, default_value = "10")]
initial_temperature: f64,
#[structopt(
short = "d",
long,
default_value = "0.1",
required_if("schedule", "Triki")
)]
pub delta: f64,
#[structopt(short = "L", long, default_value = "Markov")]
pub learning: String,
#[structopt(short = "r", long, default_value = "0.05")]
pub learning_rate: f64,
#[structopt(short = "b", long, default_value = "1.0")]
pub self_bias: f64,
#[structopt(short = "q", long, default_value = "1.0")]
pub quality_bias: f64,
#[structopt(short = "s", long, default_value = "0.5")]
pub satisficing: f64,
}
fn main() {
let args = Cli::from_args();
let learning_style = match args.learning.to_lowercase().as_str() {
"multinomial" => OperationalLearning::Multinomial {
learning_rate: args.learning_rate,
initial_learning_matrix: vec![],
},
"markov" => OperationalLearning::Markov {
learning_rate: args.learning_rate,
initial_learning_matrix: vec![],
},
"hiddenmarkov" => OperationalLearning::HiddenMarkov {
learning_rate: args.learning_rate,
initial_transition_matrix: vec![],
initial_emission_matrix: vec![],
},
"none" => OperationalLearning::None,
&_ => panic!(
"{} is not a valid option for --learning",
args.learning.as_str()
),
};
let temperature_schedule = match args.schedule.to_lowercase().as_str() {
"geometric" => TemperatureSchedule::Geometric {
initial_temperature: args.initial_temperature,
},
"cauchy" => TemperatureSchedule::Cauchy {
initial_temperature: args.initial_temperature,
},
"triki" => TemperatureSchedule::Triki {
initial_temperature: args.initial_temperature,
delta: args.delta,
},
"none" => TemperatureSchedule::None,
&_ => panic!(
"{} is not a valid option for --schedule",
args.schedule.as_str()
),
};
println!(
"Solving the {} problem with following parameters",
args.problem
);
let params = Parameters {
number_of_teams: args.teams,
number_of_agents: args.agents,
number_of_iterations: args.iter,
temperature_schedule,
operational_learning: learning_style,
communication: CommunicationStyle::None,
self_bias: args.self_bias,
quality_bias: args.quality_bias,
satisficing_fraction: args.satisficing,
};
println!("{}", params);
match args.problem.to_lowercase().as_str() {
"ackley" => {
let mut cisat = Cohort::<cisat::problems::Ackley>::new(params);
run_all(cisat, args);
}
"structure" => {
let mut cisat = Cohort::<cisat::problems::Structure>::new(params);
run_all(cisat, args);
}
&_ => panic!(
"{} is not a valid option for --problem",
args.schedule.as_str()
),
}
}
fn run_all<S: Solution, A: AgentMethods<S>, T: TeamMethods<S, A>>(
mut cisat: Cohort<S, A, T>,
args: Cli,
) {
let started = Instant::now();
if args.parallel {
cisat.solve();
} else {
let bar = ProgressBar::new(args.iter as u64);
bar.set_style(
ProgressStyle::default_bar()
.template("{spinner} [{msg}] {wide_bar} [{percent}%, ~{eta} remaining]"), );
bar.set_message("Starting...");
for _ in 1..args.iter {
cisat.iterate();
bar.set_message(format!("Best: {:.2}", cisat.get_best_solution_so_far()).as_str());
bar.inc(1);
}
bar.finish_and_clear();
}
println!(
"Done! The simulation took {}, and the best solution found was {:.2}.",
HumanDuration(started.elapsed()),
cisat.get_best_solution_so_far()
);
}