diff --git a/src/graph/logic/builder.rs b/src/graph/logic/builder.rs index fe57644..7c59f60 100644 --- a/src/graph/logic/builder.rs +++ b/src/graph/logic/builder.rs @@ -261,6 +261,7 @@ mod tests { let mut fa = fa1.clone(); fa.graph.merge(fa2.graph); + println!("{}", fa.to_graphviz()); let mut transform = LogicGraphTransformer::new(fa); transform.decompose_xor()?; diff --git a/src/graph/mod.rs b/src/graph/mod.rs index 4b8138b..a9e8e3c 100644 --- a/src/graph/mod.rs +++ b/src/graph/mod.rs @@ -72,6 +72,13 @@ impl GraphNodeKind { _ => unreachable!(), } } + + pub fn as_logic(&self) -> &Logic { + match self { + GraphNodeKind::Logic(logic) => logic, + _ => unreachable!(), + } + } } #[derive(Default, Debug, Clone)] diff --git a/src/transform/placer/mod.rs b/src/transform/placer/mod.rs index 39c93b4..38ca052 100644 --- a/src/transform/placer/mod.rs +++ b/src/transform/placer/mod.rs @@ -1,6 +1,11 @@ -use std::{collections::HashSet, iter::repeat_with}; +use std::{ + collections::{HashMap, HashSet}, + default, + iter::repeat_with, +}; -use petgraph::stable_graph::NodeIndex; +use eyre::ensure; +use itertools::Itertools; use crate::{ graph::{ @@ -10,6 +15,7 @@ use crate::{ }, GraphNodeId, GraphNodeKind, SubGraphWithGraph, }, + logic::LogicType, world::{block::Block, position::Position, world::World3D}, }; @@ -45,9 +51,10 @@ pub struct LocalPlacer<'a> { } pub const K_MAX_LOCAL_PLACE_NODE_COUNT: usize = 25; +pub const K_MAX_LOCAL_ROUTE_DISTANCE: usize = 5; impl<'a> LocalPlacer<'a> { - // you should not pass side effected sub-graph + // you should not pass side effected partitioned sub-graph pub fn new( graph: SubGraphWithGraph<'a>, try_count: usize, @@ -89,9 +96,67 @@ impl<'a> LocalPlacer<'a> { .0 } - fn next_place(&mut self) -> (WorldGraph, usize) { + fn populate_place_order(&self) -> Vec> { + fn evaluate_place_order(order: Vec) -> usize { + // TODO: calculate min-cut + todo!() + } + + // TODO: order place order + vec![self.graph.topological_order()] + } + + fn next_place(&self) -> (WorldGraph, usize) { todo!() } + + // if place fail, then return false + fn try_place( + &self, + nodes: &mut HashMap>, + inputs: Vec, + target: GraphNodeKind, + ) -> eyre::Result { + ensure!(inputs.len() <= 2, "too many inputs"); + + let exists_pos: HashSet = nodes + .iter() + .map(|(_, nodes)| nodes.iter().map(|node| node.position).collect_vec()) + .flatten() + .collect(); + + match target.as_logic().logic_type { + LogicType::Not => todo!(), + LogicType::Or => todo!(), + LogicType::And => eyre::bail!("currently, and placement not supports"), + LogicType::Xor => eyre::bail!("currently, xor placement not supports"), + } + + Ok(true) + } + + // route prev order output to next input + fn try_local_route( + &self, + nodes: &mut HashMap>, + outputs: Vec, + input: GraphNodeId, + ) -> eyre::Result { + if outputs.len() == 1 { + return Ok(true); + } + + let v = outputs + .iter() + .map(|id| nodes[id].last().unwrap().position) + .collect_vec(); + + if v[0].distance(&v[1]) > K_MAX_LOCAL_ROUTE_DISTANCE { + return Ok(false); + } + + Ok(true) + } } pub struct LocalPlacerCostEstimator<'a> { @@ -109,3 +174,9 @@ impl<'a> LocalPlacerCostEstimator<'a> { todo!() } } + +#[derive(Default)] +pub enum LocalRouteStrategy { + #[default] + MinimumDistance, +} diff --git a/src/transform/world_to_logic.rs b/src/transform/world_to_logic.rs index 2909c28..f0ff5dc 100644 --- a/src/transform/world_to_logic.rs +++ b/src/transform/world_to_logic.rs @@ -26,12 +26,17 @@ impl WorldToLogicTransformer { fn verify_input(graph: &WorldGraph) -> eyre::Result<()> { // verify no repeater lock let contains_lock_repeater = graph.graph.nodes.iter().any(|node| { - let GraphNodeKind::Block(block) = node.kind else { - return false; + let GraphNodeKind::Block(block) = node.kind else { + return false; }; - let BlockKind::Repeater { lock_input1, lock_input2 , ..} = block.kind else { - return false; + let BlockKind::Repeater { + lock_input1, + lock_input2, + .. + } = block.kind + else { + return false; }; lock_input1.is_some() || lock_input2.is_some() @@ -154,27 +159,32 @@ mod tests { #[test] fn unittest_world_to_logic_graph() -> eyre::Result<()> { - let nbt = NBTRoot::load(&"test/alu.nbt".into())?; + let nbt = NBTRoot::load(&"test/xor.nbt".into())?; let g = WorldGraphBuilder::new(&nbt.to_world()).build(); g.graph.verify()?; - let g = WorldToLogicTransformer::new(g)?.transform()?; - g.graph.verify()?; + // let g = WorldToLogicTransformer::new(g)?.transform()?; + // g.graph.verify()?; + + // let mut transform = LogicGraphTransformer::new(g); + // transform.remove_double_neg_expression(); + // transform.remove_double_neg_expression(); + // transform.remove_double_neg_expression(); + // let g = transform.finish(); - let mut transform = LogicGraphTransformer::new(g); - transform.remove_double_neg_expression(); - let sub_graphs = transform - .cluster(true) - .iter() - .map(|x| x.to_subgraph()) - .collect_vec(); - let g = transform.finish(); + println!("{}", g.to_graphviz()); + // let sub_graphs = transform + // .cluster(true) + // .iter() + // .map(|x| x.to_subgraph()) + // .collect_vec(); + // let g = transform.finish(); - println!("{}", g.to_graphviz_with_clusters(&sub_graphs)); + // println!("{}", g.to_graphviz_with_clusters(&sub_graphs)); - let clustered_g = subgraphs_to_clustered_graph(&g.graph, &sub_graphs); - println!("{}", clustered_g.to_graphviz()); + // let clustered_g = subgraphs_to_clustered_graph(&g.graph, &sub_graphs); + // println!("{}", clustered_g.to_graphviz()); Ok(()) } diff --git a/src/world/position.rs b/src/world/position.rs index 2a4eb20..41148e8 100644 --- a/src/world/position.rs +++ b/src/world/position.rs @@ -167,6 +167,10 @@ impl Position { unreachable!() } } + + pub fn distance(&self, tar: &Position) -> usize { + self.0.abs_diff(tar.0) + self.1.abs_diff(tar.1) + self.2.abs_diff(tar.2) + } } // 사이즈