Skip to content

Add LeastCost and RandomWalk MovementModes #34

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 106 commits into from
Apr 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
106 commits
Select commit Hold shift + click to select a range
a0a17ea
add lazy compute operations
rafaqz Dec 2, 2024
cda2fd9
compute on any object
rafaqz Dec 2, 2024
2faf11a
add allocate method
rafaqz Dec 2, 2024
5043bc4
add windowed ops
rafaqz Dec 2, 2024
a783626
refactor
rafaqz Dec 12, 2024
9fbbb8e
more ops
rafaqz Dec 13, 2024
1ca659f
add LinearSolve
rafaqz Dec 13, 2024
294fabc
cleanup
rafaqz Dec 13, 2024
1f45f1a
Merge remote-tracking branch 'upstream/dev' into lazy_compute_ops
rafaqz Dec 13, 2024
cc9dbe0
Working Problems
rafaqz Dec 13, 2024
d8232b8
load tiles.jl
rafaqz Dec 13, 2024
05d965b
implement better abstract heirarchies
rafaqz Dec 17, 2024
9117ff6
cleaner problems with RasterStack
rafaqz Dec 27, 2024
850c170
working tiling
rafaqz Dec 28, 2024
c1d52af
working LinearSolver with tests
rafaqz Dec 28, 2024
9d44267
update and comment tests
rafaqz Dec 28, 2024
89bca5d
tweaks
rafaqz Dec 28, 2024
ecbfe08
refactor
rafaqz Dec 28, 2024
14d2e00
bugfixes
rafaqz Dec 28, 2024
4823207
work on algorithm efficiency
rafaqz Jan 4, 2025
b7881c0
fix tests
rafaqz Jan 13, 2025
2f680a1
work reduction with traits
rafaqz Jan 14, 2025
2839f44
more memory reductions
rafaqz Jan 14, 2025
3d2b56d
more memory reductions
rafaqz Jan 14, 2025
89aa9c0
updates
rafaqz Jan 16, 2025
9ad50fc
accurate allocation estimates
rafaqz Jan 20, 2025
f7bd5d7
fix tests
rafaqz Jan 20, 2025
214793c
fix docstring warning
rafaqz Jan 21, 2025
8abcaef
tests and allocs
rafaqz Jan 24, 2025
4186033
window testing
rafaqz Jan 28, 2025
ba234c3
tweaks
rafaqz Jan 29, 2025
5b26be2
fix doc
rafaqz Jan 29, 2025
1fa786a
fix type params
rafaqz Jan 29, 2025
759b34b
add basic windowed model init
rafaqz Jan 29, 2025
3109170
assesment tweaks
rafaqz Feb 3, 2025
305fd56
updates, windowing a litte broken
rafaqz Feb 4, 2025
9c5f7ad
update for batch assesments
rafaqz Feb 6, 2025
322b520
reorganise init
rafaqz Feb 6, 2025
ef16390
nwindows
rafaqz Jan 29, 2025
94347a2
refactor allocs to init
rafaqz Feb 7, 2025
0bd3392
updates
rafaqz Feb 11, 2025
c50e7c1
vector performance
rafaqz Feb 13, 2025
bf7091f
fix tests for vector targets
rafaqz Feb 13, 2025
fa7d952
tweaks
rafaqz Feb 13, 2025
c2ea5d1
remover Plots.jl
rafaqz Feb 14, 2025
6e61433
Merge remote-tracking branch 'refs/remotes/upstream/alg_efficiency' i…
rafaqz Feb 14, 2025
1dad5b7
optimise assessment
rafaqz Feb 14, 2025
a9479b2
bugfix assess
rafaqz Feb 14, 2025
935d729
reorganise
rafaqz Feb 17, 2025
8dd54f0
move tiles to windows.jl
rafaqz Feb 17, 2025
35fe615
format everything
rafaqz Feb 17, 2025
20bac98
reorganise and document
rafaqz Feb 17, 2025
da5768f
add reassess
rafaqz Feb 18, 2025
25bc155
cleanup
rafaqz Feb 18, 2025
f65161c
resorganise bugfix and test (re)assessments
rafaqz Feb 18, 2025
26eb243
assess performance fixes
rafaqz Feb 19, 2025
523de83
bugfixes for windows
rafaqz Feb 22, 2025
ebfc76c
bugfix and passing tests
rafaqz Feb 23, 2025
7fd91e3
use spawn for window threading
rafaqz Feb 23, 2025
fe07186
gc
rafaqz Feb 23, 2025
e296e6f
fix doc
rafaqz Feb 23, 2025
8e92af7
print wanting for empty stack output
rafaqz Feb 23, 2025
008ebea
add assessment warnings
rafaqz Mar 2, 2025
82210ec
no internal mosaic for batches
rafaqz Mar 2, 2025
ef0d821
remove nans from qualities
rafaqz Mar 2, 2025
6bc31fe
fix assessmentwarnings funcs
rafaqz Mar 3, 2025
a43ad2d
reorganise
rafaqz Mar 5, 2025
4d5244b
add and use prune_unconnected
rafaqz Mar 5, 2025
93ff283
loop over subgraphs
rafaqz Mar 9, 2025
42fecbb
tweaks
rafaqz Mar 9, 2025
437f935
add new graph measure original code
rafaqz Mar 10, 2025
26bccd3
reorganise graph measure type structure
rafaqz Mar 10, 2025
8813065
reorganise connectivity measure types
rafaqz Mar 10, 2025
d5d3f5b
compute and compute_target
rafaqz Mar 11, 2025
74e8705
fixes
rafaqz Mar 11, 2025
21a425a
add GridPrecalculations
rafaqz Mar 11, 2025
7b427a6
more grid precalculation
rafaqz Mar 11, 2025
beed493
move array definition methods to grid_preallocations.jl
rafaqz Mar 11, 2025
09b169c
reorganise, and use compute for everything
rafaqz Mar 12, 2025
8068d51
start adding sensitivity
rafaqz Mar 12, 2025
223ae60
move all algs to compute format
rafaqz Mar 12, 2025
d5c23bb
more compute
rafaqz Mar 13, 2025
325f5c4
more single-target conversions
rafaqz Mar 14, 2025
1b2174d
more single target
rafaqz Mar 15, 2025
1f9c2a2
bugfix and refactor
rafaqz Mar 16, 2025
2fa9691
huge refactor, connected hab working
rafaqz Mar 17, 2025
9a6aa2f
tests passing
rafaqz Mar 18, 2025
0ae99da
tests passing
rafaqz Mar 18, 2025
37aae45
delete, rename and clean up
rafaqz Mar 19, 2025
ec89867
delete gridrsp.jl
rafaqz Mar 19, 2025
dc036a7
move sims to simulations.jl
rafaqz Mar 19, 2025
1931218
refactor
rafaqz Mar 21, 2025
13d95cc
passing tests
rafaqz Mar 22, 2025
8ec62c2
put linearsolve in an extension
rafaqz Mar 23, 2025
9b73041
tweak window init
rafaqz Mar 23, 2025
e294e33
inits
rafaqz Mar 25, 2025
13ada21
test more init patterns
rafaqz Mar 25, 2025
66e416b
fix workspace race
rafaqz Mar 25, 2025
98074db
sparse_sizes
rafaqz Mar 25, 2025
6405723
fix workspaces for emtpy grids
rafaqz Mar 25, 2025
e615077
Merge branch 'new_movements' of https://github.com/ConScape/ConScape.…
rafaqz Mar 25, 2025
054b9e0
fix LinearSolve deps
rafaqz Mar 25, 2025
87cbd8e
bugfix betweenness overflow
rafaqz Mar 25, 2025
e25faa5
add circle shape and test
rafaqz Mar 26, 2025
c827b3c
better show
rafaqz Apr 2, 2025
4e9ed1e
dont error on Inf
rafaqz Apr 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,41 @@ version = "0.3.0"

