@@ -20,8 +20,15 @@ the nodes.
20
20
- `iterations=100`: maximum number of iterations
21
21
- `initialpos=Point{dim,Ptype}[]`
22
22
23
- Provide list of initial positions. If length does not match Network size the initial
24
- positions will be truncated or filled up with random values between [-1,1] in every coordinate.
23
+ Provide `Vector` or `Dict` of initial positions. All positions will be initialized
24
+ using random coordinates between [-1,1]. Random positions will be overwritten using
25
+ the key-val-pairs provided by this argument.
26
+
27
+ - `pin=[]`: Pin node positions (won't be updated). Can be given as `Vector` or `Dict`
28
+ of node index -> value pairings. Values can be either
29
+ - `(12, 4.0)` : overwrite initial position and pin
30
+ - `true/false` : pin this position
31
+ - `(true, false, false)` : only pin certain coordinates
25
32
26
33
- `seed=1`: Seed for random initial positions.
27
34
"""
@@ -30,44 +37,45 @@ the nodes.
30
37
C:: T
31
38
K:: T
32
39
iterations:: Int
33
- initialpos:: Vector{Point{Dim,Ptype}}
40
+ initialpos:: Dict{Int,Point{Dim,Ptype}}
41
+ pin:: Dict{Int,SVector{Dim,Bool}}
34
42
seed:: UInt
35
43
end
36
44
37
45
# TODO : check SFDP default parameters
38
- function SFDP (; dim= 2 , Ptype= Float64, tol= 1.0 , C= 0.2 , K= 1.0 , iterations= 100 , initialpos= Point{dim,Ptype}[],
46
+ function SFDP (; dim= 2 , Ptype= Float64,
47
+ tol= 1.0 , C= 0.2 , K= 1.0 ,
48
+ iterations= 100 ,
49
+ initialpos= [], pin= [],
39
50
seed= 1 )
40
51
if ! isempty (initialpos)
41
- initialpos = Point .(initialpos)
42
- Ptype = eltype (eltype (initialpos))
43
- # TODO fix initial pos if list has points of multiple types
44
- Ptype == Any && error (" Please provide list of Point{N,T} with same T" )
45
- dim = length (eltype (initialpos))
52
+ dim, Ptype = infer_pointtype (initialpos)
53
+ Ptype = promote_type (Float32, Ptype) # make sure to get at least f32 if given as int
46
54
end
47
- return SFDP {dim,Ptype,typeof(tol)} (tol, C, K, iterations, initialpos, seed)
55
+ _initialpos, _pin = _sanitize_initialpos_pin (dim, Ptype, initialpos, pin)
56
+
57
+ return SFDP {dim,Ptype,typeof(tol)} (tol, C, K, iterations, _initialpos, _pin, seed)
48
58
end
49
59
50
60
function Base. iterate (iter:: LayoutIterator{SFDP{Dim,Ptype,T}} ) where {Dim,Ptype,T}
51
61
algo, adj_matrix = iter. algorithm, iter. adj_matrix
52
62
N = size (adj_matrix, 1 )
53
- M = length (algo. initialpos)
54
63
rng = MersenneTwister (algo. seed)
55
- startpos = Vector {Point{Dim,Ptype}} (undef, N)
56
- # take the first
57
- for i in 1 : min (N, M)
58
- startpos[i] = algo. initialpos[i]
59
- end
60
- # fill the rest with random points
61
- for i in (M + 1 ): N
62
- startpos[i] = 2 .* rand (rng, Point{Dim,Ptype}) .- 1
64
+ startpos = [2 .* rand (rng, Point{Dim,Ptype}) .- 1 for _ in 1 : N]
65
+
66
+ for (k, v) in algo. initialpos
67
+ startpos[k] = v
63
68
end
64
- # iteratorstate: (#iter, energy, step, progress, old pos, stopflag)
65
- return startpos, (1 , typemax (T), one (T), 0 , startpos, false )
69
+
70
+ pin = [get (algo. pin, i, SVector {Dim,Bool} (false for _ in 1 : Dim)) for i in 1 : N]
71
+
72
+ # iteratorstate: (#iter, energy, step, progress, old pos, pin, stopflag)
73
+ return startpos, (1 , typemax (T), one (T), 0 , startpos, pin, false )
66
74
end
67
75
68
76
function Base. iterate (iter:: LayoutIterator{<:SFDP} , state)
69
77
algo, adj_matrix = iter. algorithm, iter. adj_matrix
70
- iter, energy0, step, progress, locs0, stopflag = state
78
+ iter, energy0, step, progress, locs0, pin, stopflag = state
71
79
K, C, tol = algo. K, algo. C, algo. tol
72
80
73
81
# stop if stopflag (tol reached) or nr of iterations reached
@@ -93,7 +101,8 @@ function Base.iterate(iter::LayoutIterator{<:SFDP}, state)
93
101
((locs[j] .- locs[i]) / norm (locs[j] .- locs[i])))
94
102
end
95
103
end
96
- locs[i] = locs[i] .+ step .* (force ./ norm (force))
104
+ mask = (! ). (pin[i]) # where pin=true mask will multiply with 0
105
+ locs[i] = locs[i] .+ (step .* (force ./ norm (force))) .* mask
97
106
energy = energy + norm (force)^ 2
98
107
end
99
108
step, progress = update_step (step, energy, energy0, progress)
@@ -103,7 +112,7 @@ function Base.iterate(iter::LayoutIterator{<:SFDP}, state)
103
112
stopflag = true
104
113
end
105
114
106
- return locs, (iter + 1 , energy, step, progress, locs, stopflag)
115
+ return locs, (iter + 1 , energy, step, progress, locs, pin, stopflag)
107
116
end
108
117
109
118
# Calculate Attractive force
0 commit comments