selection_frequency() without changing
recurrence counts, and use pre-rendered maps in the large
forest-restoration vignette to reduce package build and check
times.load_meseta() and
load_ecosystem_services() alongside
load_sim_multiaction() as the three complete example-data
entry points. Updated the README and integrated-planning vignette;
historical data() and raster-only access remain unchanged
for compatibility.Added add_objective_max_effect() and
add_objective_min_effect() for signed changes relative to
the reference, including action interactions. Their arguments are
x, actions, features, and
alias.
add_objective_max_benefit() is deprecated with
lifecycle and delegates to add_objective_max_effect(),
retaining the development branch’s signed-net behavior. The published
positive-only behavior changed earlier in this branch.
add_objective_min_loss() is deprecated but retains
its original final negative-part criterion. min_effect() is
not an equivalent replacement: it minimizes signed change and permits
compensation. No removal date is set.
Added an educational Meseta Ibérica action-planning tutorial, bundled inputs, and a runnable script covering spatial-cost trade-offs and spatial analyses.
Improved prototype/data-cloning memory use and indexed planning-unit analyses.
Bounded polygon/raster extraction buffers to avoid eager full-raster allocation failures when building large landscape examples.
Fixed single-objective min_cost action scopes so
they agree with the MO cost criterion; planning-unit costs remain global
and feasible actions retain their original indices.
Fixed CBC crashes/short solution vectors caused by trailing empty matrix rows or columns, including fully locked legacy impact models. A redundant bound row preserves dimensions without changing the feasible decisions.
MO solves use bounded positive scalar-objective rescaling, with values returned in their original units. CBC and Gurobi receive precise numerical defaults; explicit solver parameters take precedence. Epsilon bounds are checked against reevaluated selected decisions and checks/effective settings are recorded in solution diagnostics. Binary integrality noise no longer enters objective evaluation or automatic epsilon endpoints.
After an optimal AUGMECON solve, refine normalized slacks at the attained primary level within the remaining time limit. The original augmented criterion and global status/gap are preserved and refinement is recorded.
Native model allocation reserves memory according to the actual core size rather than one million rows/columns for every temporary MO model.
Deprecated add_objective_min_intervention_impact()
with lifecycle. It keeps its original behavior and
arguments until removal in a future release. New workflows express
action consequences through effects and net benefit. The
forest-restoration example now uses deficit effects with a common
ceiling per feature and fixed restoration effort, documenting the
equivalence and its limits. Cached plans are migrated by exact affine
evaluation of their decisions.
Changed behavior:
add_objective_max_benefit() now maximizes signed net change
relative to the reference, including negative individual effects and
interaction corrections. Earlier versions counted positive effects only;
models with negative effects may select different plans. Names and
public arguments are unchanged; no separate net-benefit function is
introduced.
add_objective_min_loss() retains its loss-only
criterion, with the negative part computed after combining actions
within each planning unit and feature. Exact loss auxiliaries support
mixed signs, overlapping scopes, zero weights, secondary bounds, and
payoff/lexicographic solves in all three MO methods.
Concurrent individual effects are additive unless joint totals
are supplied. Ecological targets and result summaries count the
reference once per selected unit in their action scope, using signed
joint changes for final outcomes. selected_benefit remains
the positive-gain metric; selected_net matches the signed
benefit objective when their scopes coincide.
Modern add_effects() tables and rasters accept
registered action sets as total joint outcomes, effects, or relative
changes. Original totals and input tables are preserved separately from
sparse signed subset corrections. Missing interactions/individual
effects are explicitly assumed zero. Exact continuous AND auxiliaries
are shared across features, created only for feasible non-zero
corrections, and integrated into single-objective and all three MO
formulations. Inferred negative outcomes are excluded. Joint solution
summaries aggregate signed changes per PU/feature and count the selected
reference once. Signed ecological objectives and concurrent targets use
the final aggregation described above.
Added add_constraint_action_requires() (all/any
companions), add_constraint_action_excludes() (at most one
group member), and add_constraint_action_together() (all or
none), scoped separately by PU. Distinct rules accumulate; duplicate
identities and names are errors. Unavailable actions are treated as
zero, including missing pairs, exclusions, and filtered non-finite
costs. Relations use the same compiled feasible set for
single-objective, weighted-sum, epsilon-constraint, and AUGMECON
methods. They do not lift the default action-count limit or introduce
joint effects.
Defined a strict repeated-call contract without adding public arguments. Actions, effects (including legacy wrappers), profit, solver settings, MO methods, and unaliased objectives can be defined only once per problem. Second definitions raise an error instead of replacing data or settings. Distinct sets, constraints, spatial names, and objective aliases accumulate. Locks accumulate compatible states and reject inversions in either call order. Targets reject duplicate feature/action scopes immediately, including across absolute and relative calls. Budget identity includes cost components and area identity includes its measure. Compare configurations by deriving each alternative from a common problem before its first definition.
Added add_constraint_action_cardinality() for
per-unit minimum, maximum, or exact action counts. Repeated calls
support distinct spatial and action scopes; explicit total
maxima/equalities replace the implicit one-action limit only in their
covered units. Rules are compiled for single-objective and
multi-objective methods, including concurrent economic and ecological
workflows with final feature aggregation.
Added add_action_sets() for named lists or long
membership tables and get_action_sets() for inspecting
definitions. Actions can belong to several sets. Definitions are
independent of action feasibility, selection rules, costs, and effects;
registering them does not enable simultaneous actions.
Action-set registration validates members and identifier conflicts, adds new sets across calls, and preserves the original problem. Action catalogs are fixed after their first definition, protecting dependent sets and indices.
add_effects() now accepts exactly one of
effect, outcome, or
relative_change. Tables without pu expand over
feasible action pairs.reference_amount,
action_outcome, and signed effect, while
retaining amount_after, benefit, and
loss for compatibility.raster_aggregation and raster_type
for spatial effect inputs.add_effects() and removed legacy
syntax from implicit reserve-model setup.add_spatial_relations() now supports
allow_self = TRUE together with
directed = TRUE. Diagonal entries (i, i) in
directed relations are interpreted as unary planning-unit terms rather
than as directed self-dependencies.frontier_neighbors(),
linkage_distances(), linkage_transition(),
linkage_turnover(), and linkage_contrasts()
for objective–decision linkage analysis.get_solution_states() and
selection_consistency() for summarizing spatial decisions
across solutions.gap_limit precision.load_sim_multiaction() and its associated
simulated planning units, features, action costs, and action-specific
effects for examples, tests, and introductory documentation.restoration action, while retaining fixed conservation
commitments as spatial context.SolutionSet to support
reproducible vignette and pkgdown builds without requiring Gurobi or
rerunning the full optimization.solution_id
is shown as the first column.run_id from user-facing solution extractors and
frontier outputs; it is now kept for get_runs() and
internal matching only.internal_id from
planning-unit outputs.get_targets() so it consistently returns
solution_id instead of run_id.frontier_extremes() and
frontier_distances() to follow the same
solution_id-based output convention.get_runs().Renamed planning-unit functions and arguments to use
planning_units consistently instead of
pu.
Deprecated older function aliases kept for backwards compatibility:
get_pu() in favour of
get_planning_units();plot_spatial_pu() in favour of
plot_spatial_planning_units();add_constraint_locked_pu() in favour of the
planning-unit naming convention;add_objective_min_fragmentation_pu() in favour of
add_objective_min_fragmentation_planning_units().Deprecated older multi-objective run helpers:
run_grid() in favour of
set_runs_grid();run_manual() in favour of
set_runs_manual();mo_control() in favour of
set_runs_control().solution_id as
the main identifier for stored solutions.run_id primarily for get_runs() and
internal diagnostics, reducing ambiguity in user-facing summary
outputs.get_objectives() to return cleaner user-facing
tables while preserving run-level identifiers internally for frontier
and dominance calculations.solution/solutions terminology
consistently.normalize_weights = FALSE.feasible_only handling from
objective extraction workflows.solution_id-based
public API.run terminology
across getters, plotting, and frontier utilities.solve() consistently returns a SolutionSet,
including for single-objective problems.Solution class from the public API
and documentation. Individual run-level solutions remain available only
as internal components of a SolutionSet.solution_id identifiers to distinguish
stored solutions from attempted runs identified by
run_id.run_id and solution_id consistently across
extraction and analysis functions.SolutionSet printing and documentation to
reflect the distinction between run attempts and stored solutions.dist_features.amount_after to
represent the feature amount obtained when a planning unit is
conserved.run_grid() and run_manual().mo_control().SolutionSet run table.solution_id only to runs that produced a stored
solution.get_runs() to extract run-level status, runtime,
gap, design parameters, solution identifiers, and objective values.get_objectives() to extract objective values in
long or wide format.get_objective_specs() to extract registered
objective aliases, objective types, model types, optimization senses,
and creation metadata.run_id and
solution_id.SolutionSet architecture.solution_filter() to return a coherently filtered
SolutionSet.solution_filter() can filter by run_id,
solution_id, solver status, or feasibility.moocore.SolutionSet objects before
modification to prevent reference-based mutation of the original
object.solution_append() to combine compatible
SolutionSet objects generated from the same planning
problem.solution_append() verifies compatibility of planning
units, features, actions, effects, targets, constraints, locks, spatial
relations, and objective definitions.run_id and solution_id values.solution_unique() to retain one representative
from groups of equivalent solutions.solution_unique() can identify repeated solutions using
either complete decision vectors or objective values.frontier_extremes() to identify the observed
minimum and maximum values of each objective.best or
worst according to each objective’s optimization
sense.frontier_distances() to calculate normalized
distances to observed ideal and nadir points.SolutionSet.selection_frequency() to calculate how frequently
each planning-unit/action assignment is selected across stored
solutions.conservation action.selection_similarity() to quantify structural
similarity among solutions.Solution class.SolutionSet terminology.run_id,
solution_id, objective extraction, filtering, frontier
analysis, and selection analysis.moocore as an optional dependency for
non-dominance filtering.multiscape.Problem, Solution, and
SolutionSet classes. The public result architecture was
later unified around SolutionSet in version 1.1.0.create_problem(), add_*(),
set_*(), and solve().