Skip to content

eosfor/PSGraph

Repository files navigation

PSGraph

PowerShell GalleryCILicence

PSGraph is a PowerShell-first wrapper around the ⚡ QuickGraph / QuikGraph ecosystem.
It lets you build, query and visualise graphs directly from the pipeline without dropping down to C# or external tools. Think LINQ for graphs – but in PowerShell.

Visualization note: PSGraph now keeps graph construction, algorithms, Graphviz/DOT, GraphML, and DSM logic. Visual rendering has moved to the sibling PSGraphView project. PSGraph no longer serves as a compatibility entry point for Vega, MSAGL, or DSM view rendering.


Why another graph module?

QuickGraph/QuikGraph gives .NET a battle-tested set of graph data-structures and algorithms (DFS, BFS, Dijkstra, min-cut, spanning-tree, etc.)

PSGraph layers PowerShell ergonomics, discoverability and visualisation on top so that:

  • You can pipe any object collection into a graph, specify what constitutes vertices and edges, and explore the relationships immediately.
  • Results stay as native objects – ideal for further CLI processing, reporting or automation.

The original goal was to analyse dependencies in IaC workloads, but the module has proven handy for network flows, security events, configuration drift


Features at a glance

What you get
Idiomatic cmdlets New-Graph, Add-Vertex, Add-Edge, Get-GraphPath, New-DSM, …
Ready-made algorithms All algorithms exposed by QuikGraph are one cmdlet away.
Visualization split Keep Graphviz / GraphML export in PSGraph; use PSGraphView for Vega / MSAGL / DSM rendering.
Pipeline-friendly Import from GraphML, CSV, JSON, Matrix Market; export to Graphviz DOT and GraphML.
Test-driven Over 100 Pester tests ensure every cmdlet does what it says.
Cross-platform Runs anywhere PowerShell 7+ does (Windows, Linux, macOS).

Release validation

PSGraph has two validation contours:

  • Source-built validation runs .NET and Pester tests from the repository build output.
  • Gallery-installed validation installs PSQuickGraph from PSGallery on Linux, Windows, and macOS, imports the installed module, runs smoke checks, and then runs the Pester suite against the installed package.

The gallery-installed contour is defined in .github/workflows/gallery-installed-e2e.yml and is intended to catch packaging, import, and cross-platform issues that source-built tests can miss.


Quick install

Install-Module -Name PSQuickGraph -Scope CurrentUser

Visualization split

Current ownership is intentional:

  • PSGraph owns graph objects, graph algorithms, DSM algorithms, Graphviz DOT export, GraphML interchange, and textual DSM export.
  • PSGraphView owns the visual renderer implementations and visualization-facing cmdlets such as Export-GraphView and Export-DSMView.
  • Export-Graph and Export-DSM in PSGraph are no longer the path for visual rendering.

Practical rule of thumb:

  • Use Import-Graph / Export-Graph -Format GraphML when you need a neutral interchange format.
  • Use Export-Graph -Format Graphviz when you need textual DOT output that stays fully inside PSGraph.
  • Use PSGraphView cmdlets for Vega / MSAGL / DSM visual export.

An example of Cartesian layouts for a node-link diagram of hierarchical data.

These rendering examples assume the sibling PSGraphView module is installed.

