///|
pub(all) struct ProductResult {
  ranking : Ranking
  log_contributions : Array[Array[Double]]
  relative_products : Array[Double]
} derive(@debug.Debug)

///|
/// Scores are log products; relative_products are exp(score - best_score).
pub fn weighted_product(
  m : DecisionMatrix,
  weights : Array[Double],
  tolerance~ : Double = 1.0e-10,
) -> ProductResult raise ChoiceError {
  let w = matrix_weights(m, weights)
  let (n, p) = m.shape()
  let terms = zeros(n, p)
  for j in 0..

checked(sum(row))) let best = maximum(scores) let relative_products = scores.map(x => @math.exp(x - best)) { ranking: rank_scores(m.names, scores, tolerance~), log_contributions: terms, relative_products, } } ///| pub extend ProductResult with @debug.Debug::{to_repr}