Density dependence in an integrated population model with prior parameter estimates

50 views
Skip to first unread message

Jeffrey Hostetler

unread,
Jun 24, 2025, 1:21:41 PMJun 24
to nimble-users
Hello,

Apologies for cross-posting.

We developed an integrated population model (IPM) for a marine mammal that we're now adapting in various ways. One of these adaptations is to build in density dependence in reproductive probabilities:

  # reproduction
  for(i in 1:nYearsRepro){
    ggb[i] <- ilogit(rep.betas[i])
    rep.betas[i] <- rep.inter + rep.coef * (Ntot[i] / K[i]) + kappa[i]
    kappa[i] ~ dnorm(0, rep.prec)
  }


When we try to define the model in NIMBLE, we get the following error message:

Error in igraph::topo_sort(graph, mode = "out") :
At vendor/cigraph/src/properties/dag.c:125 : The graph has cycles; topological sorting is only possible in acyclic graphs. Invalid value

Since this is the same model of density dependence used in many other IPMs, except for the time-varying carrying capacity (K; which we're not trying to estimate in the IPM), I suspect the error message is due to the workarounds we set up to allow this sort of modeling where the data are not the direct reproductive data but previously estimated reproductive probabilities:

  rep.mu[1:nYearsRepro] ~ dmnorm(rep.betas[1:nYearsRepro],
                                 cov = rep.vcv[1:nYearsRepro,1:nYearsRepro])
  rep.prec ~ dgamma(0.001, 0.001)
  rep.sd <- rep.prec ^ -0.5
  rep.inter ~ dnorm(0, sd = 3)
  rep.coef ~ dnorm(0, sd = 3)

Does anyone know of a way we can make density dependence work within this IPM, short of duplicating previously developed complex mark-recapture models implemented in MARK?

Reproducible example attached.

Thank you,

Jeff

Jeffrey A. Hostetler, Ph.D.
Research Biologist
U.S. Geological Survey
Eastern Ecological Science Center
12100 Beech Forest Road
Laurel, MD 20708
USGS Staff Profile | ORCID


IPM_DDR_example.zip

Daniel Gibson

unread,
Jun 24, 2025, 2:07:16 PMJun 24
to Jeffrey Hostetler, nimble-users
Hi Jeffrey, 

My guess is that the multivariate normal distribution is causing the error since it is 'trying' to resolve all years of fecundity data at once, but the linear model describing fecundity (rep.betas) is being informed by parameters that are being calculated/estimated during each year of the study. I've had acyclic graph issues in the past when I've tried to include DD in the model with multivariate samplers, which were resolved by changing the multivariate sampler to a univariate distribution.

Specifically, if you change the dmnorm section of the code to the following:

  #reproduction
  for(t in 1:nYearsRepro){
     rep.mu[t] ~ dnorm(rep.betas[t],  sd = rep.vcv[t,t])
  }

results in a model that "runs" but loses the ability to leverage the covariance structure specified in the code. I am using runs in quotes since a few other errors popped up based on this parameterization, which superficially looked like initial values problems. 

Best
-Dan

--
You received this message because you are subscribed to the Google Groups "nimble-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nimble-users...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/nimble-users/e8347aa8-d652-478d-8966-e2baabfa4e8bn%40googlegroups.com.

Jeffrey Hostetler

unread,
Jun 24, 2025, 2:40:47 PMJun 24
to nimble-users
Hi Dan,

Thanks for looking into this! 

Did you change anything else? I still get the same error message when I replace the dmnorm with that. 

Jeff

David Christianson

unread,
Jun 24, 2025, 3:35:35 PMJun 24
to nimble-users
Hi Jeff,
Is there any way Ntot[i] is dependent on something on the left hand side in the model code snippets you shared?

Dr. Heather Gaya

unread,
Jun 24, 2025, 4:22:08 PMJun 24
to nimble-users
I think it something to do with this line:  

l.mean.ggp <- logit(mean(ggp[1:(nYears-1)]))

ggp = ggb, which means ggp is dependent on Ntot. In my experience, neither nimble nor JAGS like it when you try to use the mean of the posterior to inform the parameter which you are trying to get the posterior of. (Great English on my part I know :) )

So, I don't know exactly what you want to do to make that work, but you can't use the l.mean.ggp formulation you have above. If you remove that, your code runs clean. 

-Heather 

--
You received this message because you are subscribed to the Google Groups "nimble-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nimble-users...@googlegroups.com.

Jeffrey Hostetler

unread,
Jun 24, 2025, 4:48:45 PMJun 24
to nimble-users
That did it - thank you, Heather! I can work around that issue.

Jeff

Reply all
Reply to author
Forward
0 new messages