|
|
@ -1,5 +1,5 @@ |
|
|
|
use crate::city; |
|
|
|
use crate::db::{LayoutDB, SavedLayout}; |
|
|
|
use crate::db::{LayoutDB, SavedLayout, MergeLowerBound}; |
|
|
|
use crate::city::{City, House, SIZE}; |
|
|
|
use itertools::Itertools; |
|
|
|
use itertools::iproduct; |
|
|
@ -37,13 +37,38 @@ impl CompatibilityCache { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
pub fn try_combine(city: &City, left_layouts: &Vec<SavedLayout>, right_layouts: &Vec<SavedLayout>, db: &mut LayoutDB, cache: &mut CompatibilityCache, transposed: bool) -> bool { |
|
|
|
pub fn create_new_best_combination(city: &City, left_layouts: &Vec<SavedLayout>, right_layouts: &Vec<SavedLayout>, db: &mut LayoutDB, cache: &mut CompatibilityCache, transposed: bool) -> bool { |
|
|
|
let mut best_price = left_layouts.iter().chain(right_layouts.iter()) |
|
|
|
.map(|layout| city::get_price(&city, layout.houses())) |
|
|
|
.min(); |
|
|
|
|
|
|
|
let mut improved = false; |
|
|
|
|
|
|
|
let mut lefts = Vec::new(); |
|
|
|
let mut rights = Vec::new(); |
|
|
|
|
|
|
|
for left_layout in left_layouts { |
|
|
|
// We make sure that there is at least one other layout we want to compare this one with
|
|
|
|
// to avoid unnecessary house updates
|
|
|
|
let mut needed = false; |
|
|
|
for right_layout in right_layouts { |
|
|
|
if let Some(bound) = db.get_merge_lower_bound(left_layout, right_layout, transposed) { |
|
|
|
if bound < best_price.expect("No best price set while lower bounds exist") { |
|
|
|
eprintln!("Low bound; left needed ({} - {})", left_layout.id(), right_layout.id()); |
|
|
|
needed = true; |
|
|
|
break; |
|
|
|
} |
|
|
|
} else { |
|
|
|
eprintln!("No bound; left needed ({} - {})", left_layout.id(), right_layout.id()); |
|
|
|
needed = true; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if !needed { |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
// Sorted in reverse so we can remove from the end
|
|
|
|
let sorted_houses: Vec<_> = left_layout.houses().iter().sorted_by(|h1, h2| h2.x.cmp(&h1.x)).map(|x| *x).collect(); |
|
|
|
|
|
|
@ -55,6 +80,23 @@ pub fn try_combine(city: &City, left_layouts: &Vec<SavedLayout>, right_layouts: |
|
|
|
} |
|
|
|
|
|
|
|
for right_layout in right_layouts { |
|
|
|
// We make sure that there is at least one other layout we want to compare this one with
|
|
|
|
// to avoid unnecessary house updates
|
|
|
|
let mut needed = false; |
|
|
|
for left_layout in left_layouts { |
|
|
|
if let Some(bound) = db.get_merge_lower_bound(left_layout, right_layout, transposed) { |
|
|
|
if bound < best_price.expect("No best price set while lower bounds exist") { |
|
|
|
needed = true; |
|
|
|
} |
|
|
|
} else { |
|
|
|
needed = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if !needed { |
|
|
|
continue; |
|
|
|
} |
|
|
|
|
|
|
|
let mut sorted_houses: Vec<_> = right_layout.houses().iter().sorted_by(|h1, h2| h2.x.cmp(&h1.x)).map(|x| *x).collect(); |
|
|
|
|
|
|
|
let mut line = RightLine::new(); |
|
|
@ -68,10 +110,6 @@ pub fn try_combine(city: &City, left_layouts: &Vec<SavedLayout>, right_layouts: |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
let mut best_price = left_layouts.iter().chain(right_layouts.iter()) |
|
|
|
.map(|layout| city::get_price(&city, layout.houses())) |
|
|
|
.min(); |
|
|
|
|
|
|
|
let axis = if transposed { "y" } else { "x" }; |
|
|
|
|
|
|
|
// x is the last left coordinate, x+1 is right
|
|
|
@ -103,6 +141,14 @@ pub fn try_combine(city: &City, left_layouts: &Vec<SavedLayout>, right_layouts: |
|
|
|
|
|
|
|
let pairs = iproduct!(lefts.iter().enumerate(), rights.iter().enumerate()) |
|
|
|
.filter(|((left_i, _), (right_i, _))| left_i != right_i) |
|
|
|
.filter(|((_, left), (_, right))| { |
|
|
|
if let Some(bound) = db.get_merge_lower_bound(left.layout, right.layout, transposed) { |
|
|
|
if bound >= best_price.expect("No best price set while lower bounds exist") { |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
return true; |
|
|
|
}) |
|
|
|
.map(|((left_i, left), (right_i, right))| (left, right, left.line.price + right.line.price, left_i, right_i)) |
|
|
|
.sorted_by(|(_, _, price1, _, _), (_, _, price2, _, _)| price1.cmp(&price2)); |
|
|
|
|
|
|
@ -156,6 +202,17 @@ pub fn try_combine(city: &City, left_layouts: &Vec<SavedLayout>, right_layouts: |
|
|
|
eprintln!("{} incompatibles checked before {} compatible ({} cache hits)", incompatibles, compatibles, cache_hits); |
|
|
|
} |
|
|
|
|
|
|
|
if let Some(lowest_price) = best_price { |
|
|
|
let mut new_bounds = Vec::new(); |
|
|
|
|
|
|
|
for left_layout in left_layouts { |
|
|
|
for right_layout in right_layouts { |
|
|
|
new_bounds.push(MergeLowerBound::new(left_layout.id(), right_layout.id(), transposed, lowest_price)); |
|
|
|
} |
|
|
|
} |
|
|
|
db.add_merge_lower_bounds(new_bounds); |
|
|
|
} |
|
|
|
|
|
|
|
improved |
|
|
|
} |
|
|
|
|
|
|
|