From 433cbc349a4fb6b043358e503ef4f89cb8bab54e Mon Sep 17 00:00:00 2001 From: Ziyang Hu Date: Mon, 29 Aug 2022 14:31:37 +0800 Subject: [PATCH] hashing, modifying pq --- Cargo.toml | 2 ++ README.md | 2 +- src/algo/mod.rs | 1 + src/algo/shortest_path_dijkstra.rs | 33 +++++++++++------------- src/algo/triangles.rs | 40 ++++++++++++++++++++++++++++++ src/data/value.rs | 20 ++++++++++++++- tests/air_routes.rs | 1 - 7 files changed, 78 insertions(+), 21 deletions(-) create mode 100644 src/algo/triangles.rs diff --git a/Cargo.toml b/Cargo.toml index c3b5da04..c93988a0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,8 @@ rmp-serde = "1.1.0" rmpv = "1.0.0" base64 = "0.13.0" chrono = "0.4.19" +priority-queue = "1.2.3" +ordered-float = "3.0.0" num-traits = "0.2.15" itertools = "0.10.3" regex = "1.6.0" diff --git a/README.md b/README.md index b22d3942..a4d410f3 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ * [x] dfs * [x] shortest path * [ ] A* - * [ ] Yen's k-shortest + * [x] Yen's k-shortest * [ ] all-pairs shortest path * [x] single-source shortest path * [ ] minimum spanning tree diff --git a/src/algo/mod.rs b/src/algo/mod.rs index bec936f7..7def4819 100644 --- a/src/algo/mod.rs +++ b/src/algo/mod.rs @@ -27,6 +27,7 @@ pub(crate) mod shortest_path_dijkstra; pub(crate) mod strongly_connected_components; pub(crate) mod top_sort; pub(crate) mod yen; +pub(crate) mod triangles; pub(crate) trait AlgoImpl { fn run( diff --git a/src/algo/shortest_path_dijkstra.rs b/src/algo/shortest_path_dijkstra.rs index bf980686..c5876227 100644 --- a/src/algo/shortest_path_dijkstra.rs +++ b/src/algo/shortest_path_dijkstra.rs @@ -1,10 +1,13 @@ -use std::cmp::Ordering; -use std::collections::{BTreeMap, BTreeSet, BinaryHeap}; +use std::cmp::{Ordering, Reverse}; +use std::collections::{BTreeMap, BTreeSet}; use std::iter; use anyhow::{anyhow, bail, Result}; use itertools::Itertools; +use ordered_float::OrderedFloat; +use priority_queue::PriorityQueue; + use crate::algo::AlgoImpl; use crate::data::expr::Expr; use crate::data::program::{MagicAlgoRuleArg, MagicSymbol}; @@ -216,39 +219,33 @@ pub(crate) fn dijkstra( forbidden_nodes: &FN, ) -> Vec<(usize, f64, Vec)> { let mut distance = vec![f64::INFINITY; edges.len()]; - let mut heap = BinaryHeap::new(); + let mut pq = PriorityQueue::new(); let mut back_pointers = vec![usize::MAX; edges.len()]; distance[start] = 0.; - heap.push(HeapState { - cost: 0., - node: start, - }); + pq.push(start, Reverse(OrderedFloat(0.))); let mut goals_remaining = goals.clone(); - while let Some(state) = heap.pop() { - if state.cost > distance[state.node] { + while let Some((node, Reverse(OrderedFloat(cost)))) = pq.pop() { + if cost > distance[node] { continue; } - for (nxt_node, path_weight) in &edges[state.node] { + for (nxt_node, path_weight) in &edges[node] { if forbidden_nodes.is_forbidden(*nxt_node) { continue; } - if forbidden_edges.is_forbidden(state.node, *nxt_node) { + if forbidden_edges.is_forbidden(node, *nxt_node) { continue; } - let nxt_cost = state.cost + *path_weight; + let nxt_cost = cost + *path_weight; if nxt_cost < distance[*nxt_node] { - heap.push(HeapState { - cost: nxt_cost, - node: *nxt_node, - }); + pq.push_increase(*nxt_node, Reverse(OrderedFloat(nxt_cost))); distance[*nxt_node] = nxt_cost; - back_pointers[*nxt_node] = state.node; + back_pointers[*nxt_node] = node; } } - goals_remaining.visit(state.node); + goals_remaining.visit(node); if goals_remaining.is_exhausted() { break; } diff --git a/src/algo/triangles.rs b/src/algo/triangles.rs new file mode 100644 index 00000000..511cfd7e --- /dev/null +++ b/src/algo/triangles.rs @@ -0,0 +1,40 @@ +use std::collections::BTreeMap; + +use anyhow::Result; + +use crate::algo::AlgoImpl; +use crate::data::expr::Expr; +use crate::data::program::{MagicAlgoRuleArg, MagicSymbol}; +use crate::data::symb::Symbol; +use crate::runtime::derived::DerivedRelStore; +use crate::runtime::transact::SessionTx; + +pub(crate) struct ClusteringCoefficient; + +impl AlgoImpl for ClusteringCoefficient { + fn run( + &mut self, + tx: &mut SessionTx, + rels: &[MagicAlgoRuleArg], + opts: &BTreeMap, + stores: &BTreeMap, + out: &DerivedRelStore, + ) -> Result<()> { + todo!() + } +} + +pub(crate) struct Triangles; + +impl AlgoImpl for Triangles { + fn run( + &mut self, + tx: &mut SessionTx, + rels: &[MagicAlgoRuleArg], + opts: &BTreeMap, + stores: &BTreeMap, + out: &DerivedRelStore, + ) -> Result<()> { + todo!() + } +} diff --git a/src/data/value.rs b/src/data/value.rs index 2c2ce15f..665ceafb 100644 --- a/src/data/value.rs +++ b/src/data/value.rs @@ -1,6 +1,7 @@ use std::cmp::{Ordering, Reverse}; use std::collections::BTreeSet; use std::fmt::{Debug, Display, Formatter}; +use std::hash::{Hash, Hasher}; use anyhow::{bail, Result}; use regex::Regex; @@ -9,6 +10,8 @@ use serde::{Deserialize, Deserializer, Serialize}; use smallvec::SmallVec; use smartstring::{LazyCompact, SmartString}; +use ordered_float::OrderedFloat; + use crate::data::encode::EncodedVec; use crate::data::id::{EntityId, TxId}; use crate::data::triple::StoreOp; @@ -16,6 +19,12 @@ use crate::data::triple::StoreOp; #[derive(Clone)] pub(crate) struct RegexWrapper(pub(crate) Regex); +impl Hash for RegexWrapper { + fn hash(&self, state: &mut H) { + self.0.as_str().hash(state) + } +} + impl Serialize for RegexWrapper { fn serialize(&self, _serializer: S) -> std::result::Result where @@ -55,7 +64,7 @@ impl PartialOrd for RegexWrapper { } #[derive( - Clone, PartialEq, Eq, PartialOrd, Ord, serde_derive::Deserialize, serde_derive::Serialize, + Clone, PartialEq, Eq, PartialOrd, Ord, serde_derive::Deserialize, serde_derive::Serialize, Hash, )] pub(crate) enum DataValue { #[serde(rename = "n")] @@ -102,6 +111,15 @@ pub(crate) enum Number { Float(f64), } +impl Hash for Number { + fn hash(&self, state: &mut H) { + match self { + Number::Int(i) => i.hash(state), + Number::Float(f) => OrderedFloat(*f).hash(state), + } + } +} + impl Number { pub(crate) fn get_int(&self) -> Option { match self { diff --git a/tests/air_routes.rs b/tests/air_routes.rs index dcee63cb..92162b3d 100644 --- a/tests/air_routes.rs +++ b/tests/air_routes.rs @@ -197,7 +197,6 @@ fn air_routes() -> Result<()> { dbg!(yen_time.elapsed()); println!("{}", res); - return Ok(()); let starts_with_time = Instant::now(); let res = db.run_script(