1use crate::AbstractPropertyValueV0;
2use serde::Serialize;
3use std::collections::{BTreeMap, BTreeSet};
4
5#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
11#[serde(rename_all = "camelCase")]
12pub struct CascadeValueFamilyV0 {
13 pub schema_version: &'static str,
14 pub product: &'static str,
15 pub framing: &'static str,
16 pub claim_level: &'static str,
17 pub property_name: String,
18 pub supported_readings: Vec<&'static str>,
19 pub context_value_count: usize,
20 pub restriction_map_count: usize,
21 pub property_consistent: bool,
22 pub dangling_restriction_count: usize,
23 pub theorem_claimed: bool,
24 pub members: Vec<CascadeValueFamilyMemberV0>,
25 pub restriction_maps: Vec<CascadeRestrictionMapV0>,
26}
27
28#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize)]
29#[serde(rename_all = "camelCase")]
30pub struct CascadeContextV0 {
31 pub id: String,
32 #[serde(skip_serializing_if = "Option::is_none")]
33 pub parent_id: Option<String>,
34 pub selectors: Vec<String>,
35 pub conditions: Vec<String>,
36 pub layers: Vec<String>,
37}
38
39#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
40#[serde(rename_all = "camelCase")]
41pub struct CascadeValueFamilyMemberV0 {
42 pub context: CascadeContextV0,
43 pub value: AbstractPropertyValueV0,
44}
45
46#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize)]
47#[serde(rename_all = "camelCase")]
48pub struct CascadeRestrictionMapV0 {
49 pub parent_context_id: String,
50 pub child_context_id: String,
51 pub morphism: CascadeMorphismV0,
52}
53
54#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize)]
55#[serde(rename_all = "camelCase")]
56pub struct CascadeMorphismV0 {
57 pub kind: &'static str,
58 pub direction: &'static str,
59 pub preserves_property_name: bool,
60 pub evidence: Vec<&'static str>,
61}
62
63pub fn summarize_cascade_value_family_v0(
64 property_name: impl Into<String>,
65 members: Vec<CascadeValueFamilyMemberV0>,
66 restriction_maps: Vec<CascadeRestrictionMapV0>,
67) -> CascadeValueFamilyV0 {
68 let property_name = property_name.into();
69 let mut members = members;
70 members.sort_by(|left, right| left.context.id.cmp(&right.context.id));
71 members.dedup_by(|left, right| left.context.id == right.context.id);
72
73 let mut restriction_maps = restriction_maps;
74 restriction_maps.sort();
75 restriction_maps.dedup();
76
77 let context_ids = members
78 .iter()
79 .map(|member| member.context.id.as_str())
80 .collect::<BTreeSet<_>>();
81 let property_consistent = members
82 .iter()
83 .all(|member| property_value_name(&member.value) == property_name);
84 let dangling_restriction_count = restriction_maps
85 .iter()
86 .filter(|restriction| {
87 !context_ids.contains(restriction.parent_context_id.as_str())
88 || !context_ids.contains(restriction.child_context_id.as_str())
89 })
90 .count();
91 let restriction_map_count = restriction_maps.len();
92
93 CascadeValueFamilyV0 {
94 schema_version: "0",
95 product: "omena-abstract-value.cascade-value-family",
96 framing: "framingNeutralCascadeFamily",
97 claim_level: "researchStagedSubstrate",
98 property_name,
99 supported_readings: vec!["presheafCompatible", "cosheafCompatible"],
100 context_value_count: members.len(),
101 restriction_map_count,
102 property_consistent,
103 dangling_restriction_count,
104 theorem_claimed: false,
105 members,
106 restriction_maps,
107 }
108}
109
110pub fn derive_cascade_restriction_maps_v0(
111 members: &[CascadeValueFamilyMemberV0],
112) -> Vec<CascadeRestrictionMapV0> {
113 let context_ids = members
114 .iter()
115 .map(|member| member.context.id.as_str())
116 .collect::<BTreeSet<_>>();
117 let mut maps = members
118 .iter()
119 .filter_map(|member| {
120 let parent_id = member.context.parent_id.as_deref()?;
121 context_ids
122 .contains(parent_id)
123 .then(|| CascadeRestrictionMapV0 {
124 parent_context_id: parent_id.to_string(),
125 child_context_id: member.context.id.clone(),
126 morphism: cascade_context_refinement_morphism_v0(),
127 })
128 })
129 .collect::<Vec<_>>();
130 maps.sort();
131 maps.dedup();
132 maps
133}
134
135pub fn cascade_context_refinement_morphism_v0() -> CascadeMorphismV0 {
136 CascadeMorphismV0 {
137 kind: "contextRefinement",
138 direction: "parentToChildRestriction",
139 preserves_property_name: true,
140 evidence: vec![
141 "contextIndexedValueFamily",
142 "parentChildCascadeContext",
143 "noSheafTheoremClaim",
144 ],
145 }
146}
147
148pub fn cascade_value_for_context<'a>(
149 family: &'a CascadeValueFamilyV0,
150 context_id: &str,
151) -> Option<&'a AbstractPropertyValueV0> {
152 family
153 .members
154 .iter()
155 .find(|member| member.context.id == context_id)
156 .map(|member| &member.value)
157}
158
159pub fn cascade_family_context_values(
160 family: &CascadeValueFamilyV0,
161) -> BTreeMap<String, AbstractPropertyValueV0> {
162 family
163 .members
164 .iter()
165 .map(|member| (member.context.id.clone(), member.value.clone()))
166 .collect()
167}
168
169fn property_value_name(value: &AbstractPropertyValueV0) -> &str {
170 match value {
171 AbstractPropertyValueV0::Bottom { property_name }
172 | AbstractPropertyValueV0::Exact { property_name, .. }
173 | AbstractPropertyValueV0::FiniteSet { property_name, .. }
174 | AbstractPropertyValueV0::CustomPropertyReference { property_name, .. }
175 | AbstractPropertyValueV0::Top { property_name } => property_name,
176 }
177}