Add in-memory only databases
This commit is contained in:
parent
f694e4701a
commit
083d6a97b9
6 changed files with 95 additions and 24 deletions
|
@ -1,4 +1,4 @@
|
|||
use db::{LayoutDB, SavedLayout};
|
||||
use db::{SqliteLayoutDB, SavedLayout};
|
||||
use city::{City, House};
|
||||
use itertools::Itertools;
|
||||
use crate::combine::transpose_layout;
|
||||
|
@ -13,7 +13,7 @@ enum LastStep {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
let mut db = LayoutDB::from_file("layouts.sqlite").expect("Failed to load the DB");
|
||||
let mut db = SqliteLayoutDB::from_file("layouts.sqlite").expect("Failed to load the DB");
|
||||
eprintln!("Loaded the DB, {} stored layouts", db.layouts().len());
|
||||
|
||||
let city = City::read_from_file("01.in", city::INPUT_CITY_WIDTH, city::INPUT_CITY_HEIGHT);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::city;
|
||||
use crate::db::{LayoutDB, SavedLayout, MergeLowerBound};
|
||||
use crate::db::{SqliteLayoutDB, SavedLayout, MergeLowerBound, LayoutDB};
|
||||
use crate::city::{City, House};
|
||||
use itertools::Itertools;
|
||||
use itertools::iproduct;
|
||||
|
@ -37,7 +37,7 @@ impl CompatibilityCache {
|
|||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
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) -> bool {
|
||||
let mut best_price = left_layouts.iter().chain(right_layouts.iter())
|
||||
.map(|layout| city::get_price(&city, layout.houses()))
|
||||
.min();
|
||||
|
|
95
src/db.rs
95
src/db.rs
|
@ -2,8 +2,12 @@ use crate::city::House;
|
|||
use rusqlite::{Connection, NO_PARAMS, params, Result};
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct LayoutDB {
|
||||
pub struct SqliteLayoutDB {
|
||||
connection: Connection,
|
||||
memory_db: MemoryLayoutDB,
|
||||
}
|
||||
|
||||
pub struct MemoryLayoutDB {
|
||||
layouts: Vec<SavedLayout>,
|
||||
merge_lower_bounds: HashMap<(usize, usize, bool), MergeLowerBound>,
|
||||
}
|
||||
|
@ -57,7 +61,76 @@ impl SavedLayout {
|
|||
}
|
||||
}
|
||||
|
||||
impl LayoutDB {
|
||||
impl MemoryLayoutDB {
|
||||
pub fn new(layouts: Vec<SavedLayout>, merge_lower_bounds: HashMap<(usize, usize, bool), MergeLowerBound>) -> Self {
|
||||
MemoryLayoutDB { layouts, merge_lower_bounds }
|
||||
}
|
||||
|
||||
// This exists for use by the SqliteLayoutDB
|
||||
fn add_layout_with_id(&mut self, houses: &Vec<House>, layout_id: usize, fully_optimized: bool) {
|
||||
self.layouts.push(SavedLayout { id: layout_id, houses: houses.clone() });
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LayoutDB {
|
||||
fn layouts(&self) -> &Vec<SavedLayout>;
|
||||
fn add_layout(&mut self, houses: &Vec<House>, fully_optimized: bool);
|
||||
fn get_merge_lower_bound(&self, left_layout: &SavedLayout, right_layout: &SavedLayout, y_axis: bool) -> Option<u32>;
|
||||
fn add_merge_lower_bound(&mut self, lower_bound: MergeLowerBound);
|
||||
fn add_merge_lower_bounds(&mut self, lower_bounds: Vec<MergeLowerBound>);
|
||||
}
|
||||
|
||||
impl LayoutDB for MemoryLayoutDB {
|
||||
fn layouts(&self) -> &Vec<SavedLayout> {
|
||||
&self.layouts
|
||||
}
|
||||
|
||||
fn add_layout(&mut self, houses: &Vec<House>, fully_optimized: bool) {
|
||||
let layout_id = self.layouts.iter().map(|x| x.id).max().unwrap_or_default() + 1;
|
||||
self.layouts.push(SavedLayout { id: layout_id, houses: houses.clone() });
|
||||
}
|
||||
|
||||
fn get_merge_lower_bound(&self, left_layout: &SavedLayout, right_layout: &SavedLayout, y_axis: bool) -> Option<u32> {
|
||||
if let Some(bound) = self.merge_lower_bounds.get(&(left_layout.id, right_layout.id, y_axis)) {
|
||||
return Some(bound.price);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn add_merge_lower_bound(&mut self, lower_bound: MergeLowerBound) {
|
||||
self.merge_lower_bounds.insert((lower_bound.left_layout_id, lower_bound.right_layout_id, lower_bound.y_axis), lower_bound);
|
||||
}
|
||||
|
||||
fn add_merge_lower_bounds(&mut self, lower_bounds: Vec<MergeLowerBound>) {
|
||||
for lower_bound in lower_bounds {
|
||||
self.merge_lower_bounds.insert((lower_bound.left_layout_id, lower_bound.right_layout_id, lower_bound.y_axis), lower_bound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LayoutDB for SqliteLayoutDB {
|
||||
fn layouts(&self) -> &Vec<SavedLayout> {
|
||||
self.layouts()
|
||||
}
|
||||
|
||||
fn add_layout(&mut self, houses: &Vec<House>, fully_optimized: bool) {
|
||||
self.add_layout(houses, fully_optimized).unwrap();
|
||||
}
|
||||
|
||||
fn get_merge_lower_bound(&self, left_layout: &SavedLayout, right_layout: &SavedLayout, y_axis: bool) -> Option<u32> {
|
||||
self.get_merge_lower_bound(left_layout, right_layout, y_axis)
|
||||
}
|
||||
|
||||
fn add_merge_lower_bound(&mut self, lower_bound: MergeLowerBound) {
|
||||
self.add_merge_lower_bound(lower_bound).unwrap()
|
||||
}
|
||||
|
||||
fn add_merge_lower_bounds(&mut self, lower_bounds: Vec<MergeLowerBound>) {
|
||||
self.add_merge_lower_bounds(lower_bounds).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl SqliteLayoutDB {
|
||||
pub fn from_file(filename: &str) -> Result<Self> {
|
||||
let connection = Connection::open(filename)?;
|
||||
let mut layouts: HashMap<u32, Vec<(u32, u32)>> = HashMap::new();
|
||||
|
@ -102,11 +175,12 @@ impl LayoutDB {
|
|||
}
|
||||
).collect();
|
||||
|
||||
Ok(LayoutDB { connection, layouts, merge_lower_bounds: merges })
|
||||
let memory_db = MemoryLayoutDB::new(layouts, merges);
|
||||
Ok(SqliteLayoutDB { connection, memory_db})
|
||||
}
|
||||
|
||||
pub fn layouts(&self) -> &Vec<SavedLayout> {
|
||||
&self.layouts
|
||||
self.memory_db.layouts()
|
||||
}
|
||||
|
||||
pub fn add_layout(&mut self, houses: &Vec<House>, fully_optimized: bool) -> Result<()> {
|
||||
|
@ -119,15 +193,12 @@ impl LayoutDB {
|
|||
params![layout_id, house.x as u32, house.y as u32])?;
|
||||
}
|
||||
transaction.commit()?;
|
||||
self.layouts.push(SavedLayout { id: layout_id as usize, houses: houses.clone() });
|
||||
self.memory_db.add_layout_with_id(houses, layout_id as usize, fully_optimized);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_merge_lower_bound(&self, left_layout: &SavedLayout, right_layout: &SavedLayout, y_axis: bool) -> Option<u32> {
|
||||
if let Some(bound) = self.merge_lower_bounds.get(&(left_layout.id, right_layout.id, y_axis)) {
|
||||
return Some(bound.price);
|
||||
}
|
||||
None
|
||||
self.memory_db.get_merge_lower_bound(left_layout, right_layout, y_axis)
|
||||
}
|
||||
|
||||
pub fn add_merge_lower_bound(&mut self, lower_bound: MergeLowerBound) -> Result<()> {
|
||||
|
@ -140,13 +211,13 @@ impl LayoutDB {
|
|||
],
|
||||
)?;
|
||||
transaction.commit()?;
|
||||
self.merge_lower_bounds.insert((lower_bound.left_layout_id, lower_bound.right_layout_id, lower_bound.y_axis), lower_bound);
|
||||
self.memory_db.add_merge_lower_bound(lower_bound);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add_merge_lower_bounds(&mut self, lower_bounds: Vec<MergeLowerBound>) -> Result<()> {
|
||||
let transaction = self.connection.transaction()?;
|
||||
for lower_bound in lower_bounds {
|
||||
for lower_bound in &lower_bounds {
|
||||
transaction.execute("INSERT INTO merge_lower_bounds (left_layout_id, right_layout_id, axis, price) VALUES (?1, ?2, ?3, ?4) ON CONFLICT(left_layout_id, right_layout_id) DO UPDATE SET price = ?4",
|
||||
params![lower_bound.left_layout_id as u32,
|
||||
lower_bound.right_layout_id as u32,
|
||||
|
@ -154,9 +225,9 @@ impl LayoutDB {
|
|||
lower_bound.price
|
||||
],
|
||||
)?;
|
||||
self.merge_lower_bounds.insert((lower_bound.left_layout_id, lower_bound.right_layout_id, lower_bound.y_axis), lower_bound);
|
||||
}
|
||||
transaction.commit()?;
|
||||
self.memory_db.add_merge_lower_bounds(lower_bounds);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::io;
|
|||
use std::io::BufRead;
|
||||
use regex::Regex;
|
||||
use crate::city::House;
|
||||
use crate::db::LayoutDB;
|
||||
use crate::db::SqliteLayoutDB;
|
||||
|
||||
mod city;
|
||||
mod db;
|
||||
|
@ -14,7 +14,7 @@ enum State {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
let mut db = LayoutDB::from_file("layouts.sqlite").expect("Failed to load the DB");
|
||||
let mut db = SqliteLayoutDB::from_file("layouts.sqlite").expect("Failed to load the DB");
|
||||
let stdin = io::stdin();
|
||||
|
||||
let price_regex = Regex::new("^Price ([0-9]*), seed ([0-9]*)$").unwrap();
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::fmt;
|
|||
use std::fmt::Formatter;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use city::{HouseLayout, City, House};
|
||||
use crate::db::LayoutDB;
|
||||
use crate::db::SqliteLayoutDB;
|
||||
use crate::population::{build_house_probabilities, populate_from_saved_layout};
|
||||
use itertools::Itertools;
|
||||
|
||||
|
@ -23,7 +23,7 @@ enum RunType {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
let mut db = LayoutDB::from_file("layouts.sqlite").expect("Failed to load the DB");
|
||||
let mut db = SqliteLayoutDB::from_file("layouts.sqlite").expect("Failed to load the DB");
|
||||
eprintln!("Loaded the DB, {} stored layouts", db.layouts().len());
|
||||
|
||||
let city = City::read_from_file("01.in", city::INPUT_CITY_WIDTH, city::INPUT_CITY_HEIGHT);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use rand::Rng;
|
||||
use crate::city::{House, HouseLayout, City};
|
||||
use rand::prelude::*;
|
||||
use crate::db::{LayoutDB, SavedLayout};
|
||||
use crate::db::{SqliteLayoutDB, SavedLayout, LayoutDB};
|
||||
use crate::city;
|
||||
use std::collections::HashMap;
|
||||
use std::ops::Add;
|
||||
|
@ -26,7 +26,7 @@ pub 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>){
|
||||
pub fn build_house_probabilities<TDB : LayoutDB>(city: &City, db: &TDB, 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;
|
||||
|
@ -44,8 +44,8 @@ pub fn build_house_probabilities(city: &City, db: &LayoutDB, min_score: f64, max
|
|||
(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);
|
||||
pub fn populate_using_db<TDB: LayoutDB>(layout: &mut HouseLayout, mut rng: &mut StdRng, db: &TDB, 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 {
|
||||
|
|
Loading…
Reference in a new issue