Browse Source

Small changes to subcity runner; used ranges

master
Jirka Sejkora 4 years ago
parent
commit
d60dee1772
  1. 96
      src/optimize-subcity.rs

96
src/optimize-subcity.rs

@ -25,10 +25,32 @@ fn main() {
.next().expect("No best layout found"); .next().expect("No best layout found");
eprintln!("Found best layout, ID {}, price {}", best_layout.id(), get_price(&city, best_layout.houses())); eprintln!("Found best layout, ID {}, price {}", best_layout.id(), get_price(&city, best_layout.houses()));
let x_range = 5533..=12000; //let x_range = 5533..=12000;
let y_range = 4750..=12500; //let y_range = 4750..=12500;
//let x_range = 5533..=8000; //let x_range = 9500..=14100;
//let y_range = 4750..=8000; //let y_range = 10300..=14400;
//let x_range = 14900..=16200;
//let y_range = 7720..=10400;
//let x_range = 9982..=16383;
//let y_range = 0..=2720;
//let x_range = 7720..=12000;
//let y_range = 5608..=11000;
//let x_range = 3542..=8423;
//let y_range = 4832..=8423;
//let x_range = 1200..=9200;
//let y_range = 9000..=16383;
//let x_range = 9200..=16383;
//let y_range = 9200..=16383;
//let x_range = 9201..=16383;
//let y_range = 0..=7500;
//let x_range = 11100..=13333;
//let y_range = 14700..=16383;
//let x_range = 0..=7500;
//let y_range = 0..=7500;
let x_range = 0..=7500;
let y_range = 9500..=16383;
//let x_range = 9500..=16383;
//let y_range = 0..=7500;
eprintln!("X {}-{}, Y {}-{}", x_range.start(), x_range.end(), y_range.start(), y_range.end()); eprintln!("X {}-{}, Y {}-{}", x_range.start(), x_range.end(), y_range.start(), y_range.end());
let static_houses: Vec<House> = best_layout.houses().iter() let static_houses: Vec<House> = best_layout.houses().iter()
@ -56,11 +78,21 @@ fn main() {
//let mut subcity_db = MemoryLayoutDB::new(); //let mut subcity_db = MemoryLayoutDB::new();
let filename = format!("X{}_{}Y{}_{}ID{}.sqlite", x_range.start(), x_range.end(), y_range.start(), y_range.end(), best_layout.id()); let filename = format!("X{}_{}Y{}_{}ID{}.sqlite", x_range.start(), x_range.end(), y_range.start(), y_range.end(), best_layout.id());
let mut subcity_db = SqliteLayoutDB::from_file(&filename).unwrap(); let mut subcity_db = SqliteLayoutDB::from_file(&filename, true).unwrap();
// The following part merges best subcity layouts back into the global layout and
// inserting them into the database
// Setting this value allows attempts at improving suboptimal subcities after merging them back.
// A subcity may result in a better score than original even if the subcity is worse than the
// original if global improvements improve the cost.
//const SUBOPTIMAL_SUBCITY_COST_MARGIN: u32 = 5000;
//const CHECKED_CITY_LIMIT: usize = 50;
//for layout in subcity_db.layouts().iter() //for layout in subcity_db.layouts().iter()
// .filter(|x| get_price(subcity.city(), x.houses()) < removed_price) // .filter(|x| get_price(subcity.city(), x.houses()) < removed_price + SUBOPTIMAL_SUBCITY_COST_MARGIN)
// .sorted_by(|x, y| get_price(subcity.city(), x.houses()).cmp(&get_price(subcity.city(), y.houses()))) { // .sorted_by(|x, y| get_price(subcity.city(), x.houses()).cmp(&get_price(subcity.city(), y.houses())))
// .take(CHECKED_CITY_LIMIT) {
// let price = get_price(subcity.city(), layout.houses()); // let price = get_price(subcity.city(), layout.houses());
// let mut full_houses = subcity.to_full_houses(layout.houses()); // let mut full_houses = subcity.to_full_houses(layout.houses());
// assert!(city::is_valid(&city, &full_houses).is_some()); // assert!(city::is_valid(&city, &full_houses).is_some());
@ -71,7 +103,7 @@ fn main() {
// } // }
// let seed: u64 = thread_rng().gen(); // let seed: u64 = thread_rng().gen();
// let mut rng = StdRng::seed_from_u64(seed); // let mut rng = StdRng::seed_from_u64(seed);
// optimization::iterate_improvements(&mut house_layout, &mut rng, true); // optimization::iterate_improvements(&mut house_layout, &mut rng, true, false);
// eprintln!("Improvements finished"); // eprintln!("Improvements finished");
// assert!(house_layout.is_valid()); // assert!(house_layout.is_valid());
// let improved_price = city::get_price(&city, house_layout.houses()); // let improved_price = city::get_price(&city, house_layout.houses());
@ -82,9 +114,17 @@ fn main() {
// assert!(city::is_valid(&city, &full_houses).is_some()); // assert!(city::is_valid(&city, &full_houses).is_some());
// println!("Layout {}, price {}, full price {}", layout.id(), price, city::get_price(&city, &full_houses)); // println!("Layout {}, price {}, full price {}", layout.id(), price, city::get_price(&city, &full_houses));
// if improved_price < city::get_price(&city, best_layout.houses()) {
// eprintln!("Found a new best layout for the full city");
// println!("Found a new best layout for the full city");
// println!("Layout {}, price {}, full price {}", layout.id(), price, city::get_price(&city, &full_houses));
// }
// //eprintln!("NOT inserting into the DB");
// // Be careful with duplicates here // // Be careful with duplicates here
// //sqlite_db.add_layout(&full_houses, true); // sqlite_db.add_layout(&full_houses, true);
// //println!("Inserted into the global DB"); // eprintln!("Inserted into the global DB");
// println!("Inserted into the global DB");
// //}
//} //}
//return; //return;
@ -96,12 +136,16 @@ fn main() {
// Generate `WEIGHTED_RANDOM_LAYOUTS` layouts weighted by scores from existing layouts // Generate `WEIGHTED_RANDOM_LAYOUTS` layouts weighted by scores from existing layouts
// } // }
const FULL_RANDOM_LAYOUTS: usize = 100; const FULL_RANDOM_LAYOUTS: usize = 200;
const DB_CHOICE_PROBABILITY: f64 = 0.90; const DB_CHOICE_PROBABILITY: f64 = 0.95;
const WEIGHTED_RANDOM_LAYOUTS: usize = 200; const WEIGHTED_RANDOM_LAYOUTS: usize = 100;
const CUT_COMBINE_TOP_LAYOUTS: usize = 500; const CUT_COMBINE_TOP_LAYOUTS: usize = 500;
const IGNORED_WEIGHT_RATIO: f64 = 0.5; const IGNORED_WEIGHT_RATIO: f64 = 0.5;
const THREAD_COUNT: usize = 12;
rayon::ThreadPoolBuilder::new().num_threads(THREAD_COUNT).build_global();
if subcity_db.layouts().len() == 0 { if subcity_db.layouts().len() == 0 {
let mut full_random_layouts = Vec::new(); let mut full_random_layouts = Vec::new();
@ -119,7 +163,7 @@ fn main() {
})); }));
for houses in &full_random_layouts { for houses in &full_random_layouts {
subcity_db.add_layout(houses, true); subcity_db.add_layout(houses, true).expect("Failed to add new layout");
} }
eprintln!("Finished initial full random population"); eprintln!("Finished initial full random population");
@ -127,9 +171,13 @@ fn main() {
eprintln!("Skipping initial full random population because DB is non-empty [{} layouts]", subcity_db.layouts().len()); eprintln!("Skipping initial full random population because DB is non-empty [{} layouts]", subcity_db.layouts().len());
} }
let best_price: u32 = subcity_db.layouts().iter().map(|layout| layout.houses().iter().map(|h| subcity.city().get_price(*h) as u32).sum()).min().unwrap(); fn print_status<TDB: LayoutDB>(db: &TDB, subcity: &City) {
let worst_price: u32 = subcity_db.layouts().iter().map(|layout| layout.houses().iter().map(|h| subcity.city().get_price(*h) as u32).sum()).max().unwrap(); let best_price: u32 = db.layouts().iter().map(|layout| layout.houses().iter().map(|h| subcity.get_price(*h) as u32).sum()).min().unwrap();
eprintln!("Best {}, worst {} [{} layouts]", best_price, worst_price, subcity_db.layouts().len()); let worst_price: u32 = db.layouts().iter().map(|layout| layout.houses().iter().map(|h| subcity.get_price(*h) as u32).sum()).max().unwrap();
eprintln!("Best {}, worst {} [{} layouts]", best_price, worst_price, db.layouts().len());
}
print_status(&subcity_db, subcity.city());
let mut cache = combine::CompatibilityCache::new(); let mut cache = combine::CompatibilityCache::new();
@ -138,10 +186,8 @@ fn main() {
// This is a bottleneck when it comes to multithreading, it only runs on a single thread // This is a bottleneck when it comes to multithreading, it only runs on a single thread
combine::iterate_combines(&mut subcity_db, CUT_COMBINE_TOP_LAYOUTS, subcity.city(), &mut cache, false); combine::iterate_combines(&mut subcity_db, CUT_COMBINE_TOP_LAYOUTS, subcity.city(), &mut cache, false);
let best_price: u32 = subcity_db.layouts().iter().map(|layout| layout.houses().iter().map(|h| subcity.city().get_price(*h) as u32).sum()).min().unwrap();
let worst_price: u32 = subcity_db.layouts().iter().map(|layout| layout.houses().iter().map(|h| subcity.city().get_price(*h) as u32).sum()).max().unwrap();
eprintln!("Finished cut combines"); eprintln!("Finished cut combines");
eprintln!("Best {}, worst {} [{} layouts]", best_price, worst_price, subcity_db.layouts().len()); print_status(&subcity_db, subcity.city());
let mut weighted_random_layouts = Vec::new(); let mut weighted_random_layouts = Vec::new();
// Only using the underlying memory-based DB is required here as the SqliteLayoutDB // Only using the underlying memory-based DB is required here as the SqliteLayoutDB
@ -152,25 +198,25 @@ fn main() {
let mut rng = StdRng::seed_from_u64(seed); let mut rng = StdRng::seed_from_u64(seed);
let mut layout = HouseLayout::new(subcity.city()); let mut layout = HouseLayout::new(subcity.city());
let best_price: u32 = memory_db.layouts().iter().map(|layout| layout.houses().iter().map(|h| subcity.city().get_price(*h) as u32).sum()).min().unwrap();
let worst_price: u32 = memory_db.layouts().iter().map(|layout| layout.houses().iter().map(|h| subcity.city().get_price(*h) as u32).sum()).max().unwrap();
let price_range = worst_price - best_price; let price_range = worst_price - best_price;
let max_price = best_price as f64 + (price_range as f64 * (1. - IGNORED_WEIGHT_RATIO)); let max_price = best_price as f64 + (price_range as f64 * (1. - IGNORED_WEIGHT_RATIO));
//eprintln!("Starting random weighted population {}, using DB, score range {}-{}, DB use probability {}...", i, best_price, worst_price, DB_CHOICE_PROBABILITY); //eprintln!("Starting random weighted population {}, using DB, score range {}-{}, DB use probability {}...", i, best_price, worst_price, DB_CHOICE_PROBABILITY);
population::populate_using_db(&mut layout, &mut rng, memory_db, best_price as f64, max_price as f64, DB_CHOICE_PROBABILITY); population::populate_using_db(&mut layout, &mut rng, memory_db, best_price as f64, max_price as f64, DB_CHOICE_PROBABILITY);
//eprintln!("Finished random init {}, price: {}, houses: {}", i, layout.price(), layout.houses().len()); //eprintln!("Finished random init {}, price: {}, houses: {}", i, layout.price(), layout.houses().len());
optimization::iterate_improvements(&mut layout, &mut rng, false); optimization::iterate_improvements(&mut layout, &mut rng, false, false);
//eprintln!("Finished iterated improvements {}, price: {}, houses: {}", i, layout.price(), layout.houses().len()); //eprintln!("Finished iterated improvements {}, price: {}, houses: {}", i, layout.price(), layout.houses().len());
layout.houses().clone() layout.houses().clone()
})); }));
for houses in &weighted_random_layouts { for houses in &weighted_random_layouts {
subcity_db.add_layout(houses, true); subcity_db.add_layout(houses, true).expect("Failed to add new layout");
} }
let w_best: u32 = weighted_random_layouts.iter().map(|houses| houses.iter().map(|h| subcity.city().get_price(*h) as u32).sum()).min().unwrap(); let w_best: u32 = weighted_random_layouts.iter().map(|houses| houses.iter().map(|h| subcity.city().get_price(*h) as u32).sum()).min().unwrap();
let w_worst: u32 = weighted_random_layouts.iter().map(|houses| houses.iter().map(|h| subcity.city().get_price(*h) as u32).sum()).max().unwrap(); let w_worst: u32 = weighted_random_layouts.iter().map(|houses| houses.iter().map(|h| subcity.city().get_price(*h) as u32).sum()).max().unwrap();
let best_price: u32 = subcity_db.layouts().iter().map(|layout| layout.houses().iter().map(|h| subcity.city().get_price(*h) as u32).sum()).min().unwrap();
let worst_price: u32 = subcity_db.layouts().iter().map(|layout| layout.houses().iter().map(|h| subcity.city().get_price(*h) as u32).sum()).max().unwrap();
eprintln!("Finished weighted random population, price range {}-{}", w_best, w_worst); eprintln!("Finished weighted random population, price range {}-{}", w_best, w_worst);
eprintln!("Best {}, worst {} [{} layouts]", best_price, worst_price, subcity_db.layouts().len()); print_status(&subcity_db, subcity.city());
} }
} }

Loading…
Cancel
Save