Compute pheromone increments (delta_phi) for each node in the ant colony
optimization search tree and update the global pheromone levels (phi)
based on the ants' paths in the current round.
Usage
phi.calculate(
r,
search.space = "ivbase",
fitness_history = NULL,
nodeslst.hist = NULL,
Q = 1,
alpha = 1,
rho = 0.5,
diff_tol = 1,
phi0 = 2,
phi_min = 1,
phi_max = Inf
)Arguments
- r
Integer. Current optimization round.
- search.space
Character, one of "ivbase" or "oralbase". Default is "ivbase".
- fitness_history
Data frame. History of ants' fitness values and decision variable selections across rounds.
- nodeslst.hist
Data frame. History of node-level pheromone values across previous rounds.
- Q
A positive numeric value. Pheromone scaling constant controlling the amount of pheromone deposited by high-quality solutions during each iteration. Defaults to 1.
- alpha
A non-negative numeric value. Exponent controlling the influence of pheromone values on the probability of selecting a component during solution construction. Defaults to 1.
- rho
Numeric in (0, 1). Pheromone evaporation rate. Higher values increase evaporation, encouraging exploration. Defaults to 0.5.
- diff_tol
Numeric. Tolerance threshold controlling when differences in fitness values are treated as meaningful during pheromone updates. Defaults to 1.
- phi0
A non-negative numeric value. Initial pheromone value assigned to all nodes at the start of the search. Defaults to 2.
- phi_min
A non-negative numeric value. Lower bound for pheromone values, preventing premature convergence. Defaults to 1.
- phi_max
A non-negative numeric value. Upper bound for pheromone values, limiting excessive reinforcement. Defaults to Inf.
Details
The update proceeds as follows:
Initialize the node list for the given search space with \(phi = 0\).
Subset the ants from the current round in
fitness_history.Compute rank-based weights so better-performing ants contribute more: $$\Delta \phi \propto 1 / \mathrm{rank}^{\alpha}.$$
Extract the decision columns and attach the computed weights to form a working table of ant paths and contributions.
Map local decision indices to global node numbers using
node.noandlocal.edge.nofrom the node list.For each node, sum contributions from ants that selected the node to obtain \(\Delta \phi\), then update pheromone with evaporation: $$\phi_{\mathrm{new}} = (1 - \rho)\,\phi_{\mathrm{prev}} + \Delta \phi.$$
Clamp updated \(\phi\) to be between
phi_minandphi_max.
Examples
# Define search space
search.space <- "ivbase"
# Example fitness_history from round 1
fitness_history <- data.frame(
round = rep(1, 8),
mod.no = 1:8,
no.cmpt = c(1, 1, 2, 2, 3, 3, 2, 2),
eta.km = c(0, 0, 0, 0, 0, 0, 0, 0),
eta.vc = c(0, 0, 0, 0, 0, 0, 1, 1),
eta.vp = c(0, 0, 0, 0, 0, 0, 0, 1),
eta.vp2 = c(0, 0, 0, 0, 0, 0, 0, 0),
eta.q = c(0, 0, 0, 0, 0, 0, 0, 0),
eta.q2 = c(0, 0, 0, 0, 0, 0, 0, 0),
mm = c(0, 0, 0, 0, 0, 0, 1, 0),
mcorr = c(0, 0, 0, 0, 0, 0, 0, 0),
rv = c(1, 2, 1, 2, 1, 2, 1, 1),
fitness = c(1243.874, 1200.762, 31249.876, 31202.200,
51259.286, 51204.839, 61032.572, 41031.825),
allrank = c(2, 1, 4, 3, 7, 6, 8, 5)
)
# Example node list history
nodeslst.hist <- initNodeList(
search.space = search.space,
phi0 = 2
)
phi.calculate(
r = 1,
search.space = search.space,
fitness_history = fitness_history,
nodeslst.hist = nodeslst.hist
)
#> travel node.no node.name edge.no local.edge.no edge.name phi
#> 1 1 1 compartments 1 1 1Cmpt 2.500000
#> 2 1 1 compartments 2 2 2Cmpt 1.908333
#> 3 1 1 compartments 3 3 3Cmpt 1.309524
#> 4 1 2 eta_vp2 4 0 eta.vp2.no 3.717857
#> 5 1 2 eta_vp2 5 1 eta.vp2.yes 1.000000
#> 6 1 3 eta_q2 6 0 eta.q2.no 3.717857
#> 7 1 3 eta_q2 7 1 eta.q2.yes 1.000000
#> 8 1 4 eta_vp 8 0 eta.vp.no 3.517857
#> 9 1 4 eta_vp 9 1 eta.vp.yes 1.200000
#> 10 1 5 eta_q 10 0 eta.q.no 3.717857
#> 11 1 5 eta_q 11 1 eta.q.yes 1.000000
#> 12 1 6 eta_vc 12 0 eta.vc.no 3.392857
#> 13 1 6 eta_vc 13 1 eta.vc.yes 1.325000
#> 14 1 7 mm 14 0 mm.no 3.592857
#> 15 1 7 mm 15 1 mm.yes 1.125000
#> 16 1 8 eta_km 16 0 eta.km.no 3.717857
#> 17 1 8 eta_km 17 1 eta.km.yes 1.000000
#> 18 1 9 mcorr 18 0 mcorr.no 3.717857
#> 19 1 9 mcorr 19 1 mcorr.yes 1.000000
#> 20 1 10 residual 20 1 add 2.217857
#> 21 1 10 residual 21 2 prop 2.500000
#> 22 1 10 residual 22 3 comb 1.000000
#> delta_phi p
#> 1 1.5000000 0.333
#> 2 0.9083333 0.333
#> 3 0.3095238 0.333
#> 4 2.7178571 0.500
#> 5 0.0000000 0.500
#> 6 2.7178571 0.500
#> 7 0.0000000 0.500
#> 8 2.5178571 0.500
#> 9 0.2000000 0.500
#> 10 2.7178571 0.500
#> 11 0.0000000 0.500
#> 12 2.3928571 0.500
#> 13 0.3250000 0.500
#> 14 2.5928571 0.500
#> 15 0.1250000 0.500
#> 16 2.7178571 0.500
#> 17 0.0000000 0.500
#> 18 2.7178571 0.500
#> 19 0.0000000 0.500
#> 20 1.2178571 0.333
#> 21 1.5000000 0.333
#> 22 0.0000000 0.333