Browse Source

Add in-memory only databases

master
Jirka Sejkora 4 years ago
parent
commit
083d6a97b9
  1. 4
      src/combine-layouts.rs
  2. 4
      src/combine.rs
  3. 95
      src/db.rs
  4. 4
      src/import-logs.rs
  5. 4
      src/main.rs
  6. 8
      src/population.rs

4
src/combine-layouts.rs

@ -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);

4
src/combine.rs

@ -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

@ -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(())
}
}

4
src/import-logs.rs

@ -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
src/main.rs

@ -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);

8
src/population.rs

@ -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…
Cancel
Save