Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 102 additions & 10 deletions lib/solvers/PortPointPathingSolver/PortPointPathingSolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import {
cloneAndShuffleArray,
seededRandom,
} from "lib/utils/cloneAndShuffleArray"
import { computeFeaturesForMl } from "scripts/ml-data-collection/ml-data-collection-features"
import { predictHighDensitySolverSuccess } from "scripts/ml-data-collection/hd_solver_predictor"

export interface PortPointPathingHyperParameters {
SHUFFLE_SEED?: number
Expand Down Expand Up @@ -297,14 +299,25 @@ export class PortPointPathingSolver extends BaseSolver {
}

/** Base node cost with the currently-committed port points (no candidate additions) */
private getBaseNodeFailureCost(nodeId: CapacityMeshNodeId): number {
private getBaseNodeFailureCost(
nodeId: CapacityMeshNodeId,
connectionsWithResults: ConnectionPathResult[],
alreadyConnectedPath: PortPoint[],
): number {
const cached = this.baseNodeCostCache.get(nodeId)
if (cached != null) return cached

const node = this.nodeMap.get(nodeId)
if (!node) return 0

const pfBefore = this.computeNodePf(node)
// NOTE: connectionsWithResults and alreadyConnectedPath are accepted but
// currently ignored in the Pf calculation. They are reserved for future
// improvements where Pf may depend on more global path context.
const pfBefore = this.computeNodePf(
node,
connectionsWithResults,
alreadyConnectedPath,
)
const baseCost = this.pfToFailureCost(pfBefore)
this.baseNodeCostCache.set(nodeId, baseCost)
return baseCost
Expand All @@ -322,6 +335,8 @@ export class PortPointPathingSolver extends BaseSolver {
nodeId: CapacityMeshNodeId,
entry: PortPoint,
exit: PortPoint,
connectionsWithResults: ConnectionPathResult[],
alreadyConnectedPath: PortPoint[],
): number {
const key = `${nodeId}|${this.pointKey(
{ x: entry.x, y: entry.y },
Expand All @@ -337,9 +352,18 @@ export class PortPointPathingSolver extends BaseSolver {
const node = this.nodeMap.get(nodeId)
if (!node) return 0

const baseCost = this.getBaseNodeFailureCost(nodeId)
const baseCost = this.getBaseNodeFailureCost(
nodeId,
connectionsWithResults,
alreadyConnectedPath,
)

const pfAfter = this.computeNodePf(node, [entry, exit])
const pfAfter = this.computeNodePf(
node,
connectionsWithResults,
alreadyConnectedPath,
[entry, exit],
)
const afterCost = this.pfToFailureCost(pfAfter)

// If the estimator ever yields a lower Pf after adding points, don't reward it here.
Expand Down Expand Up @@ -433,6 +457,8 @@ export class PortPointPathingSolver extends BaseSolver {
*/
computeNodePf(
node: InputNodeWithPortPoints,
connectionsWithResults: ConnectionPathResult[],
alreadyConnectedPath: PortPoint[],
additionalPortPoints?: PortPoint[],
): number {
if (node._containsTarget) return 0
Expand All @@ -443,12 +469,47 @@ export class PortPointPathingSolver extends BaseSolver {
)
const crossings = getIntraNodeCrossings(nodeWithPortPoints)

return calculateNodeProbabilityOfFailure(
this.capacityMeshNodeMap.get(node.capacityMeshNodeId)!,
crossings.numSameLayerCrossings,
crossings.numEntryExitLayerChanges,
crossings.numTransitionPairCrossings,
)
// TODO: use this features to make a good ml estimator for Pf
const features = computeFeaturesForMl({
numEntryExitLayerChanges: crossings.numEntryExitLayerChanges,
numSameLayerCrossings: crossings.numSameLayerCrossings,
numTransitionPairCrossings: crossings.numTransitionPairCrossings,
node,
traceWidth: this.simpleRouteJson.minTraceWidth ?? 0.15,
viaSize: this.simpleRouteJson.minViaDiameter ?? 0.6,
connectionsWithResults,
alreadyConnectedPath,
})

const cost =
crossings.numEntryExitLayerChanges +
crossings.numSameLayerCrossings +
crossings.numTransitionPairCrossings

return predictHighDensitySolverSuccess({
totalCrossingsNormalizedToArea:
features.total_crossings_normalized_to_area,
entryExitLayerChangesNormalizedToArea:
features.entry_exit_layer_changes_normalized_to_area,
singleViaAreaNormalizedToArea:
features.single_via_area_normalized_to_area,
twoViaAreaNormalizedToArea: features.two_via_area_normalized_to_area,
transitionPairCrossingsNormalizedToArea:
features.transition_pair_crossings_normalized_to_area,
cost,
viaDiameterNormalizedToMinSide:
features.via_diameter_normalized_to_min_side,
traceWidthNormalizedToMinSide:
features.trace_width_normalized_to_min_side,
transitionPairCrossingsFractionOfTotal:
features.transition_pair_crossings_fraction_of_total,
transitionPairCrossingsNormalizedToTraceWidth:
features.transition_pair_crossings_normalized_to_trace_width,
entryExitLayerChangesNormalizedToTraceWidth:
features.entry_exit_layer_changes_normalized_to_trace_width,
entryExitLayerChangesFractionOfTotal:
features.entry_exit_layer_changes_fraction_of_total,
})
}

/**
Expand Down Expand Up @@ -478,6 +539,21 @@ export class PortPointPathingSolver extends BaseSolver {
return null
}

private buildAlreadyConnectedPath(
candidate: PortPointCandidate,
connectionName: string,
rootConnectionName?: string,
): PortPoint[] {
const pathCandidates = this.getBacktrackedPath(candidate)
return pathCandidates.map((c) => ({
x: c.point.x,
y: c.point.y,
z: c.z,
connectionName,
rootConnectionName,
}))
}

/**
* Exact step cost from prevCandidate to exiting current node via `exitPortPoint`.
*
Expand Down Expand Up @@ -515,10 +591,18 @@ export class PortPointPathingSolver extends BaseSolver {
rootConnectionName,
}

const alreadyConnectedPath = this.buildAlreadyConnectedPath(
prevCandidate,
connectionName,
rootConnectionName,
)

const nodeDeltaCost = this.getNodeDeltaFailureCostForSegment(
leavingNodeId,
entry,
exit,
this.connectionsWithResults,
alreadyConnectedPath,
)

const reusePenalty = this.getPortPointReusePenalty(
Expand Down Expand Up @@ -572,10 +656,18 @@ export class PortPointPathingSolver extends BaseSolver {
rootConnectionName,
}

const alreadyConnectedPath = this.buildAlreadyConnectedPath(
candidateAtEndNode,
connectionName,
rootConnectionName,
)

const nodeDeltaCost = this.getNodeDeltaFailureCostForSegment(
endNodeId,
entry,
exit,
this.connectionsWithResults,
alreadyConnectedPath,
)

return (
Expand Down
Loading