use genetic_algorithm_traits::Individual;
use genetic_algorithm_tsp::distance_mat;
use genetic_algorithm_tsp_api::tsp_solver;
use rocket::serde::json;
use serde::Deserialize;
use serde::Serialize;
use std::time;
#[macro_use]
extern crate rocket;
#[get("/alive")]
fn liveness_probe() -> json::Value {
json::json!("alive")
}
#[derive(Serialize, Deserialize)]
struct SolveTspData {
distances: Vec<Vec<f64>>,
n_generations: usize,
}
#[derive(Serialize, Deserialize)]
struct RouteWithFitness {
route: Vec<usize>,
fitness: f64,
}
#[post("/tsp", format = "json", data = "<input_parameters>")]
fn solve_tsp(input_parameters: json::Json<SolveTspData>) -> json::Value {
let input_parameters: SolveTspData = input_parameters.into_inner();
let distances = distance_mat::DistanceMat::new(input_parameters.distances);
println!("{:?}", distances);
let before = time::Instant::now();
let best_invdividuals =
tsp_solver::solve_tsp(&distances, input_parameters.n_generations, 30, 10, 3);
let duration = tsp_solver::duration_to_ms(before.elapsed());
println!("Computation took {}", duration);
let best_individuals_with_fitness = best_invdividuals
.iter()
.map(|individual| RouteWithFitness {
route: individual.indexes.clone(),
fitness: -individual.fitness(&distances),
})
.collect::<Vec<RouteWithFitness>>();
json::json!(best_individuals_with_fitness)
}
#[catch(404)]
fn not_found() -> json::Value {
json::json!("Not found!")
}
#[catch(500)]
fn failed_computation() -> json::Value {
json::json!("Your computation could not be done.")
}
#[launch]
fn rocket() -> _ {
rocket::build()
.mount("/", routes![liveness_probe, solve_tsp])
.register("/", catchers![not_found, failed_computation])
}
#[cfg(test)]
mod test {
use super::rocket;
use super::*;
use rocket::http;
use rocket::local::blocking;
use serde_json;
#[test]
fn test_not_found() {
let client = blocking::Client::tracked(rocket()).unwrap();
let response = client.get("/does/not/exist").dispatch();
assert_eq!(response.status(), http::Status { code: 404 });
assert_eq!(response.content_type(), Some(http::ContentType::JSON));
assert_eq!(
response.into_string().unwrap(),
String::from(r##""Not found!""##)
);
}
#[test]
fn test_liveness() {
let client = blocking::Client::tracked(rocket()).unwrap();
let response = client.get("/alive").dispatch();
assert_eq!(response.status(), http::Status::Ok);
assert_eq!(response.content_type(), Some(http::ContentType::JSON));
assert_eq!(
response.into_string().unwrap(),
String::from(r##""alive""##)
);
}
#[test]
fn test_tsp() {
let client = blocking::Client::tracked(rocket()).unwrap();
let response = client
.post("/tsp")
.header(http::ContentType::JSON)
.body(
r##"{
"distances": [
[0,64,378,519,434,200],
[64,0,318,455,375,164],
[378,318,0,170,265,344],
[519,455,170,0,223,428],
[434,375,265,223,0,273],
[200,164,344,428,273,0]],
"n_generations": 10000
}"##,
)
.dispatch();
assert_eq!(response.status(), http::Status::Ok);
assert_eq!(response.content_type(), Some(http::ContentType::JSON));
let returned_routes: Vec<RouteWithFitness> =
serde_json::from_str(&response.into_string().unwrap()).unwrap();
assert_eq!(returned_routes.len(), 3);
}
}