[deps]
ArnoldiMethod = "ec485272-7323-5ecc-a04f-4719b315124d"
CommonSolve = "38540f10-b2f7-11e9-35d8-d573e4eb0ff2"
ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab"
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
ProgressLogging = "33c8b6b6-d38a-422a-b730-caa89a2f386c"
Rasters = "a3a2b9e3-a471-40c9-b274-f788e487c689"
SimpleWeightedGraphs = "47aef6b3-ad0c-573a-a1e2-d07658019622"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[weakdeps]
LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae"

[extensions]
ConScapeLinearSolveExt = "LinearSolve"

[compat]
ArnoldiMethod = "0.0.4, 0.4"
CommonSolve = "0.2"
ConstructionBase = "1.5.8"
DelimitedFiles = "1"
Graphs = "1"
LaTeXStrings = "1.1"
LinearSolve = "2.38.0"
Plots = "1.4"
ProgressLogging = "0.1"
Rasters = "0.12"
Rasters = "0.14"
SimpleWeightedGraphs = "1.1"
julia = "1.10"

[extras]
ArchGDAL = "c9ce4bd3-c3d5-55b8-8973-c0e20141b8c3"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"

[targets]
test = ["ArchGDAL"]
test = ["ArchGDAL","Plots"]
77 changes: 76 additions & 1 deletion examples/2_landmarks.jmd
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Landmark function for testing purposes

