oxiz_sat/parallel/
proof_check.rs1#![allow(missing_docs, dead_code)] #[allow(unused_imports)]
7use crate::prelude::*;
8use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
9
10#[derive(Debug, Clone)]
12pub struct ProofCheckConfig {
13 pub num_workers: usize,
15 pub chunk_size: usize,
17 pub detailed_errors: bool,
19}
20
21impl Default for ProofCheckConfig {
22 fn default() -> Self {
23 Self {
24 num_workers: std::thread::available_parallelism()
25 .map(|n| n.get())
26 .unwrap_or(4),
27 chunk_size: 100,
28 detailed_errors: true,
29 }
30 }
31}
32
33#[derive(Debug, Clone)]
35pub enum ProofCheckResult {
36 Valid,
38 Invalid { step_id: usize, reason: String },
40 Incomplete,
42}
43
44pub struct ParallelProofChecker {
46 config: ProofCheckConfig,
47}
48
49impl ParallelProofChecker {
50 pub fn new(config: ProofCheckConfig) -> Self {
52 Self { config }
53 }
54
55 pub fn default_config() -> Self {
57 Self::new(ProofCheckConfig::default())
58 }
59
60 pub fn check_proof(&self, _proof_steps: &[ProofStep]) -> ProofCheckResult {
62 let chunks: Vec<_> = _proof_steps.chunks(self.config.chunk_size).collect();
67
68 let results: Vec<_> = chunks
70 .par_iter()
71 .enumerate()
72 .map(|(chunk_idx, chunk)| self.check_chunk(chunk, chunk_idx * self.config.chunk_size))
73 .collect();
74
75 for result in results {
77 if let ProofCheckResult::Invalid { .. } = result {
78 return result;
79 }
80 }
81
82 ProofCheckResult::Valid
83 }
84
85 fn check_chunk(&self, _steps: &[ProofStep], _base_idx: usize) -> ProofCheckResult {
87 ProofCheckResult::Valid
90 }
91
92 fn verify_step(&self, _step: &ProofStep, _context: &ProofContext) -> bool {
94 true
96 }
97}
98
99#[derive(Debug, Clone)]
101pub struct ProofStep {
102 pub id: usize,
103 pub rule: ProofRule,
104 pub premises: Vec<usize>,
105}
106
107#[derive(Debug, Clone, Copy)]
109pub enum ProofRule {
110 Input,
111 Resolution,
112 Deletion,
113}
114
115#[derive(Debug, Clone)]
117struct ProofContext {
118 derived_clauses: FxHashMap<usize, Vec<i32>>,
119}
120
121impl ProofContext {
122 fn new() -> Self {
123 Self {
124 derived_clauses: FxHashMap::default(),
125 }
126 }
127}
128
129#[cfg(test)]
130mod tests {
131 use super::*;
132
133 #[test]
134 fn test_proof_checker_creation() {
135 let checker = ParallelProofChecker::default_config();
136 assert_eq!(checker.config.chunk_size, 100);
137 }
138
139 #[test]
140 fn test_empty_proof() {
141 let checker = ParallelProofChecker::default_config();
142 let result = checker.check_proof(&[]);
143 assert!(matches!(result, ProofCheckResult::Valid));
144 }
145
146 #[test]
147 fn test_proof_check_result() {
148 let valid = ProofCheckResult::Valid;
149 assert!(matches!(valid, ProofCheckResult::Valid));
150
151 let invalid = ProofCheckResult::Invalid {
152 step_id: 42,
153 reason: "test".to_string(),
154 };
155 assert!(matches!(invalid, ProofCheckResult::Invalid { .. }));
156 }
157}