|
@ -1,6 +1,6 @@ |
|
|
use crate::city; |
|
|
use crate::city; |
|
|
use crate::db::{SqliteLayoutDB, SavedLayout, MergeLowerBound, LayoutDB}; |
|
|
use crate::db::{SqliteLayoutDB, SavedLayout, MergeLowerBound, LayoutDB}; |
|
|
use crate::city::{City, House}; |
|
|
use crate::city::{City, House, HouseDistances}; |
|
|
use itertools::Itertools; |
|
|
use itertools::Itertools; |
|
|
use itertools::iproduct; |
|
|
use itertools::iproduct; |
|
|
use std::collections::{VecDeque, HashMap}; |
|
|
use std::collections::{VecDeque, HashMap}; |
|
@ -60,13 +60,19 @@ pub fn iterate_combines<TDB: LayoutDB>(mut db: &mut TDB, top_layout_count: usize |
|
|
let transposed_city = transpose_city(&city); |
|
|
let transposed_city = transpose_city(&city); |
|
|
if print_progress { eprintln!("Finished building a transposed city"); } |
|
|
if print_progress { eprintln!("Finished building a transposed city"); } |
|
|
|
|
|
|
|
|
|
|
|
if print_progress { eprintln!("Building right distances..."); } |
|
|
|
|
|
let right_distances = city::build_distances_right(&city); |
|
|
|
|
|
if print_progress { eprintln!("Building right distances (transposed)..."); } |
|
|
|
|
|
let right_distances_transposed = city::build_distances_right(&city); |
|
|
|
|
|
if print_progress { eprintln!("Finished building right distances"); } |
|
|
|
|
|
|
|
|
let mut last_improve_step = LastStep::None; |
|
|
let mut last_improve_step = LastStep::None; |
|
|
loop { |
|
|
loop { |
|
|
if last_improve_step == LastStep::Vertical { break; } |
|
|
if last_improve_step == LastStep::Vertical { break; } |
|
|
if print_progress { eprintln!("Starting to combine {} top houses DB; vertical cuts", top_layout_count); } |
|
|
if print_progress { eprintln!("Starting to combine {} top houses DB; vertical cuts", top_layout_count); } |
|
|
|
|
|
|
|
|
let chosen_layouts = choose_layouts(db, &city, top_layout_count); |
|
|
let chosen_layouts = choose_layouts(db, &city, top_layout_count); |
|
|
if create_new_best_combination(&city, &chosen_layouts, &chosen_layouts, db, &mut cache, false, print_progress) { |
|
|
if create_new_best_combination(&city, &chosen_layouts, &chosen_layouts, db, &mut cache, &right_distances, false, print_progress) { |
|
|
last_improve_step = LastStep::Vertical; |
|
|
last_improve_step = LastStep::Vertical; |
|
|
} |
|
|
} |
|
|
if print_progress { eprintln!("Finished vertical cuts, improvement: {}", last_improve_step == LastStep::Vertical); } |
|
|
if print_progress { eprintln!("Finished vertical cuts, improvement: {}", last_improve_step == LastStep::Vertical); } |
|
@ -77,7 +83,7 @@ pub fn iterate_combines<TDB: LayoutDB>(mut db: &mut TDB, top_layout_count: usize |
|
|
let transposed_chosen_layouts: Vec<_> = chosen_layouts.iter().map(|x| transpose_saved_layout(x)).collect(); |
|
|
let transposed_chosen_layouts: Vec<_> = chosen_layouts.iter().map(|x| transpose_saved_layout(x)).collect(); |
|
|
|
|
|
|
|
|
if print_progress { eprintln!("Starting to combine {} top houses DB; horizontal cuts", top_layout_count); } |
|
|
if print_progress { eprintln!("Starting to combine {} top houses DB; horizontal cuts", top_layout_count); } |
|
|
if create_new_best_combination(&transposed_city, &transposed_chosen_layouts, &transposed_chosen_layouts, db, &mut cache, true, print_progress) { |
|
|
if create_new_best_combination(&transposed_city, &transposed_chosen_layouts, &transposed_chosen_layouts, db, &mut cache, &right_distances_transposed, true, print_progress) { |
|
|
last_improve_step = LastStep::Horizontal; |
|
|
last_improve_step = LastStep::Horizontal; |
|
|
} |
|
|
} |
|
|
if print_progress { eprintln!("Finished horizontal cuts, improvement: {}", last_improve_step == LastStep::Horizontal); } |
|
|
if print_progress { eprintln!("Finished horizontal cuts, improvement: {}", last_improve_step == LastStep::Horizontal); } |
|
@ -108,7 +114,7 @@ fn transpose_saved_layout(layout: &SavedLayout) -> SavedLayout { |
|
|
SavedLayout::new(layout.id(), transposed) |
|
|
SavedLayout::new(layout.id(), transposed) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
pub fn create_new_best_combination<TDB: LayoutDB>(city: &City, left_layouts: &Vec<SavedLayout>, right_layouts: &Vec<SavedLayout>, db: &mut TDB, cache: &mut CompatibilityCache, transposed: bool, print_progress: bool) -> bool { |
|
|
pub fn create_new_best_combination<TDB: LayoutDB>(city: &City, left_layouts: &Vec<SavedLayout>, right_layouts: &Vec<SavedLayout>, db: &mut TDB, cache: &mut CompatibilityCache, right_distances: &HouseDistances, transposed: bool, print_progress: bool) -> bool { |
|
|
let mut best_price = left_layouts.iter().chain(right_layouts.iter()) |
|
|
let mut best_price = left_layouts.iter().chain(right_layouts.iter()) |
|
|
.map(|layout| city::get_price(&city, layout.houses())) |
|
|
.map(|layout| city::get_price(&city, layout.houses())) |
|
|
.min(); |
|
|
.min(); |
|
@ -248,7 +254,7 @@ pub fn create_new_best_combination<TDB: LayoutDB>(city: &City, left_layouts: &Ve |
|
|
} |
|
|
} |
|
|
let compatible = match cache.is_compatible(left.layout, right.layout, left.line.last_update_x, right.line.last_update_x, transposed) { |
|
|
let compatible = match cache.is_compatible(left.layout, right.layout, left.line.last_update_x, right.line.last_update_x, transposed) { |
|
|
None => { |
|
|
None => { |
|
|
let compatible = is_compatible(city, &left.line, &right.line); |
|
|
let compatible = is_compatible(city, right_distances, &left.line, &right.line); |
|
|
cache.set_compatible(left.layout, right.layout, left.line.last_update_x, right.line.last_update_x, transposed, compatible); |
|
|
cache.set_compatible(left.layout, right.layout, left.line.last_update_x, right.line.last_update_x, transposed, compatible); |
|
|
compatible |
|
|
compatible |
|
|
} |
|
|
} |
|
@ -306,14 +312,13 @@ pub fn create_new_best_combination<TDB: LayoutDB>(city: &City, left_layouts: &Ve |
|
|
improved |
|
|
improved |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
fn is_compatible(city: &City, left: &LeftLine, right: &RightLine) -> bool { |
|
|
fn is_compatible(city: &City, right_distances: &HouseDistances, left: &LeftLine, right: &RightLine) -> bool { |
|
|
for y in 0..city.height() { |
|
|
for y in 0..city.height() { |
|
|
let max_left_covered_x = left.get_max_covered_x(y); |
|
|
let max_left_covered_x = left.get_max_covered_x(y); |
|
|
let min_right_covered_x = right.get_min_covered_x(y); |
|
|
let min_right_covered_x = right.get_min_covered_x(y); |
|
|
|
|
|
|
|
|
// This range will often be empty
|
|
|
if let Some(right_house) = right_distances.get_closest_house_xy(max_left_covered_x, y) { |
|
|
for x in (max_left_covered_x + 1)..min_right_covered_x { |
|
|
if right_house.x < min_right_covered_x { |
|
|
if city.is_house_xy(x, y) { |
|
|
|
|
|
return false; |
|
|
return false; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|