```julia
nothing
using ConScape, Rasters, ArchGDAL, SparseArrays, LinearAlgebra, Plots
```

Expand Down Expand Up @@ -83,7 +84,7 @@ heatmap(qbetw)

```julia
qbetw_coarse = ConScape.betweenness_qweighted(h_coarse);
ConScape.heatmap(qbetw_coarse)
heatmap(qbetw_coarse)
```

```julia
Expand All @@ -99,6 +100,80 @@ kbetw_coarse = @time ConScape.betweenness_kweighted(h_coarse, distance_transform
cor(filter(!isnan, kbetw), filter(!isnan, kbetw_coarse))
```

We can write this using a lazy problem definition:

```julia
# Put least cost, random walk, and rsp
problem = ConScape.Problem(;
graph_measures = (;
func=ConScape.ConnectedHabitat(),
qbetw=ConScape.BetweennessQweighted(),
kbetw=ConScape.BetweennessKweighted(),
),
connectivity_measure=ConScape.ExpectedCost(
θ=1.0,
distance_transformation = (exp=x -> exp(-x/75), oddsfor=ConScape.OddsFor())
),
solver=ConScape.MatrixSolver(),
# solver=ConScape.VectorSolver(nothing),
)
```

Then run it for all operations on both normal and coarse grids

```julia
rast = RasterStack((; affinities=mov_prob, qualities=hab_qual))
rast_coarse = ConScape.coarse_graining(rast, 20)
result = ConScape.solve(problem, rast)
result_coarse = ConScape.solve(problem, rast_coarse)
```

We can plot these outputs:
```julia
heatmap(result.qbetw_oddsfor)
heatmap(result_coarse.qbetw_oddsfor)
heatmap(result.qbetw_exp)
heatmap(result_coarse.qbetw_exp)
heatmap(result.kbetw_exp)
heatmap(result_coarse.kbetw_exp)
heatmap(result.func_exp)
heatmap(result.coarse_func_exp)
```


```julia
windowed_problem = ConScape.WindowedProblem(problem;
radius=20, overlap=5, threaded=true
)
@time result = ConScape.solve(windowed_problem, rast)
plot(result)
plot(result.func_exp)
```


```julia
stored_problem = ConScape.BatchProblem(problem;
path=".", radius=20, overlap=30, threaded=true
)
ConScape.solve(stored_problem, rast)
result = mosaic(stored_problem; to=rast)
plot(result)
plot(result.func_exp)

# Calculate job ids to run on a cluster
jobs = ConScape.batch_ids(stored_problem, rast)
```

And we can check the corelation similarly to above, by getting
layers from `res` and `res_coarse`
```julia
cor(filter(!isnan, res.qbetw.oddsfor), filter(!isnan, res_coarse.qbetw.oddsfor))
cor(filter(!isnan, res.qbetw.oddsfor), filter(!isnan, res_coarse.qbetw.oddsfor))
cor(filter(!isnan, res.kbetw.oddsfor), filter(!isnan, res_coarse.kbetw.oddsfor))
cor(filter(!isnan, res.kbetw.exp), filter(!isnan, res_coarse.kbetw.exp))
cor(filter(!isnan, res.func.exp), filter(!isnan, res_coarse.func.exp))
```

# Test landmark performance for amount of connected habitat

