% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/optimJTC_.R
\name{optimTP.GA}
\alias{optimTP.GA}
\title{Genetic-algorithm optimal phase 2 design for a two-phase genetic association study.}
\usage{
optimTP.GA(
  formula,
  miscov,
  auxvar,
  family,
  n,
  data,
  beta,
  p_gz,
  disp = NULL,
  ga.popsize,
  ga.propelit,
  ga.proptourney,
  ga.ngen,
  ga.mutrate,
  ga.initpop = NULL,
  optimMeasure,
  K.idx = NULL,
  seed = 1,
  verbose = 0,
  cluster = NULL
)
}
\arguments{
\item{formula}{A two-sided \code{\link{formula}} specifying the regression
model of interest, e.g. \code{Y ~ G + Z}.  All variables except those in
\code{miscov} must be present in \code{data}.}

\item{miscov}{Right-hand-side formula identifying the missing-by-design
covariate(s) (the sequencing variant), e.g. \code{~ G}.}

\item{auxvar}{Right-hand-side formula identifying the auxiliary variable
(the GWAS tag SNP), e.g. \code{~ Z}.  Must be present in \code{data}.}

\item{family}{GLM family object (see \code{\link{family}}).  Default:
\code{gaussian()}.}

\item{n}{Integer.  Target phase 2 sample size.}

\item{data}{A \code{data.frame} containing the phase 1 data.  Must include
all variables in \code{formula} (except those in \code{miscov}) and
\code{auxvar}.}

\item{beta}{Numeric vector of assumed regression coefficients, one per
term in \code{formula} (including the intercept).  Setting
\code{beta[G] = 0} triggers the score-test (null-model) criterion; any
non-zero value triggers the Wald (alternative-model) criterion.}

\item{p_gz}{A \code{data.frame} with the assumed joint distribution of
(\code{miscov}, \code{auxvar}).  Must contain columns for each variable
in \code{miscov} and \code{auxvar} and a column \code{q} of
non-negative probability masses summing to 1.  Rows with \code{q <= 0}
are silently removed.}

\item{disp}{Numeric dispersion parameter (variance for Gaussian/Gamma;
fixed at 1 for binomial/Poisson).  If \code{NULL} (default),
estimated as \code{var(Y)}.}

\item{ga.popsize}{Integer.  GA population size (number of candidate
solutions maintained per generation).}

\item{ga.propelit}{Numeric in \eqn{(0, 1)}.  Proportion of the population
that is elite (carried forward unchanged to the next generation).
The elite count is \code{ceiling(ga.popsize * ga.propelit)}.}

\item{ga.proptourney}{Numeric in \eqn{(0, 1)}.  Proportion of the
population used in each tournament selection.  The tournament size is
\code{max(ceiling(ga.popsize * ga.proptourney), 2)}.}

\item{ga.ngen}{Integer.  Number of GA generations to run.}

\item{ga.mutrate}{Numeric in \eqn{[0, 1]}.  Per-index mutation probability.
At each mutation step, each of the \code{n} selected indices is
independently replaced by a randomly chosen non-selected index with
probability \code{ga.mutrate}.}

\item{ga.initpop}{Optional \code{ga.popsize}-by-\code{n} integer matrix of
starting solutions (each row is a candidate subset of size \code{n}).
If \code{NULL} (default), the initial population is generated randomly.
When \code{cluster} is provided, the rows are split evenly across
workers.}

\item{optimMeasure}{Character string specifying the optimality criterion.
One of \code{"Par-spec"} (parameter-specific), \code{"A-opt"}
(A-optimality), or \code{"D-opt"} (D-optimality).}

\item{K.idx}{Integer index (or vector of indices) identifying the
parameter(s) of primary interest.  Required when
\code{optimMeasure = "Par-spec"}.}

\item{seed}{Integer random seed, set before GA initialisation.  Default: 1.}

\item{verbose}{Integer.  If \code{> 0}, the best objective value is printed
every \code{verbose} generations.  Default: \code{0} (silent).}

\item{cluster}{An optional parallel cluster object created by
\code{\link[parallel]{makeCluster}}.  When provided,
\code{length(cluster)} independent GA searches are run in parallel
(each worker receives an equal share of \code{ga.initpop} rows, or a
random initial population if \code{ga.initpop = NULL}), and the best
solution across all workers is returned.  The caller is responsible for
starting and stopping the cluster.  Default: \code{NULL} (sequential
single-run GA).}
}
\value{
An object of class \code{"kofnGA"} (see
  \code{\link[kofnGA]{kofnGA}}) with the following elements:
  \describe{
    \item{bestsol}{Integer vector of length \code{n} giving the row indices
      (in \code{data}) of the selected phase 2 individuals.}
    \item{bestobj}{Numeric value of the optimality criterion at
      \code{bestsol}.}
    \item{pop}{Final population matrix (\code{ga.popsize} rows,
      \code{n} columns), sorted by fitness.}
    \item{obj}{Objective values for each row of \code{pop}.}
    \item{old}{List with per-generation \code{best}, \code{obj}, and
      \code{avg} records.}
    \item{time.elapsed}{Named numeric vector with the pre-processing
      (\code{preproc}) and GA (\code{GA}) times in seconds.}
  }
}
\description{
Uses a genetic algorithm (GA) to search over individual-level phase 2
selection indicators \eqn{R_i \in \{0,1\}} for the subset of size
\code{n} that maximises the anticipated Fisher information for the
regression parameters of interest.  Wraps \code{\link[kofnGA]{kofnGA}}.
When a parallel cluster is supplied, multiple independent GA runs are
executed in parallel and the best solution across all runs is returned.
}
\details{
The fitness function evaluates the anticipated Fisher information
matrix (FIM) for a candidate selection indicator \eqn{R}:
\deqn{\mathrm{FIM}(R) = I_3/N + \sum_{i: R_i=1}(I_{2,i} - I_{3,i})/N,}
where \eqn{I_3} is the empirical score outer-product estimator (the
numerically stable approximation to the full Louis (1982) observed FIM
valid for large \eqn{N}, since \eqn{I_1 \approx I_2} in the genotype
expansion context), and \eqn{I_{2,i}}, \eqn{I_{3,i}} are the
per-individual complete-data score outer product and observed-data
score outer product, respectively.  Under \eqn{H_0} (\code{beta[G] = 0})
the score-test Schur complement is optimised; under \eqn{H_a} the full
inverse FIM is optimised.
}
\examples{
\donttest{
data <- DataGeneration_TPD(N = 500)
data <- data[, c("Y", "Z")]  # phase-1 data: no G column
p_gz <- data.frame(Z = c(0, 0, 0, 1, 1, 1, 2, 2, 2), # theoretical joint distribution
        G1 = c(0, 1, 2, 0, 1, 2, 0, 1, 2), # between G and Z (LD = 0.75, MAF_G = 0.2, MAF_Z = 0.3)
        q = c(0.486, 0.004, 0, 0.143, 0.276, 0.001, 0.011, 0.04, 0.039)) 

res_ga <- optimTP.GA(
  formula      = Y ~ Z + G1,
  miscov       = ~ G1,
  auxvar       = ~ Z,
  family       = gaussian(),
  n            = 100,
  data         = data,
  beta         = c(2, 0.5, 0.1),
  p_gz         = p_gz,
  ga.popsize   = 40,
  ga.propelit  = 0.1,
  ga.proptourney = 0.1,
  ga.ngen      = 50,
  ga.mutrate   = 0.01,
  optimMeasure = "Par-spec",
  K.idx        = 2L
)
cat("Best objective:", res_ga$bestobj, "\n")
cat("Selected indices (first 10):", head(res_ga$bestsol, 10), "\n")

## Parallel processing (2 workers)
cl <- parallel::makeCluster(2L)
res_par <- optimTP.GA(
  formula      = Y ~ Z + G1,
  miscov       = ~ G1,
  auxvar       = ~ Z,
  family       = gaussian(),
  n            = 100,
  data         = data,
  beta         = c(2, 0.5, 0.1),
  p_gz         = p_gz,
  ga.popsize   = 40,
  ga.propelit  = 0.1,
  ga.proptourney = 0.1,
  ga.ngen      = 50,
  ga.mutrate   = 0.01,
  optimMeasure = "Par-spec",
  K.idx        = 2L,
  cluster      = cl
)
parallel::stopCluster(cl)
cat("Best objective (parallel):", res_par$bestobj, "\n")
}

}
\seealso{
\code{\link[kofnGA]{kofnGA}}, \code{\link{twoPhaseDesign}},
  \code{\link{optimTP.LM}}
}
