Skip to content

Commit 1dacc67

Browse files
committed
seed random positions
1 parent 43e1df9 commit 1dacc67

File tree

6 files changed

+28
-14
lines changed

6 files changed

+28
-14
lines changed

Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ version = "0.4.0"
55
[deps]
66
GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326"
77
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
8+
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
89
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
910
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
1011

docs/src/index.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ set_theme!(resolution=(800, 400)) #hide
1414
CairoMakie.inline!(true) # hide
1515
using NetworkLayout
1616
using GraphMakie, LightGraphs
17-
import Random; Random.seed!(2) # hide
1817
nothing #hide
1918
```
2019

@@ -104,15 +103,14 @@ Stress
104103
```@example layouts
105104
g = complete_graph(10)
106105
layout = Stress()
107-
Random.seed!(1)
108106
f, ax, p = graphplot(g, layout=layout)
109107
hidedecorations!(ax); hidespines!(ax); ax.aspect = DataAspect(); f #hide
110108
```
111109

112110
### Iterator Example
113111
```@example layouts
114112
iterator = LayoutIterator(layout, adjacency_matrix(g))
115-
record(f, "stress_animation.mp4", iterator; framerate = 100) do pos
113+
record(f, "stress_animation.mp4", iterator; framerate = 10) do pos
116114
p[:node_positions][] = pos
117115
autolimits!(ax)
118116
end

src/NetworkLayout.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module NetworkLayout
33
using GeometryBasics
44
using Requires
55
using LinearAlgebra: norm
6+
using Random
67

78
export LayoutIterator, layout
89

src/sfdp.jl

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,39 +22,44 @@ the nodes.
2222
2323
Provide list of initial positions. If length does not match Network size the initial
2424
positions will be truncated or filled up with random values between [-1,1] in every coordinate.
25+
26+
- `seed=1`: Seed for random initial positions.
2527
"""
2628
struct SFDP{Dim,Ptype,T<:AbstractFloat} <: IterativeLayout{Dim,Ptype}
2729
tol::T
2830
C::T
2931
K::T
3032
iterations::Int
3133
initialpos::Vector{Point{Dim,Ptype}}
34+
seed::UInt
3235
end
3336

3437
# TODO: check SFDP default parameters
35-
function SFDP(; dim=2, Ptype=Float64, tol=1.0, C=0.2, K=1.0, iterations=100, initialpos=Point{dim,Ptype}[])
38+
function SFDP(; dim=2, Ptype=Float64, tol=1.0, C=0.2, K=1.0, iterations=100, initialpos=Point{dim,Ptype}[],
39+
seed=1)
3640
if !isempty(initialpos)
3741
initialpos = Point.(initialpos)
3842
Ptype = eltype(eltype(initialpos))
3943
# TODO fix initial pos if list has points of multiple types
4044
Ptype == Any && error("Please provide list of Point{N,T} with same T")
4145
dim = length(eltype(initialpos))
4246
end
43-
return SFDP{dim,Ptype,typeof(tol)}(tol, C, K, iterations, initialpos)
47+
return SFDP{dim,Ptype,typeof(tol)}(tol, C, K, iterations, initialpos, seed)
4448
end
4549

4650
function Base.iterate(iter::LayoutIterator{SFDP{Dim,Ptype,T}}) where {Dim,Ptype,T}
4751
algo, adj_matrix = iter.algorithm, iter.adj_matrix
4852
N = size(adj_matrix, 1)
4953
M = length(algo.initialpos)
54+
rng = MersenneTwister(algo.seed)
5055
startpos = Vector{Point{Dim,Ptype}}(undef, N)
5156
# take the first
5257
for i in 1:min(N, M)
5358
startpos[i] = algo.initialpos[i]
5459
end
5560
# fill the rest with random points
5661
for i in (M + 1):N
57-
startpos[i] = 2 .* rand(Point{Dim,Ptype}) .- 1
62+
startpos[i] = 2 .* rand(rng, Point{Dim,Ptype}) .- 1
5863
end
5964
# iteratorstate: (#iter, energy, step, progress, old pos, stopflag)
6065
return startpos, (1, typemax(T), one(T), 0, startpos, false)
@@ -98,7 +103,7 @@ function Base.iterate(iter::LayoutIterator{<:SFDP}, state)
98103
stopflag = true
99104
end
100105

101-
return locs, (iter+1, energy, step, progress, locs, stopflag)
106+
return locs, (iter + 1, energy, step, progress, locs, stopflag)
102107
end
103108

104109
# Calculate Attractive force

src/spring.jl

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,37 +25,42 @@ the nodes.
2525
2626
Provide list of initial positions. If length does not match Network size the initial
2727
positions will be truncated or filled up with random values between [-1,1] in every coordinate.
28+
29+
- `seed=1`: Seed for random initial positions.
2830
"""
2931
struct Spring{Dim,Ptype} <: IterativeLayout{Dim,Ptype}
3032
C::Float64
3133
iterations::Int
3234
initialtemp::Float64
3335
initialpos::Vector{Point{Dim,Ptype}}
36+
seed::UInt
3437
end
3538

36-
function Spring(; dim=2, Ptype=Float64, C=2.0, iterations=100, initialtemp=2.0, initialpos=Point{dim,Ptype}[])
39+
function Spring(; dim=2, Ptype=Float64, C=2.0, iterations=100, initialtemp=2.0, initialpos=Point{dim,Ptype}[],
40+
seed=1)
3741
if !isempty(initialpos)
3842
initialpos = Point.(initialpos)
3943
Ptype = eltype(eltype(initialpos))
4044
# TODO fix initial pos if list has points of multiple types
4145
Ptype == Any && error("Please provide list of Point{N,T} with same T")
4246
dim = length(eltype(initialpos))
4347
end
44-
return Spring{dim,Ptype}(C, iterations, initialtemp, initialpos)
48+
return Spring{dim,Ptype}(C, iterations, initialtemp, initialpos, seed)
4549
end
4650

47-
function Base.iterate(iter::LayoutIterator{<:Spring{Dim, Ptype}}) where {Dim, Ptype}
51+
function Base.iterate(iter::LayoutIterator{<:Spring{Dim,Ptype}}) where {Dim,Ptype}
4852
algo, adj_matrix = iter.algorithm, iter.adj_matrix
4953
N = size(adj_matrix, 1)
5054
M = length(algo.initialpos)
55+
rng = MersenneTwister(algo.seed)
5156
startpos = Vector{Point{Dim,Ptype}}(undef, N)
5257
# take the first
5358
for i in 1:min(N, M)
5459
startpos[i] = algo.initialpos[i]
5560
end
5661
# fill the rest with random points
5762
for i in (M + 1):N
58-
startpos[i] = 2 .* rand(Point{Dim,Ptype}) .- 1
63+
startpos[i] = 2 .* rand(rng, Point{Dim,Ptype}) .- 1
5964
end
6065
# iteratorstate: #iter nr, old pos
6166
return (startpos, (1, startpos))

src/stress.jl

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ representation of a network and returns coordinates of the nodes.
4242
Provide list of initial positions. If length does not match Network size the initial
4343
positions will be truncated or filled up with random normal distributed values in every coordinate.
4444
45+
- `seed=1`: Seed for random initial positions.
46+
4547
## Reference:
4648
The main equation to solve is (8) of:
4749
@@ -67,11 +69,12 @@ struct Stress{Dim,Ptype,IT<:Union{Symbol,Int},FT<:AbstractFloat,M<:AbstractMatri
6769
abstolx::FT
6870
weights::M
6971
initialpos::Vector{Point{Dim,Ptype}}
72+
seed::UInt
7073
end
7174

7275
function Stress(; dim=2, Ptype=Float64, iterations=:auto, abstols=((eps(Float64))),
7376
reltols=((eps(Float64))), abstolx=((eps(Float64))), weights=Array{Float64}(undef, 0, 0),
74-
initialpos=Point{dim,Ptype}[])
77+
initialpos=Point{dim,Ptype}[], seed=1)
7578
if !isempty(initialpos)
7679
initialpos = Point.(initialpos)
7780
Ptype = eltype(eltype(initialpos))
@@ -80,7 +83,7 @@ function Stress(; dim=2, Ptype=Float64, iterations=:auto, abstols=(√(eps(Float
8083
dim = length(eltype(initialpos))
8184
end
8285
IT, FT, WT = typeof(iterations), typeof(abstols), typeof(weights)
83-
Stress{dim,Ptype,IT,FT,WT}(iterations, abstols, reltols, abstolx, weights, initialpos)
86+
Stress{dim,Ptype,IT,FT,WT}(iterations, abstols, reltols, abstolx, weights, initialpos, seed)
8487
end
8588

8689
function initialweights(D, T)::SparseMatrixCSC{T,Int64}
@@ -94,14 +97,15 @@ function Base.iterate(iter::LayoutIterator{<:Stress{Dim,Ptype,IT,FT}}) where {Di
9497
algo, δ = iter.algorithm, iter.adj_matrix
9598
N = size(δ, 1)
9699
M = length(algo.initialpos)
100+
rng = MersenneTwister(algo.seed)
97101
startpos = Vector{Point{Dim,Ptype}}(undef, N)
98102
# take the first
99103
for i in 1:min(N, M)
100104
startpos[i] = algo.initialpos[i]
101105
end
102106
# fill the rest with random points
103107
for i in (M + 1):N
104-
startpos[i] = randn(Point{Dim,Ptype})
108+
startpos[i] = randn(rng, Point{Dim,Ptype})
105109
end
106110

107111
# calculate iteration if :auto

0 commit comments

Comments
 (0)