@@ -24,29 +24,78 @@ the nodes.
24
24
positions will be truncated or filled up with random values between [-1,1] in every coordinate.
25
25
26
26
- `seed=1`: Seed for random initial positions.
27
- - `fixed = false ` : Anchors initial positions.
27
+ - `pin::Union{Nothing, Vector{Point{Dim,Bool}}}=nothing ` : Anchors positions of nodes to initial position
28
28
"""
29
29
@addcall struct SFDP{Dim,Ptype,T<: AbstractFloat } <: IterativeLayout{Dim,Ptype}
30
30
tol:: T
31
31
C:: T
32
32
K:: T
33
33
iterations:: Int
34
- initialpos:: Vector{ Point{Dim,Ptype}}
34
+ initialpos:: Dict{Int, Point{Dim,Ptype}}
35
35
seed:: UInt
36
- fixed:: Bool
36
+ pin:: Vector{Point{Dim,Bool}}
37
+ function SFDP (tol, C, K, iterations, initialpos, seed, pin)
38
+ for (ix, p) in enumerate (pin)
39
+ for (id, c) in enumerate (p)
40
+ c && ! haskey (initialpos, ix) && error (" Please provide coordinate for every pinned position" )
41
+ end
42
+ end
43
+ dim = get_pt_dim (initialpos)
44
+ ptype = get_pt_ptype (initialpos)
45
+ new {dim, ptype, typeof(tol)} (tol, C, K, iterations, initialpos, seed, pin)
46
+ end
37
47
end
38
48
39
49
# TODO : check SFDP default parameters
40
- function SFDP (; dim= 2 , Ptype= Float64, tol= 1.0 , C= 0.2 , K= 1.0 , iterations= 100 , initialpos= Point{dim,Ptype}[],
41
- seed= 1 , fixed = false )
42
- if ! isempty (initialpos)
43
- initialpos = Point .(initialpos)
44
- Ptype = eltype (eltype (initialpos))
45
- # TODO fix initial pos if list has points of multiple types
46
- Ptype == Any && error (" Please provide list of Point{N,T} with same T" )
47
- dim = length (eltype (initialpos))
50
+ function SFDP (; dim= 2 , Ptype= Float64, tol= 1.0 , C= 0.2 , K= 1.0 , iterations= 100 , initialpos= Dict {Int, Point{dim,Ptype}} (),
51
+ seed:: UInt = UInt (1 ), pin = Vector {Bool} ())
52
+ @show initialpos
53
+ return SFDP (tol, C, K, iterations, initialpos, seed, pin)
54
+ end
55
+
56
+ function SFDP (tol:: T , C:: T , K:: T , iterations:: Int , initialpos:: Vector , seed:: UInt , pin) where T<: AbstractFloat
57
+ @info " sfdp with ip vec"
58
+ dim = get_pt_dim (initialpos)
59
+ initialpos = Dict (zip (1 : length (initialpos), Point .(initialpos)))
60
+ Ptype = get_pt_ptype (initialpos)
61
+ # TODO fix initial pos if list has points of multiple types
62
+ return SFDP (tol, C, K, iterations, initialpos, seed, pin)
63
+ end
64
+
65
+ function SFDP (tol:: T , C:: T , K:: T , iterations:: Int , initialpos:: Dict{Int, <:Point} , seed:: UInt , pin:: Dict{Int, <:Point} ) where {T<: AbstractFloat }
66
+ @info " sfdp with ip dict and pin dict"
67
+ fixed = falses (maximum (keys (pin)))
68
+ for (i, p) in pin
69
+ haskey (initialpos, i) && @warn " overwriting initial position of node $i with pin position"
70
+ initialpos[i] = p
71
+ fixed[i] = true
48
72
end
49
- return SFDP {dim,Ptype,typeof(tol)} (tol, C, K, iterations, initialpos, seed, fixed)
73
+ dim = get_pt_dim (initialpos)
74
+ Ptype = get_pt_ptype (initialpos)
75
+ return SFDP (tol, C, K, iterations, initialpos, seed, Point {dim,Bool} .(fixed))
76
+ end
77
+
78
+ function SFDP (tol:: T , C:: T , K:: T , iterations:: Int , initialpos:: Dict{Int, <:Point} , seed:: UInt , pin:: Vector{Bool} ) where T<: AbstractFloat
79
+ @info " sfdp with ip dict and pin vec"
80
+ dim = get_pt_dim (initialpos)
81
+ Ptype = get_pt_ptype (initialpos)
82
+ return SFDP (tol, C, K, iterations, initialpos, seed, Point {dim, Bool} .(pin))
83
+ end
84
+
85
+ function get_pt_ptype (ip:: Dict{Int, <:Point} )
86
+ ptype = eltype (eltype (values (ip)))
87
+ ptype == Any && error (" Please provide list of Point{N,T} with same T" )
88
+ return ptype
89
+ end
90
+
91
+ function get_pt_dim (ip:: Vector )
92
+ dims = length .(ip)
93
+ length (unique (dims)) != 1 && error (" Please provide list of Point{N,T} with same N" )
94
+ return first (dims)
95
+ end
96
+
97
+ function get_pt_dim (ip:: Dict{Int, <:Point} )
98
+ return typeof (ip). parameters[2 ]. parameters[1 ] # based on type of point
50
99
end
51
100
52
101
function Base. iterate (iter:: LayoutIterator{SFDP{Dim,Ptype,T}} ) where {Dim,Ptype,T}
@@ -55,22 +104,23 @@ function Base.iterate(iter::LayoutIterator{SFDP{Dim,Ptype,T}}) where {Dim,Ptype,
55
104
M = length (algo. initialpos)
56
105
rng = MersenneTwister (algo. seed)
57
106
startpos = Vector {Point{Dim,Ptype}} (undef, N)
58
- startposbounds = (min = zero (Point{Dim, Ptype}), max = zero ((Point{Dim, Ptype})) .+ one (Ptype))
59
107
# take the first
60
- for i in 1 : min (N, M)
61
- startpos[i] = algo . initialpos[i]
108
+ for (i, p) in algo . initialpos
109
+ startpos[i] = p
62
110
end
63
111
64
112
# create bounds for random initial positions
65
- if M > 0
113
+ if isempty (algo. initialpos)
114
+ startposbounds = (min = zero (Point{Dim, Ptype}), max = zero ((Point{Dim, Ptype})) .+ one (Ptype))
115
+ else
66
116
startposbounds = (
67
- min = Point {Dim, Ptype} ([minimum ((p[d] for p in startpos[ 1 : min (N, M)] )) for d in 1 : Dim]),
68
- max = Point {Dim, Ptype} ([maximum ((p[d] for p in startpos[ 1 : min (N, M)] )) for d in 1 : Dim])
117
+ min = Point {Dim, Ptype} ([minimum ((p[d] for p in values (algo . initialpos) )) for d in 1 : Dim]),
118
+ max = Point {Dim, Ptype} ([maximum ((p[d] for p in values (algo . initialpos) )) for d in 1 : Dim])
69
119
)
70
120
end
71
121
72
122
# fill the rest with random points
73
- for i in (M + 1 ) : N
123
+ for i in setdiff ( 1 : N, keys (algo . initialpos))
74
124
startpos[i] = (startposbounds. max .- startposbounds. min) .* (2 .* rand (rng, Point{Dim,Ptype}) .- 1 ) .+ startposbounds. min
75
125
end
76
126
# iteratorstate: (#iter, energy, step, progress, old pos, stopflag)
@@ -91,7 +141,7 @@ function Base.iterate(iter::LayoutIterator{<:SFDP}, state)
91
141
energy = zero (energy0)
92
142
Ftype = eltype (locs)
93
143
N = size (adj_matrix, 1 )
94
- M = algo. fixed ? length (algo. initialpos) : 0
144
+ pin = N > length ( algo. pin) ? vcat (algo . pin, falses (N - length (algo. pin))) : algo . pin
95
145
for i in 1 : N
96
146
force = zero (Ftype)
97
147
for j in 1 : N
@@ -106,7 +156,7 @@ function Base.iterate(iter::LayoutIterator{<:SFDP}, state)
106
156
((locs[j] .- locs[i]) / norm (locs[j] .- locs[i])))
107
157
end
108
158
end
109
- if i > M
159
+ if ! pin[i]
110
160
locs[i] = locs[i] .+ step .* (force ./ norm (force))
111
161
end
112
162
energy = energy + norm (force)^ 2
0 commit comments