Draw from the layout DB
This commit is contained in:
parent
d4093d6000
commit
9bd654a8e6
4 changed files with 78 additions and 6 deletions
|
@ -179,7 +179,7 @@ impl<'a> HouseLayout<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_price(city: &City, houses: &Vec<House>) -> u32 {
|
pub fn get_price(city: &City, houses: &Vec<House>) -> u32 {
|
||||||
let mut price = 0u32;
|
let mut price = 0u32;
|
||||||
for &house in houses {
|
for &house in houses {
|
||||||
price += city.get_price(house) as u32;
|
price += city.get_price(house) as u32;
|
||||||
|
|
|
@ -12,6 +12,12 @@ pub struct SavedLayout {
|
||||||
houses: Vec<House>
|
houses: Vec<House>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SavedLayout {
|
||||||
|
pub fn houses(&self) -> &Vec<House> {
|
||||||
|
&self.houses
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl LayoutDB {
|
impl LayoutDB {
|
||||||
pub fn from_file(filename: &str) -> Result<Self> {
|
pub fn from_file(filename: &str) -> Result<Self> {
|
||||||
let connection = Connection::open(filename)?;
|
let connection = Connection::open(filename)?;
|
||||||
|
@ -55,6 +61,7 @@ impl LayoutDB {
|
||||||
params![layout_id, house.x as u32, house.y as u32])?;
|
params![layout_id, house.x as u32, house.y as u32])?;
|
||||||
}
|
}
|
||||||
transaction.commit()?;
|
transaction.commit()?;
|
||||||
|
self.layouts.push(SavedLayout {id: layout_id as usize, houses: houses.clone()});
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
14
src/main.rs
14
src/main.rs
|
@ -5,6 +5,7 @@ use std::fmt::Formatter;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use city::{HouseLayout, City, House};
|
use city::{HouseLayout, City, House};
|
||||||
use crate::db::LayoutDB;
|
use crate::db::LayoutDB;
|
||||||
|
use crate::population::build_house_probabilities;
|
||||||
|
|
||||||
mod optimization;
|
mod optimization;
|
||||||
mod population;
|
mod population;
|
||||||
|
@ -16,6 +17,12 @@ fn main() {
|
||||||
eprintln!("Loaded the DB, {} stored layouts", db.layouts().len());
|
eprintln!("Loaded the DB, {} stored layouts", db.layouts().len());
|
||||||
|
|
||||||
let city = City::read_from_file("01.in");
|
let city = City::read_from_file("01.in");
|
||||||
|
eprintln!("Loaded the city file, {} houses", city.get_house_count());
|
||||||
|
|
||||||
|
const MIN_WEIGHT_SCORE: f64 = 600000.;
|
||||||
|
const MAX_WEIGHT_SCORE: f64 = 700000.;
|
||||||
|
const DB_CHOICE_PROBABILITY: f64 = 0.9;
|
||||||
|
|
||||||
let mut best_price: Option<u32> = None;
|
let mut best_price: Option<u32> = None;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
@ -23,8 +30,11 @@ fn main() {
|
||||||
eprintln!("Starting seed {}", seed);
|
eprintln!("Starting seed {}", seed);
|
||||||
let mut rng = StdRng::seed_from_u64(seed);
|
let mut rng = StdRng::seed_from_u64(seed);
|
||||||
let mut layout = HouseLayout::new(&city);
|
let mut layout = HouseLayout::new(&city);
|
||||||
eprintln!("Starting random population...");
|
//eprintln!("Starting random population...");
|
||||||
population::populate_random(&mut layout, &mut rng);
|
//population::populate_random(&mut layout, &mut rng);
|
||||||
|
eprintln!("Starting random population, using DB ({}-{} {})...",
|
||||||
|
MIN_WEIGHT_SCORE, MAX_WEIGHT_SCORE, DB_CHOICE_PROBABILITY);
|
||||||
|
population::populate_using_db(&mut layout, &mut rng, &db, MIN_WEIGHT_SCORE, MAX_WEIGHT_SCORE, DB_CHOICE_PROBABILITY);
|
||||||
eprintln!("Finished random init, price: {}", layout.price());
|
eprintln!("Finished random init, price: {}", layout.price());
|
||||||
loop {
|
loop {
|
||||||
let mut improved = false;
|
let mut improved = false;
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use crate::city::{SIZE, House, HouseLayout};
|
use crate::city::{SIZE, House, HouseLayout, City};
|
||||||
use rand::prelude::StdRng;
|
use rand::prelude::*;
|
||||||
|
use crate::db::LayoutDB;
|
||||||
|
use crate::city;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::ops::Add;
|
||||||
|
use itertools::Itertools;
|
||||||
|
use rand::distributions::WeightedIndex;
|
||||||
|
|
||||||
pub(crate) fn populate_random(layout: &mut HouseLayout, rng: &mut StdRng) {
|
pub fn populate_random(layout: &mut HouseLayout, rng: &mut StdRng) {
|
||||||
loop {
|
loop {
|
||||||
loop {
|
loop {
|
||||||
let x = rng.gen_range(0..SIZE);
|
let x = rng.gen_range(0..SIZE);
|
||||||
|
@ -19,3 +25,52 @@ pub(crate) fn populate_random(layout: &mut HouseLayout, rng: &mut StdRng) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn build_house_probabilities(city: &City, db: &LayoutDB, min_score: f64, max_score: f64) -> (WeightedIndex<f64>, Vec<House>){
|
||||||
|
let mut counts: HashMap<House, f64> = HashMap::new();
|
||||||
|
for layout in db.layouts() {
|
||||||
|
let price = city::get_price(&city, layout.houses()) as f64;
|
||||||
|
let value_range = max_score - min_score;
|
||||||
|
let value = 1. - ((price - min_score) / value_range).max(0.).min(1.);
|
||||||
|
|
||||||
|
for house in layout.houses() {
|
||||||
|
*counts.entry(*house).or_default() += value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let houses: Vec<_> = counts.into_iter().filter(|(house, price)| *price != 0.).collect();
|
||||||
|
let index = WeightedIndex::new(houses.iter().map(|(house, price)| price)).unwrap();
|
||||||
|
|
||||||
|
(index, houses.iter().map(|(house, _)| *house).collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn populate_using_db(layout: &mut HouseLayout, mut rng: &mut StdRng, db: &LayoutDB, min_score: f64, max_score: f64, db_probability: f64) {
|
||||||
|
let (mut index, houses) = build_house_probabilities(&layout.city, &db, min_score, max_score);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if rng.gen::<f64>() < db_probability {
|
||||||
|
// TODO: Test without allowing buying covered tiles
|
||||||
|
let house = houses[index.sample(&mut rng)];
|
||||||
|
|
||||||
|
layout.add_house(house);
|
||||||
|
|
||||||
|
if layout.is_valid() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
loop {
|
||||||
|
let x = rng.gen_range(0..SIZE);
|
||||||
|
let y = rng.gen_range(0..SIZE);
|
||||||
|
let house = House::new(x, y);
|
||||||
|
if layout.city.is_house_xy(x, y) && !layout.is_covered(house) {
|
||||||
|
layout.add_house(house);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if layout.is_valid() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue