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",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "factorio-graph"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "factorio-layout"
|
||||
version = "0.1.0"
|
||||
|
|
@ -608,6 +615,7 @@ dependencies = [
|
|||
"criterion",
|
||||
"factorio-blueprint",
|
||||
"factorio-core",
|
||||
"factorio-graph",
|
||||
"flate2",
|
||||
"image",
|
||||
"miette",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
[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"
|
||||
]
|
||||
resolver = "2"
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ pub mod beltoptions;
|
|||
pub mod block;
|
||||
pub mod color;
|
||||
pub mod direction;
|
||||
pub mod misc;
|
||||
pub mod pathfield;
|
||||
pub mod position;
|
||||
pub mod quaterdirection;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,27 @@ where
|
|||
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 {
|
||||
x + y * self.width
|
||||
}
|
||||
|
|
@ -91,3 +91,14 @@ impl From<(PositionType, PositionType)> for Position {
|
|||
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)
|
||||
}
|
||||
|
||||
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 {
|
||||
let c = [
|
||||
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;
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
pub mod adjacency_list;
|
||||
pub mod shortest_path;
|
||||
pub mod steiner_tree;
|
||||
|
||||
pub trait WheightedGraph: Sized {
|
||||
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
|
||||
P: PriorityQueue<QueueObject<G::Node>> + Debug,
|
||||
P::Handle: Debug,
|
||||
G::Node: Eq + Hash + Clone + Debug,
|
||||
G: WheightedGraph,
|
||||
E: Fn(&'_ G::Node) -> bool,
|
||||
{
|
||||
let span = trace_span!("graph", seen_nodes = Empty, visited_nodes = Empty).entered();
|
||||
if start == end {
|
||||
if end(&start) {
|
||||
return Some(vec![start]);
|
||||
}
|
||||
|
||||
|
|
@ -75,13 +76,15 @@ where
|
|||
|
||||
let mut visited_nodes: usize = 1;
|
||||
|
||||
let mut end_node = None;
|
||||
while let Some(o) = q.pop_min() {
|
||||
visited_nodes += 1;
|
||||
if let Some(m) = map.get_mut(&o.node) {
|
||||
m.key = None;
|
||||
}
|
||||
|
||||
if o.node == end {
|
||||
if end(&o.node) {
|
||||
end_node = Some(o.node);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -106,9 +109,10 @@ where
|
|||
span.record("seen_nodes", map.len());
|
||||
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);
|
||||
|
||||
|
|
@ -123,6 +127,9 @@ where
|
|||
result.reverse();
|
||||
|
||||
Some(result)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
P: PriorityQueue<QueueObject<G::Node>> + Debug,
|
||||
P::Handle: Debug,
|
||||
G::Node: Eq + Hash + Clone + Debug,
|
||||
G: WheightedGraph,
|
||||
E: Fn(&'_ G::Node) -> bool,
|
||||
F: Fn(&G::Node) -> f64,
|
||||
{
|
||||
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)]
|
||||
mod test {
|
||||
|
||||
use crate::{
|
||||
graph::wheighted_graph::{
|
||||
adjacency_list::WheightedAdjacencyList, shortest_path::dijkstra, WheightedGraph,
|
||||
},
|
||||
priority_queue::{binary_heap::BinaryHeap, fibonacci_heap::FibonacciHeap},
|
||||
wheighted_graph::{
|
||||
WheightedGraph, adjacency_list::WheightedAdjacencyList, shortest_path::dijkstra,
|
||||
},
|
||||
};
|
||||
|
||||
#[test]
|
||||
|
|
@ -172,7 +180,7 @@ mod test {
|
|||
};
|
||||
|
||||
assert_eq!(
|
||||
dijkstra::<WheightedAdjacencyList, BinaryHeap<_>>(&a, 0, 1),
|
||||
dijkstra::<WheightedAdjacencyList, BinaryHeap<_>, _>(&a, 0, |&n| n == 1),
|
||||
Some(vec![0, 1])
|
||||
);
|
||||
}
|
||||
|
|
@ -197,19 +205,19 @@ mod test {
|
|||
};
|
||||
|
||||
assert_eq!(
|
||||
dijkstra::<WheightedAdjacencyList, BinaryHeap<_>>(&a, 0, 4),
|
||||
dijkstra::<WheightedAdjacencyList, BinaryHeap<_>, _>(&a, 0, |&n| n == 4),
|
||||
Some(vec![0, 1, 2, 5, 4])
|
||||
);
|
||||
assert_eq!(
|
||||
dijkstra::<WheightedAdjacencyList, BinaryHeap<_>>(&a, 0, 6),
|
||||
dijkstra::<WheightedAdjacencyList, BinaryHeap<_>, _>(&a, 0, |&n| n == 6),
|
||||
None
|
||||
);
|
||||
assert_eq!(
|
||||
dijkstra::<WheightedAdjacencyList, FibonacciHeap<_>>(&a, 0, 4),
|
||||
dijkstra::<WheightedAdjacencyList, FibonacciHeap<_>, _>(&a, 0, |&n| n == 4),
|
||||
Some(vec![0, 1, 2, 5, 4])
|
||||
);
|
||||
assert_eq!(
|
||||
dijkstra::<WheightedAdjacencyList, FibonacciHeap<_>>(&a, 0, 6),
|
||||
dijkstra::<WheightedAdjacencyList, FibonacciHeap<_>, _>(&a, 0, |&n| n == 6),
|
||||
None
|
||||
);
|
||||
}
|
||||
|
|
@ -264,10 +272,6 @@ mod test {
|
|||
height: 600,
|
||||
};
|
||||
|
||||
dbg!(dijkstra::<Grid, BinaryHeap<_>>(
|
||||
&g,
|
||||
(0, 0),
|
||||
(g.width - 1, g.height - 1)
|
||||
));
|
||||
dbg!(dijkstra::<Grid, BinaryHeap<_>, _>(&g, (0, 0), |&n| n == (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]
|
||||
factorio-core = { path = "../factorio-core" }
|
||||
factorio-graph = { path = "../factorio-graph" }
|
||||
factorio-blueprint = { path = "../factorio-blueprint" }
|
||||
base64 = "0.22.1"
|
||||
bon = "3.0.2"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use factorio_core::{pathfield::PathField, prelude::*, visualize::Visualize};
|
||||
use std::time::Instant;
|
||||
|
||||
use crate::misc::Map;
|
||||
use factorio_core::misc::Map;
|
||||
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct BruteforceField {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use crate::{belt_finding::brute_force::BruteforceBuilder, misc::Map};
|
||||
use factorio_blueprint::{belt::convert_to_blueprint, BlueprintEntity};
|
||||
use crate::belt_finding::brute_force::BruteforceBuilder;
|
||||
use factorio_blueprint::{BlueprintEntity, belt::convert_to_blueprint};
|
||||
use factorio_core::misc::Map;
|
||||
use factorio_core::{
|
||||
beltoptions::Beltspeed, pathfield::PathField, prelude::*, visualize::Visualize,
|
||||
};
|
||||
|
|
@ -7,7 +8,7 @@ use std::{
|
|||
ops::RangeInclusive,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
use tracing::{span, Level};
|
||||
use tracing::{Level, span};
|
||||
|
||||
use super::Problem;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ use crate::Map as _;
|
|||
use crate::SinglePathInput;
|
||||
use crate::SinglePathfinder;
|
||||
use crate::examples::HashMapMap;
|
||||
use crate::graph::wheighted_graph::WheightedGraph;
|
||||
use crate::graph::wheighted_graph::shortest_path::a_star;
|
||||
use crate::misc::Map;
|
||||
use crate::priority_queue::binary_heap::FastBinaryHeap;
|
||||
use factorio_core::misc::Map;
|
||||
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 tracing::Level;
|
||||
use tracing::span;
|
||||
|
|
@ -222,7 +222,11 @@ struct MapInternal<'a> {
|
|||
impl WheightedGraph for MapInternal<'_> {
|
||||
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);
|
||||
next.in_range(
|
||||
&Position::new(0, 0),
|
||||
|
|
@ -276,10 +280,10 @@ impl Problem {
|
|||
};
|
||||
let p = {
|
||||
// dijkstra::<MapInternal, FastBinaryHeap<_>>(&m, self.start[i], self.end[i])
|
||||
a_star::<MapInternal, FastBinaryHeap<_>, _>(
|
||||
a_star::<MapInternal, FastBinaryHeap<_>, _, _>(
|
||||
&m,
|
||||
self.start[i],
|
||||
self.end[i],
|
||||
|&n| n == self.end[i],
|
||||
|&(p, _)| {
|
||||
1.5 * (PositionType::abs_diff(p.x, self.end[i].0.x)
|
||||
+ 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 examples;
|
||||
pub mod graph;
|
||||
pub mod misc;
|
||||
pub mod priority_queue;
|
||||
|
||||
pub struct PathInput<'c, M> {
|
||||
pub connections: &'c [Connection],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue