Skip to content

Commit

Permalink
Bench
Browse files Browse the repository at this point in the history
  • Loading branch information
arjo129 committed Jan 2, 2025
1 parent e4edc98 commit b08a1d5
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 16 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ Cargo.lock
tarpaulin-report.html
perf.txt
perf.teg.txt
data*
Binary file added docs/lift_scalability.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/solution_times_teg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions evaluate_lift.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/bash
cargo build --release --example lift_session
for ((i=0;i<20;i++)); do
timeout 300 ./target/release/examples/lift_session
export COPY_DIR=data/15robot_6lift_OPT_LOW_TRAVEL$(date +%s%N)
mkdir $COPY_DIR
mv perf.txt $COPY_DIR/
mv perf.teg.txt $COPY_DIR/
mv time.txt $COPY_DIR/
mv time.teg.txt $COPY_DIR/
mv greedy.time.txt $COPY_DIR/
done
132 changes: 119 additions & 13 deletions examples/lift_session.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
use std::{
collections::HashMap,
io::Write,
sync::{atomic::AtomicBool, Arc},
time::SystemTime,
collections::{HashMap, HashSet}, hash::RandomState, io::Write, sync::{atomic::AtomicBool, Arc}, time::SystemTime
};

use chrono::{TimeZone, Utc};
use chrono::{DateTime, TimeZone, Utc};
use rmf_reservations::{
algorithms::{
sat_flexible_time_model::{Problem, SATFlexibleTimeModel},
sat_flexible_time_model::{Assignment, Problem, SATFlexibleTimeModel},
sat_teg::TEGSolver,
},
cost_function::static_cost,
Expand All @@ -27,7 +24,7 @@ impl ClockSource for FakeClock {
return time;
}
}

#[derive(Clone, Debug)]
struct Robot {
time_from_start_to_lift_travel: Vec<chrono::Duration>,
time_from_lift_to_destination: Vec<chrono::Duration>,
Expand Down Expand Up @@ -91,7 +88,7 @@ impl LiftAssigner {
}

// Now calculate transition costs
/*for (_lift_id, tasks) in &request_id_to_lift {
for (_lift_id, tasks) in &request_id_to_lift {
for from in 0..tasks.len() {
for to in 0..tasks.len() {
if from == to {
Expand All @@ -113,19 +110,97 @@ impl LiftAssigner {
problem.require_minimum_gap(&prev_req_id, &next_req_id, transition_time);
}
}
}*/
}
}

problem
}

// This uses the greedy policy to get the makespan.
fn greedy_policy(&self) -> chrono::Duration {
let mut nearest_lift_queue = HashMap::new();
for (id,robot) in self.robots.iter().enumerate() {
nearest_lift_queue.insert(id, robot.time_from_start_to_lift_travel.iter().enumerate().map(|(a,b)| (*b,a)).min().unwrap().1);
}

let mut lift_queues: HashMap<usize, Vec<usize>> = HashMap::new();
for (robot_id, lift_id) in nearest_lift_queue.iter() {
if let Some(lift_queue) = lift_queues.get_mut(lift_id) {
lift_queue.push(*robot_id);
}
else {
lift_queues.insert(*lift_id, vec![*robot_id]);
}
}

let mut max_make_span = chrono::Duration::zero();
for (lift_id, _) in self.lifts.iter().enumerate() {
let mut curr_time = chrono::Duration::zero();
let mut current_floor = 0;
if let Some(robots) = lift_queues.get(&lift_id) {
let mut robots_2 = robots.clone();
let mut robot_list = self.robots.clone();
robots_2.sort_by(move |r1, r2| robot_list[*r1].time_from_start_to_lift_travel[lift_id].cmp(&robot_list[*r2].time_from_start_to_lift_travel[lift_id]));
for robot in robots_2 {
let time_start = self.robots[robot].time_from_start_to_lift_travel[lift_id];
let x = (0..self.robots[robot].start_floor.abs_diff(current_floor)).fold(chrono::Duration::zero(), |q,_| q+self.lift_time_per_floor);
if curr_time + x < time_start {
curr_time = time_start;
}
else {
curr_time += x;
}
let det_floor = self.robots[robot].end_floor;
curr_time += (0..self.robots[robot].start_floor.abs_diff(det_floor)).fold(chrono::Duration::zero(), |q,_| q+self.lift_time_per_floor);
current_floor = det_floor;
}
max_make_span = max_make_span.max(curr_time);
// Nearest floor heuristic ignoring constraints
/*let mut current_lift_pos = 1;
let mut robots_to_pick_up: HashSet<usize, RandomState> = HashSet::from_iter(robots.into_iter().map(|r| *r));
while robots_to_pick_up.len() != 0 {
//let dist_to_lift = ;
let mut selected_floor = 100000usize;
let mut dest_floor = 10000000usize;
let mut selected_robot = 0usize;
for robot in robots_to_pick_up {
let start_floor = self.robots[robot].start_floor;
if selected_floor.abs_diff(start_floor) < selected_floor.abs_diff(current_lift_pos) {
selected_floor = start_floor;
dest_floor = self.robots[robot].end_floor;
selected_robot = robot;
}
}
current_lift_pos = dest_floor;
robots_to_pick_up.remove(&selected_robot);
}*/

}
}
max_make_span
}
}



fn get_makespan(final_schedule: HashMap<String, Vec<Assignment>>, problem: Problem) -> Option<DateTime<Utc>> {
final_schedule
.iter()
.filter(|(_resource, assignment)| assignment.len() != 0)
.map(move |(_resource, assignment)| {
let assignment = &assignment[assignment.len() - 1];
assignment.start_time + problem.requests[assignment.id.0][assignment.id.1].parameters.duration.unwrap_or(chrono::Duration::new(0, 0).unwrap())
})
.max()
}

fn main() {
let num_robots = 10;
let num_robots = 15;
let max_floors = 30;
let num_lifts = 2;
let num_lifts = 6;

let max_time_to = 500;
let max_time_to = 300;

let mut num = rand::thread_rng();

Expand All @@ -147,12 +222,13 @@ fn main() {
let lift_assigner = LiftAssigner {
robots,
lifts,
lift_time_per_floor: chrono::Duration::new(60, 0).unwrap(),
lift_time_per_floor: chrono::Duration::new(15, 0).unwrap(),
start_time: my_clock.now(),
};

let problem = lift_assigner.get_problem();
let problem2 = problem.clone();
let problem3 = problem.clone();
let (sender, rx) = std::sync::mpsc::channel();
let stop = Arc::new(AtomicBool::new(false));
let s = SATFlexibleTimeModel {
Expand All @@ -171,27 +247,57 @@ fn main() {
start: my_clock.now(),
};

let my_clock2 = my_clock.clone();
let problem4 = problem3.clone();
let child2 = std::thread::spawn(move || {
let mut file = std::fs::File::create("perf.teg.txt").unwrap();
let (sender, rx) = std::sync::mpsc::channel();
let stop = Arc::new(AtomicBool::new(false));

let mut file2 = std::fs::File::create("time.teg.txt").unwrap();
let timer = SystemTime::now();
std::thread::spawn(move || {
let soln = solver.solve_optimally(problem2, sender, stop);
file2.write(format!("Opt Time {:?}\n", soln).as_bytes());
file2.write(format!("Opt Time {:?}\n", get_makespan(soln.unwrap(), problem4.clone()).unwrap() - my_clock2.now()).as_bytes());
});
//
for c in rx.iter() {
let res = format!("TEG solution found in: {:?}\n", timer.elapsed());
file.write(&res.as_bytes());
/*match c {
rmf_reservations::algorithms::AlgorithmState::FeasibleScheduleSolution(hash_map) => {file2.write(format!("Subopt Time {:?}\n", get_makespan(hash_map, problem4.clone()).unwrap() - my_clock2.now()).as_bytes());} ,
rmf_reservations::algorithms::AlgorithmState::OptimalScheduleSolution(hash_map) => {file2.write(format!("Opt Time {:?}\n", get_makespan(hash_map, problem4.clone()).unwrap() - my_clock2.now()).as_bytes());},
rmf_reservations::algorithms::AlgorithmState::OptimalSolution(hash_map) => todo!(),
rmf_reservations::algorithms::AlgorithmState::PartialSolution(hash_map, _) => todo!(),
rmf_reservations::algorithms::AlgorithmState::NotFound => todo!(),
rmf_reservations::algorithms::AlgorithmState::UnSolveable => todo!(),
};*/
}
let res = format!("Optimal TEG solution found in: {:?}\n", timer.elapsed());
file.write(&res.as_bytes());
});

let timer = SystemTime::now();
let mut file = std::fs::File::create("perf.txt").unwrap();
let mut file2 = std::fs::File::create("time.txt").unwrap();
for c in rx.iter() {
let res = format!("Sub-optimal solution found in: {:?}\n", timer.elapsed());
file.write(&res.as_bytes());

match c {
rmf_reservations::algorithms::AlgorithmState::FeasibleScheduleSolution(hash_map) => {file2.write(format!("Subopt Time {:?}", get_makespan(hash_map, problem3.clone()).unwrap() - my_clock.now()).as_bytes());} ,
rmf_reservations::algorithms::AlgorithmState::OptimalScheduleSolution(hash_map) => {file2.write(format!("Opt Time {:?}", get_makespan(hash_map, problem3.clone()).unwrap() - my_clock.now()).as_bytes());},
rmf_reservations::algorithms::AlgorithmState::OptimalSolution(hash_map) => todo!(),
rmf_reservations::algorithms::AlgorithmState::PartialSolution(hash_map, _) => todo!(),
rmf_reservations::algorithms::AlgorithmState::NotFound => todo!(),
rmf_reservations::algorithms::AlgorithmState::UnSolveable => todo!(),
};
}
let res = format!("Optimal found in: {:?}\n", timer.elapsed());
file.write(&res.as_bytes());
child2.join();
let mut file3 = std::fs::File::create("greedy.time.txt").unwrap();
let res = format!("FIFO: {:?}\n", lift_assigner.greedy_policy());
file3.write(&res.as_bytes());
}
Binary file added optimal_solntimes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 13 additions & 3 deletions src/algorithms/sat_teg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,7 @@ impl TEGSolver {
}
}

println!("Initial search");
let mut solver = Solver::new();
solver.add_formula(&formula);
let Ok(ok) = solver.solve() else {
Expand All @@ -522,6 +523,7 @@ impl TEGSolver {
let Some(model) = solver.model() else {
return Err("Unable to get model".to_string());
};
println!("Refinement search");

// Optimizer
let mut latest_time = model
Expand All @@ -533,16 +535,22 @@ impl TEGSolver {
let mut best_model = model.clone();
while !optimal_found && !stop.load(std::sync::atomic::Ordering::Relaxed) {
// TODO(arjoc): tweak for suboptimal solutions
latest_time = latest_time - 1;
if latest_time == 1 {
optimal_found = true;
break;
}
latest_time -= 1;
println!("latest_time {:?}",latest_time );


// Shrink time window
let constricted_formula = CnfFormula::new();
let mut constricted_formula = CnfFormula::new();
for time in latest_time..max_time_idx {
for res in 0..decision_vars[time as usize].len() {
for req_id in 0..decision_vars[time as usize][res].len() {
for alt_id in 0..decision_vars[time as usize][res][req_id].len() {
let var = decision_vars[time as usize][res][req_id][alt_id];
formula.add_clause(&[Lit::from_var(var, false)]);
constricted_formula.add_clause(&[Lit::from_var(var, false)]);
}
}
}
Expand All @@ -562,6 +570,7 @@ impl TEGSolver {
};
best_model = model.clone();
sender.send(AlgorithmState::FeasibleScheduleSolution(HashMap::new()));

}

// Reconstruct schedule
Expand Down Expand Up @@ -609,6 +618,7 @@ impl TEGSolver {
);
}
}

for (_, vec) in unordered_schedule.iter_mut() {
vec.sort_by(|a, b| a.start_time.cmp(&b.start_time))
}
Expand Down
Binary file added subopt.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added teg_lifts.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tord_lifts.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit b08a1d5

Please sign in to comment.