use crate::{
core::{Domain, Measure, Measurement, Metric, MetricSpace, PrivacyMap},
error::Fallible,
measures::{Approximate, MaxDivergence, PrivacyProfile, SmoothedMaxDivergence},
traits::InfSub,
};
#[cfg(feature = "ffi")]
mod ffi;
#[cfg(test)]
mod test;
pub fn make_fix_delta<DI, MI, MO, TO>(
m: &Measurement<DI, MI, MO, TO>,
delta: f64,
) -> Fallible<Measurement<DI, MI, MO::FixedMeasure, TO>>
where
DI: Domain,
MI: 'static + Metric,
MO: 'static + FixDeltaMeasure,
(DI, MI): MetricSpace,
{
let privacy_map = m.privacy_map.clone();
let output_measure: MO = m.output_measure.clone();
m.with_map(
m.input_metric.clone(),
m.output_measure.new_fixed_measure()?,
PrivacyMap::new_fallible(move |d_in| {
let profile = privacy_map.eval(d_in)?;
output_measure.fix_delta(&profile, delta)
}),
)
}
pub trait FixDeltaMeasure: Measure {
type FixedMeasure: Measure;
fn new_fixed_measure(&self) -> Fallible<Self::FixedMeasure>;
fn fix_delta(
&self,
curve: &Self::Distance,
delta: f64,
) -> Fallible<<Self::FixedMeasure as Measure>::Distance>;
}
impl FixDeltaMeasure for SmoothedMaxDivergence {
type FixedMeasure = Approximate<MaxDivergence>;
fn new_fixed_measure(&self) -> Fallible<Self::FixedMeasure> {
Ok(Approximate::default())
}
fn fix_delta(&self, profile: &Self::Distance, delta: f64) -> Fallible<(f64, f64)> {
profile.epsilon(delta).map(|v| (v, delta.clone()))
}
}
impl FixDeltaMeasure for Approximate<SmoothedMaxDivergence> {
type FixedMeasure = Approximate<MaxDivergence>;
fn new_fixed_measure(&self) -> Fallible<Self::FixedMeasure> {
Ok(Approximate::default())
}
fn fix_delta(
&self,
(curve, fixed_delta): &(PrivacyProfile, f64),
delta: f64,
) -> Fallible<(f64, f64)> {
let remaining_delta = delta.neg_inf_sub(&fixed_delta)?;
curve.epsilon(remaining_delta).map(|v| (v, delta.clone()))
}
}