Changes in Version 0.5.0
  o Input validation of IsingSampler() and the distribution functions was fixed and broadened. IsingSampler() previously guarded 'graph' and 'thresholds' with an OR condition, so supplying only one of them passed the check and later failed with an obscure error; it now requires each explicitly with a clear message. IsingSampler() additionally validates that 'graph' is a numeric square symmetric matrix, that 'n' and 'nIter' are single positive integers, that 'beta' is a single finite numeric value, and that 'thresholds' has length 1 or the number of nodes. The same graph / threshold-length checks were mirrored in IsingDir(), IsingLikelihood(), IsingSumLikelihood() and IsingStateProb(); IsingStateProb() now also checks that 'graph' is symmetric and that each supplied state has length equal to the number of nodes.
  o The 'constrain' argument of IsingSampler() is now honored by all three sampling methods (fixes GitHub issue #1). Previously constraints were silently ignored for method = "CFTP" and method = "direct" and only worked for method = "MH". Constrained (clamped) nodes are fixed to the given value and the remaining nodes are sampled from the conditional distribution given the clamped nodes: for "CFTP" clamped nodes are never updated in the coupling chains (yielding exact conditional samples), and for "direct" the state space is restricted to the states matching each constraint row and the probabilities are renormalized. In addition, 'constrain' is now validated for all methods: it must be an n x N (samples by nodes) matrix and all non-NA entries must be members of 'responses'.
  o Fixed IsingPL(): the 'beta' (inverse temperature) argument was silently ignored in the C++ pseudo-likelihood computation, so any value of 'beta' returned the pseudo-likelihood for beta = 1. The node-conditional term now applies beta to both the observed-state term and the normalizing constant, whose log-sum-exp is computed with a max-shift for numerical stability at large beta. In addition, the 'responses' argument was truncated to integers internally; it is now passed as numeric, so non-integer response options (supported everywhere else since 0.3.1) are preserved. Results for the default binary c(0, 1) responses with beta = 1 (including EstimateIsingPL(), which uses beta = 1) are unchanged.
  o The 'beta' argument of the non-regularized estimators (EstimateIsing() and EstimateIsingPL(), EstimateIsingUni(), EstimateIsingBi(), EstimateIsingLL()) was accepted but ignored. It is now honored under a single convention: since the Ising measure depends on the parameters only through beta * graph and beta * thresholds, all estimators return parameters that, combined with the supplied beta, reproduce the data-generating distribution (i.e. the beta = 1 estimates divided by beta). For 'pl' this is achieved by optimizing the pseudolikelihood at the supplied beta; for 'uni', 'bi' and 'll' by rescaling the beta = 1 estimates. The raw 'results' element is not rescaled. In addition, EstimateIsingPL() no longer ignores its 'responses' argument (previously it always recomputed the response coding from the data) and warns when a supplied 'responses' coding does not match the values present in the data. Results with the default beta = 1 are unchanged.
  o IsingSampler(..., method = "direct") now returns an unnamed matrix, matching methods "MH" and "CFTP" (and the "A matrix" documented in ?IsingSampler). Previously "direct" returned a data.frame. Integer-valued responses give integer storage and non-integer responses give double storage, exactly as for the other methods; this holds whether or not a 'constrain' matrix is supplied.
  o Fixed the minimum sum-score correction of EstimateIsingUni(): 'min_sum' refers to sum scores on the original response coding, but the per-node row filter ran after the data were recoded to 0/1, so for data coded differently (e.g. c(1, 2) or c(-1, 1)) it filtered the wrong rows (usually none). The biased-row condition is now evaluated on the raw data: for node i a row is dropped iff its rest score is compatible with the truncation when node i takes the high response but not when it takes the low response. For 0/1-coded data this reduces exactly to the previous filter, so results on 0/1 data are unchanged; the default min_sum = -Inf continues to drop no rows.
  o The misspelled IsingEntrophy() has been renamed to the correctly spelled IsingEntropy() (fixes GitHub issue #3). The old name IsingEntrophy() is retained as a deprecated wrapper that emits a deprecation warning and forwards to IsingEntropy(), so existing code keeps working. Behaviour is otherwise unchanged.
  o Removed dead C++ code from src/IsingCpp_CFTP.cpp: the exported but never-called Broderick2013() estimator and its private helpers expvalues(), vec2Thresh() and vec2Graph() (which were only used by Broderick2013()), together with adjacent large commented-out blocks (vecSampler, FakeUnif, ExchangeAlgo and a commented progress_bar). Broderick2013() could not produce meaningful estimates (its importance-weight expression self-cancels and its initialization was immediately overwritten), so keeping a broken estimator compiled into the package invited accidental use. No user-facing functionality is affected.
  o Package hygiene: Rcpp was moved from Depends to Imports (it is only used internally, via import(Rcpp) and LinkingTo), so it is no longer attached to the user's search path; a duplicate export(EstimateIsing) directive was removed from NAMESPACE; and the stray editor backup file inst/COPYRIGHTS~ was removed from the sources.
  o The CFTP retry diagnostic ("Restarting CFTP chain, attempt: ...") is now emitted with message() instead of cat(), so it can be silenced with suppressMessages() and is sent to the message stream rather than standard output.
  o Added a regression test suite under tests/ (plain stopifnot scripts, no new dependencies), covering input validation, the 'constrain' argument, pseudo-likelihood and estimator behaviour, return types, entropy, the minimum sum-score correction, and the sampling distributions: the empirical state distributions of all three sampling methods are checked against the exact IsingLikelihood() probabilities, IsingStateProb() and IsingSumLikelihood() are checked to define proper (normalized) distributions, and LinTransform() is checked to leave state probabilities invariant across the 0/1 and -1/1 codings.
  o IsingEntropy() and NodeInformation() gained a 'delta' argument (default 0), mirroring IsingLikelihood(), so entropy and mutual-information computations can be made under a Blume-Capel (per-node quadratic) term; it is forwarded to the underlying IsingLikelihood() call. NodeInformation(), which returns for each node the mutual information I(node; rest of network) = H(rest) - H(rest | node), is now exported and documented (previously its export was commented out and it lacked a help page).
  o LinTransform() now validates its arguments: 'from' and 'to' must each have length 2, and 'a' and 'b' must be supplied together or not at all (supplying exactly one now gives a clear error instead of a silent partial transform).
  o Documentation fixes: the 'constrain' matrix layout (n x N, NA marks a free node) is now illustrated with a runnable example in ?IsingSampler showing all three methods honoring it, and ?EstimateIsing gained a note that method "bi" (EstimateIsingBi) can be unreliable when the joint high-high (1, 1) response pair is rarely observed.
Changes in version 0.4.0
  o Added BlumeCapelSampler(), a wrapper around IsingSampler() for the Blume-Capel model: an Ising model with an additional on-site quadratic ("single-ion anisotropy" / crystal-field) term entering the Hamiltonian as delta_i * s_i^2. By default it uses the spin-1 response options c(-1, 0, 1) and requires the quadratic parameter 'delta'.
  o IsingSampler(), IsingLikelihood(), IsingSumLikelihood() and IsingStateProb() gained a 'delta' argument (default 0, i.e. the ordinary Ising model). 'delta' may be a single value (recycled over nodes) or one value per node, exactly like 'thresholds'; a single 'thresholds' value is now likewise recycled over nodes. A positive delta favours response options near zero, a negative delta favours the extreme options.
  o The 'delta' term only has an identifiable effect with more than two response options. With two response options it is folded into the thresholds (and is constant, hence has no effect, for symmetric responses such as c(-1, 1)); method = "CFTP" therefore remains binary-only and accounts for delta exactly via this folding.

Changes in version 0.3.1
  o Response options may now be any numeric values, including non-integers (e.g. seq(-1, 1, by = 0.5)). The sampler (methods "MH", "CFTP" and "direct") and the distribution functions all work with real-valued responses; in that case states are returned as a numeric (double) matrix. Integer-valued responses continue to return integer matrices, so existing binary/ordinal use is unchanged. Internally states, response options, the 'constrain' matrix and the sampled output are now double-valued throughout the C++ code.
  o IsingSampler, IsingLikelihood, IsingSumLikelihood, IsingStateProb and IsingEntrophy support more than two response options (e.g. c(-1L, 0L, 1L) or 1:5). Sampling with method = "MH" uses the categorical (softmax) generalization of the binary conditional and initializes the chain uniformly over all response options; method = "direct" and the likelihood functions sum over all response combinations. The pairwise interaction enters the Hamiltonian as J_ij * s_i * s_j and each node keeps a single threshold. Binary (two-level) behaviour is unchanged.
  o method = "CFTP" remains restricted to two response options (with an informative error for more than two), but now also works with two non-integer responses.
  o The 'responses' argument is now validated: a clear error is given when it contains fewer than two options or any non-numeric or missing (NA) values.
  o IsingEntrophy and NodeInformation now use the current dplyr API (group_by()/summarise()), fixing an error under recent dplyr versions.
  o Removed the obsolete src/Makevars and src/Makevars.win (the deprecated Rcpp:::LdFlags() call is no longer needed); the package now passes R CMD check --as-cran without warnings.

Changes in version 0.2.4
  o Fixed URL in DESCRIPTION

Changes in version 0.2.2
  o Small change to help file

Changes in version 0.2.2
  o Added thresholding and minimum sum score correction to EstimateIsing Uni method
  o 'uni' is now the default for EstimateIsing

Changes in version 0.2.1
  o Added an option to IsingLikelihood to return the potential of each state

Changes in version 0.2:
  o Added methods for estimating the Ising model without regularization, see ?EstimateIsing