1use antecedent_core::ExecutionContext;
9use antecedent_estimate::EstimationWorkspace;
10
11use crate::bootstrap_refute::BootstrapRefute;
12use crate::common::{RefutationProblem, RefutationReport};
13use crate::data_subset::DataSubsetRefuter;
14use crate::dummy_outcome::DummyOutcome;
15use crate::error::ValidationError;
16use crate::evalue::EValue;
17use crate::graph_refute::GraphRefuter;
18use crate::overlap::OverlapRefuter;
19use crate::overlap_rule::OverlapRuleRefuter;
20use crate::placebo::PlaceboTreatment;
21use crate::rcc::RandomCommonCause;
22use crate::reisz::ReiszSensitivity;
23use crate::sensitivity::{LinearSensitivity, NonparametricSensitivity, PartialLinearSensitivity};
24use crate::unobserved_common_cause::UnobservedCommonCause;
25
26mod sealed {
27 pub trait Sealed {}
28}
29
30pub trait Validator<A>: sealed::Sealed {
37 type Prepared;
39 type Report;
41
42 fn prepare(
48 &self,
49 artifact: &A,
50 ctx: &ExecutionContext,
51 ) -> Result<Self::Prepared, ValidationError>;
52
53 fn validate(
59 &self,
60 prepared: &mut Self::Prepared,
61 workspace: &mut EstimationWorkspace,
62 ctx: &ExecutionContext,
63 ) -> Result<Self::Report, ValidationError>;
64}
65
66#[derive(Clone, Copy, Debug)]
68pub struct PreparedRefutation<'a> {
69 pub problem: RefutationProblem<'a>,
71}
72
73pub fn run_validator<'a, V>(
79 validator: &V,
80 problem: &RefutationProblem<'a>,
81 workspace: &mut EstimationWorkspace,
82 ctx: &ExecutionContext,
83) -> Result<RefutationReport, ValidationError>
84where
85 V: Validator<
86 RefutationProblem<'a>,
87 Prepared = PreparedRefutation<'a>,
88 Report = RefutationReport,
89 >,
90{
91 let mut prepared = validator.prepare(problem, ctx)?;
92 validator.validate(&mut prepared, workspace, ctx)
93}
94
95macro_rules! impl_effect_validator {
96 ($ty:ty, $call:expr) => {
97 impl crate::validator::sealed::Sealed for $ty {}
98 impl<'a> Validator<RefutationProblem<'a>> for $ty {
99 type Prepared = PreparedRefutation<'a>;
100 type Report = RefutationReport;
101
102 fn prepare(
103 &self,
104 artifact: &RefutationProblem<'a>,
105 _ctx: &ExecutionContext,
106 ) -> Result<Self::Prepared, ValidationError> {
107 Ok(PreparedRefutation { problem: *artifact })
108 }
109
110 fn validate(
111 &self,
112 prepared: &mut Self::Prepared,
113 workspace: &mut EstimationWorkspace,
114 ctx: &ExecutionContext,
115 ) -> Result<Self::Report, ValidationError> {
116 ($call)(self, &prepared.problem, workspace, ctx)
117 }
118 }
119 };
120}
121
122impl_effect_validator!(PlaceboTreatment, |this: &PlaceboTreatment, p, ws, ctx| {
123 this.refute(p, ws, ctx)
124});
125impl_effect_validator!(RandomCommonCause, |this: &RandomCommonCause, p, ws, ctx| {
126 this.refute(p, ws, ctx)
127});
128impl_effect_validator!(BootstrapRefute, |this: &BootstrapRefute, p, ws, ctx| {
129 this.refute(p, ws, ctx)
130});
131impl_effect_validator!(UnobservedCommonCause, |this: &UnobservedCommonCause, p, ws, ctx| {
132 this.refute(p, ws, ctx)
133});
134impl_effect_validator!(DataSubsetRefuter, |this: &DataSubsetRefuter, p, ws, ctx| {
135 this.refute(p, ws, ctx)
136});
137impl_effect_validator!(DummyOutcome, |this: &DummyOutcome, p, ws, ctx| { this.refute(p, ws, ctx) });
138impl_effect_validator!(GraphRefuter, |this: &GraphRefuter, p, ws, ctx| { this.refute(p, ws, ctx) });
139impl_effect_validator!(LinearSensitivity, |this: &LinearSensitivity, p, ws, ctx| {
140 this.refute(p, ws, ctx)
141});
142impl_effect_validator!(PartialLinearSensitivity, |this: &PartialLinearSensitivity, p, ws, ctx| {
143 this.refute(p, ws, ctx)
144});
145impl_effect_validator!(NonparametricSensitivity, |this: &NonparametricSensitivity, p, ws, ctx| {
146 this.refute(p, ws, ctx)
147});
148impl_effect_validator!(ReiszSensitivity, |this: &ReiszSensitivity, p, ws, ctx| {
149 this.refute(p, ws, ctx)
150});
151
152macro_rules! impl_stateless_effect_validator {
154 ($ty:ty, $call:expr) => {
155 impl crate::validator::sealed::Sealed for $ty {}
156 impl<'a> Validator<RefutationProblem<'a>> for $ty {
157 type Prepared = PreparedRefutation<'a>;
158 type Report = RefutationReport;
159
160 fn prepare(
161 &self,
162 artifact: &RefutationProblem<'a>,
163 _ctx: &ExecutionContext,
164 ) -> Result<Self::Prepared, ValidationError> {
165 Ok(PreparedRefutation { problem: *artifact })
166 }
167
168 fn validate(
169 &self,
170 prepared: &mut Self::Prepared,
171 _workspace: &mut EstimationWorkspace,
172 _ctx: &ExecutionContext,
173 ) -> Result<Self::Report, ValidationError> {
174 ($call)(self, &prepared.problem)
175 }
176 }
177 };
178}
179
180impl_stateless_effect_validator!(OverlapRefuter, |this: &OverlapRefuter, p| this.refute(p));
181impl_stateless_effect_validator!(OverlapRuleRefuter, |this: &OverlapRuleRefuter, p| {
182 this.refute(p)
183});
184impl_stateless_effect_validator!(EValue, |this: &EValue, p| this.refute(p));