% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/matching_distance_cache.R
\name{compute_distances}
\alias{compute_distances}
\title{Compute and Cache Distance Matrix for Reuse}
\usage{
compute_distances(
  left,
  right,
  vars,
  distance = "euclidean",
  weights = NULL,
  scale = FALSE,
  auto_scale = FALSE,
  left_id = "id",
  right_id = "id",
  block_id = NULL,
  memory_mode = "auto"
)
}
\arguments{
\item{left}{Left dataset (data frame)}

\item{right}{Right dataset (data frame)}

\item{vars}{Character vector of variable names to use for distance computation}

\item{distance}{Distance metric (default: "euclidean")}

\item{weights}{Optional numeric vector of variable weights}

\item{scale}{Scaling method: FALSE, "standardize", "range", or "robust"}

\item{auto_scale}{Apply automatic preprocessing (default: FALSE)}

\item{left_id}{Name of ID column in left (default: "id")}

\item{right_id}{Name of ID column in right (default: "id")}

\item{block_id}{Optional block ID column name for blocked matching}

\item{memory_mode}{One of "auto" (default), "dense", or "lazy". "auto"
warns (or, for a built-in distance metric, switches) when the dense
matrix would consume a large fraction of free system RAM. "lazy" returns
a \code{lazy_cost_spec} instead of a matrix (built-in distance metrics only);
pass it straight to \code{match_couples()} the same way as a dense
\code{cost_matrix}. "dense" skips the RAM check entirely.}
}
\value{
An S3 object of class "distance_object" containing:
\itemize{
\item \code{cost_matrix}: Numeric matrix of distances
\item \code{left_ids}: Character vector of left IDs
\item \code{right_ids}: Character vector of right IDs
\item \code{block_id}: Block ID column name (if specified)
\item \code{metadata}: List with computation details (vars, distance, scale, etc.)
\item \code{original_left}: Original left dataset (for later joining)
\item \code{original_right}: Original right dataset (for later joining)
}
}
\description{
Precomputes a distance matrix between left and right datasets, allowing
it to be reused across multiple matching operations with different
constraints. This is particularly useful when exploring different matching
parameters (max_distance, calipers, methods) without recomputing distances.
}
\details{
This function computes distances once and stores them in a reusable object.
The resulting distance_object can be passed to \code{match_couples()}
(optionally with \code{method = "greedy"}) instead of providing datasets and
variables.

Benefits:
\itemize{
\item \strong{Performance}: Avoid recomputing distances when trying different constraints
\item \strong{Exploration}: Quickly test max_distance, calipers, or methods
\item \strong{Consistency}: Ensures same distances used across comparisons
}

With the default \code{memory_mode = "auto"}/\code{"dense"}, the stored \code{cost_matrix}
is a plain dense matrix; couplr has no sparse matrix representation, so
forbidden pairs (\code{Inf}) still occupy a cell rather than being dropped from
storage. With \code{memory_mode = "lazy"}, \code{cost_matrix} is instead a
\code{lazy_cost_spec} that recomputes distances on demand from the underlying
feature data.

The distance_object stores the original datasets, allowing downstream
functions like \code{join_matched()} to work seamlessly.
}
\examples{
# Compute distances once
left <- data.frame(id = 1:5, age = c(25, 30, 35, 40, 45), income = c(45, 52, 48, 61, 55) * 1000)
right <- data.frame(id = 6:10, age = c(24, 29, 36, 41, 44), income = c(46, 51, 47, 60, 54) * 1000)

dist_obj <- compute_distances(
  left, right,
  vars = c("age", "income"),
  scale = "standardize"
)

# Reuse for different matching strategies
result1 <- match_couples(dist_obj, max_distance = 0.5)
result2 <- match_couples(dist_obj, max_distance = 1.0)
result3 <- match_couples(dist_obj, method = "greedy", strategy = "sorted")

# All use the same precomputed distances

}