```julia
Expand Down
37 changes: 37 additions & 0 deletions ext/ConScapeCUDSS.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
module ConScapeCUDSS

using ConScape
using CUDA
using CUDA.CUSPARSE
using CUDSS
using SparseArrays
using LinearAlgebra

using ConScape: FundamentalMeasure, AbstractProblem, Grid, setup_sparse_problem

struct CUDSSsolver <: Solver end

function ConScape.solve(m::CUDSSsolver, cm::FundamentalMeasure, p::AbstractProblem, g::Grid)
(; A, B, Pref, W) = setup_sparse_problem(g, cm)
Z = zeros(T, size(B))

A_gpu = CuSparseMatrixCSR(A |> tril)
Z_gpu = CuMatrix(Z)
B_gpu = CuMatrix(B)

solver = CudssSolver(A_gpu, "S", "L")

cudss("analysis", solver, Z_gpu, B_gpu)
cudss("factorization", solver, Z_gpu, B_gpu)
cudss("solve", solver, Z_gpu, B_gpu)

Z .= Z_gpu
# TODO: maybe graph measures can run on GPU as well?
grsp = GridRSP(g, cm.θ, Pref, W, Z)
results = map(p.graph_measures) do gm
compute(gm, p, grsp)
end
return _merge_to_stack(results)
end

end
53 changes: 53 additions & 0 deletions ext/ConScapeLinearSolveExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
module ConScapeLinearSolveExt

using ConScape
using LinearSolve
import CommonSolve

function CommonSolve.init(solver::LinearSolver, A::AbstractMatrix)
b = zeros(eltype(A), size(A, 2))
# Define and initialise the linear problem
linprob = LinearProblem(A, b)
linsolve = init(linprob, solver.args...; solver.keywords...)
# TODO what is needed here?
# Create a channel to store problem b vectors for threads
# see https://juliafolds2.github.io/OhMyThreads.jl/stable/literate/tls/tls/
if isthreaded(solver)
nbuffers = Threads.nthreads()
channel = Channel{Tuple{typeof(linsolve),Vector{Float64}}}(nbuffers)
for i in 1:nbuffers
# TODO fix this in LinearSolve.jl with batching
# We should not need to `deepcopy` the whole problem we
# just need to replicate the specific workspace arrays
# that will cause race conditions.
# But currently there is no parallel mode for LinearSolve.jl
# See https://github.com/SciML/LinearSolve.jl/issues/552
put!(channel, (deepcopy(linsolve), Vector{eltype(A)}(undef, size(A, 2))))
end
return channel
else
return linsolve
end
end

function LinearAlgebra.ldiv!(s::LinearSolver, B, init, B_copy)
# TODO: for now we define a Z matrix, but later modify ops
# to run column by column without materialising Z
if isthreaded(s)
channel = init
# Get column memory from the channel
linsolve = take!(channel)
# Update solver with new b values
reinit!(linsolve; b=vec(B_copy), reuse_precs=true)
sol = LinearSolve.solve!(vec(B), linsolve, s.args...; s.keywords...)
vec(B) .= sol.u
put!(channel, linsolve)
else
linsolve = init
reinit!(linsolve; b=vec(B_copy), reuse_precs=true)
sol = LinearSolve.solve(linsolve, s.args...; s.keywords...)
vec(B) .= sol.u
end
return B
end
end
81 changes: 55 additions & 26 deletions src/ConScape.jl
Original file line number Diff line number Diff line change
@@ -1,30 +1,59 @@
module ConScape

using SparseArrays, LinearAlgebra
using Graphs, Plots, SimpleWeightedGraphs, ProgressLogging, ArnoldiMethod
using Rasters
using Rasters.DimensionalData

abstract type ConnectivityFunction <: Function end
abstract type DistanceFunction <: ConnectivityFunction end
abstract type ProximityFunction <: ConnectivityFunction end

struct least_cost_distance <: DistanceFunction end
struct expected_cost <: DistanceFunction end
struct free_energy_distance <: DistanceFunction end

struct survival_probability <: ProximityFunction end
struct power_mean_proximity <: ProximityFunction end

# Randomized shortest path algorithms
include("randomizedshortestpath.jl")
# Grid struct and methods
include("grid.jl")
# GridRSP (randomized shortest path) struct and methods
include("gridrsp.jl")
# IO
include("io.jl")
# Utilities
include("utils.jl")
using ArnoldiMethod
using ConstructionBase
using Graphs
using LinearAlgebra
using Rasters
using SimpleWeightedGraphs
using SparseArrays
using Rasters.DimensionalData

import CommonSolve
import CommonSolve: solve, init

export RandomisedShortestPath, LeastCost, RandomWalk

export ExpectedCost, FreeEnergyDistance, SurvivalProbability, PowerMeanProximity, KullbackLeiblerDivergence

export Betweenness, EdgeBetweenness, ConnectedHabitat, Criticality, EigMax, Sensitivity

export QualityWeighted, QualityAndProximityWeighted, ProximityWeighted

export VectorSolver, LinearSolver

export MinusLog, MinusLogAlpha, Inv, OddsFor, OddsAgainst, ExpMinus, ExpMinusAlpha

export solve, init, assess

export WindowedProblem, BatchProblem

"""
Solver

Abstract supertype for ConScape solvers.
"""
abstract type AbstractProblem end
abstract type Solver end

# Randomized shortest path algorithms
# Grid struct and methods
include("transformations.jl")
# Grid struct and methods
include("grid.jl")
# Utilities
include("utils.jl")
# Problems
include("workspaces.jl")
include("measures.jl")
include("movement_modes.jl")
include("problem.jl")
include("initialisation.jl")
include("return.jl")
include("solvers.jl")
include("compute_measures.jl")
include("windows.jl")
include("assessment.jl")
include("simulations.jl")

end
Loading