mirror of https://codeberg.org/topola/topola.git
fix: get rid of some indeterminism by using B-trees instead of hash maps
I have replaced all instances of `HashMap<...>` with `BTreeMap<...>`, of `HashSet<...>` with `BTreeSet<...>`, and all the uses of the `Hash` trait with `Ord`. I have done a few manual tests and found the behavior to be deterministic between the GUI application launches. However, undoing an autoroute command and then manually executing it once again continues to produce variable results. I suppose this is because of some bug in the code where edits are applied. Hence, the issue https://codeberg.org/topola/topola/issues/46 is only partially resolved.
This commit is contained in:
parent
9c007a8ccb
commit
9664f1a31a
|
|
@ -5,8 +5,8 @@
|
|||
//! Module for handling Specctra's mesadata - design rules, as well as layers
|
||||
//! or net properties
|
||||
|
||||
use bimap::BiHashMap;
|
||||
use std::collections::HashMap;
|
||||
use bimap::BiBTreeMap;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use crate::{
|
||||
rules::{AccessRules, Conditions},
|
||||
|
|
@ -74,22 +74,22 @@ pub struct SpecctraMesadata {
|
|||
// net class name -> rule
|
||||
/// A map from net class names to their specific `SpecctraRule` constraints.
|
||||
/// These rules are applied to all nets belonging to the respective net clas
|
||||
class_rules: HashMap<String, SpecctraRule>,
|
||||
class_rules: BTreeMap<String, SpecctraRule>,
|
||||
|
||||
// layername <-> layer for Layout
|
||||
/// A bidirectional map between layer indices and layer names, allowing translation
|
||||
/// between index-based layers in the layout and user-defined layer names.
|
||||
pub layer_layername: BiHashMap<usize, String>,
|
||||
pub layer_layername: BiBTreeMap<usize, String>,
|
||||
|
||||
// netname <-> net for Layout
|
||||
/// A bidirectional map between network indices and network names in the PCB layout,
|
||||
/// providing an easy way to reference nets by name or index.
|
||||
pub net_netname: BiHashMap<usize, String>,
|
||||
pub net_netname: BiBTreeMap<usize, String>,
|
||||
|
||||
// net -> netclass
|
||||
/// A map that associates network indices with their respective net class names.
|
||||
/// This is used to apply net class-specific routing rules to each net.
|
||||
net_netclass: HashMap<usize, String>,
|
||||
net_netclass: BTreeMap<usize, String>,
|
||||
}
|
||||
|
||||
impl SpecctraMesadata {
|
||||
|
|
@ -98,7 +98,7 @@ impl SpecctraMesadata {
|
|||
/// This function extracts the necessary metadata from the `Pcb` struct, such as
|
||||
/// layer-to-layer name mappings, net-to-net name mappings, and net class rules.
|
||||
pub fn from_pcb(pcb: &Pcb) -> Self {
|
||||
let layer_layername = BiHashMap::from_iter(
|
||||
let layer_layername = BiBTreeMap::from_iter(
|
||||
pcb.structure
|
||||
.layers
|
||||
.iter()
|
||||
|
|
@ -119,11 +119,11 @@ impl SpecctraMesadata {
|
|||
tmp.sort_unstable();
|
||||
tmp.dedup();
|
||||
|
||||
BiHashMap::from_iter(tmp.into_iter().cloned().enumerate())
|
||||
BiBTreeMap::from_iter(tmp.into_iter().cloned().enumerate())
|
||||
};
|
||||
|
||||
let mut net_netclass = HashMap::new();
|
||||
let class_rules = HashMap::from_iter(
|
||||
let mut net_netclass = BTreeMap::new();
|
||||
let class_rules = BTreeMap::from_iter(
|
||||
pcb.network
|
||||
.classes
|
||||
.iter()
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||
#[serde(default)]
|
||||
|
|
@ -28,7 +28,7 @@ pub struct Colors {
|
|||
#[derive(Clone, Debug, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||
pub struct LayerColors {
|
||||
default: LayerColor,
|
||||
colors: HashMap<String, LayerColor>,
|
||||
colors: BTreeMap<String, LayerColor>,
|
||||
}
|
||||
|
||||
impl LayerColors {
|
||||
|
|
@ -54,7 +54,7 @@ impl Default for Config {
|
|||
normal: egui::Color32::from_rgb(255, 255, 255),
|
||||
highlighted: egui::Color32::from_rgb(255, 255, 255),
|
||||
},
|
||||
colors: HashMap::from([
|
||||
colors: BTreeMap::from([
|
||||
(
|
||||
"F.Cu".to_string(),
|
||||
LayerColor {
|
||||
|
|
@ -106,7 +106,7 @@ impl Default for Config {
|
|||
normal: egui::Color32::from_rgb(0, 0, 0),
|
||||
highlighted: egui::Color32::from_rgb(0, 0, 0),
|
||||
},
|
||||
colors: HashMap::from([
|
||||
colors: BTreeMap::from([
|
||||
(
|
||||
"F.Cu".to_string(),
|
||||
LayerColor {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
//! structures for representing graph nodes and edges with associated metadata,
|
||||
//! as well as functions for constructing and manipulating these graphs.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use enum_dispatch::enum_dispatch;
|
||||
use geo::Point;
|
||||
|
|
@ -27,7 +27,7 @@ use crate::{
|
|||
primitive::MakePrimitiveShape,
|
||||
rules::AccessRules,
|
||||
},
|
||||
geometry::{compound::ManageCompounds, shape::AccessShape},
|
||||
geometry::shape::AccessShape,
|
||||
graph::{GenericIndex, GetPetgraphIndex},
|
||||
layout::{
|
||||
poly::{MakePolyShape, PolyWeight},
|
||||
|
|
@ -92,7 +92,7 @@ impl Ratsnest {
|
|||
graph: UnGraph::default(),
|
||||
};
|
||||
|
||||
let mut triangulations = HashMap::new();
|
||||
let mut triangulations = BTreeMap::new();
|
||||
let node_bound = layout.drawing().geometry().graph().node_bound();
|
||||
|
||||
for layer in 0..layout.drawing().layer_count() {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
use rstar::AABB;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
|
@ -10,12 +10,12 @@ use serde::{Deserialize, Serialize};
|
|||
use crate::{
|
||||
board::{mesadata::AccessMesadata, BandName, Board},
|
||||
drawing::graph::{GetLayer, MakePrimitive, PrimitiveIndex},
|
||||
geometry::{compound::ManageCompounds, GenericNode},
|
||||
geometry::GenericNode,
|
||||
graph::{GenericIndex, GetPetgraphIndex},
|
||||
layout::{poly::PolyWeight, CompoundWeight, NodeIndex},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
|
||||
pub struct PinSelector {
|
||||
pub pin: String,
|
||||
pub layer: String,
|
||||
|
|
@ -58,7 +58,7 @@ impl PinSelector {
|
|||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
pub struct PinSelection(HashSet<PinSelector>);
|
||||
pub struct PinSelection(BTreeSet<PinSelector>);
|
||||
|
||||
impl PinSelection {
|
||||
pub fn new() -> Self {
|
||||
|
|
@ -87,7 +87,7 @@ impl PinSelection {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
|
||||
pub struct BandSelector {
|
||||
pub band: BandName,
|
||||
}
|
||||
|
|
@ -118,7 +118,7 @@ impl BandSelector {
|
|||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
pub struct BandSelection(HashSet<BandSelector>);
|
||||
pub struct BandSelection(BTreeSet<BandSelector>);
|
||||
|
||||
impl BandSelection {
|
||||
pub fn new() -> Self {
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@ pub mod mesadata {
|
|||
pub use specctra_core::mesadata::AccessMesadata;
|
||||
}
|
||||
|
||||
use std::{cmp::Ordering, collections::HashMap};
|
||||
use std::{cmp::Ordering, collections::BTreeMap};
|
||||
|
||||
use bimap::BiHashMap;
|
||||
use bimap::BiBTreeMap;
|
||||
use derive_getters::Getters;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ use crate::{
|
|||
};
|
||||
|
||||
/// Represents a band between two pins.
|
||||
#[derive(Debug, Hash, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, Deserialize, Eq, PartialOrd, Ord, PartialEq, Serialize)]
|
||||
pub struct BandName(String, String);
|
||||
|
||||
impl BandName {
|
||||
|
|
@ -60,9 +60,9 @@ pub struct Board<M> {
|
|||
layout: Layout<M>,
|
||||
// TODO: Simplify access logic to these members so that `#[getter(skip)]`s can be removed.
|
||||
#[getter(skip)]
|
||||
node_to_pinname: HashMap<NodeIndex, String>,
|
||||
node_to_pinname: BTreeMap<NodeIndex, String>,
|
||||
#[getter(skip)]
|
||||
band_bandname: BiHashMap<BandUid, BandName>,
|
||||
band_bandname: BiBTreeMap<BandUid, BandName>,
|
||||
}
|
||||
|
||||
impl<M> Board<M> {
|
||||
|
|
@ -70,8 +70,8 @@ impl<M> Board<M> {
|
|||
pub fn new(layout: Layout<M>) -> Self {
|
||||
Self {
|
||||
layout,
|
||||
node_to_pinname: HashMap::new(),
|
||||
band_bandname: BiHashMap::new(),
|
||||
node_to_pinname: BTreeMap::new(),
|
||||
band_bandname: BiBTreeMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,6 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// FIXME (implement Hash for BandUid and such)
|
||||
#![allow(clippy::derived_hash_with_manual_eq)]
|
||||
|
||||
use enum_dispatch::enum_dispatch;
|
||||
use petgraph::stable_graph::NodeIndex;
|
||||
|
||||
|
|
@ -22,7 +19,7 @@ use super::{
|
|||
Drawing,
|
||||
};
|
||||
|
||||
#[derive(Debug, Hash, Clone, Copy)]
|
||||
#[derive(Clone, Copy, Debug, Ord, PartialOrd)]
|
||||
pub struct BandUid(pub BandTermsegIndex, pub BandTermsegIndex);
|
||||
|
||||
impl BandUid {
|
||||
|
|
@ -45,7 +42,7 @@ impl PartialEq for BandUid {
|
|||
impl Eq for BandUid {}
|
||||
|
||||
#[enum_dispatch(GetPetgraphIndex)]
|
||||
#[derive(Debug, Hash, Clone, Copy)]
|
||||
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||
pub enum BandTermsegIndex {
|
||||
Straight(LoneLooseSegIndex),
|
||||
Bended(SeqLooseSegIndex),
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ use crate::{
|
|||
use petgraph::stable_graph::NodeIndex;
|
||||
|
||||
#[enum_dispatch(GetPetgraphIndex, MakePrimitive)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||
pub enum BendIndex {
|
||||
Fixed(FixedBendIndex),
|
||||
Loose(LooseBendIndex),
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ use crate::{
|
|||
};
|
||||
|
||||
#[enum_dispatch(GetPetgraphIndex, MakePrimitive)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||
pub enum DotIndex {
|
||||
Fixed(FixedDotIndex),
|
||||
Loose(LooseDotIndex),
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ macro_rules! impl_loose_weight {
|
|||
// TODO: This enum shouldn't exist: we shouldn't be carrying the tag around like this. Instead we
|
||||
// should be getting it from the graph when it's needed.
|
||||
#[enum_dispatch(GetPetgraphIndex, MakePrimitive)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||
pub enum PrimitiveIndex {
|
||||
FixedDot(FixedDotIndex),
|
||||
LooseDot(LooseDotIndex),
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ use crate::{
|
|||
use petgraph::stable_graph::NodeIndex;
|
||||
|
||||
#[enum_dispatch(GetPetgraphIndex, MakePrimitive)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||
pub enum SegIndex {
|
||||
Fixed(FixedSegIndex),
|
||||
LoneLoose(LoneLooseSegIndex),
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use std::{collections::HashMap, hash::Hash, marker::PhantomData};
|
||||
use std::{collections::BTreeMap, marker::PhantomData};
|
||||
|
||||
use crate::{
|
||||
drawing::graph::{GetLayer, Retag},
|
||||
|
|
@ -17,10 +17,10 @@ pub trait ApplyGeometryEdit<
|
|||
SW: AccessSegWeight<PW> + GetLayer,
|
||||
BW: AccessBendWeight<PW> + GetLayer,
|
||||
CW: Copy,
|
||||
PI: GetPetgraphIndex + TryInto<DI> + TryInto<SI> + TryInto<BI> + Eq + Hash + Copy,
|
||||
DI: GetPetgraphIndex + Into<PI> + Eq + Hash + Copy,
|
||||
SI: GetPetgraphIndex + Into<PI> + Eq + Hash + Copy,
|
||||
BI: GetPetgraphIndex + Into<PI> + Eq + Hash + Copy,
|
||||
PI: GetPetgraphIndex + TryInto<DI> + TryInto<SI> + TryInto<BI> + Eq + Ord + Copy,
|
||||
DI: GetPetgraphIndex + Into<PI> + Eq + Ord + Copy,
|
||||
SI: GetPetgraphIndex + Into<PI> + Eq + Ord + Copy,
|
||||
BI: GetPetgraphIndex + Into<PI> + Eq + Ord + Copy,
|
||||
>
|
||||
{
|
||||
fn apply(&mut self, edit: &GeometryEdit<PW, DW, SW, BW, CW, PI, DI, SI, BI>);
|
||||
|
|
@ -28,10 +28,11 @@ pub trait ApplyGeometryEdit<
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct GeometryEdit<PW, DW, SW, BW, CW, PI, DI, SI, BI> {
|
||||
pub(super) dots: HashMap<DI, (Option<DW>, Option<DW>)>,
|
||||
pub(super) segs: HashMap<SI, (Option<((DI, DI), SW)>, Option<((DI, DI), SW)>)>,
|
||||
pub(super) bends: HashMap<BI, (Option<((DI, DI, DI), BW)>, Option<((DI, DI, DI), BW)>)>,
|
||||
pub(super) compounds: HashMap<GenericIndex<CW>, (Option<(Vec<PI>, CW)>, Option<(Vec<PI>, CW)>)>,
|
||||
pub(super) dots: BTreeMap<DI, (Option<DW>, Option<DW>)>,
|
||||
pub(super) segs: BTreeMap<SI, (Option<((DI, DI), SW)>, Option<((DI, DI), SW)>)>,
|
||||
pub(super) bends: BTreeMap<BI, (Option<((DI, DI, DI), BW)>, Option<((DI, DI, DI), BW)>)>,
|
||||
pub(super) compounds:
|
||||
BTreeMap<GenericIndex<CW>, (Option<(Vec<PI>, CW)>, Option<(Vec<PI>, CW)>)>,
|
||||
primitive_weight_marker: PhantomData<PW>,
|
||||
}
|
||||
|
||||
|
|
@ -41,18 +42,18 @@ impl<
|
|||
SW: AccessSegWeight<PW> + GetLayer,
|
||||
BW: AccessBendWeight<PW> + GetLayer,
|
||||
CW: Copy,
|
||||
PI: GetPetgraphIndex + TryInto<DI> + TryInto<SI> + TryInto<BI> + Eq + Hash + Copy,
|
||||
DI: GetPetgraphIndex + Into<PI> + Eq + Hash + Copy,
|
||||
SI: GetPetgraphIndex + Into<PI> + Eq + Hash + Copy,
|
||||
BI: GetPetgraphIndex + Into<PI> + Eq + Hash + Copy,
|
||||
PI: GetPetgraphIndex + TryInto<DI> + TryInto<SI> + TryInto<BI> + Eq + Ord + Copy,
|
||||
DI: GetPetgraphIndex + Into<PI> + Eq + Ord + Copy,
|
||||
SI: GetPetgraphIndex + Into<PI> + Eq + Ord + Copy,
|
||||
BI: GetPetgraphIndex + Into<PI> + Eq + Ord + Copy,
|
||||
> GeometryEdit<PW, DW, SW, BW, CW, PI, DI, SI, BI>
|
||||
{
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
dots: HashMap::new(),
|
||||
segs: HashMap::new(),
|
||||
bends: HashMap::new(),
|
||||
compounds: HashMap::new(),
|
||||
dots: BTreeMap::new(),
|
||||
segs: BTreeMap::new(),
|
||||
bends: BTreeMap::new(),
|
||||
compounds: BTreeMap::new(),
|
||||
primitive_weight_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ pub enum GeometryLabel {
|
|||
Compound,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)]
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
|
||||
pub enum GenericNode<P, C> {
|
||||
Primitive(P),
|
||||
Compound(C),
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use std::collections::hash_map::Entry as HashMapEntry;
|
||||
use std::hash::Hash;
|
||||
use std::collections::btree_map::Entry as BTreeMapEntry;
|
||||
|
||||
use geo::Point;
|
||||
use petgraph::stable_graph::StableDiGraph;
|
||||
|
|
@ -33,10 +32,10 @@ impl<
|
|||
SW: AccessSegWeight<PW> + GetLayer,
|
||||
BW: AccessBendWeight<PW> + GetLayer,
|
||||
CW: Copy,
|
||||
PI: GetPetgraphIndex + TryInto<DI> + TryInto<SI> + TryInto<BI> + Eq + Hash + Copy,
|
||||
DI: GetPetgraphIndex + Into<PI> + Eq + Hash + Copy,
|
||||
SI: GetPetgraphIndex + Into<PI> + Eq + Hash + Copy,
|
||||
BI: GetPetgraphIndex + Into<PI> + Eq + Hash + Copy,
|
||||
PI: GetPetgraphIndex + TryInto<DI> + TryInto<SI> + TryInto<BI> + Eq + Ord + Copy,
|
||||
DI: GetPetgraphIndex + Into<PI> + Eq + Ord + Copy,
|
||||
SI: GetPetgraphIndex + Into<PI> + Eq + Ord + Copy,
|
||||
BI: GetPetgraphIndex + Into<PI> + Eq + Ord + Copy,
|
||||
> RecordingGeometryWithRtree<PW, DW, SW, BW, CW, PI, DI, SI, BI>
|
||||
{
|
||||
pub fn new(layer_count: usize) -> Self {
|
||||
|
|
@ -316,23 +315,23 @@ impl<
|
|||
}
|
||||
}
|
||||
|
||||
fn edit_remove_from_map<I, T>(
|
||||
map: &mut std::collections::HashMap<I, (Option<T>, Option<T>)>,
|
||||
fn edit_remove_from_map<I: Ord, T>(
|
||||
map: &mut std::collections::BTreeMap<I, (Option<T>, Option<T>)>,
|
||||
index: I,
|
||||
data: T,
|
||||
) where
|
||||
I: core::cmp::Eq + Hash,
|
||||
I: core::cmp::Eq + Ord,
|
||||
{
|
||||
let to_be_inserted = (Some(data), None);
|
||||
match map.entry(index) {
|
||||
HashMapEntry::Occupied(mut occ) => {
|
||||
BTreeMapEntry::Occupied(mut occ) => {
|
||||
if let (None, Some(_)) = occ.get() {
|
||||
occ.remove();
|
||||
} else {
|
||||
*occ.get_mut() = to_be_inserted;
|
||||
}
|
||||
}
|
||||
HashMapEntry::Vacant(vac) => {
|
||||
BTreeMapEntry::Vacant(vac) => {
|
||||
vac.insert(to_be_inserted);
|
||||
}
|
||||
}
|
||||
|
|
@ -344,10 +343,10 @@ impl<
|
|||
SW: AccessSegWeight<PW> + GetLayer,
|
||||
BW: AccessBendWeight<PW> + GetLayer,
|
||||
CW: Copy,
|
||||
PI: GetPetgraphIndex + TryInto<DI> + TryInto<SI> + TryInto<BI> + Eq + Hash + Copy,
|
||||
DI: GetPetgraphIndex + Into<PI> + Eq + Hash + Copy,
|
||||
SI: GetPetgraphIndex + Into<PI> + Eq + Hash + Copy,
|
||||
BI: GetPetgraphIndex + Into<PI> + Eq + Hash + Copy,
|
||||
PI: GetPetgraphIndex + TryInto<DI> + TryInto<SI> + TryInto<BI> + Eq + Ord + Copy,
|
||||
DI: GetPetgraphIndex + Into<PI> + Eq + Ord + Copy,
|
||||
SI: GetPetgraphIndex + Into<PI> + Eq + Ord + Copy,
|
||||
BI: GetPetgraphIndex + Into<PI> + Eq + Ord + Copy,
|
||||
> ApplyGeometryEdit<PW, DW, SW, BW, CW, PI, DI, SI, BI>
|
||||
for RecordingGeometryWithRtree<PW, DW, SW, BW, CW, PI, DI, SI, BI>
|
||||
{
|
||||
|
|
|
|||
20
src/graph.rs
20
src/graph.rs
|
|
@ -2,10 +2,7 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use std::{
|
||||
hash::{Hash, Hasher},
|
||||
marker::PhantomData,
|
||||
};
|
||||
use std::{cmp::Ordering, marker::PhantomData};
|
||||
|
||||
use enum_dispatch::enum_dispatch;
|
||||
use petgraph::stable_graph::NodeIndex;
|
||||
|
|
@ -50,6 +47,8 @@ impl<W> core::clone::Clone for GenericIndex<W> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<W> core::marker::Copy for GenericIndex<W> {}
|
||||
|
||||
impl<W> core::fmt::Debug for GenericIndex<W> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
f.debug_tuple("GenericIndex")
|
||||
|
|
@ -65,12 +64,17 @@ impl<W> PartialEq for GenericIndex<W> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<W> core::marker::Copy for GenericIndex<W> {}
|
||||
impl<W> Eq for GenericIndex<W> {}
|
||||
|
||||
impl<W> Hash for GenericIndex<W> {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.node_index.hash(state)
|
||||
impl<W> PartialOrd for GenericIndex<W> {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
self.node_index.partial_cmp(&other.node_index)
|
||||
}
|
||||
}
|
||||
|
||||
impl<W> Ord for GenericIndex<W> {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.node_index.cmp(&other.node_index)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,10 +3,8 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||
use std::collections::{BinaryHeap, HashMap, VecDeque};
|
||||
use std::collections::{btree_map::Entry, BTreeMap, BinaryHeap, VecDeque};
|
||||
|
||||
use std::hash::Hash;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
use petgraph::algo::Measure;
|
||||
|
|
@ -63,19 +61,19 @@ impl<K: PartialOrd, T> Ord for MinScored<K, T> {
|
|||
pub struct PathTracker<G>
|
||||
where
|
||||
G: GraphBase,
|
||||
G::NodeId: Eq + Hash,
|
||||
G::NodeId: Eq + Ord,
|
||||
{
|
||||
came_from: HashMap<G::NodeId, G::NodeId>,
|
||||
came_from: BTreeMap<G::NodeId, G::NodeId>,
|
||||
}
|
||||
|
||||
impl<G> PathTracker<G>
|
||||
where
|
||||
G: GraphBase,
|
||||
G::NodeId: Eq + Hash,
|
||||
G::NodeId: Eq + Ord,
|
||||
{
|
||||
fn new() -> PathTracker<G> {
|
||||
PathTracker {
|
||||
came_from: HashMap::new(),
|
||||
came_from: BTreeMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -101,7 +99,7 @@ where
|
|||
pub trait AstarStrategy<G, K, R>
|
||||
where
|
||||
G: GraphBase,
|
||||
G::NodeId: Eq + Hash,
|
||||
G::NodeId: Eq + Ord,
|
||||
for<'a> &'a G: IntoEdges<NodeId = G::NodeId, EdgeId = G::EdgeId> + MakeEdgeRef,
|
||||
K: Measure + Copy,
|
||||
{
|
||||
|
|
@ -122,14 +120,14 @@ pub trait MakeEdgeRef: IntoEdgeReferences {
|
|||
pub struct Astar<G, K>
|
||||
where
|
||||
G: GraphBase,
|
||||
G::NodeId: Eq + Hash,
|
||||
G::NodeId: Eq + Ord,
|
||||
for<'a> &'a G: IntoEdges<NodeId = G::NodeId, EdgeId = G::EdgeId> + MakeEdgeRef,
|
||||
K: Measure + Copy,
|
||||
{
|
||||
pub graph: G,
|
||||
pub visit_next: BinaryHeap<MinScored<K, G::NodeId>>,
|
||||
pub scores: HashMap<G::NodeId, K>,
|
||||
pub estimate_scores: HashMap<G::NodeId, K>,
|
||||
pub scores: BTreeMap<G::NodeId, K>,
|
||||
pub estimate_scores: BTreeMap<G::NodeId, K>,
|
||||
pub path_tracker: PathTracker<G>,
|
||||
pub maybe_curr_node: Option<G::NodeId>,
|
||||
// FIXME: To work around edge references borrowing from the graph we collect then reiterate over tem.
|
||||
|
|
@ -154,7 +152,7 @@ pub enum AstarError {
|
|||
impl<G, K> Astar<G, K>
|
||||
where
|
||||
G: GraphBase,
|
||||
G::NodeId: Eq + Hash,
|
||||
G::NodeId: Eq + Ord,
|
||||
for<'a> &'a G: IntoEdges<NodeId = G::NodeId, EdgeId = G::EdgeId> + MakeEdgeRef,
|
||||
K: Measure + Copy,
|
||||
{
|
||||
|
|
@ -162,8 +160,8 @@ where
|
|||
let mut this = Self {
|
||||
graph,
|
||||
visit_next: BinaryHeap::new(),
|
||||
scores: HashMap::new(),
|
||||
estimate_scores: HashMap::new(),
|
||||
scores: BTreeMap::new(),
|
||||
estimate_scores: BTreeMap::new(),
|
||||
path_tracker: PathTracker::<G>::new(),
|
||||
maybe_curr_node: None,
|
||||
edge_ids: VecDeque::new(),
|
||||
|
|
@ -182,7 +180,7 @@ impl<G, K, R, S: AstarStrategy<G, K, R>> Step<S, (K, Vec<G::NodeId>, R), AstarCo
|
|||
for Astar<G, K>
|
||||
where
|
||||
G: GraphBase,
|
||||
G::NodeId: Eq + Hash,
|
||||
G::NodeId: Eq + Ord,
|
||||
for<'a> &'a G: IntoEdges<NodeId = G::NodeId, EdgeId = G::EdgeId> + MakeEdgeRef,
|
||||
K: Measure + Copy,
|
||||
{
|
||||
|
|
@ -209,7 +207,7 @@ where
|
|||
let next_score = node_score + edge_cost;
|
||||
|
||||
match self.scores.entry(next) {
|
||||
Occupied(mut entry) => {
|
||||
Entry::Occupied(mut entry) => {
|
||||
// No need to add neighbors that we have already reached through a
|
||||
// shorter path than now.
|
||||
if *entry.get() <= next_score {
|
||||
|
|
@ -217,7 +215,7 @@ where
|
|||
}
|
||||
entry.insert(next_score);
|
||||
}
|
||||
Vacant(entry) => {
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(next_score);
|
||||
}
|
||||
}
|
||||
|
|
@ -248,7 +246,7 @@ where
|
|||
}
|
||||
|
||||
match self.estimate_scores.entry(node) {
|
||||
Occupied(mut entry) => {
|
||||
Entry::Occupied(mut entry) => {
|
||||
// If the node has already been visited with an equal or lower score than
|
||||
// now, then we do not need to re-visit it.
|
||||
if *entry.get() <= estimate_score {
|
||||
|
|
@ -256,7 +254,7 @@ where
|
|||
}
|
||||
entry.insert(estimate_score);
|
||||
}
|
||||
Vacant(entry) => {
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(estimate_score);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use enum_dispatch::enum_dispatch;
|
||||
use geo::Point;
|
||||
|
|
@ -37,7 +37,7 @@ use crate::{
|
|||
|
||||
use super::RouterOptions;
|
||||
|
||||
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||
pub struct NavvertexIndex(NodeIndex<usize>);
|
||||
|
||||
impl GetPetgraphIndex for NavvertexIndex {
|
||||
|
|
@ -50,7 +50,7 @@ impl GetPetgraphIndex for NavvertexIndex {
|
|||
/// counterclockwise. Unlike their constituents, binavvertices are themselves
|
||||
/// not considered navvertices.
|
||||
#[enum_dispatch(GetPetgraphIndex, MakePrimitive)]
|
||||
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum BinavvertexNodeIndex {
|
||||
FixedDot(FixedDotIndex),
|
||||
FixedBend(FixedBendIndex),
|
||||
|
|
@ -84,7 +84,7 @@ impl From<BinavvertexNodeIndex> for GearIndex {
|
|||
///
|
||||
/// The name "trianvertex" is a shortening of "triangulation vertex".
|
||||
#[enum_dispatch(GetPetgraphIndex, MakePrimitive)]
|
||||
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||
enum TrianvertexNodeIndex {
|
||||
FixedDot(FixedDotIndex),
|
||||
FixedBend(FixedBendIndex),
|
||||
|
|
@ -210,8 +210,7 @@ impl Navmesh {
|
|||
let mut origin_navvertex = None;
|
||||
let mut destination_navvertex = None;
|
||||
|
||||
// `HashMap` is obviously suboptimal here.
|
||||
let mut map = HashMap::new();
|
||||
let mut map = BTreeMap::new();
|
||||
|
||||
for trianvertex in triangulation.node_identifiers() {
|
||||
if trianvertex == origin.into() {
|
||||
|
|
@ -302,7 +301,7 @@ impl Navmesh {
|
|||
|
||||
fn add_node_to_graph_and_map_as_binavvertex(
|
||||
graph: &mut UnGraph<NavvertexWeight, (), usize>,
|
||||
map: &mut HashMap<TrianvertexNodeIndex, Vec<(NodeIndex<usize>, NodeIndex<usize>)>>,
|
||||
map: &mut BTreeMap<TrianvertexNodeIndex, Vec<(NodeIndex<usize>, NodeIndex<usize>)>>,
|
||||
trianvertex: TrianvertexNodeIndex,
|
||||
node: BinavvertexNodeIndex,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@
|
|||
//! Design DSN file, creating the [`Board`] object from the file, as well as
|
||||
//! exporting the session file
|
||||
|
||||
use std::collections::{btree_map::Entry as BTreeMapEntry, BTreeMap};
|
||||
|
||||
use geo::{point, Point, Rotate};
|
||||
use std::collections::{hash_map::Entry as HashMapEntry, HashMap};
|
||||
|
||||
use crate::{
|
||||
board::{mesadata::AccessMesadata, Board},
|
||||
|
|
@ -73,7 +74,7 @@ impl SpecctraDesign {
|
|||
let mesadata = board.mesadata();
|
||||
let drawing = board.layout().drawing();
|
||||
|
||||
let mut net_outs = HashMap::<usize, structure::NetOut>::new();
|
||||
let mut net_outs = BTreeMap::<usize, structure::NetOut>::new();
|
||||
for index in drawing.primitive_nodes() {
|
||||
let primitive = index.primitive(drawing);
|
||||
|
||||
|
|
@ -131,8 +132,8 @@ impl SpecctraDesign {
|
|||
};
|
||||
|
||||
let net_out = match net_outs.entry(net) {
|
||||
HashMapEntry::Occupied(occ) => occ.into_mut(),
|
||||
HashMapEntry::Vacant(vac) => vac.insert(structure::NetOut {
|
||||
BTreeMapEntry::Occupied(occ) => occ.into_mut(),
|
||||
BTreeMapEntry::Vacant(vac) => vac.insert(structure::NetOut {
|
||||
name: mesadata
|
||||
.net_netname(net)
|
||||
.ok_or_else(|| {
|
||||
|
|
@ -208,7 +209,7 @@ impl SpecctraDesign {
|
|||
})
|
||||
// flatten the nested iters into a single stream of tuples
|
||||
.flatten()
|
||||
.collect::<HashMap<String, usize>>();
|
||||
.collect::<BTreeMap<String, usize>>();
|
||||
|
||||
// add pins from components
|
||||
for component in &self.pcb.placement.components {
|
||||
|
|
|
|||
Loading…
Reference in New Issue