Poniżej jest moja implementacji grafu skierowane
Na początku tworzymy obiekt, który będzie zawierał listę krawędzi:
function Create-Graph
{
return new-object PSObject |
Add-Member -PassThru -MemberType NoteProperty -Name Edges -Value @() -TypeName "array"
}Do dodawania krawędzi potrzebujemy dodatkowych funkcja. Zakładamy, że krawędź będzie zawierała informację o połączeniu dwóch wierzchołków oraz wartości tego połączenia.
function Create-Edge
{
param(
[ValidateNotNullOrEmpty()]
[string]$from,
[ValidateNotNullOrEmpty()]
[string]$to,
[int]$weight=1
)
return @{
From = $from;
To = $to;
Weight = $weight;
}
}
function Add-Edge
{
param(
[Parameter(Mandatory=$true, Position=1,ValueFromPipeline=$true)]
[ValidateNotNull()]
$graph,
[Parameter(Mandatory=$true, Position=2)]
[ValidateNotNull()]
$edge
)
process{
$graph.Edges +=$edge
return $graph
}
}
Wtedy poniższy kod tworzy graf skierowany:
$graph = Create-Graph |
Add-Edge -edge (Create-Edge A B 1 ) |
Add-Edge -edge (Create-Edge A C 5) |
Add-Edge -edge (Create-Edge A D 3) |
Add-Edge -edge (Create-Edge A E 11) |
Add-Edge -edge (Create-Edge B C 9) |
Add-Edge -edge (Create-Edge B D 1) |
Add-Edge -edge (Create-Edge B E 2) |
Add-Edge -edge (Create-Edge C D 6) |
Add-Edge -edge (Create-Edge C E 4) |
Add-Edge -edge (Create-Edge D E 3)
Do sprawdzenia nazw wierzchołków pomocne będą poniższe funkcje:function Get-EdgesNumber
{
param(
[Parameter(Mandatory=$true, Position=1)]
[ValidateNotNull()]
$graph
)
return $graph.Edges.Count
}
function Get-Vertices
{
[cmdletBinding(SupportsShouldProcess=$true,ConfirmImpact='Medium')]
param(
[Parameter(Mandatory=$true, Position=1)]
[ValidateNotNull()]
$graph
)
Write-Verbose "Getting number of Vertices in graph"
[array] $toVertices = $graph.Edges.To
[array] $fromVertices = $graph.Edges.From
return [array](($toVertices + $fromVertices) | select -Unique | sort)
}
function ConvertFrom-Graph
{
[cmdletBinding(SupportsShouldProcess=$true,ConfirmImpact='Medium')]
param(
[Parameter(Mandatory=$true, Position=1,ValueFromPipeline=$true)]
[ValidateNotNull()]
$graph
)
process {
$graph.Edges | %{
$from = $_.From
$to = $_.To
$weight = $_.Weight
Write-Verbose "Weight is $weight for:"
"$from -> $to"
}
}
}
A poniżej przedstawione są wywołania tych funkcji:
Get-EdgesNumber $graph Get-Vertices $graph $graph | ConvertFrom-Graph
Oprócz reprezentacji grafu za pomocą kolekcji krawędzi można przedstawić graf za pomocą macierzy:
function ConvertTo-Matrix
{
param(
[Parameter(Mandatory=$true, Position=1,ValueFromPipeline=$true)]
[ValidateNotNull()]
$graph
)
process{
$vertices= Get-Vertices $graph
$dim = $vertices.Length
[object[][]]$matrix = Create-ZeroMatrix $dim
$graph.Edges | % {
$from = $_.From
$to = $_.To
$weight = $_.Weight
$fromIndex = $vertices.IndexOf($from)
$toIndex = $vertices.IndexOf($to)
$matrix[$fromIndex][$toIndex]= $weight
}
return $matrix
}
}
function Create-ZeroMatrix
{
param(
[ValidateScript({$_ -ge 0})]
[int]$dim
)
$matrix = New-Object 'object[][]' $dim,$dim
for($i =0; $i -lt $dim; $i++ )
{
for($j=0; $j -lt $dim ; $j++)
{
$matrix[$i][$j] = 0
}
}
return $matrix
}
function ConvertFrom-Matrix
{
[cmdletBinding(SupportsShouldProcess=$true,ConfirmImpact='Medium')]
param(
[Parameter(Mandatory=$true, Position=1)]
[object[][]]$matrix,
[string]$seperator = ' '
)
for($i=0; $i -lt $matrix.Length; $i++)
{
Write-Verbose $i
$(($matrix[$i]) -join $seperator)
}
}
Konwersja kolekcji krawędzi na macierz jest przestawiona poniżej:$matrix = $graph | ConvertTo-Matrix ConvertFrom-Matrix $matrixOczywiście jeszcze wiele muszę poprawić m.in. konwersja z reprezentacji macierzowej do kolekcji krawędzi, modyfikacja wierzchołków, modyfikacja grafu skierowanego na graf nieskierowanego, walidacja czy wszystkie punkty są ze sobą połączone, ujednolicenie operacji na grafie itd.
Brak komentarzy:
Prześlij komentarz