$data = (Invoke-WebRequest -Uri https://raw.githubusercontent.com/vega/vega-datasets/refs/heads/main/data/flare.json).Content | ConvertFrom-Json
$index = [object[]]::new($data.count + 1)
$data | % { $index[$_.id] = $_ }

$g = New-Graph

$data | Group-Object -Property parent | % {
    $currentGroup = $_
    if ([string]::IsNullOrEmpty($currentGroup.name)) {
        $currentGroup.Group | % {
            Add-Vertex -Vertex $_.name -Graph $g
        }
    }
    else {
        $parentLabel = $index[$currentGroup.name].name
        $currentGroup.Group | % {
            Add-Edge -From $parentLabel -To $_.name -Graph $g
        }
    }
}

$tempDir = [System.IO.Path]::GetTempPath()
$outFile = Join-Path $tempDir 'x.tree.html'
Export-GraphView -Graph $g -Renderer VegaTreeLayout -As Html -Path $outFile

This rendering path now lives in PSGraphView.

tree

Same graph but using Force Directed layout

$tempDir = [System.IO.Path]::GetTempPath()
$outFile = Join-Path $tempDir 'x.force.html'
Export-GraphView -Graph $g -Renderer VegaForceDirected -As Html -Path $outFile

This rendering path also lives in PSGraphView.

tree


DSM Clustering (Design Structure Matrix)

PSGraph includes experimental DSM clustering capabilities with two algorithms:

  • Classic (simulated annealing heuristic)
  • GraphBased (SCC condensation + topological ordering)

You can tune algorithms via a single -AlgorithmConfig parameter that accepts:

  • A strongly typed record ([PSGraph.DesignStructureMatrix.DsmSimulatedAnnealingConfig])
  • A hashtable / ordered dictionary
  • A PSCustomObject

Quick Example (Hashtable configuration)

$dsm = New-DSM -Graph (New-Graph | % { Add-Vertex -Graph $_ -Vertex 'A' }) # minimal placeholder

# Build a sample dependency graph
$g = New-Graph
'A','B','C','D' | ForEach-Object { Add-Vertex -Graph $g -Vertex $_ | Out-Null }
Add-Edge -From A -To B -Graph $g | Out-Null
Add-Edge -From B -To C -Graph $g | Out-Null
Add-Edge -From C -To A -Graph $g | Out-Null # cycle
Add-Edge -From C -To D -Graph $g | Out-Null
$dsm = New-DSM -Graph $g

# Run classic clustering (simulated annealing) with a tuned config
$cfg = @{ Times = 2; StableLimit = 2; MaxRepeat = 200; PowCc = 1 }
$result = Start-DSMClustering -Dsm $dsm -ClusteringAlgorithm Classic -AlgorithmConfig $cfg -Detailed

$result.Passes       # number of passes performed
$result.BestCost     # best coordination cost achieved
$result.CostHistory  # cost trajectory

Strongly Typed Config Example

$saCfg = [PSGraph.DesignStructureMatrix.DsmSimulatedAnnealingConfig]::new(
    PowCc = 1,
    PowBid = 0,
    PowDep = 0,
    Times = 3,
    StableLimit = 2,
    MaxRepeat = 500,
    InitialTemperature = $null,
    CoolingRate = 0.92,
    MinTemperature = 0.001
)
$result = Start-DSMClustering -Dsm $dsm -ClusteringAlgorithm Classic -AlgorithmConfig $saCfg -Detailed

Graph-Based (Deterministic) Example

$graphResult = Start-DSMClustering -Dsm $dsm -ClusteringAlgorithm GraphBased -Detailed
$graphResult.CostHistory # single value: cross-SCC edge count

Tip: For hashtable / PSCustomObject configs, keys are matched case-insensitively to record constructor parameters. Missing values fall back to defaults.

Simulated Annealing Parameters Explained

These fields tune the Classic (simulated annealing) DSM clustering. Use a strongly typed DsmSimulatedAnnealingConfig, or supply them via hashtable / PSCustomObject.

Parameter Role / Effect Raise To Lower To
PowCc Exponent on cluster size in intra / extra cluster cost (penalises large clusters). Split oversized clusters more aggressively. Allow larger clusters.
PowBid Exponent on cluster size in bid denominator ( (inOut^PowDep)/(size^PowBid) ). Bias toward smaller clusters. Reduce size pressure.
PowDep Exponent amplifying interaction strength (inOut) in bid numerator. Emphasise strong coupling. Downplay link intensity.
Times Move attempts per pass = Times * N. More exploration (slower). Faster passes, less search.
StableLimit Passes w/out improvement before considered stable. Avoid premature convergence. Stop earlier.
MaxRepeat Hard cap on passes. Permit longer searches. Force early cutoff.
InitialTemperature Starting T; null ⇒ auto-scale to initial cost (adaptive). Accept more uphill moves early. Greedier start.
CoolingRate Per-pass decay (T *= CoolingRate). Maintain exploration longer. Freeze faster.
MinTemperature Convergence threshold on T. Extend late stochastic phase. Terminate sooner.
EpochLength Moves per annealing epoch; 0 ⇒ auto (Times * N). More sampling before each cooling step. More frequent cooling.
CoolingSchedule Temperature schedule: Geometric, Linear, Logarithmic. Control cooling shape. Use default Geometric for stability.
InitialAcceptanceProbability Target probability for auto-T0 calibration. Hotter initial search. Colder initial search.
TemperatureCalibrationMoves Number of sampled moves for auto-T0. Smoother/robust T0 estimate. Faster startup.
RandomSeed Optional deterministic seed. Reproducible runs/tests. More randomness across runs.

Heuristics:

  • Quick coarse result: Times=1, CoolingRate=0.90, lower MaxRepeat.
  • Higher quality dense graphs: Times=5+, CoolingRate=0.97..0.99, higher StableLimit.
  • Discourage giant clusters: raise PowCc / PowBid.
  • Emphasise connectivity: raise PowDep.

Example tuned config:

$saCfg = [pscustomobject]@{
    PowCc = 1; PowBid = 1; PowDep = 1;
    Times = 5; StableLimit = 3; MaxRepeat = 800;
    InitialTemperature = $null; # auto-scale to initial cost
    CoolingRate = 0.985; MinTemperature = 0.0005
}
$result = Start-DSMClustering -Dsm $dsm -ClusteringAlgorithm Classic -AlgorithmConfig $saCfg -Detailed

Leaving InitialTemperature as $null makes runs scale-aware across different matrix sizes; set a numeric value for strict comparability.

When Start-DSMClustering -Detailed is used with Classic, the extended result now also includes:

  • StopReason (TemperatureDepleted, StableLimitReached, MaxRepeatReached, EmptyGraph)
  • AcceptedMoves, RejectedMoves, AcceptedWorseMoves
  • AcceptanceRate

Fast Reachability Checks

For quickly determining whether any path exists between two vertices (without retrieving the actual edge sequence) use Test-GraphPath which leverages strongly connected components and a condensed DAG search under the hood.

$g = New-Graph
'A','B','C','D','E' | ForEach-Object { Add-Vertex -Graph $g -Vertex $_ }
Add-Edge -From A -To B -Graph $g | Out-Null
Add-Edge -From B -To C -Graph $g | Out-Null
Add-Edge -From C -To D -Graph $g | Out-Null
Add-Edge -From A -To E -Graph $g | Out-Null

Test-GraphPath -Graph $g -From A -To D   # True
Test-GraphPath -Graph $g -From D -To A   # False (directional)
Test-GraphPath -Graph $g -From A -To A   # True (trivial)

Use Get-GraphPath when you need the actual path (edges) rather than just a boolean.


Examples Index

Jump straight to focused, copy‑paste friendly examples for each major task. All examples assume the module is imported and use concise variable names.

Graph Construction & Mutation

  • New-Graph – create an empty bidirectional graph (docs/New-Graph.md)
  • New-AdjacencyGraph – create an adjacency-list backed graph (docs/New-AdjacencyGraph.md)
  • Add-Vertex – add (or dedupe) vertices (docs/Add-Vertex.md)
  • Add-Edge – add directed edges with optional tag (docs/Add-Edge.md)
  • Import-Graph – load GraphML, CSV, JSON, or Matrix Market into a new graph; GraphML remains the neutral interchange format (docs/Import-Graph.md)
  • Export-Graph – Graphviz / GraphML export (docs/Export-Graph.md)

Graph Query & Analysis

  • Get-GraphPath – shortest path (Dijkstra) between two vertices (docs/Get-GraphPath.md)
  • Test-GraphPath – fast reachability boolean (docs/Test-GraphPath.md)
  • Get-InEdge / Get-OutEdge – incoming / outgoing edge enumeration (docs/Get-InEdge.md, docs/Get-OutEdge.md)
  • Get-GraphTopologicalSort – DAG dependency ordering (docs/Get-GraphTopologicalSort.md)
  • Get-GraphDistanceVector – root-based distance levels (docs/Get-GraphDistanceVector.md)

Design Structure Matrix (DSM)

  • New-DSM – wrap a graph as a DSM (docs/New-DSM.md)
  • Start-DSMClustering – cluster / partition with SA or graph-based algorithms (docs/Start-DSMClustering.md)
  • Start-DSMSequencing – reorder to expose sources / cycles / sinks (docs/Start-DSMSequencing.md)
  • Export-DSM – text export (docs/Export-DSM.md)

Typical End-to-End Flows

  • Build → Query: New-Graph → Add-Vertex / Add-Edge → Get-GraphPath / Get-InEdge
  • DAG → Execution Order: New-Graph → Add-Edge → Get-GraphTopologicalSort
  • Import → Analyse → Export: Import-Graph → Get-GraphDistanceVector → Export-Graph
  • Graph → DSM Insight: New-Graph → Add-* → New-DSM → Start-DSMClustering / Start-DSMSequencing → Export-DSM

Tip: Each linked doc contains multiple scenarios; skim the first example for the minimal pattern, then look for advanced sections (weights, tagging, configs).

About

Powershell module around QuickGraph

Topics

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors