1use std::collections::{BTreeMap, HashMap};
6
7use super::functions::*;
8
9#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct ArenaMove {
12 pub id: usize,
14 pub polarity: Polarity,
16 pub initial: bool,
18}
19#[derive(Debug, Clone, PartialEq, Eq)]
21pub struct FinitePartialOrder {
22 pub n: usize,
24 pub leq: Vec<Vec<bool>>,
26}
27impl FinitePartialOrder {
28 pub fn discrete(n: usize) -> Self {
30 let leq = (0..n).map(|i| (0..n).map(|j| i == j).collect()).collect();
31 FinitePartialOrder { n, leq }
32 }
33 pub fn flat(n: usize) -> Self {
35 let k = n + 1;
36 let leq = (0..k)
37 .map(|i| (0..k).map(|j| i == j || i == 0).collect())
38 .collect();
39 FinitePartialOrder { n: k, leq }
40 }
41 pub fn is_reflexive(&self) -> bool {
43 (0..self.n).all(|i| self.leq[i][i])
44 }
45 pub fn is_transitive(&self) -> bool {
47 for i in 0..self.n {
48 for j in 0..self.n {
49 for k in 0..self.n {
50 if self.leq[i][j] && self.leq[j][k] && !self.leq[i][k] {
51 return false;
52 }
53 }
54 }
55 }
56 true
57 }
58 pub fn is_antisymmetric(&self) -> bool {
60 for i in 0..self.n {
61 for j in 0..self.n {
62 if i != j && self.leq[i][j] && self.leq[j][i] {
63 return false;
64 }
65 }
66 }
67 true
68 }
69 pub fn is_valid(&self) -> bool {
71 self.is_reflexive() && self.is_transitive() && self.is_antisymmetric()
72 }
73 pub fn lub(&self, a: usize, b: usize) -> Option<usize> {
75 let ubs: Vec<usize> = (0..self.n)
76 .filter(|&x| self.leq[a][x] && self.leq[b][x])
77 .collect();
78 ubs.iter()
79 .find(|&&x| ubs.iter().all(|&y| self.leq[x][y]))
80 .copied()
81 }
82 pub fn glb(&self, a: usize, b: usize) -> Option<usize> {
84 let lbs: Vec<usize> = (0..self.n)
85 .filter(|&x| self.leq[x][a] && self.leq[x][b])
86 .collect();
87 lbs.iter()
88 .find(|&&x| lbs.iter().all(|&y| self.leq[y][x]))
89 .copied()
90 }
91}
92#[derive(Debug, Clone, PartialEq, Eq)]
94pub struct Trace<A: Clone + Eq> {
95 pub actions: Vec<A>,
97}
98impl<A: Clone + Eq> Trace<A> {
99 pub fn empty() -> Self {
101 Trace { actions: vec![] }
102 }
103 pub fn new(actions: Vec<A>) -> Self {
105 Trace { actions }
106 }
107 pub fn extend(&self, a: A) -> Self {
109 let mut acts = self.actions.clone();
110 acts.push(a);
111 Trace { actions: acts }
112 }
113 pub fn concat(&self, other: &Self) -> Self {
115 let mut acts = self.actions.clone();
116 acts.extend_from_slice(&other.actions);
117 Trace { actions: acts }
118 }
119 pub fn is_prefix_of(&self, other: &Self) -> bool {
121 other.actions.starts_with(&self.actions)
122 }
123 pub fn len(&self) -> usize {
125 self.actions.len()
126 }
127 pub fn is_empty(&self) -> bool {
129 self.actions.is_empty()
130 }
131}
132#[derive(Debug, Clone)]
134pub struct KleenePCA {
135 pub combinators: HashMap<String, usize>,
137 pub apply_table: HashMap<(usize, usize), usize>,
139 next_idx: usize,
140}
141impl KleenePCA {
142 pub fn with_ks() -> Self {
144 let mut pca = KleenePCA {
145 combinators: HashMap::new(),
146 apply_table: HashMap::new(),
147 next_idx: 6,
148 };
149 pca.combinators.insert("K".to_string(), 0);
150 pca.combinators.insert("S".to_string(), 1);
151 pca.combinators.insert("I".to_string(), 2);
152 for a in 0usize..3 {
153 let ka = 3 + a;
154 pca.apply_table.insert((0, a), ka);
155 for b in 0usize..3 {
156 pca.apply_table.insert((ka, b), a);
157 }
158 }
159 for a in 0usize..3 {
160 pca.apply_table.insert((2, a), a);
161 }
162 pca
163 }
164 pub fn lookup(&self, name: &str) -> Option<usize> {
166 self.combinators.get(name).copied()
167 }
168 pub fn apply(&self, f: usize, x: usize) -> Option<usize> {
170 self.apply_table.get(&(f, x)).copied()
171 }
172 pub fn add_element(&mut self, name: impl Into<String>) -> usize {
174 let idx = self.next_idx;
175 self.combinators.insert(name.into(), idx);
176 self.next_idx += 1;
177 idx
178 }
179 pub fn define_app(&mut self, f: usize, x: usize, result: usize) {
181 self.apply_table.insert((f, x), result);
182 }
183 pub fn check_k_law(&self) -> bool {
185 let k = match self.lookup("K") {
186 Some(v) => v,
187 None => return false,
188 };
189 for a in 0usize..3 {
190 let ka = match self.apply(k, a) {
191 Some(v) => v,
192 None => return false,
193 };
194 for b in 0usize..3 {
195 match self.apply(ka, b) {
196 Some(r) if r == a => {}
197 _ => return false,
198 }
199 }
200 }
201 true
202 }
203 pub fn check_i_law(&self) -> bool {
205 let i = match self.lookup("I") {
206 Some(v) => v,
207 None => return false,
208 };
209 (0..3).all(|a| self.apply(i, a) == Some(a))
210 }
211}
212#[derive(Debug, Clone, Copy, PartialEq, Eq)]
214pub enum Polarity {
215 O,
217 P,
219}
220#[derive(Debug, Clone)]
222pub struct BilimitApprox {
223 pub levels: Vec<BilimitStep>,
225}
226impl BilimitApprox {
227 pub fn new(levels: Vec<BilimitStep>) -> Self {
229 BilimitApprox { levels }
230 }
231 pub fn depth(&self) -> usize {
233 self.levels.len()
234 }
235 pub fn project_to_base(&self, mut x: usize, l: usize) -> usize {
237 for step in self.levels.iter().take(l).rev() {
238 x = step.project(x);
239 }
240 x
241 }
242}
243#[derive(Debug, Clone)]
245pub struct LogicalRelation {
246 pub pairs: HashMap<String, Vec<(usize, usize)>>,
248}
249impl LogicalRelation {
250 pub fn new() -> Self {
252 LogicalRelation {
253 pairs: HashMap::new(),
254 }
255 }
256 pub fn add(&mut self, ty_code: impl Into<String>, a: usize, b: usize) {
258 self.pairs.entry(ty_code.into()).or_default().push((a, b));
259 }
260 pub fn relates(&self, ty_code: &str, a: usize, b: usize) -> bool {
262 self.pairs
263 .get(ty_code)
264 .map_or(false, |v| v.contains(&(a, b)))
265 }
266 pub fn is_reflexive_on(&self, ty_code: &str, domain_size: usize) -> bool {
268 (0..domain_size).all(|a| self.relates(ty_code, a, a))
269 }
270 pub fn is_symmetric_on(&self, ty_code: &str) -> bool {
272 if let Some(pairs) = self.pairs.get(ty_code) {
273 pairs.iter().all(|&(a, b)| pairs.contains(&(b, a)))
274 } else {
275 true
276 }
277 }
278 pub fn size(&self, ty_code: &str) -> usize {
280 self.pairs.get(ty_code).map_or(0, |v| v.len())
281 }
282}
283#[derive(Debug, Clone, PartialEq, Eq)]
285pub enum LambdaTerm {
286 Var(usize),
288 Lam(Box<LambdaTerm>),
290 App(Box<LambdaTerm>, Box<LambdaTerm>),
292 Const(String),
294}
295impl LambdaTerm {
296 pub fn var(n: usize) -> Self {
298 LambdaTerm::Var(n)
299 }
300 pub fn lam(body: LambdaTerm) -> Self {
302 LambdaTerm::Lam(Box::new(body))
303 }
304 pub fn app(f: LambdaTerm, x: LambdaTerm) -> Self {
306 LambdaTerm::App(Box::new(f), Box::new(x))
307 }
308 pub fn cst(s: impl Into<String>) -> Self {
310 LambdaTerm::Const(s.into())
311 }
312 pub fn size(&self) -> usize {
314 match self {
315 LambdaTerm::Var(_) | LambdaTerm::Const(_) => 1,
316 LambdaTerm::Lam(b) => 1 + b.size(),
317 LambdaTerm::App(f, x) => 1 + f.size() + x.size(),
318 }
319 }
320 pub fn has_free_var(&self, depth: usize, target: usize) -> bool {
322 match self {
323 LambdaTerm::Var(n) => *n == target + depth,
324 LambdaTerm::Const(_) => false,
325 LambdaTerm::Lam(b) => b.has_free_var(depth + 1, target),
326 LambdaTerm::App(f, x) => f.has_free_var(depth, target) || x.has_free_var(depth, target),
327 }
328 }
329}
330#[derive(Debug, Clone, PartialEq, Eq)]
332pub struct MaybeInterp {
333 pub fuel: u64,
335}
336impl MaybeInterp {
337 pub fn new(fuel: u64) -> Self {
339 MaybeInterp { fuel }
340 }
341 pub fn ret(v: PCFValue) -> Option<PCFValue> {
343 Some(v)
344 }
345 pub fn bind<F>(m: Option<PCFValue>, f: F) -> Option<PCFValue>
347 where
348 F: FnOnce(PCFValue) -> Option<PCFValue>,
349 {
350 m.and_then(f)
351 }
352 pub fn eval(&self, term: &PCFTerm) -> Option<PCFValue> {
354 let v = pcf_eval(term, self.fuel);
355 if v.is_bottom() {
356 None
357 } else {
358 Some(v)
359 }
360 }
361 pub fn guard(cond: bool) -> Option<()> {
363 if cond {
364 Some(())
365 } else {
366 None
367 }
368 }
369 pub fn seq(&self, t1: &PCFTerm, t2: &PCFTerm) -> Option<PCFValue> {
371 Self::bind(self.eval(t1), |_| self.eval(t2))
372 }
373 pub fn map<F>(m: Option<PCFValue>, f: F) -> Option<PCFValue>
375 where
376 F: FnOnce(PCFValue) -> PCFValue,
377 {
378 m.map(f)
379 }
380}
381#[derive(Debug, Clone, PartialEq, Eq)]
383pub struct ScottOpen {
384 pub domain_size: usize,
386 pub elements: Vec<usize>,
388}
389impl ScottOpen {
390 pub fn new(domain_size: usize, elems: impl IntoIterator<Item = usize>) -> Self {
392 let mut v: Vec<usize> = elems
393 .into_iter()
394 .filter(|&x| x > 0 && x < domain_size)
395 .collect();
396 v.sort_unstable();
397 v.dedup();
398 ScottOpen {
399 domain_size,
400 elements: v,
401 }
402 }
403 pub fn top(domain_size: usize) -> Self {
405 ScottOpen {
406 domain_size,
407 elements: (1..domain_size).collect(),
408 }
409 }
410 pub fn empty(domain_size: usize) -> Self {
412 ScottOpen {
413 domain_size,
414 elements: vec![],
415 }
416 }
417 pub fn contains(&self, x: usize) -> bool {
419 self.elements.binary_search(&x).is_ok()
420 }
421 pub fn union(&self, other: &Self) -> Self {
423 let mut v = self.elements.clone();
424 for &x in &other.elements {
425 if !self.contains(x) {
426 v.push(x);
427 }
428 }
429 v.sort_unstable();
430 ScottOpen {
431 domain_size: self.domain_size,
432 elements: v,
433 }
434 }
435 pub fn intersection(&self, other: &Self) -> Self {
437 let v: Vec<usize> = self
438 .elements
439 .iter()
440 .filter(|&&x| other.contains(x))
441 .copied()
442 .collect();
443 ScottOpen {
444 domain_size: self.domain_size,
445 elements: v,
446 }
447 }
448 pub fn is_scott_open(&self) -> bool {
450 !self.contains(0)
451 }
452 pub fn characteristic(&self, x: usize) -> bool {
454 self.contains(x)
455 }
456}
457#[derive(Debug, Clone)]
459pub struct GameArena {
460 pub moves: Vec<ArenaMove>,
462 pub enables: HashMap<usize, Vec<usize>>,
464}
465impl GameArena {
466 pub fn new(moves: Vec<ArenaMove>) -> Self {
468 GameArena {
469 moves,
470 enables: HashMap::new(),
471 }
472 }
473 pub fn add_enables(&mut self, from: usize, to: usize) {
475 self.enables.entry(from).or_default().push(to);
476 }
477 pub fn initial_moves(&self) -> Vec<&ArenaMove> {
479 self.moves.iter().filter(|m| m.initial).collect()
480 }
481}
482#[derive(Debug, Clone, PartialEq, Eq)]
484pub enum PCFValue {
485 Num(u64),
487 Bool(bool),
489 Bottom,
491 Closure(Box<PCFTerm>, usize),
493}
494impl PCFValue {
495 pub fn is_bottom(&self) -> bool {
497 matches!(self, PCFValue::Bottom)
498 }
499 pub fn is_nat(&self) -> bool {
501 matches!(self, PCFValue::Num(_))
502 }
503}
504#[derive(Clone)]
507pub struct MonotoneMap {
508 pub table: Vec<usize>,
510}
511impl MonotoneMap {
512 pub fn new(table: Vec<usize>) -> Self {
514 MonotoneMap { table }
515 }
516 pub fn apply(&self, x: usize) -> usize {
518 self.table[x]
519 }
520 pub fn is_monotone(&self, po: &FinitePartialOrder) -> bool {
522 for i in 0..po.n.min(self.table.len()) {
523 for j in 0..po.n.min(self.table.len()) {
524 if po.leq[i][j] {
525 let fi = self.table[i];
526 let fj = self.table[j];
527 if fi < po.n && fj < po.n && !po.leq[fi][fj] {
528 return false;
529 }
530 }
531 }
532 }
533 true
534 }
535}
536#[derive(Debug, Clone, PartialEq, Eq)]
538pub enum PCFTerm {
539 Var(usize),
541 Zero,
543 True,
545 False,
547 Succ(Box<PCFTerm>),
549 Pred(Box<PCFTerm>),
551 IsZero(Box<PCFTerm>),
553 Lam(Box<PCFTerm>),
555 App(Box<PCFTerm>, Box<PCFTerm>),
557 Fix(Box<PCFTerm>),
559 If(Box<PCFTerm>, Box<PCFTerm>, Box<PCFTerm>),
561}
562impl PCFTerm {
563 pub fn label(&self) -> &'static str {
565 match self {
566 PCFTerm::Var(_) => "Var",
567 PCFTerm::Zero => "Zero",
568 PCFTerm::True => "True",
569 PCFTerm::False => "False",
570 PCFTerm::Succ(_) => "Succ",
571 PCFTerm::Pred(_) => "Pred",
572 PCFTerm::IsZero(_) => "IsZero",
573 PCFTerm::Lam(_) => "Lam",
574 PCFTerm::App(_, _) => "App",
575 PCFTerm::Fix(_) => "Fix",
576 PCFTerm::If(_, _, _) => "If",
577 }
578 }
579}
580#[derive(Debug, Clone)]
583pub struct BilimitStep {
584 pub size: usize,
586 pub proj: Vec<usize>,
588}
589impl BilimitStep {
590 pub fn new(size: usize, proj: Vec<usize>) -> Self {
592 BilimitStep { size, proj }
593 }
594 pub fn project(&self, x: usize) -> usize {
596 self.proj.get(x).copied().unwrap_or(0)
597 }
598}
599#[derive(Debug, Clone, PartialEq, Eq)]
601pub enum PCFType {
602 Nat,
604 Bool,
606 Arrow(Box<PCFType>, Box<PCFType>),
608}
609impl PCFType {
610 pub fn arrow(t1: PCFType, t2: PCFType) -> Self {
612 PCFType::Arrow(Box::new(t1), Box::new(t2))
613 }
614 pub fn name(&self) -> String {
616 match self {
617 PCFType::Nat => "Nat".to_string(),
618 PCFType::Bool => "Bool".to_string(),
619 PCFType::Arrow(a, b) => format!("({} → {})", a.name(), b.name()),
620 }
621 }
622}
623#[derive(Debug, Clone)]
625pub struct FiniteValuation {
626 pub masses: BTreeMap<String, f64>,
628}
629impl FiniteValuation {
630 pub fn empty() -> Self {
632 FiniteValuation {
633 masses: BTreeMap::new(),
634 }
635 }
636 pub fn dirac(x: impl Into<String>) -> Self {
638 let mut m = BTreeMap::new();
639 m.insert(x.into(), 1.0);
640 FiniteValuation { masses: m }
641 }
642 pub fn total_mass(&self) -> f64 {
644 self.masses.values().sum()
645 }
646 pub fn is_sub_probability(&self) -> bool {
648 self.total_mass() <= 1.0 + 1e-9
649 }
650 pub fn mix(&self, other: &Self, p: f64) -> Self {
652 let mut m = BTreeMap::new();
653 for (k, v) in &self.masses {
654 *m.entry(k.clone()).or_insert(0.0) += (1.0 - p) * v;
655 }
656 for (k, v) in &other.masses {
657 *m.entry(k.clone()).or_insert(0.0) += p * v;
658 }
659 FiniteValuation { masses: m }
660 }
661 pub fn stochastic_leq(&self, other: &Self) -> bool {
665 for (k, v) in &self.masses {
666 let w = other.masses.get(k).copied().unwrap_or(0.0);
667 if *v > w + 1e-9 {
668 return false;
669 }
670 }
671 true
672 }
673}
674#[derive(Debug, Clone, PartialEq, Eq)]
677pub struct HoareElement {
678 pub elems: Vec<usize>,
680}
681impl HoareElement {
682 pub fn new(iter: impl IntoIterator<Item = usize>) -> Self {
684 let mut v: Vec<usize> = iter.into_iter().collect();
685 v.sort_unstable();
686 v.dedup();
687 HoareElement { elems: v }
688 }
689 pub fn hoare_leq(&self, other: &Self) -> bool {
691 self.elems.iter().all(|x| other.elems.contains(x))
692 }
693 pub fn union(&self, other: &Self) -> Self {
695 let mut v = self.elems.clone();
696 for x in &other.elems {
697 if !v.contains(x) {
698 v.push(*x);
699 }
700 }
701 v.sort_unstable();
702 HoareElement { elems: v }
703 }
704}
705#[derive(Debug, Clone)]
708pub struct InnocentStrategy {
709 pub responses: HashMap<Vec<usize>, usize>,
711}
712impl InnocentStrategy {
713 pub fn new() -> Self {
715 InnocentStrategy {
716 responses: HashMap::new(),
717 }
718 }
719 pub fn add_response(&mut self, view: Vec<usize>, p_move: usize) {
721 self.responses.insert(view, p_move);
722 }
723 pub fn respond(&self, view: &[usize]) -> Option<usize> {
725 self.responses.get(view).copied()
726 }
727 pub fn size(&self) -> usize {
729 self.responses.len()
730 }
731}