Add a star for shortest path

This commit is contained in:
hal8174 2025-02-11 20:16:19 +01:00
parent b96ef6f2c1
commit b53d1e87bc
4 changed files with 65 additions and 19 deletions

View file

@ -29,20 +29,20 @@ fn main() {
let l = ValidLayout { let l = ValidLayout {
max_tries: 4, max_tries: 4,
retries: 4, retries: 4,
start_size: Position::new(128, 128), start_size: Position::new(256, 256),
growth: Position::new(16, 16), growth: Position::new(16, 16),
}; };
let l = GeneticAlgorithm { let l = GeneticAlgorithm {
mutation_retries: 20, mutation_retries: 20,
population_size: 40, population_size: 5,
population_keep: 8, population_keep: 8,
population_new: 2, population_new: 2,
generations: 40, generations: 5,
valid_layout: l, valid_layout: l,
}; };
let p = ConflictAvoidance { let p = ConflictAvoidance {
timeout: Some(std::time::Duration::from_millis(20)), timeout: Some(std::time::Duration::from_millis(100)),
}; };
let mut rng = SmallRng::seed_from_u64(args.seed); let mut rng = SmallRng::seed_from_u64(args.seed);

View file

@ -90,14 +90,14 @@ pub fn generate_factory<L: Layouter, P: Pathfinder>(
input_connections.first_chunk() input_connections.first_chunk()
{ {
let c0_bigger = c0.amount > c1.amount + c2.amount; let c0_bigger = c0.amount > c1.amount + c2.amount;
intermediate_connections.push(dbg!(( intermediate_connections.push((
HashMap::from([ HashMap::from([
(connection_id0, (block_index, if c0_bigger { 1 } else { 0 })), (connection_id0, (block_index, if c0_bigger { 1 } else { 0 })),
(connection_id1, (block_index + 1, 0)), (connection_id1, (block_index + 1, 0)),
(connection_id2, (block_index + 1, 1)), (connection_id2, (block_index + 1, 1)),
]), ]),
intermediate_output_connection, intermediate_output_connection,
))); ));
let beltspeed = let beltspeed =
Beltspeed::from_items_per_second(2.0 * f64::max(c1.amount, c2.amount)); Beltspeed::from_items_per_second(2.0 * f64::max(c1.amount, c2.amount));
@ -144,13 +144,13 @@ pub fn generate_factory<L: Layouter, P: Pathfinder>(
} else if let Some(&[(connection_id0, c0), (connection_id1, c1)]) = } else if let Some(&[(connection_id0, c0), (connection_id1, c1)]) =
input_connections.first_chunk() input_connections.first_chunk()
{ {
intermediate_connections.push(dbg!(( intermediate_connections.push((
HashMap::from([ HashMap::from([
(connection_id0, (block_index, 0)), (connection_id0, (block_index, 0)),
(connection_id1, (block_index, 1)), (connection_id1, (block_index, 1)),
]), ]),
intermediate_output_connection, intermediate_output_connection,
))); ));
( (
Beltspeed::from_items_per_second(c0.amount), Beltspeed::from_items_per_second(c0.amount),
Some(Beltspeed::from_items_per_second(c1.amount)), Some(Beltspeed::from_items_per_second(c1.amount)),
@ -201,17 +201,18 @@ pub fn generate_factory<L: Layouter, P: Pathfinder>(
} }
} }
Building::ExternalConnection { inputs, outputs } => { Building::ExternalConnection { inputs, outputs } => {
let step = 4;
blocks.push(MacroBlock { blocks.push(MacroBlock {
size: Position::new(1, (inputs + outputs) as PositionType), size: Position::new(1, step * (inputs + outputs) as PositionType),
input: (0..*inputs) input: (0..*inputs)
.map(|y| Interface { .map(|y| Interface {
offset: Position::new(0, y as PositionType), offset: Position::new(0, step * y as PositionType),
dir: Direction::Left, dir: Direction::Left,
}) })
.collect(), .collect(),
output: (0..*outputs) output: (0..*outputs)
.map(|y| Interface { .map(|y| Interface {
offset: Position::new(0, (inputs + y) as PositionType), offset: Position::new(0, step * (inputs + y) as PositionType),
dir: Direction::Right, dir: Direction::Right,
}) })
.collect(), .collect(),
@ -279,7 +280,12 @@ pub fn generate_factory<L: Layouter, P: Pathfinder>(
let mut blueprint = Blueprint::new(); let mut blueprint = Blueprint::new();
blueprint.add_entity(Entity::new_splitter( blueprint.add_entity(Entity::new_splitter(
Beltspeed::from_items_per_second( Beltspeed::from_items_per_second(
input_connections.iter().map(|&(_, c)| c.amount).sum(), input_connections
.iter()
.chain(output_connections.iter())
.map(|&(_, c)| c.amount)
.max_by(|x, y| x.partial_cmp(y).unwrap())
.unwrap_or(1.0),
), ),
Position::new(2, 1), Position::new(2, 1),
Direction::Up, Direction::Up,
@ -324,10 +330,10 @@ pub fn generate_factory<L: Layouter, P: Pathfinder>(
} }
} }
} }
dbg!(&intermediate_connections); // dbg!(&intermediate_connections);
for (i, c) in factory_graph.factory_connections.iter().enumerate() { for (i, c) in factory_graph.factory_connections.iter().enumerate() {
dbg!(i, c); // dbg!(i, c);
connections.push(Connection { connections.push(Connection {
startblock: intermediate_connections[c.from].1[&i].0, startblock: intermediate_connections[c.from].1[&i].0,
startpoint: intermediate_connections[c.from].1[&i].1, startpoint: intermediate_connections[c.from].1[&i].1,
@ -338,8 +344,8 @@ pub fn generate_factory<L: Layouter, P: Pathfinder>(
}); });
} }
dbg!(&blocks); // dbg!(&blocks);
dbg!(&connections); // dbg!(&connections);
let layout_input = LayoutInput { let layout_input = LayoutInput {
blocks, blocks,

View file

@ -1,4 +1,5 @@
use crate::examples::HashMapMap; use crate::examples::HashMapMap;
use crate::graph::wheighted_graph::shortest_path::a_star;
use crate::graph::wheighted_graph::WheightedGraph; use crate::graph::wheighted_graph::WheightedGraph;
use crate::misc::Map; use crate::misc::Map;
use crate::priority_queue::binary_heap::BinaryHeap; use crate::priority_queue::binary_heap::BinaryHeap;
@ -107,7 +108,7 @@ impl Problem {
let mut weight = 0.0; let mut weight = 0.0;
if self.map.get(x, y).blocked { if self.map.get(x, y).blocked {
weight += 100.0; weight += 10000.0;
} }
self.map.get_mut(x, y).weight = weight; self.map.get_mut(x, y).weight = weight;
@ -117,7 +118,7 @@ impl Problem {
for (i, path) in self.path.iter().enumerate() { for (i, path) in self.path.iter().enumerate() {
if i != without { if i != without {
for p in path { for p in path {
let weight = 10.0; let weight = 1000.0;
let x = p.0.x as usize; let x = p.0.x as usize;
let y = p.0.y as usize; let y = p.0.y as usize;
@ -269,7 +270,17 @@ impl Problem {
map: &self.map, map: &self.map,
end: self.end[i], end: self.end[i],
}; };
let p = dijkstra::<MapInternal, FastBinaryHeap<_>>(&m, self.start[i], self.end[i]); // let p = dijkstra::<MapInternal, FastBinaryHeap<_>>(&m, self.start[i], self.end[i]);
let p = a_star::<MapInternal, FastBinaryHeap<_>, _>(
&m,
self.start[i],
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))
as f64
},
);
if let Some(p) = p { if let Some(p) = p {
self.path[i] = p; self.path[i] = p;
} else { } else {

View file

@ -116,6 +116,35 @@ where
Some(result) Some(result)
} }
struct GraphWrapper<'a, G, F> {
g: &'a G,
f: F,
}
impl<G: WheightedGraph, F: Fn(&G::Node) -> f64> WheightedGraph for GraphWrapper<'_, G, F> {
type Node = G::Node;
fn edge(&self, node: &Self::Node, num: usize) -> Option<(Self::Node, f64)> {
self.g.edge(node, num).map(|(n, s)| {
let s = s - (self.f)(node) + (self.f)(&n);
(n, s)
})
}
}
pub fn a_star<G, P, F>(graph: &G, start: G::Node, end: G::Node, dist: F) -> Option<Vec<G::Node>>
where
P: PriorityQueue<QueueObject<G::Node>> + Debug,
P::Handle: Debug,
G::Node: Eq + Hash + Clone + Debug,
G: WheightedGraph,
F: Fn(&G::Node) -> f64,
{
let g = GraphWrapper { g: graph, f: dist };
dijkstra::<GraphWrapper<G, F>, P>(&g, start, end)
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {