1
- using LinearAlgebra: checksquare, norm, pinv, mul!
1
+ using LinearAlgebra: checksquare, norm, pinv, mul!, nullspace
2
2
3
3
export Stress, stress
4
4
@@ -57,8 +57,13 @@ The main equation to solve is (8) in Gansner, Koren and North (2005,
57
57
58
58
Create rng based on seed. Defaults to `MersenneTwister`, can be specified
59
59
by overwriting `DEFAULT_RNG[]`
60
+
61
+ - `uncon_dist=(maxdist, Ncomps)->maxdist*Ncomps^(1/3)`
62
+
63
+ Per default, unconnected vertices in the graph get a pairwise "ideal" distance which scales
64
+ with the number of connected components and the maximum distance within the components.
60
65
"""
61
- @addcall struct Stress{Dim,Ptype,IT<: Union{Symbol,Int} ,FT<: AbstractFloat ,M<: AbstractMatrix ,RNG} < :
66
+ @addcall struct Stress{Dim,Ptype,IT<: Union{Symbol,Int} ,FT<: AbstractFloat ,M<: AbstractMatrix ,F, RNG} < :
62
67
IterativeLayout{Dim,Ptype}
63
68
iterations:: IT
64
69
abstols:: FT
@@ -67,6 +72,7 @@ The main equation to solve is (8) in Gansner, Koren and North (2005,
67
72
weights:: M
68
73
initialpos:: Dict{Int,Point{Dim,Ptype}}
69
74
pin:: Dict{Int,SVector{Dim,Bool}}
75
+ uncon_dist:: F
70
76
rng:: RNG
71
77
end
72
78
@@ -76,6 +82,7 @@ function Stress(; dim=2,
76
82
abstols= 0.0 ,
77
83
reltols= 10e-6 ,
78
84
abstolx= 10e-6 ,
85
+ uncon_dist= (maxd, N)-> maxd* N^ (1 / 3 ),
79
86
weights= Array {Float64} (undef, 0 , 0 ),
80
87
initialpos= [], pin= [],
81
88
seed= 1 , rng= DEFAULT_RNG[](seed))
@@ -86,8 +93,8 @@ function Stress(; dim=2,
86
93
87
94
_initialpos, _pin = _sanitize_initialpos_pin (dim, Ptype, initialpos, pin)
88
95
89
- IT, FT, WT, RNG = typeof (iterations), typeof (abstols), typeof (weights), typeof (rng)
90
- Stress {dim,Ptype,IT,FT,WT,RNG} (iterations, abstols, reltols, abstolx, weights, _initialpos, _pin, rng)
96
+ IT, FT, WT, RNG, F = typeof (iterations), typeof (abstols), typeof (weights), typeof (rng), typeof (uncon_dist )
97
+ Stress {dim,Ptype,IT,FT,WT,F, RNG} (iterations, abstols, reltols, abstolx, weights, _initialpos, _pin, uncon_dist , rng)
91
98
end
92
99
93
100
function Base. iterate (iter:: LayoutIterator{<:Stress{Dim,Ptype,IT,FT}} ) where {Dim,Ptype,IT,FT}
@@ -116,6 +123,20 @@ function Base.iterate(iter::LayoutIterator{<:Stress{Dim,Ptype,IT,FT}}) where {Di
116
123
# if user provided weights not empty try those
117
124
make_symmetric! (δ)
118
125
distances = pairwise_distance (δ, FT)
126
+
127
+ # check for unconnected commponents and set pairwise distances
128
+ if any (isequal (typemax (FT)), distances)
129
+ maxd = maximum (filter (isfinite, distances))
130
+ laplacian = weightedlaplacian (δ)
131
+ Ncomponents = size (nullspace (laplacian),2 )
132
+ _dist = algo. uncon_dist (maxd, Ncomponents)
133
+ for i in eachindex (distances)
134
+ if isinf (distances[i])
135
+ distances[i] = _dist
136
+ end
137
+ end
138
+ end
139
+
119
140
weights = isempty (algo. weights) ? distances .^ (- 2 ) : algo. weights
120
141
121
142
@assert length (startpos) == size (δ, 1 ) == size (δ, 2 ) == size (weights, 1 ) == size (weights, 2 ) " Wrong size of weights?"
0 commit comments