1- using LinearAlgebra: checksquare, norm, pinv, mul!
1+ using LinearAlgebra: checksquare, norm, pinv, mul!, nullspace
22
33export Stress, stress
44
@@ -57,8 +57,13 @@ The main equation to solve is (8) in Gansner, Koren and North (2005,
5757
5858 Create rng based on seed. Defaults to `MersenneTwister`, can be specified
5959 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.
6065"""
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} < :
6267 IterativeLayout{Dim,Ptype}
6368 iterations:: IT
6469 abstols:: FT
@@ -67,6 +72,7 @@ The main equation to solve is (8) in Gansner, Koren and North (2005,
6772 weights:: M
6873 initialpos:: Dict{Int,Point{Dim,Ptype}}
6974 pin:: Dict{Int,SVector{Dim,Bool}}
75+ uncon_dist:: F
7076 rng:: RNG
7177end
7278
@@ -76,6 +82,7 @@ function Stress(; dim=2,
7682 abstols= 0.0 ,
7783 reltols= 10e-6 ,
7884 abstolx= 10e-6 ,
85+ uncon_dist= (maxd, N)-> maxd* N^ (1 / 3 ),
7986 weights= Array {Float64} (undef, 0 , 0 ),
8087 initialpos= [], pin= [],
8188 seed= 1 , rng= DEFAULT_RNG[](seed))
@@ -86,8 +93,8 @@ function Stress(; dim=2,
8693
8794 _initialpos, _pin = _sanitize_initialpos_pin (dim, Ptype, initialpos, pin)
8895
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)
9198end
9299
93100function 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
116123 # if user provided weights not empty try those
117124 make_symmetric! (δ)
118125 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+
119140 weights = isempty (algo. weights) ? distances .^ (- 2 ) : algo. weights
120141
121142 @assert length (startpos) == size (δ, 1 ) == size (δ, 2 ) == size (weights, 1 ) == size (weights, 2 ) " Wrong size of weights?"
0 commit comments