# *shortr* 1.0.3

## Performance

### Simulated annealing

- O(`base::ceiling(base::log(stop.temp / start.temp) / base::log(cool.fact))` · `n`) time, O(`n^2`) space → O(`base::ceiling(base::log(stop.temp / start.temp) / base::log(cool.fact))` · `k`) time, O(`n^2`) space. Swap evaluation now computes delta updates via unchanged indices (`unch.idx`), replacing the maintained `link` vector and matching the brute force update pattern.

# *shortr* 1.0.2

## Arguments and value

### Renamed arguments

- `adj.mat` → `n.mat`. The first argument of interest is n.mat, not necessarily a symmetric adjacency matrix of numeric, but a symmetric matrix of numeric corresponding to the symmetric matrix of associations (e.g., of zero-order polychoric correlation coefficients) computed from the set of items comprised in the original version of the said psychometric instrument.
- `method` → `algorithm`. The third argument of interest is algorithm (rather than method), a character matching either “brute.force” or “simulated.annealing” corresponding to the combinatorial search algorithm.

### Removed arguments

- `absolute` now always `TRUE`.
- `max.iter` now always `base::ceiling(base::log(stop.temp / start.temp) / base::log(cool.fact))`.

### Renamed value

- `optimal.S` → `solution.character`.
- `optimal.function.S` → `solution.numeric`.

## Robustness and correctness

- `base::set.seed()` no longer permanently alters the global RNG state. `.Random.seed` is now saved and restored via `base::on.exit()`.
- Progress bars are now closed via `base::on.exit()`, ensuring cleanup even on early exit or error.
- The diagonal of the input matrix is now explicitly set to zero before computation, preventing self-associations from inflating the objective.
- `NA`/`NaN` values in the input matrix now trigger a warning with a count of affected entries before being replaced with zeros.
- Input validation now checks for `Inf` values, non-numeric entries, non-square matrices, and matrices smaller than 2 × 2.
- Scalar parameter validation now checks length, type, and `NA` status consistently across all parameters.
- `algorithm` now uses `base::match.arg()` instead of manual `%in%` checking, supporting partial matching.
- SA-specific parameters (`start.temp`, `cool.fact`, `stop.temp`, `n.runs`, `seed`) are now validated only when `algorithm = "simulated.annealing"`.
- Error messages now use `call. = FALSE` for cleaner console output.
- `k = 0` and `k = n` are now rejected during validation rather than handled as special cases inside the algorithm.
- `seed` now explicitly accepts `NULL` to skip setting the RNG state.

## Performance

### Brute force

- Subsets are now enumerated incrementally with delta updates to the objective function, replacing the previous approach of generating all candidate subsets in memory via `utils::combn()`. This reduces memory from O(C(n,k) × k) to O(n) and avoids recomputing the full objective at each step.
- When `k > n / 2`, enumeration is performed over the smaller complement, reducing the number of combinations to evaluate.
- The absolute value matrix is now precomputed once, rather than recomputed inside the objective function at every evaluation.
- Brute force now detects intractable problems (C(n,k) exceeding `.Machine$integer.max`) and exits with a recommendation to use simulated annealing, rather than attempting to allocate the full combination matrix.

### Simulated annealing

- Swap evaluation now runs in O(n) via a maintained `link` vector, replacing the previous full matrix subsetting at each step.
- The complement set is now maintained incrementally via a logical membership vector, replacing repeated `base::setdiff()` calls.
- Removed the hash environment that stored all visited subsets as character keys, eliminating unbounded memory growth over long runs.

# shortr 1.0.1

- Initial *CRAN* release.
