Ratio
Robust measure of scale ratio between two samples — the multiplicative dual of .
- Asymptotic — geometric median of pairwise ratios (via log-space aggregation)
- Domain — ,
- Assumptions — positivity(x), positivity(y)
- Unit — dimensionless
- Complexity —
Properties
- Self-ratio
- Scale equivariance
- Multiplicative antisymmetry
Example
Ratio([1, 2, 4, 8, 16], [2, 4, 8, 16, 32]) = 0.5Ratio(x, x) = 1Ratio(2x, 5y) = 0.4 · Ratio(x, y)
Relationship to Shift
is the multiplicative analog of . While computes the median of pairwise differences , computes the median of pairwise ratios via log-transformation. This relationship is expressed formally as:
The log-transformation converts multiplicative relationships to additive ones, allowing the fast algorithm to compute the result efficiently. The exp-transformation converts back to the ratio scale.
is appropriate for multiplicative relationships rather than additive differences. If one system is twice as fast or prices are 30% lower, the underlying thinking is in ratios. A result of 0.5 means the first group is typically half the size of the second; 2.0 means twice as large. This estimator is appropriate for quantities like prices, response times, and concentrations where relative comparisons make more sense than absolute ones. Both samples must contain strictly positive values.
Algorithm
The estimator measures the typical multiplicative relationship between elements of two samples. Given samples and with all positive values, this estimator is defined as:
A naive approach would compute all ratios, sort them, and extract the median. With , this creates 100 million values, requiring quadratic memory and time.
The presented algorithm avoids this cost by exploiting the multiplicative-additive duality. Taking the logarithm of a ratio yields a difference:
This transforms the problem of finding the median of pairwise ratios into finding the median of pairwise differences in log-space.
The algorithm operates in three steps:
-
Log-transform — Apply to each element of both samples. If was sorted, remains sorted (log is monotonically increasing for positive values).
-
Delegate to Shift — Use the Shift algorithm to compute the desired quantile of pairwise differences in log-space. This leverages the complexity of the Shift algorithm.
-
Exp-transform — Apply to convert the result back to ratio-space. If the log-space median is , then is the original ratio.
The total complexity is per quantile, where represents the convergence precision in the log-space binary search. This is dramatically more efficient than the naive approach.
Memory usage is for storing the log-transformed samples, compared to for materializing all pairwise ratios.
namespace Pragmastat.Algorithms;
using System;
using System.Collections.Generic;
using System.Linq;
using Pragmastat.Exceptions;
using Pragmastat.Internal;
/// <summary>
/// Computes quantiles of pairwise ratios via log-transformation and FastShift delegation.
/// Ratio(x, y) = exp(Shift(log(x), log(y)))
/// </summary>
public static class FastRatio
{
/// <summary>
/// Computes quantiles of all pairwise ratios { x_i / y_j }.
/// Time: O((m + n) * log(precision)) per quantile. Space: O(m + n).
/// </summary>
/// <remarks>
/// Log-transformation preserves sort order for positive values.
/// </remarks>
/// <param name="x">First sample (must be strictly positive).</param>
/// <param name="y">Second sample (must be strictly positive).</param>
/// <param name="p">Probabilities in [0, 1].</param>
/// <param name="assumeSorted">If true, assumes x and y are already sorted in ascending order.</param>
/// <returns>Quantile values for each probability in p.</returns>
public static double[] Estimate(IReadOnlyList<double> x, IReadOnlyList<double> y, double[] p, bool assumeSorted = false)
{
// Log-transform both samples (includes positivity check)
var logX = MathExtensions.Log(x, Subject.X);
var logY = MathExtensions.Log(y, Subject.Y);
// Delegate to FastShift in log-space
var logResult = FastShift.Estimate(logX, logY, p, assumeSorted);
// Exp-transform back to ratio-space
return logResult.Select(v => Math.Exp(v)).ToArray();
}
}
Tests
The test suite contains 37 test cases (25 original + 12 unsorted), excluding zero values due to division constraints. The new definition uses geometric interpolation (via log-space), which affects expected values for even cases.
Demo examples () — from manual introduction, validating properties:
demo-1: , , expected output: (base case, odd )demo-2: , , expected output: (identity property)demo-3: , (= [2×demo-1.x, 5×demo-1.y]), expected output: (scale property)
Natural sequences () — 9 combinations:
natural-1-1: , , expected output:natural-1-2: , , expected output: (, geometric interpolation)natural-1-3: , , expected output:natural-2-1: , , expected output: (, geometric interpolation)natural-2-2: , , expected output:natural-2-3: , , expected output: (geometric interpolation)natural-3-1: , , expected output:natural-3-2: , , expected output: (geometric interpolation)natural-3-3: , , expected output:
Additive distribution () — 9 combinations with :
additive-5-5,additive-5-10,additive-5-30additive-10-5,additive-10-10,additive-10-30additive-30-5,additive-30-10,additive-30-30- Random generation: uses seed 0, uses seed 1
Uniform distribution () — 4 combinations with :
uniform-5-5,uniform-5-100,uniform-100-5,uniform-100-100- Random generation: uses seed 2, uses seed 3
- Note: all generated values are strictly positive (no zeros); values near zero test numerical stability of log-transformation
The natural sequences verify the identity property () and validate ratio calculations with simple integer inputs. Note that implementations should handle the practical constraint of avoiding division by values near zero.
Unsorted tests — verify independent sorting for ratio calculation (12 tests):
unsorted-x-natural-{n}-{m}for : X unsorted (reversed), Y sorted (2 tests)unsorted-y-natural-{n}-{m}for : X sorted, Y unsorted (reversed) (2 tests)unsorted-both-natural-{n}-{m}for : both unsorted (reversed) (2 tests)unsorted-demo-unsorted-x: , (demo-1 with X unsorted)unsorted-demo-unsorted-y: , (demo-1 with Y unsorted)unsorted-demo-both-unsorted: , (demo-1 both unsorted)unsorted-identity-unsorted: , (identity property, both unsorted)unsorted-asymmetric-unsorted-2-3: , (asymmetric, both unsorted)unsorted-power-unsorted-5: , (powers of 2 unsorted)