Refactor graph and misc
This commit is contained in:
parent
5f5fe0c149
commit
8f163269bd
22 changed files with 126 additions and 45 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
|
@ -581,6 +581,13 @@ dependencies = [
|
||||||
"termcolor",
|
"termcolor",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "factorio-graph"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "factorio-layout"
|
name = "factorio-layout"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
@ -608,6 +615,7 @@ dependencies = [
|
||||||
"criterion",
|
"criterion",
|
||||||
"factorio-blueprint",
|
"factorio-blueprint",
|
||||||
"factorio-core",
|
"factorio-core",
|
||||||
|
"factorio-graph",
|
||||||
"flate2",
|
"flate2",
|
||||||
"image",
|
"image",
|
||||||
"miette",
|
"miette",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [ "factorio-blueprint", "factorio-blueprint-generator", "factorio-core", "factorio-layout",
|
members = [ "factorio-blueprint", "factorio-blueprint-generator", "factorio-core", "factorio-graph", "factorio-layout",
|
||||||
"factorio-pathfinding"
|
"factorio-pathfinding"
|
||||||
]
|
]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ pub mod beltoptions;
|
||||||
pub mod block;
|
pub mod block;
|
||||||
pub mod color;
|
pub mod color;
|
||||||
pub mod direction;
|
pub mod direction;
|
||||||
|
pub mod misc;
|
||||||
pub mod pathfield;
|
pub mod pathfield;
|
||||||
pub mod position;
|
pub mod position;
|
||||||
pub mod quaterdirection;
|
pub mod quaterdirection;
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,27 @@ where
|
||||||
data,
|
data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Map<T>
|
||||||
|
where
|
||||||
|
T: Clone,
|
||||||
|
{
|
||||||
|
pub fn new_with(width: usize, height: usize, value: T) -> Self {
|
||||||
|
let mut data = Vec::new();
|
||||||
|
for _ in 0..(width * height) {
|
||||||
|
data.push(value.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
Self {
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Map<T> {
|
||||||
fn index(&self, x: usize, y: usize) -> usize {
|
fn index(&self, x: usize, y: usize) -> usize {
|
||||||
x + y * self.width
|
x + y * self.width
|
||||||
}
|
}
|
||||||
|
|
@ -91,3 +91,14 @@ impl From<(PositionType, PositionType)> for Position {
|
||||||
Self::new(value.0, value.1)
|
Self::new(value.0, value.1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::ops::Div<PositionType> for Position {
|
||||||
|
type Output = Position;
|
||||||
|
|
||||||
|
fn div(self, rhs: PositionType) -> Self::Output {
|
||||||
|
Self {
|
||||||
|
x: self.x / rhs,
|
||||||
|
y: self.y / rhs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,14 @@ impl Color {
|
||||||
Self::new(255, 255, 255)
|
Self::new(255, 255, 255)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cyan() -> Self {
|
||||||
|
Self::new(0x0f, 0xf0, 0xfc)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn gray(l: u8) -> Self {
|
||||||
|
Self::new(l, l, l)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn index(i: usize) -> Self {
|
pub fn index(i: usize) -> Self {
|
||||||
let c = [
|
let c = [
|
||||||
Color::new(0xe6, 0x00, 0x49),
|
Color::new(0xe6, 0x00, 0x49),
|
||||||
|
|
|
||||||
7
factorio-graph/Cargo.toml
Normal file
7
factorio-graph/Cargo.toml
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
[package]
|
||||||
|
name = "factorio-graph"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
tracing = "0.1.41"
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
|
pub mod priority_queue;
|
||||||
pub mod wheighted_graph;
|
pub mod wheighted_graph;
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
pub mod adjacency_list;
|
pub mod adjacency_list;
|
||||||
pub mod shortest_path;
|
pub mod shortest_path;
|
||||||
|
pub mod steiner_tree;
|
||||||
|
|
||||||
pub trait WheightedGraph: Sized {
|
pub trait WheightedGraph: Sized {
|
||||||
type Node;
|
type Node;
|
||||||
|
|
@ -56,15 +56,16 @@ impl<N, H> MapObject<N, H> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dijkstra<G, P>(graph: &G, start: G::Node, end: G::Node) -> Option<Vec<G::Node>>
|
pub fn dijkstra<G, P, E>(graph: &G, start: G::Node, end: E) -> Option<Vec<G::Node>>
|
||||||
where
|
where
|
||||||
P: PriorityQueue<QueueObject<G::Node>> + Debug,
|
P: PriorityQueue<QueueObject<G::Node>> + Debug,
|
||||||
P::Handle: Debug,
|
P::Handle: Debug,
|
||||||
G::Node: Eq + Hash + Clone + Debug,
|
G::Node: Eq + Hash + Clone + Debug,
|
||||||
G: WheightedGraph,
|
G: WheightedGraph,
|
||||||
|
E: Fn(&'_ G::Node) -> bool,
|
||||||
{
|
{
|
||||||
let span = trace_span!("graph", seen_nodes = Empty, visited_nodes = Empty).entered();
|
let span = trace_span!("graph", seen_nodes = Empty, visited_nodes = Empty).entered();
|
||||||
if start == end {
|
if end(&start) {
|
||||||
return Some(vec![start]);
|
return Some(vec![start]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -75,13 +76,15 @@ where
|
||||||
|
|
||||||
let mut visited_nodes: usize = 1;
|
let mut visited_nodes: usize = 1;
|
||||||
|
|
||||||
|
let mut end_node = None;
|
||||||
while let Some(o) = q.pop_min() {
|
while let Some(o) = q.pop_min() {
|
||||||
visited_nodes += 1;
|
visited_nodes += 1;
|
||||||
if let Some(m) = map.get_mut(&o.node) {
|
if let Some(m) = map.get_mut(&o.node) {
|
||||||
m.key = None;
|
m.key = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
if o.node == end {
|
if end(&o.node) {
|
||||||
|
end_node = Some(o.node);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,9 +109,10 @@ where
|
||||||
span.record("seen_nodes", map.len());
|
span.record("seen_nodes", map.len());
|
||||||
span.record("visited_nodes", visited_nodes);
|
span.record("visited_nodes", visited_nodes);
|
||||||
|
|
||||||
map.get(&end)?;
|
if let Some(end_node) = end_node {
|
||||||
|
map.get(&end_node)?;
|
||||||
|
|
||||||
let mut result = vec![end];
|
let mut result = vec![end_node];
|
||||||
|
|
||||||
// dbg!(&map);
|
// dbg!(&map);
|
||||||
|
|
||||||
|
|
@ -123,6 +127,9 @@ where
|
||||||
result.reverse();
|
result.reverse();
|
||||||
|
|
||||||
Some(result)
|
Some(result)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GraphWrapper<'a, G, F> {
|
struct GraphWrapper<'a, G, F> {
|
||||||
|
|
@ -141,27 +148,28 @@ impl<G: WheightedGraph, F: Fn(&G::Node) -> f64> WheightedGraph for GraphWrapper<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn a_star<G, P, F>(graph: &G, start: G::Node, end: G::Node, dist: F) -> Option<Vec<G::Node>>
|
pub fn a_star<G, P, E, F>(graph: &G, start: G::Node, end: E, dist: F) -> Option<Vec<G::Node>>
|
||||||
where
|
where
|
||||||
P: PriorityQueue<QueueObject<G::Node>> + Debug,
|
P: PriorityQueue<QueueObject<G::Node>> + Debug,
|
||||||
P::Handle: Debug,
|
P::Handle: Debug,
|
||||||
G::Node: Eq + Hash + Clone + Debug,
|
G::Node: Eq + Hash + Clone + Debug,
|
||||||
G: WheightedGraph,
|
G: WheightedGraph,
|
||||||
|
E: Fn(&'_ G::Node) -> bool,
|
||||||
F: Fn(&G::Node) -> f64,
|
F: Fn(&G::Node) -> f64,
|
||||||
{
|
{
|
||||||
let g = GraphWrapper { g: graph, f: dist };
|
let g = GraphWrapper { g: graph, f: dist };
|
||||||
|
|
||||||
dijkstra::<GraphWrapper<G, F>, P>(&g, start, end)
|
dijkstra::<GraphWrapper<G, F>, P, E>(&g, start, end)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
graph::wheighted_graph::{
|
|
||||||
adjacency_list::WheightedAdjacencyList, shortest_path::dijkstra, WheightedGraph,
|
|
||||||
},
|
|
||||||
priority_queue::{binary_heap::BinaryHeap, fibonacci_heap::FibonacciHeap},
|
priority_queue::{binary_heap::BinaryHeap, fibonacci_heap::FibonacciHeap},
|
||||||
|
wheighted_graph::{
|
||||||
|
WheightedGraph, adjacency_list::WheightedAdjacencyList, shortest_path::dijkstra,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -172,7 +180,7 @@ mod test {
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
dijkstra::<WheightedAdjacencyList, BinaryHeap<_>>(&a, 0, 1),
|
dijkstra::<WheightedAdjacencyList, BinaryHeap<_>, _>(&a, 0, |&n| n == 1),
|
||||||
Some(vec![0, 1])
|
Some(vec![0, 1])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -197,19 +205,19 @@ mod test {
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
dijkstra::<WheightedAdjacencyList, BinaryHeap<_>>(&a, 0, 4),
|
dijkstra::<WheightedAdjacencyList, BinaryHeap<_>, _>(&a, 0, |&n| n == 4),
|
||||||
Some(vec![0, 1, 2, 5, 4])
|
Some(vec![0, 1, 2, 5, 4])
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
dijkstra::<WheightedAdjacencyList, BinaryHeap<_>>(&a, 0, 6),
|
dijkstra::<WheightedAdjacencyList, BinaryHeap<_>, _>(&a, 0, |&n| n == 6),
|
||||||
None
|
None
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
dijkstra::<WheightedAdjacencyList, FibonacciHeap<_>>(&a, 0, 4),
|
dijkstra::<WheightedAdjacencyList, FibonacciHeap<_>, _>(&a, 0, |&n| n == 4),
|
||||||
Some(vec![0, 1, 2, 5, 4])
|
Some(vec![0, 1, 2, 5, 4])
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
dijkstra::<WheightedAdjacencyList, FibonacciHeap<_>>(&a, 0, 6),
|
dijkstra::<WheightedAdjacencyList, FibonacciHeap<_>, _>(&a, 0, |&n| n == 6),
|
||||||
None
|
None
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -264,10 +272,6 @@ mod test {
|
||||||
height: 600,
|
height: 600,
|
||||||
};
|
};
|
||||||
|
|
||||||
dbg!(dijkstra::<Grid, BinaryHeap<_>>(
|
dbg!(dijkstra::<Grid, BinaryHeap<_>, _>(&g, (0, 0), |&n| n == (g.width - 1, g.height - 1)));
|
||||||
&g,
|
|
||||||
(0, 0),
|
|
||||||
(g.width - 1, g.height - 1)
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
17
factorio-graph/src/wheighted_graph/steiner_tree.rs
Normal file
17
factorio-graph/src/wheighted_graph/steiner_tree.rs
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
use crate::priority_queue::PriorityQueue;
|
||||||
|
use std::hash::Hash;
|
||||||
|
use std::{collections::HashSet, fmt::Debug};
|
||||||
|
|
||||||
|
use super::{WheightedGraph, shortest_path::QueueObject};
|
||||||
|
|
||||||
|
pub fn takaheshi_matsuyama<G, P>(graph: G, nodes: &[G::Node]) -> Option<Vec<Vec<G::Node>>>
|
||||||
|
where
|
||||||
|
P: PriorityQueue<QueueObject<G::Node>> + Debug,
|
||||||
|
P::Handle: Debug,
|
||||||
|
G::Node: Eq + Hash + Clone,
|
||||||
|
G: WheightedGraph,
|
||||||
|
{
|
||||||
|
let end_nodes: HashSet<G::Node> = HashSet::from_iter(nodes.iter().cloned());
|
||||||
|
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
@ -15,6 +15,7 @@ harness = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
factorio-core = { path = "../factorio-core" }
|
factorio-core = { path = "../factorio-core" }
|
||||||
|
factorio-graph = { path = "../factorio-graph" }
|
||||||
factorio-blueprint = { path = "../factorio-blueprint" }
|
factorio-blueprint = { path = "../factorio-blueprint" }
|
||||||
base64 = "0.22.1"
|
base64 = "0.22.1"
|
||||||
bon = "3.0.2"
|
bon = "3.0.2"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use factorio_core::{pathfield::PathField, prelude::*, visualize::Visualize};
|
use factorio_core::{pathfield::PathField, prelude::*, visualize::Visualize};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
use crate::misc::Map;
|
use factorio_core::misc::Map;
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone)]
|
#[derive(Default, Debug, Clone)]
|
||||||
pub struct BruteforceField {
|
pub struct BruteforceField {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::{belt_finding::brute_force::BruteforceBuilder, misc::Map};
|
use crate::belt_finding::brute_force::BruteforceBuilder;
|
||||||
use factorio_blueprint::{belt::convert_to_blueprint, BlueprintEntity};
|
use factorio_blueprint::{BlueprintEntity, belt::convert_to_blueprint};
|
||||||
|
use factorio_core::misc::Map;
|
||||||
use factorio_core::{
|
use factorio_core::{
|
||||||
beltoptions::Beltspeed, pathfield::PathField, prelude::*, visualize::Visualize,
|
beltoptions::Beltspeed, pathfield::PathField, prelude::*, visualize::Visualize,
|
||||||
};
|
};
|
||||||
|
|
@ -7,7 +8,7 @@ use std::{
|
||||||
ops::RangeInclusive,
|
ops::RangeInclusive,
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
use tracing::{span, Level};
|
use tracing::{Level, span};
|
||||||
|
|
||||||
use super::Problem;
|
use super::Problem;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,11 @@ use crate::Map as _;
|
||||||
use crate::SinglePathInput;
|
use crate::SinglePathInput;
|
||||||
use crate::SinglePathfinder;
|
use crate::SinglePathfinder;
|
||||||
use crate::examples::HashMapMap;
|
use crate::examples::HashMapMap;
|
||||||
use crate::graph::wheighted_graph::WheightedGraph;
|
use factorio_core::misc::Map;
|
||||||
use crate::graph::wheighted_graph::shortest_path::a_star;
|
|
||||||
use crate::misc::Map;
|
|
||||||
use crate::priority_queue::binary_heap::FastBinaryHeap;
|
|
||||||
use factorio_core::{prelude::*, visualize::Visualize};
|
use factorio_core::{prelude::*, visualize::Visualize};
|
||||||
|
use factorio_graph::priority_queue::binary_heap::FastBinaryHeap;
|
||||||
|
use factorio_graph::wheighted_graph::WheightedGraph;
|
||||||
|
use factorio_graph::wheighted_graph::shortest_path::a_star;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tracing::Level;
|
use tracing::Level;
|
||||||
use tracing::span;
|
use tracing::span;
|
||||||
|
|
@ -222,7 +222,11 @@ struct MapInternal<'a> {
|
||||||
impl WheightedGraph for MapInternal<'_> {
|
impl WheightedGraph for MapInternal<'_> {
|
||||||
type Node = (Position, Direction);
|
type Node = (Position, Direction);
|
||||||
|
|
||||||
fn edge(&self, node: &Self::Node, num: usize) -> Option<(Self::Node, f64)> {
|
fn edge(
|
||||||
|
&self,
|
||||||
|
node: &(Position, Direction),
|
||||||
|
num: usize,
|
||||||
|
) -> Option<((Position, Direction), f64)> {
|
||||||
let next = node.0.in_direction(&node.1, 1);
|
let next = node.0.in_direction(&node.1, 1);
|
||||||
next.in_range(
|
next.in_range(
|
||||||
&Position::new(0, 0),
|
&Position::new(0, 0),
|
||||||
|
|
@ -276,10 +280,10 @@ impl Problem {
|
||||||
};
|
};
|
||||||
let p = {
|
let p = {
|
||||||
// dijkstra::<MapInternal, FastBinaryHeap<_>>(&m, self.start[i], self.end[i])
|
// dijkstra::<MapInternal, FastBinaryHeap<_>>(&m, self.start[i], self.end[i])
|
||||||
a_star::<MapInternal, FastBinaryHeap<_>, _>(
|
a_star::<MapInternal, FastBinaryHeap<_>, _, _>(
|
||||||
&m,
|
&m,
|
||||||
self.start[i],
|
self.start[i],
|
||||||
self.end[i],
|
|&n| n == self.end[i],
|
||||||
|&(p, _)| {
|
|&(p, _)| {
|
||||||
1.5 * (PositionType::abs_diff(p.x, self.end[i].0.x)
|
1.5 * (PositionType::abs_diff(p.x, self.end[i].0.x)
|
||||||
+ PositionType::abs_diff(p.y, self.end[i].0.y))
|
+ PositionType::abs_diff(p.y, self.end[i].0.y))
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,6 @@ use factorio_core::{beltoptions::Beltspeed, pathfield::PathField, prelude::*};
|
||||||
|
|
||||||
pub mod belt_finding;
|
pub mod belt_finding;
|
||||||
pub mod examples;
|
pub mod examples;
|
||||||
pub mod graph;
|
|
||||||
pub mod misc;
|
|
||||||
pub mod priority_queue;
|
|
||||||
|
|
||||||
pub struct PathInput<'c, M> {
|
pub struct PathInput<'c, M> {
|
||||||
pub connections: &'c [Connection],
|
pub connections: &'c [Connection],
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue