mirror of https://codeberg.org/topola/topola.git
refactor(autorouter/autoroute): Move permutator to new file, `permutator.rs`
This commit is contained in:
parent
e5e5f9513e
commit
f99f31e356
|
|
@ -25,6 +25,7 @@ allowed_scopes = [
|
||||||
"autorouter/history",
|
"autorouter/history",
|
||||||
"autorouter/invoker",
|
"autorouter/invoker",
|
||||||
"autorouter/measure_length",
|
"autorouter/measure_length",
|
||||||
|
"autorouter/permutator",
|
||||||
"autorouter/place_via",
|
"autorouter/place_via",
|
||||||
"autorouter/pointroute",
|
"autorouter/pointroute",
|
||||||
"autorouter/ratsnest",
|
"autorouter/ratsnest",
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,7 @@
|
||||||
//! Manages autorouting of ratlines in a layout, tracking status and processed
|
//! Manages autorouting of ratlines in a layout, tracking status and processed
|
||||||
//! routing steps.
|
//! routing steps.
|
||||||
|
|
||||||
use itertools::{Itertools, Permutations};
|
use std::ops::ControlFlow;
|
||||||
use std::{iter::Skip, ops::ControlFlow};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
board::{
|
board::{
|
||||||
|
|
@ -20,7 +19,7 @@ use crate::{
|
||||||
router::{
|
router::{
|
||||||
navcord::Navcord, navmesh::Navmesh, thetastar::ThetastarStepper, RouteStepper, Router,
|
navcord::Navcord, navmesh::Navmesh, thetastar::ThetastarStepper, RouteStepper, Router,
|
||||||
},
|
},
|
||||||
stepper::{Abort, EstimateProgress, Permute, Step},
|
stepper::{Abort, EstimateProgress, Permutate, Step},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
|
|
@ -224,11 +223,11 @@ impl<M: AccessMesadata> Abort<Autorouter<M>> for AutorouteExecutionStepper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M: AccessMesadata> Permute<Autorouter<M>> for AutorouteExecutionStepper {
|
impl<M: AccessMesadata> Permutate<Autorouter<M>> for AutorouteExecutionStepper {
|
||||||
type Index = RatlineIndex;
|
type Index = RatlineIndex;
|
||||||
type Output = Result<(), AutorouterError>;
|
type Output = Result<(), AutorouterError>;
|
||||||
|
|
||||||
fn permute(
|
fn permutate(
|
||||||
&mut self,
|
&mut self,
|
||||||
autorouter: &mut Autorouter<M>,
|
autorouter: &mut Autorouter<M>,
|
||||||
permutation: Vec<RatlineIndex>,
|
permutation: Vec<RatlineIndex>,
|
||||||
|
|
@ -277,99 +276,3 @@ impl GetDebugOverlayData for AutorouteExecutionStepper {
|
||||||
self.route.as_ref().map_or(&[], |route| route.obstacles())
|
self.route.as_ref().map_or(&[], |route| route.obstacles())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AutorouteExecutionPermutator {
|
|
||||||
stepper: AutorouteExecutionStepper,
|
|
||||||
permutations_iter: Skip<Permutations<std::vec::IntoIter<RatlineIndex>>>,
|
|
||||||
options: AutorouterOptions,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AutorouteExecutionPermutator {
|
|
||||||
pub fn new(
|
|
||||||
autorouter: &mut Autorouter<impl AccessMesadata>,
|
|
||||||
ratlines: Vec<RatlineIndex>,
|
|
||||||
options: AutorouterOptions,
|
|
||||||
) -> Result<Self, AutorouterError> {
|
|
||||||
let ratlines_len = ratlines.len();
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
stepper: AutorouteExecutionStepper::new(autorouter, ratlines.clone(), options)?,
|
|
||||||
// Note: I assume here that the first permutation is the same as the original order.
|
|
||||||
permutations_iter: ratlines.into_iter().permutations(ratlines_len).skip(1),
|
|
||||||
options,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<M: AccessMesadata> Step<Autorouter<M>, Option<BoardEdit>, AutorouteContinueStatus>
|
|
||||||
for AutorouteExecutionPermutator
|
|
||||||
{
|
|
||||||
type Error = AutorouterError;
|
|
||||||
|
|
||||||
fn step(
|
|
||||||
&mut self,
|
|
||||||
autorouter: &mut Autorouter<M>,
|
|
||||||
) -> Result<ControlFlow<Option<BoardEdit>, AutorouteContinueStatus>, AutorouterError> {
|
|
||||||
match self.stepper.step(autorouter) {
|
|
||||||
Ok(ok) => Ok(ok),
|
|
||||||
Err(err) => {
|
|
||||||
if !self.options.permutate {
|
|
||||||
return Err(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let Some(permutation) = self.permutations_iter.next() else {
|
|
||||||
return Ok(ControlFlow::Break(None));
|
|
||||||
};
|
|
||||||
|
|
||||||
match self.stepper.permute(autorouter, permutation) {
|
|
||||||
Ok(()) => break,
|
|
||||||
Err(AutorouterError::NothingToUndoForPermutation) => continue,
|
|
||||||
Err(err) => return Err(err),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.stepper.step(autorouter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<M: AccessMesadata> Abort<Autorouter<M>> for AutorouteExecutionPermutator {
|
|
||||||
fn abort(&mut self, autorouter: &mut Autorouter<M>) {
|
|
||||||
self.permutations_iter.all(|_| true);
|
|
||||||
self.stepper.abort(autorouter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EstimateProgress for AutorouteExecutionPermutator {
|
|
||||||
type Value = f64;
|
|
||||||
|
|
||||||
fn estimate_progress_value(&self) -> f64 {
|
|
||||||
// TODO.
|
|
||||||
self.stepper.estimate_progress_value()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn estimate_progress_maximum(&self) -> f64 {
|
|
||||||
// TODO.
|
|
||||||
self.stepper.estimate_progress_maximum()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetDebugOverlayData for AutorouteExecutionPermutator {
|
|
||||||
fn maybe_thetastar(&self) -> Option<&ThetastarStepper<Navmesh, f64>> {
|
|
||||||
self.stepper.maybe_thetastar()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn maybe_navcord(&self) -> Option<&Navcord> {
|
|
||||||
self.stepper.maybe_navcord()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ghosts(&self) -> &[PrimitiveShape] {
|
|
||||||
self.stepper.ghosts()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn obstacles(&self) -> &[PrimitiveIndex] {
|
|
||||||
self.stepper.obstacles()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ use std::{cmp::Ordering, collections::BTreeSet};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
autorouter::permutator::AutorouteExecutionPermutator,
|
||||||
board::{AccessMesadata, Board},
|
board::{AccessMesadata, Board},
|
||||||
drawing::{band::BandTermsegIndex, Infringement},
|
drawing::{band::BandTermsegIndex, Infringement},
|
||||||
geometry::shape::MeasureLength,
|
geometry::shape::MeasureLength,
|
||||||
|
|
@ -22,7 +23,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
autoroute::{AutorouteExecutionPermutator, AutorouteExecutionStepper},
|
autoroute::AutorouteExecutionStepper,
|
||||||
compare_detours::CompareDetoursExecutionStepper,
|
compare_detours::CompareDetoursExecutionStepper,
|
||||||
measure_length::MeasureLengthExecutionStepper,
|
measure_length::MeasureLengthExecutionStepper,
|
||||||
place_via::PlaceViaExecutionStepper,
|
place_via::PlaceViaExecutionStepper,
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ use enum_dispatch::enum_dispatch;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
autorouter::permutator::AutorouteExecutionPermutator,
|
||||||
board::{edit::BoardEdit, AccessMesadata},
|
board::{edit::BoardEdit, AccessMesadata},
|
||||||
layout::via::ViaWeight,
|
layout::via::ViaWeight,
|
||||||
router::ng,
|
router::ng,
|
||||||
|
|
@ -15,7 +16,6 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
autoroute::AutorouteExecutionPermutator,
|
|
||||||
compare_detours::CompareDetoursExecutionStepper,
|
compare_detours::CompareDetoursExecutionStepper,
|
||||||
invoker::{GetDebugOverlayData, Invoker, InvokerError},
|
invoker::{GetDebugOverlayData, Invoker, InvokerError},
|
||||||
measure_length::MeasureLengthExecutionStepper,
|
measure_length::MeasureLengthExecutionStepper,
|
||||||
|
|
|
||||||
|
|
@ -28,11 +28,11 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
autoroute::AutorouteExecutionPermutator,
|
|
||||||
compare_detours::CompareDetoursExecutionStepper,
|
compare_detours::CompareDetoursExecutionStepper,
|
||||||
execution::{Command, ExecutionStepper},
|
execution::{Command, ExecutionStepper},
|
||||||
history::{History, HistoryError},
|
history::{History, HistoryError},
|
||||||
measure_length::MeasureLengthExecutionStepper,
|
measure_length::MeasureLengthExecutionStepper,
|
||||||
|
permutator::AutorouteExecutionPermutator,
|
||||||
place_via::PlaceViaExecutionStepper,
|
place_via::PlaceViaExecutionStepper,
|
||||||
remove_bands::RemoveBandsExecutionStepper,
|
remove_bands::RemoveBandsExecutionStepper,
|
||||||
Autorouter, AutorouterError,
|
Autorouter, AutorouterError,
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
//! Manages autorouting process, under work for now
|
|
||||||
|
|
||||||
pub mod autoroute;
|
pub mod autoroute;
|
||||||
mod autorouter;
|
mod autorouter;
|
||||||
pub mod compare_detours;
|
pub mod compare_detours;
|
||||||
|
|
@ -11,6 +9,7 @@ pub mod execution;
|
||||||
pub mod history;
|
pub mod history;
|
||||||
pub mod invoker;
|
pub mod invoker;
|
||||||
pub mod measure_length;
|
pub mod measure_length;
|
||||||
|
pub mod permutator;
|
||||||
pub mod place_via;
|
pub mod place_via;
|
||||||
pub mod pointroute;
|
pub mod pointroute;
|
||||||
pub mod ratline;
|
pub mod ratline;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
// SPDX-FileCopyrightText: 2025 Topola contributors
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
use std::{iter::Skip, ops::ControlFlow};
|
||||||
|
|
||||||
|
use itertools::{Itertools, Permutations};
|
||||||
|
use specctra_core::mesadata::AccessMesadata;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
autorouter::{
|
||||||
|
autoroute::{AutorouteContinueStatus, AutorouteExecutionStepper},
|
||||||
|
invoker::GetDebugOverlayData,
|
||||||
|
ratline::RatlineIndex,
|
||||||
|
Autorouter, AutorouterError, AutorouterOptions,
|
||||||
|
},
|
||||||
|
board::edit::BoardEdit,
|
||||||
|
drawing::graph::PrimitiveIndex,
|
||||||
|
geometry::primitive::PrimitiveShape,
|
||||||
|
router::{navcord::Navcord, navmesh::Navmesh, thetastar::ThetastarStepper},
|
||||||
|
stepper::{Abort, EstimateProgress, Permutate, Step},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct AutorouteExecutionPermutator {
|
||||||
|
stepper: AutorouteExecutionStepper,
|
||||||
|
permutations_iter: Skip<Permutations<std::vec::IntoIter<RatlineIndex>>>,
|
||||||
|
options: AutorouterOptions,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AutorouteExecutionPermutator {
|
||||||
|
pub fn new(
|
||||||
|
autorouter: &mut Autorouter<impl AccessMesadata>,
|
||||||
|
ratlines: Vec<RatlineIndex>,
|
||||||
|
options: AutorouterOptions,
|
||||||
|
) -> Result<Self, AutorouterError> {
|
||||||
|
let ratlines_len = ratlines.len();
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
stepper: AutorouteExecutionStepper::new(autorouter, ratlines.clone(), options)?,
|
||||||
|
// Note: I assume here that the first permutation is the same as the original order.
|
||||||
|
permutations_iter: ratlines.into_iter().permutations(ratlines_len).skip(1),
|
||||||
|
options,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<M: AccessMesadata> Step<Autorouter<M>, Option<BoardEdit>, AutorouteContinueStatus>
|
||||||
|
for AutorouteExecutionPermutator
|
||||||
|
{
|
||||||
|
type Error = AutorouterError;
|
||||||
|
|
||||||
|
fn step(
|
||||||
|
&mut self,
|
||||||
|
autorouter: &mut Autorouter<M>,
|
||||||
|
) -> Result<ControlFlow<Option<BoardEdit>, AutorouteContinueStatus>, AutorouterError> {
|
||||||
|
match self.stepper.step(autorouter) {
|
||||||
|
Ok(ok) => Ok(ok),
|
||||||
|
Err(err) => {
|
||||||
|
if !self.options.permutate {
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let Some(permutation) = self.permutations_iter.next() else {
|
||||||
|
return Ok(ControlFlow::Break(None));
|
||||||
|
};
|
||||||
|
|
||||||
|
match self.stepper.permutate(autorouter, permutation) {
|
||||||
|
Ok(()) => break,
|
||||||
|
Err(AutorouterError::NothingToUndoForPermutation) => continue,
|
||||||
|
Err(err) => return Err(err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.stepper.step(autorouter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<M: AccessMesadata> Abort<Autorouter<M>> for AutorouteExecutionPermutator {
|
||||||
|
fn abort(&mut self, autorouter: &mut Autorouter<M>) {
|
||||||
|
self.permutations_iter.all(|_| true);
|
||||||
|
self.stepper.abort(autorouter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EstimateProgress for AutorouteExecutionPermutator {
|
||||||
|
type Value = f64;
|
||||||
|
|
||||||
|
fn estimate_progress_value(&self) -> f64 {
|
||||||
|
// TODO.
|
||||||
|
self.stepper.estimate_progress_value()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn estimate_progress_maximum(&self) -> f64 {
|
||||||
|
// TODO.
|
||||||
|
self.stepper.estimate_progress_maximum()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GetDebugOverlayData for AutorouteExecutionPermutator {
|
||||||
|
fn maybe_thetastar(&self) -> Option<&ThetastarStepper<Navmesh, f64>> {
|
||||||
|
self.stepper.maybe_thetastar()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn maybe_navcord(&self) -> Option<&Navcord> {
|
||||||
|
self.stepper.maybe_navcord()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ghosts(&self) -> &[PrimitiveShape] {
|
||||||
|
self.stepper.ghosts()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn obstacles(&self) -> &[PrimitiveIndex] {
|
||||||
|
self.stepper.obstacles()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -54,11 +54,11 @@ pub trait Abort<Ctx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Some steppers may be permuted from their initial order.
|
/// Some steppers may be permuted from their initial order.
|
||||||
pub trait Permute<Ctx> {
|
pub trait Permutate<Ctx> {
|
||||||
type Index;
|
type Index;
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
fn permute(&mut self, context: &mut Ctx, ordering: Vec<Self::Index>) -> Self::Output;
|
fn permutate(&mut self, context: &mut Ctx, ordering: Vec<Self::Index>) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Steppers that can receive discrete events and act on them implement this
|
/// Steppers that can receive discrete events and act on them implement this
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue