1use std::collections::BTreeSet;
8use std::sync::Arc;
9
10use xlog_core::{symbol, Result, XlogError};
11use xlog_cuda::CudaKernelProvider;
12use xlog_ir::EirEpistemicMode;
13use xlog_logic::ast::{Atom, Evidence, Program, Term};
14use xlog_logic::parse_program;
15use xlog_runtime::{EpistemicGpuBatchExecutionResult, EpistemicGpuExecutionResult};
16
17use crate::compilation::{encode_cnf_gpu, GpuPirGraph, GpuPirRoots};
18#[cfg(feature = "host-io")]
19use crate::epistemic::EpistemicAssumptionKind;
20use crate::epistemic::EpistemicEvidenceTerm;
21use crate::epistemic::{
22 AcceptedWorldViewEvidence, CircuitUpdate, CircuitUpdateMode, EpistemicAssumption,
23 EpistemicCircuit,
24};
25#[cfg(feature = "host-io")]
26use crate::exact::ExactProgramOrigin;
27use crate::exact::{ExactDdnnfProgram, GpuConfig};
28#[cfg(feature = "host-io")]
29use crate::exact::{ExactResult, ExactResultWithGrads};
30use crate::pir::{PirNode, PirNodeId};
31use crate::provenance::Value;
32use crate::provenance::{extract_from_program, Provenance};
33
34macro_rules! epistemic_prob_trace_transaction {
35 ($adapter:ident, $body:block) => {{
36 let trace_before = $adapter.trace;
37 let result: Result<_> = (|| $body)();
38 match result {
39 Ok(value) => Ok(value),
40 Err(err) => {
41 $adapter.trace = trace_before;
42 Err(err)
43 }
44 }
45 }};
46}
47
48macro_rules! checked_prob_trace_counter_inc {
49 ($adapter:ident, $field:ident) => {{
50 $adapter.trace.$field = EpistemicProbProductionAdapter::checked_trace_counter_add(
51 $adapter.trace.$field,
52 1,
53 stringify!($field),
54 )?;
55 }};
56}
57
58#[derive(Debug, Clone, Copy, PartialEq, Eq)]
60pub enum EpistemicProbProductionCapabilityStatus {
61 Available,
63 Blocked,
65}
66
67#[derive(Debug, Clone, Copy, PartialEq, Eq)]
69pub struct EpistemicProbProductionCapabilities {
70 pub gpu_exact_provenance: EpistemicProbProductionCapabilityStatus,
72 pub gpu_pir_cnf: EpistemicProbProductionCapabilityStatus,
74 pub gpu_knowledge_compilation: EpistemicProbProductionCapabilityStatus,
76 pub gpu_exact_query_and_gradient: EpistemicProbProductionCapabilityStatus,
78 pub fixture_circuit_allowed: bool,
80 pub gpu_knowledge_compilation_blocker: &'static str,
82}
83
84pub fn production_capabilities() -> EpistemicProbProductionCapabilities {
86 EpistemicProbProductionCapabilities {
87 gpu_exact_provenance: EpistemicProbProductionCapabilityStatus::Available,
88 gpu_pir_cnf: EpistemicProbProductionCapabilityStatus::Available,
89 gpu_knowledge_compilation: EpistemicProbProductionCapabilityStatus::Available,
90 gpu_exact_query_and_gradient: EpistemicProbProductionCapabilityStatus::Available,
91 fixture_circuit_allowed: false,
92 gpu_knowledge_compilation_blocker: "",
93 }
94}
95
96#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
98pub struct EpistemicProbProductionTrace {
99 pub gpu_exact_source_compiles: u64,
101 pub gpu_exact_program_compiles: u64,
103 pub accepted_world_view_evidence_consumed: u64,
105 pub accepted_g91_world_view_evidence_consumed: u64,
108 pub accepted_faeel_world_view_evidence_consumed: u64,
110 pub accepted_evidence_assumptions_consumed: u64,
112 pub accepted_gpu_nonzero_arity_evidence_assumptions_consumed: u64,
114 pub accepted_gpu_max_evidence_arity_consumed: u32,
116 pub accepted_gpu_tuple_key_column_reads_consumed: u64,
118 pub accepted_gpu_final_tuple_row_filters_consumed: u64,
120 pub accepted_gpu_final_tuple_negated_row_filters_consumed: u64,
122 pub accepted_gpu_row_specific_membership_row_capacity_consumed: u64,
124 pub accepted_gpu_row_filter_fallback_row_capacity_consumed: u64,
126 pub accepted_gpu_constraint_relations_checked_consumed: u64,
128 pub accepted_gpu_constraint_row_count_device_reads_consumed: u64,
130 pub accepted_gpu_batch_evidence_consumed: u64,
132 pub accepted_gpu_batch_component_evidence_consumed: u64,
134 pub accepted_incremental_circuit_updates: u64,
138 pub gpu_exact_query_evaluations: u64,
140 pub gpu_source_exact_query_evaluations: u64,
142 pub gpu_program_exact_query_evaluations: u64,
144 pub gpu_exact_gradient_evaluations: u64,
146 pub gpu_source_exact_gradient_evaluations: u64,
148 pub gpu_program_exact_gradient_evaluations: u64,
150 pub gpu_source_conditioned_gradient_evaluations: u64,
152 pub gpu_program_conditioned_gradient_evaluations: u64,
154 pub gpu_pir_graph_uploads: u64,
156 pub gpu_source_pir_graph_uploads: u64,
158 pub gpu_program_pir_graph_uploads: u64,
160 pub gpu_cnf_encodes: u64,
162 pub gpu_source_cnf_encodes: u64,
164 pub gpu_program_cnf_encodes: u64,
166 pub gpu_knowledge_compilation_end_to_end_runs: u64,
168 pub accepted_gpu_production_path_events: u64,
170 pub gpu_source_knowledge_compilation_end_to_end_runs: u64,
172 pub gpu_program_knowledge_compilation_end_to_end_runs: u64,
174 pub gpu_conditioned_evidence_facts: u64,
176 pub accepted_conditioned_world_view_evidence_consumed: u64,
178 pub accepted_source_conditioned_world_view_evidence_consumed: u64,
180 pub accepted_program_conditioned_world_view_evidence_consumed: u64,
182 pub gpu_conditioned_nonzero_arity_evidence_facts: u64,
184 pub gpu_conditioned_max_evidence_arity: u32,
186 pub gpu_conditioned_negative_evidence_facts: u64,
188 pub gpu_source_conditioned_evidence_facts: u64,
190 pub gpu_source_conditioned_nonzero_arity_evidence_facts: u64,
192 pub gpu_source_conditioned_max_evidence_arity: u32,
194 pub gpu_program_conditioned_evidence_facts: u64,
196 pub gpu_program_conditioned_nonzero_arity_evidence_facts: u64,
198 pub gpu_program_conditioned_max_evidence_arity: u32,
200 pub gpu_source_conditioned_negative_evidence_facts: u64,
202 pub gpu_program_conditioned_negative_evidence_facts: u64,
204 pub gpu_conditioned_know_evidence_facts: u64,
206 pub gpu_conditioned_possible_evidence_facts: u64,
208 pub gpu_conditioned_not_known_evidence_facts: u64,
210 pub gpu_conditioned_not_possible_evidence_facts: u64,
212 pub gpu_source_conditioned_know_evidence_facts: u64,
214 pub gpu_source_conditioned_possible_evidence_facts: u64,
216 pub gpu_source_conditioned_not_known_evidence_facts: u64,
218 pub gpu_source_conditioned_not_possible_evidence_facts: u64,
220 pub gpu_program_conditioned_know_evidence_facts: u64,
222 pub gpu_program_conditioned_possible_evidence_facts: u64,
224 pub gpu_program_conditioned_not_known_evidence_facts: u64,
226 pub gpu_program_conditioned_not_possible_evidence_facts: u64,
228 pub cpu_only_probability_recomputations: u64,
230 pub fixture_circuit_evaluations: u64,
232}
233
234impl EpistemicProbProductionTrace {
235 fn checked_gpu_production_path_events(&self) -> Result<u64> {
236 Self::checked_production_event_sum(
237 "gpu_production_path_events",
238 &[
239 self.gpu_exact_source_compiles,
240 self.gpu_exact_program_compiles,
241 self.gpu_exact_query_evaluations,
242 self.gpu_source_exact_query_evaluations,
243 self.gpu_program_exact_query_evaluations,
244 self.gpu_exact_gradient_evaluations,
245 self.gpu_source_exact_gradient_evaluations,
246 self.gpu_program_exact_gradient_evaluations,
247 self.gpu_source_conditioned_gradient_evaluations,
248 self.gpu_program_conditioned_gradient_evaluations,
249 self.gpu_pir_graph_uploads,
250 self.gpu_source_pir_graph_uploads,
251 self.gpu_program_pir_graph_uploads,
252 self.gpu_cnf_encodes,
253 self.gpu_source_cnf_encodes,
254 self.gpu_program_cnf_encodes,
255 self.gpu_knowledge_compilation_end_to_end_runs,
256 self.gpu_source_knowledge_compilation_end_to_end_runs,
257 self.gpu_program_knowledge_compilation_end_to_end_runs,
258 ],
259 )
260 }
261
262 fn checked_production_event_sum(counter: &str, values: &[u64]) -> Result<u64> {
263 values.iter().try_fold(0u64, |acc, value| {
264 acc.checked_add(*value)
265 .ok_or_else(|| XlogError::UnsupportedEpistemicConstruct {
266 construct: "epistemic probabilistic production trace accounting".to_string(),
267 context: format!(
268 "GPU probability production counter {counter} overflowed while adding \
269 {value} to {acc}"
270 ),
271 })
272 })
273 }
274
275 fn require_pir_cnf_accounting_pair(
276 construct: &'static str,
277 pir_graph_uploads: u64,
278 cnf_encodes: u64,
279 path: &'static str,
280 ) -> Result<()> {
281 if pir_graph_uploads != cnf_encodes {
282 return Err(XlogError::UnsupportedEpistemicConstruct {
283 construct: construct.to_string(),
284 context: format!(
285 "PIR/CNF production accounting must match for {path} path, got \
286 pir_graph_uploads={} cnf_encodes={}",
287 pir_graph_uploads, cnf_encodes
288 ),
289 });
290 }
291 Ok(())
292 }
293
294 fn require_pir_cnf_accounting(&self) -> Result<()> {
295 let construct = "epistemic probabilistic production metric gate";
296 Self::require_pir_cnf_accounting_pair(
297 construct,
298 self.gpu_pir_graph_uploads,
299 self.gpu_cnf_encodes,
300 "aggregate",
301 )?;
302 Self::require_pir_cnf_accounting_pair(
303 construct,
304 self.gpu_source_pir_graph_uploads,
305 self.gpu_source_cnf_encodes,
306 "source",
307 )?;
308 Self::require_pir_cnf_accounting_pair(
309 construct,
310 self.gpu_program_pir_graph_uploads,
311 self.gpu_program_cnf_encodes,
312 "program",
313 )
314 }
315
316 pub fn require_zero_cpu_recompute(&self) -> Result<()> {
318 if self.cpu_only_probability_recomputations != 0 || self.fixture_circuit_evaluations != 0 {
319 return Err(XlogError::UnsupportedEpistemicConstruct {
320 construct: "epistemic probabilistic production adapter".to_string(),
321 context: format!(
322 "CPU probabilistic fallback counters must be zero, got recompute={} fixture={}",
323 self.cpu_only_probability_recomputations, self.fixture_circuit_evaluations
324 ),
325 });
326 }
327 Ok(())
328 }
329
330 pub fn require_accepted_gpu_tuple_evidence_trace(&self) -> Result<()> {
332 if self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed
333 > self.accepted_evidence_assumptions_consumed
334 {
335 return Err(XlogError::UnsupportedEpistemicConstruct {
336 construct: "epistemic probabilistic production metric gate".to_string(),
337 context: format!(
338 "accepted nonzero-arity evidence assumptions cannot exceed accepted \
339 evidence assumptions: nonzero={} total={}",
340 self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed,
341 self.accepted_evidence_assumptions_consumed
342 ),
343 });
344 }
345 if self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed == 0
346 && self.accepted_gpu_max_evidence_arity_consumed > 0
347 {
348 return Err(XlogError::UnsupportedEpistemicConstruct {
349 construct: "epistemic probabilistic production metric gate".to_string(),
350 context: format!(
351 "accepted max evidence arity {} requires at least one accepted \
352 nonzero-arity GPU evidence assumption",
353 self.accepted_gpu_max_evidence_arity_consumed
354 ),
355 });
356 }
357 if self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed > 0
358 && self.accepted_gpu_max_evidence_arity_consumed == 0
359 {
360 return Err(XlogError::UnsupportedEpistemicConstruct {
361 construct: "epistemic probabilistic production metric gate".to_string(),
362 context: format!(
363 "accepted nonzero-arity GPU evidence requires accepted max evidence arity, \
364 got nonzero_assumptions={} max_arity=0",
365 self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed
366 ),
367 });
368 }
369 if self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed == 0
370 && self.accepted_gpu_tuple_key_column_reads_consumed != 0
371 {
372 return Err(XlogError::UnsupportedEpistemicConstruct {
373 construct: "epistemic probabilistic production metric gate".to_string(),
374 context: format!(
375 "accepted tuple-key reads require accepted nonzero-arity GPU evidence, got \
376 nonzero_assumptions=0 tuple_key_reads={}",
377 self.accepted_gpu_tuple_key_column_reads_consumed
378 ),
379 });
380 }
381 if self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed > 0
382 && self.accepted_gpu_tuple_key_column_reads_consumed == 0
383 {
384 return Err(XlogError::UnsupportedEpistemicConstruct {
385 construct: "epistemic probabilistic production metric gate".to_string(),
386 context: format!(
387 "accepted nonzero-arity GPU evidence requires tuple-key device column reads, \
388 got nonzero_assumptions={} tuple_key_reads=0",
389 self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed
390 ),
391 });
392 }
393 if self.accepted_gpu_final_tuple_negated_row_filters_consumed
394 > self.accepted_gpu_final_tuple_row_filters_consumed
395 {
396 return Err(XlogError::UnsupportedEpistemicConstruct {
397 construct: "epistemic probabilistic production metric gate".to_string(),
398 context: format!(
399 "accepted negated final-tuple row filters cannot exceed total row filters: \
400 negated={} total={}",
401 self.accepted_gpu_final_tuple_negated_row_filters_consumed,
402 self.accepted_gpu_final_tuple_row_filters_consumed
403 ),
404 });
405 }
406 if self.accepted_gpu_final_tuple_row_filters_consumed == 0
407 && (self.accepted_gpu_row_specific_membership_row_capacity_consumed != 0
408 || self.accepted_gpu_row_filter_fallback_row_capacity_consumed != 0)
409 {
410 return Err(XlogError::UnsupportedEpistemicConstruct {
411 construct: "epistemic probabilistic production metric gate".to_string(),
412 context: format!(
413 "accepted row-specific/fallback tuple capacity requires accepted GPU row \
414 filters, got row_filters=0 row_specific_capacity={} fallback_capacity={}",
415 self.accepted_gpu_row_specific_membership_row_capacity_consumed,
416 self.accepted_gpu_row_filter_fallback_row_capacity_consumed
417 ),
418 });
419 }
420 if self.accepted_gpu_final_tuple_row_filters_consumed > 0
421 && self.accepted_gpu_row_specific_membership_row_capacity_consumed == 0
422 {
423 return Err(XlogError::UnsupportedEpistemicConstruct {
424 construct: "epistemic probabilistic production metric gate".to_string(),
425 context: format!(
426 "accepted GPU final-tuple row filters require row-specific model-slot \
427 capacity, got row_filters={} row_specific_capacity=0",
428 self.accepted_gpu_final_tuple_row_filters_consumed
429 ),
430 });
431 }
432 if self.accepted_gpu_constraint_row_count_device_reads_consumed
433 > self.accepted_gpu_constraint_relations_checked_consumed
434 {
435 return Err(XlogError::UnsupportedEpistemicConstruct {
436 construct: "epistemic probabilistic production metric gate".to_string(),
437 context: format!(
438 "accepted constraint row-count device reads cannot exceed checked reduced \
439 constraint relations, got reads={} checked={}",
440 self.accepted_gpu_constraint_row_count_device_reads_consumed,
441 self.accepted_gpu_constraint_relations_checked_consumed
442 ),
443 });
444 }
445 Ok(())
446 }
447
448 pub fn require_accepted_gpu_world_view_evidence_trace(&self) -> Result<()> {
450 let mode_count = self
451 .accepted_g91_world_view_evidence_consumed
452 .checked_add(self.accepted_faeel_world_view_evidence_consumed)
453 .ok_or_else(|| XlogError::UnsupportedEpistemicConstruct {
454 construct: "epistemic probabilistic production metric gate".to_string(),
455 context: "accepted GPU world-view mode counters overflowed".to_string(),
456 })?;
457 if self.accepted_world_view_evidence_consumed != 0
458 && mode_count != self.accepted_world_view_evidence_consumed
459 {
460 return Err(XlogError::UnsupportedEpistemicConstruct {
461 construct: "epistemic probabilistic production metric gate".to_string(),
462 context: format!(
463 "accepted GPU world-view evidence must be classified by epistemic mode, got \
464 evidence={} gelfond_1991={} faeel={}",
465 self.accepted_world_view_evidence_consumed,
466 self.accepted_g91_world_view_evidence_consumed,
467 self.accepted_faeel_world_view_evidence_consumed
468 ),
469 });
470 }
471 if self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed
472 > self.accepted_evidence_assumptions_consumed
473 {
474 return Err(XlogError::UnsupportedEpistemicConstruct {
475 construct: "epistemic probabilistic production metric gate".to_string(),
476 context: format!(
477 "accepted nonzero-arity GPU evidence assumptions cannot exceed accepted \
478 assumptions, got nonzero={} assumptions={}",
479 self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed,
480 self.accepted_evidence_assumptions_consumed
481 ),
482 });
483 }
484 if self.accepted_world_view_evidence_consumed != 0
485 && self.accepted_evidence_assumptions_consumed
486 < self.accepted_world_view_evidence_consumed
487 {
488 return Err(XlogError::UnsupportedEpistemicConstruct {
489 construct: "epistemic probabilistic production metric gate".to_string(),
490 context: format!(
491 "accepted GPU world-view evidence requires at least one accepted epistemic \
492 assumption per evidence record, got evidence={} assumptions={}",
493 self.accepted_world_view_evidence_consumed,
494 self.accepted_evidence_assumptions_consumed
495 ),
496 });
497 }
498 if self.accepted_gpu_batch_component_evidence_consumed
499 < self.accepted_gpu_batch_evidence_consumed
500 {
501 return Err(XlogError::UnsupportedEpistemicConstruct {
502 construct: "epistemic probabilistic production metric gate".to_string(),
503 context: format!(
504 "accepted GPU batch component evidence must cover accepted batch evidence, \
505 got batches={} components={}",
506 self.accepted_gpu_batch_evidence_consumed,
507 self.accepted_gpu_batch_component_evidence_consumed
508 ),
509 });
510 }
511 if self.accepted_gpu_batch_component_evidence_consumed
512 > self.accepted_world_view_evidence_consumed
513 {
514 return Err(XlogError::UnsupportedEpistemicConstruct {
515 construct: "epistemic probabilistic production metric gate".to_string(),
516 context: format!(
517 "accepted GPU batch component evidence cannot exceed accepted world-view \
518 evidence, got components={} evidence={}",
519 self.accepted_gpu_batch_component_evidence_consumed,
520 self.accepted_world_view_evidence_consumed
521 ),
522 });
523 }
524 if self.accepted_conditioned_world_view_evidence_consumed
525 > self.accepted_world_view_evidence_consumed
526 {
527 return Err(XlogError::UnsupportedEpistemicConstruct {
528 construct: "epistemic probabilistic production metric gate".to_string(),
529 context: format!(
530 "accepted conditioned world-view evidence cannot exceed accepted world-view \
531 evidence, got conditioned={} evidence={}",
532 self.accepted_conditioned_world_view_evidence_consumed,
533 self.accepted_world_view_evidence_consumed
534 ),
535 });
536 }
537 Ok(())
538 }
539
540 fn require_conditioned_counter_sum(
541 counter: &'static str,
542 aggregate: u64,
543 source: u64,
544 program: u64,
545 ) -> Result<()> {
546 let expected = source.checked_add(program).ok_or_else(|| {
547 XlogError::UnsupportedEpistemicConstruct {
548 construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
549 context: format!(
550 "conditioned evidence counter {counter} overflowed while adding source={} \
551 program={}",
552 source, program
553 ),
554 }
555 })?;
556 if aggregate != expected {
557 return Err(XlogError::UnsupportedEpistemicConstruct {
558 construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
559 context: format!(
560 "conditioned evidence counter {counter} must equal source+program, got \
561 aggregate={} source={} program={}",
562 aggregate, source, program
563 ),
564 });
565 }
566 Ok(())
567 }
568
569 fn require_gpu_path_counter_sum(
570 counter: &'static str,
571 aggregate: u64,
572 source: u64,
573 program: u64,
574 ) -> Result<()> {
575 let expected = source.checked_add(program).ok_or_else(|| {
576 XlogError::UnsupportedEpistemicConstruct {
577 construct: "epistemic probabilistic production metric gate".to_string(),
578 context: format!(
579 "GPU production path counter {counter} overflowed while adding source={} \
580 program={}",
581 source, program
582 ),
583 }
584 })?;
585 if aggregate != expected {
586 return Err(XlogError::UnsupportedEpistemicConstruct {
587 construct: "epistemic probabilistic production metric gate".to_string(),
588 context: format!(
589 "GPU production path accounting must match source+program for {counter}, \
590 got aggregate={} source={} program={}",
591 aggregate, source, program
592 ),
593 });
594 }
595 Ok(())
596 }
597
598 fn require_gpu_path_accounting(&self) -> Result<()> {
599 Self::require_gpu_path_counter_sum(
600 "exact_query_evaluations",
601 self.gpu_exact_query_evaluations,
602 self.gpu_source_exact_query_evaluations,
603 self.gpu_program_exact_query_evaluations,
604 )?;
605 Self::require_gpu_path_counter_sum(
606 "exact_gradient_evaluations",
607 self.gpu_exact_gradient_evaluations,
608 self.gpu_source_exact_gradient_evaluations,
609 self.gpu_program_exact_gradient_evaluations,
610 )?;
611 Self::require_gpu_path_counter_sum(
612 "pir_graph_uploads",
613 self.gpu_pir_graph_uploads,
614 self.gpu_source_pir_graph_uploads,
615 self.gpu_program_pir_graph_uploads,
616 )?;
617 Self::require_gpu_path_counter_sum(
618 "cnf_encodes",
619 self.gpu_cnf_encodes,
620 self.gpu_source_cnf_encodes,
621 self.gpu_program_cnf_encodes,
622 )?;
623 Self::require_gpu_path_counter_sum(
624 "knowledge_compilation_end_to_end_runs",
625 self.gpu_knowledge_compilation_end_to_end_runs,
626 self.gpu_source_knowledge_compilation_end_to_end_runs,
627 self.gpu_program_knowledge_compilation_end_to_end_runs,
628 )
629 }
630
631 pub fn require_conditioned_evidence_trace(&self) -> Result<()> {
633 Self::require_conditioned_counter_sum(
634 "accepted_world_view_evidence",
635 self.accepted_conditioned_world_view_evidence_consumed,
636 self.accepted_source_conditioned_world_view_evidence_consumed,
637 self.accepted_program_conditioned_world_view_evidence_consumed,
638 )?;
639 Self::require_conditioned_counter_sum(
640 "evidence_facts",
641 self.gpu_conditioned_evidence_facts,
642 self.gpu_source_conditioned_evidence_facts,
643 self.gpu_program_conditioned_evidence_facts,
644 )?;
645 Self::require_conditioned_counter_sum(
646 "nonzero_arity_evidence_facts",
647 self.gpu_conditioned_nonzero_arity_evidence_facts,
648 self.gpu_source_conditioned_nonzero_arity_evidence_facts,
649 self.gpu_program_conditioned_nonzero_arity_evidence_facts,
650 )?;
651 Self::require_conditioned_counter_sum(
652 "negative_evidence_facts",
653 self.gpu_conditioned_negative_evidence_facts,
654 self.gpu_source_conditioned_negative_evidence_facts,
655 self.gpu_program_conditioned_negative_evidence_facts,
656 )?;
657 Self::require_conditioned_counter_sum(
658 "know_evidence_facts",
659 self.gpu_conditioned_know_evidence_facts,
660 self.gpu_source_conditioned_know_evidence_facts,
661 self.gpu_program_conditioned_know_evidence_facts,
662 )?;
663 Self::require_conditioned_counter_sum(
664 "possible_evidence_facts",
665 self.gpu_conditioned_possible_evidence_facts,
666 self.gpu_source_conditioned_possible_evidence_facts,
667 self.gpu_program_conditioned_possible_evidence_facts,
668 )?;
669 Self::require_conditioned_counter_sum(
670 "not_known_evidence_facts",
671 self.gpu_conditioned_not_known_evidence_facts,
672 self.gpu_source_conditioned_not_known_evidence_facts,
673 self.gpu_program_conditioned_not_known_evidence_facts,
674 )?;
675 Self::require_conditioned_counter_sum(
676 "not_possible_evidence_facts",
677 self.gpu_conditioned_not_possible_evidence_facts,
678 self.gpu_source_conditioned_not_possible_evidence_facts,
679 self.gpu_program_conditioned_not_possible_evidence_facts,
680 )?;
681
682 if (self.gpu_conditioned_evidence_facts != 0
683 && self.accepted_conditioned_world_view_evidence_consumed == 0)
684 || (self.gpu_source_conditioned_evidence_facts != 0
685 && self.accepted_source_conditioned_world_view_evidence_consumed == 0)
686 || (self.gpu_program_conditioned_evidence_facts != 0
687 && self.accepted_program_conditioned_world_view_evidence_consumed == 0)
688 {
689 return Err(XlogError::UnsupportedEpistemicConstruct {
690 construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
691 context: format!(
692 "conditioned exact evidence facts require accepted conditioned world-view \
693 evidence, got facts={} evidence={} source_facts={} source_evidence={} \
694 program_facts={} program_evidence={}",
695 self.gpu_conditioned_evidence_facts,
696 self.accepted_conditioned_world_view_evidence_consumed,
697 self.gpu_source_conditioned_evidence_facts,
698 self.accepted_source_conditioned_world_view_evidence_consumed,
699 self.gpu_program_conditioned_evidence_facts,
700 self.accepted_program_conditioned_world_view_evidence_consumed
701 ),
702 });
703 }
704
705 if self.gpu_conditioned_evidence_facts
706 < self.accepted_conditioned_world_view_evidence_consumed
707 || self.gpu_source_conditioned_evidence_facts
708 < self.accepted_source_conditioned_world_view_evidence_consumed
709 || self.gpu_program_conditioned_evidence_facts
710 < self.accepted_program_conditioned_world_view_evidence_consumed
711 {
712 return Err(XlogError::UnsupportedEpistemicConstruct {
713 construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
714 context: format!(
715 "conditioned exact evidence facts must cover each accepted conditioned \
716 world-view evidence record, got facts={} evidence={} source_facts={} \
717 source_evidence={} program_facts={} program_evidence={}",
718 self.gpu_conditioned_evidence_facts,
719 self.accepted_conditioned_world_view_evidence_consumed,
720 self.gpu_source_conditioned_evidence_facts,
721 self.accepted_source_conditioned_world_view_evidence_consumed,
722 self.gpu_program_conditioned_evidence_facts,
723 self.accepted_program_conditioned_world_view_evidence_consumed
724 ),
725 });
726 }
727
728 if self.gpu_conditioned_nonzero_arity_evidence_facts > self.gpu_conditioned_evidence_facts
729 || self.gpu_source_conditioned_nonzero_arity_evidence_facts
730 > self.gpu_source_conditioned_evidence_facts
731 || self.gpu_program_conditioned_nonzero_arity_evidence_facts
732 > self.gpu_program_conditioned_evidence_facts
733 {
734 return Err(XlogError::UnsupportedEpistemicConstruct {
735 construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
736 context: format!(
737 "conditioned nonzero-arity facts cannot exceed conditioned evidence facts: \
738 nonzero={} total={} source_nonzero={} source_total={} program_nonzero={} \
739 program_total={}",
740 self.gpu_conditioned_nonzero_arity_evidence_facts,
741 self.gpu_conditioned_evidence_facts,
742 self.gpu_source_conditioned_nonzero_arity_evidence_facts,
743 self.gpu_source_conditioned_evidence_facts,
744 self.gpu_program_conditioned_nonzero_arity_evidence_facts,
745 self.gpu_program_conditioned_evidence_facts
746 ),
747 });
748 }
749 if self.gpu_conditioned_negative_evidence_facts > self.gpu_conditioned_evidence_facts
750 || self.gpu_source_conditioned_negative_evidence_facts
751 > self.gpu_source_conditioned_evidence_facts
752 || self.gpu_program_conditioned_negative_evidence_facts
753 > self.gpu_program_conditioned_evidence_facts
754 {
755 return Err(XlogError::UnsupportedEpistemicConstruct {
756 construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
757 context: format!(
758 "conditioned negative facts cannot exceed conditioned evidence facts: \
759 negative={} total={} source_negative={} source_total={} program_negative={} \
760 program_total={}",
761 self.gpu_conditioned_negative_evidence_facts,
762 self.gpu_conditioned_evidence_facts,
763 self.gpu_source_conditioned_negative_evidence_facts,
764 self.gpu_source_conditioned_evidence_facts,
765 self.gpu_program_conditioned_negative_evidence_facts,
766 self.gpu_program_conditioned_evidence_facts
767 ),
768 });
769 }
770
771 let operator_fact_count = self
772 .gpu_conditioned_know_evidence_facts
773 .checked_add(self.gpu_conditioned_possible_evidence_facts)
774 .and_then(|sum| sum.checked_add(self.gpu_conditioned_not_known_evidence_facts))
775 .and_then(|sum| sum.checked_add(self.gpu_conditioned_not_possible_evidence_facts))
776 .ok_or_else(|| XlogError::UnsupportedEpistemicConstruct {
777 construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
778 context: "conditioned operator evidence fact counters overflowed".to_string(),
779 })?;
780 if operator_fact_count != self.gpu_conditioned_evidence_facts {
781 return Err(XlogError::UnsupportedEpistemicConstruct {
782 construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
783 context: format!(
784 "conditioned operator evidence facts must equal total evidence facts, got \
785 operators={} total={}",
786 operator_fact_count, self.gpu_conditioned_evidence_facts
787 ),
788 });
789 }
790
791 let source_operator_fact_count = self
792 .gpu_source_conditioned_know_evidence_facts
793 .checked_add(self.gpu_source_conditioned_possible_evidence_facts)
794 .and_then(|sum| sum.checked_add(self.gpu_source_conditioned_not_known_evidence_facts))
795 .and_then(|sum| {
796 sum.checked_add(self.gpu_source_conditioned_not_possible_evidence_facts)
797 })
798 .ok_or_else(|| XlogError::UnsupportedEpistemicConstruct {
799 construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
800 context: "source conditioned operator evidence fact counters overflowed"
801 .to_string(),
802 })?;
803 if source_operator_fact_count != self.gpu_source_conditioned_evidence_facts {
804 return Err(XlogError::UnsupportedEpistemicConstruct {
805 construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
806 context: format!(
807 "source conditioned operator evidence facts must equal source evidence \
808 facts, got operators={} total={}",
809 source_operator_fact_count, self.gpu_source_conditioned_evidence_facts
810 ),
811 });
812 }
813
814 let program_operator_fact_count = self
815 .gpu_program_conditioned_know_evidence_facts
816 .checked_add(self.gpu_program_conditioned_possible_evidence_facts)
817 .and_then(|sum| sum.checked_add(self.gpu_program_conditioned_not_known_evidence_facts))
818 .and_then(|sum| {
819 sum.checked_add(self.gpu_program_conditioned_not_possible_evidence_facts)
820 })
821 .ok_or_else(|| XlogError::UnsupportedEpistemicConstruct {
822 construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
823 context: "program conditioned operator evidence fact counters overflowed"
824 .to_string(),
825 })?;
826 if program_operator_fact_count != self.gpu_program_conditioned_evidence_facts {
827 return Err(XlogError::UnsupportedEpistemicConstruct {
828 construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
829 context: format!(
830 "program conditioned operator evidence facts must equal program evidence \
831 facts, got operators={} total={}",
832 program_operator_fact_count, self.gpu_program_conditioned_evidence_facts
833 ),
834 });
835 }
836
837 let expected_max_arity = self
838 .gpu_source_conditioned_max_evidence_arity
839 .max(self.gpu_program_conditioned_max_evidence_arity);
840 if self.gpu_conditioned_max_evidence_arity != expected_max_arity {
841 return Err(XlogError::UnsupportedEpistemicConstruct {
842 construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
843 context: format!(
844 "conditioned max evidence arity must equal max(source, program), got \
845 aggregate={} source={} program={}",
846 self.gpu_conditioned_max_evidence_arity,
847 self.gpu_source_conditioned_max_evidence_arity,
848 self.gpu_program_conditioned_max_evidence_arity
849 ),
850 });
851 }
852 if (self.gpu_conditioned_nonzero_arity_evidence_facts == 0)
853 != (self.gpu_conditioned_max_evidence_arity == 0)
854 {
855 return Err(XlogError::UnsupportedEpistemicConstruct {
856 construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
857 context: format!(
858 "conditioned max evidence arity must be nonzero exactly when nonzero-arity \
859 facts are present, got nonzero={} max_arity={}",
860 self.gpu_conditioned_nonzero_arity_evidence_facts,
861 self.gpu_conditioned_max_evidence_arity
862 ),
863 });
864 }
865 if (self.gpu_source_conditioned_nonzero_arity_evidence_facts == 0)
866 != (self.gpu_source_conditioned_max_evidence_arity == 0)
867 {
868 return Err(XlogError::UnsupportedEpistemicConstruct {
869 construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
870 context: format!(
871 "source conditioned max evidence arity must be nonzero exactly when \
872 source nonzero-arity facts are present, got nonzero={} max_arity={}",
873 self.gpu_source_conditioned_nonzero_arity_evidence_facts,
874 self.gpu_source_conditioned_max_evidence_arity
875 ),
876 });
877 }
878 if (self.gpu_program_conditioned_nonzero_arity_evidence_facts == 0)
879 != (self.gpu_program_conditioned_max_evidence_arity == 0)
880 {
881 return Err(XlogError::UnsupportedEpistemicConstruct {
882 construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
883 context: format!(
884 "program conditioned max evidence arity must be nonzero exactly when \
885 program nonzero-arity facts are present, got nonzero={} max_arity={}",
886 self.gpu_program_conditioned_nonzero_arity_evidence_facts,
887 self.gpu_program_conditioned_max_evidence_arity
888 ),
889 });
890 }
891 if (self.accepted_evidence_assumptions_consumed != 0
892 || self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed != 0
893 || self.accepted_gpu_max_evidence_arity_consumed != 0)
894 && (self.gpu_conditioned_evidence_facts > self.accepted_evidence_assumptions_consumed
895 || self.gpu_conditioned_nonzero_arity_evidence_facts
896 > self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed
897 || self.gpu_conditioned_max_evidence_arity
898 > self.accepted_gpu_max_evidence_arity_consumed)
899 {
900 return Err(XlogError::UnsupportedEpistemicConstruct {
901 construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
902 context: format!(
903 "conditioned evidence facts must be bounded by accepted GPU evidence, got \
904 facts={}/{} nonzero={}/{} max_arity={}/{}",
905 self.gpu_conditioned_evidence_facts,
906 self.accepted_evidence_assumptions_consumed,
907 self.gpu_conditioned_nonzero_arity_evidence_facts,
908 self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed,
909 self.gpu_conditioned_max_evidence_arity,
910 self.accepted_gpu_max_evidence_arity_consumed
911 ),
912 });
913 }
914 Ok(())
915 }
916
917 pub fn require_production_metric_eligibility(&self) -> Result<()> {
922 let capabilities = production_capabilities();
923 if capabilities.fixture_circuit_allowed {
924 return Err(XlogError::UnsupportedEpistemicConstruct {
925 construct: "epistemic probabilistic production metric gate".to_string(),
926 context: "bounded EpistemicCircuit fixtures are not allowed for production metrics"
927 .to_string(),
928 });
929 }
930 if capabilities.gpu_exact_provenance != EpistemicProbProductionCapabilityStatus::Available {
931 return Err(XlogError::UnsupportedEpistemicConstruct {
932 construct: "epistemic probabilistic production metric gate".to_string(),
933 context: "GPU exact/provenance production capability is not available".to_string(),
934 });
935 }
936 if capabilities.gpu_pir_cnf != EpistemicProbProductionCapabilityStatus::Available {
937 return Err(XlogError::UnsupportedEpistemicConstruct {
938 construct: "epistemic probabilistic production metric gate".to_string(),
939 context: "GPU PIR/CNF production capability is not available".to_string(),
940 });
941 }
942 if capabilities.gpu_knowledge_compilation
943 != EpistemicProbProductionCapabilityStatus::Available
944 {
945 return Err(XlogError::UnsupportedEpistemicConstruct {
946 construct: "epistemic probabilistic production metric gate".to_string(),
947 context: capabilities.gpu_knowledge_compilation_blocker.to_string(),
948 });
949 }
950 if capabilities.gpu_exact_query_and_gradient
951 != EpistemicProbProductionCapabilityStatus::Available
952 {
953 return Err(XlogError::UnsupportedEpistemicConstruct {
954 construct: "epistemic probabilistic production metric gate".to_string(),
955 context: "GPU exact query/gradient production capability is not available"
956 .to_string(),
957 });
958 }
959 if self.accepted_world_view_evidence_consumed == 0 {
960 return Err(XlogError::UnsupportedEpistemicConstruct {
961 construct: "epistemic probabilistic production metric gate".to_string(),
962 context: "production probability metrics require accepted world-view evidence"
963 .to_string(),
964 });
965 }
966 let gpu_production_path_events = self.checked_gpu_production_path_events()?;
967 if gpu_production_path_events == 0 {
968 return Err(XlogError::UnsupportedEpistemicConstruct {
969 construct: "epistemic probabilistic production metric gate".to_string(),
970 context: "production probability metrics require an existing GPU exact/provenance/PIR/CNF/knowledge-compilation counter"
971 .to_string(),
972 });
973 }
974 if self.accepted_gpu_production_path_events == 0 {
975 return Err(XlogError::UnsupportedEpistemicConstruct {
976 construct: "epistemic probabilistic production metric gate".to_string(),
977 context: "production probability metrics require GPU exact/provenance/PIR/CNF/knowledge-compilation work inside an accepted world-view evidence gate"
978 .to_string(),
979 });
980 }
981 if self.accepted_gpu_production_path_events > gpu_production_path_events {
982 return Err(XlogError::UnsupportedEpistemicConstruct {
983 construct: "epistemic probabilistic production metric gate".to_string(),
984 context: format!(
985 "accepted GPU probability production events cannot exceed total GPU production events: accepted={} total={}",
986 self.accepted_gpu_production_path_events, gpu_production_path_events
987 ),
988 });
989 }
990 if self.accepted_gpu_production_path_events < self.accepted_world_view_evidence_consumed {
991 return Err(XlogError::UnsupportedEpistemicConstruct {
992 construct: "epistemic probabilistic production metric gate".to_string(),
993 context: format!(
994 "accepted GPU probability production events must cover each accepted \
995 world-view evidence record, got accepted_events={} evidence={}",
996 self.accepted_gpu_production_path_events,
997 self.accepted_world_view_evidence_consumed
998 ),
999 });
1000 }
1001 self.require_accepted_gpu_world_view_evidence_trace()?;
1002 self.require_accepted_gpu_tuple_evidence_trace()?;
1003 self.require_conditioned_evidence_trace()?;
1004 self.require_pir_cnf_accounting()?;
1005 self.require_gpu_path_accounting()?;
1006 self.require_zero_cpu_recompute()
1007 }
1008
1009 fn require_conditioned_evidence_metric_witness(&self) -> Result<()> {
1010 if self.accepted_conditioned_world_view_evidence_consumed == 0
1011 || self.gpu_conditioned_evidence_facts == 0
1012 {
1013 return Err(XlogError::UnsupportedEpistemicConstruct {
1014 construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
1015 context:
1016 "production probability metrics require accepted world-view evidence compiled as exact evidence facts"
1017 .to_string(),
1018 });
1019 }
1020 Ok(())
1021 }
1022
1023 pub fn require_conditioned_evidence_metric_eligibility(&self) -> Result<()> {
1030 self.require_production_metric_eligibility()?;
1031 self.require_conditioned_evidence_metric_witness()?;
1032 if self.gpu_conditioned_nonzero_arity_evidence_facts > 0
1033 && self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed == 0
1034 {
1035 return Err(XlogError::UnsupportedEpistemicConstruct {
1036 construct: "epistemic probabilistic conditioned evidence metric gate".to_string(),
1037 context: format!(
1038 "conditioned nonzero-arity evidence facts require accepted GPU nonzero-arity \
1039 assumptions, got conditioned_nonzero={} accepted_nonzero={}",
1040 self.gpu_conditioned_nonzero_arity_evidence_facts,
1041 self.accepted_gpu_nonzero_arity_evidence_assumptions_consumed
1042 ),
1043 });
1044 }
1045 self.require_zero_cpu_recompute()
1046 }
1047}
1048
1049#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
1051pub struct EpistemicProbPirCnfEvidence {
1052 pub pir_nodes: usize,
1054 pub root_count: usize,
1056 pub cnf_var_cap: u32,
1058 pub cnf_clause_cap: u32,
1060 pub cnf_lit_cap: u32,
1062}
1063
1064#[derive(Clone, Copy)]
1066pub struct EpistemicProbGpuExecutionEvidence<'a> {
1067 pub result: &'a EpistemicGpuExecutionResult,
1069 pub assumptions: &'a [EpistemicAssumption],
1071}
1072
1073pub struct EpistemicProbGpuBatchExecutionEvidence<'a> {
1075 pub batch: &'a EpistemicGpuBatchExecutionResult,
1077 pub assumptions_by_component: &'a [&'a [EpistemicAssumption]],
1079}
1080
1081#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1082enum EpistemicProbPirCnfPath {
1083 Source,
1084 Program,
1085}
1086
1087pub struct EpistemicProbProductionAdapter {
1089 config: GpuConfig,
1090 trace: EpistemicProbProductionTrace,
1091}
1092
1093#[cfg(feature = "host-io")]
1094#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1095enum EpistemicProbConditionedEvidencePath {
1096 Source,
1097 Program,
1098}
1099
1100impl EpistemicProbProductionAdapter {
1101 fn checked_trace_counter_add(current: u64, delta: u64, counter: &str) -> Result<u64> {
1102 current
1103 .checked_add(delta)
1104 .ok_or_else(|| XlogError::UnsupportedEpistemicConstruct {
1105 construct: "epistemic probabilistic production trace accounting".to_string(),
1106 context: format!(
1107 "accepted GPU probability trace counter {counter} overflowed while adding \
1108 {delta} to {current}"
1109 ),
1110 })
1111 }
1112
1113 #[cfg(feature = "host-io")]
1114 fn record_gpu_exact_query_evaluation(&mut self, program: &ExactDdnnfProgram) -> Result<()> {
1115 checked_prob_trace_counter_inc!(self, gpu_exact_query_evaluations);
1116 match program.origin() {
1117 ExactProgramOrigin::Source => {
1118 checked_prob_trace_counter_inc!(self, gpu_source_exact_query_evaluations);
1119 }
1120 ExactProgramOrigin::Program => {
1121 checked_prob_trace_counter_inc!(self, gpu_program_exact_query_evaluations);
1122 }
1123 }
1124 Ok(())
1125 }
1126
1127 #[cfg(feature = "host-io")]
1128 fn record_gpu_exact_gradient_evaluation(&mut self, program: &ExactDdnnfProgram) -> Result<()> {
1129 self.record_gpu_exact_gradient_evaluation_for_origin(program.origin())
1130 }
1131
1132 #[cfg(feature = "host-io")]
1133 fn record_gpu_exact_gradient_evaluation_for_origin(
1134 &mut self,
1135 origin: ExactProgramOrigin,
1136 ) -> Result<()> {
1137 checked_prob_trace_counter_inc!(self, gpu_exact_gradient_evaluations);
1138 match origin {
1139 ExactProgramOrigin::Source => {
1140 checked_prob_trace_counter_inc!(self, gpu_source_exact_gradient_evaluations);
1141 }
1142 ExactProgramOrigin::Program => {
1143 checked_prob_trace_counter_inc!(self, gpu_program_exact_gradient_evaluations);
1144 }
1145 }
1146 Ok(())
1147 }
1148
1149 pub fn new(config: GpuConfig) -> Self {
1151 Self {
1152 config,
1153 trace: EpistemicProbProductionTrace {
1154 cpu_only_probability_recomputations: 0,
1155 fixture_circuit_evaluations: 0,
1156 ..EpistemicProbProductionTrace::default()
1157 },
1158 }
1159 }
1160
1161 pub fn trace(&self) -> EpistemicProbProductionTrace {
1163 self.trace
1164 }
1165
1166 pub fn apply_accepted_world_view_to_circuit(
1172 &mut self,
1173 circuit: &mut EpistemicCircuit,
1174 evidence: AcceptedWorldViewEvidence,
1175 ) -> Result<CircuitUpdate> {
1176 epistemic_prob_trace_transaction!(self, {
1177 self.consume_accepted_evidence(&evidence)?;
1178 let update = circuit.apply_accepted_world_view(evidence)?;
1179 if update.mode == CircuitUpdateMode::IncrementalEvidence {
1180 self.trace.accepted_incremental_circuit_updates = Self::checked_trace_counter_add(
1181 self.trace.accepted_incremental_circuit_updates,
1182 1,
1183 "accepted_incremental_circuit_updates",
1184 )?;
1185 }
1186 self.trace.require_zero_cpu_recompute()?;
1187 Ok(update)
1188 })
1189 }
1190
1191 pub fn apply_accepted_world_view_to_circuit_with_gpu_execution_result(
1193 &mut self,
1194 circuit: &mut EpistemicCircuit,
1195 provider: &CudaKernelProvider,
1196 result: &EpistemicGpuExecutionResult,
1197 assumptions: Vec<EpistemicAssumption>,
1198 ) -> Result<CircuitUpdate> {
1199 let evidence =
1200 AcceptedWorldViewEvidence::from_gpu_execution_result(provider, result, assumptions)?;
1201 self.apply_accepted_world_view_to_circuit(circuit, evidence)
1202 }
1203
1204 pub fn apply_accepted_world_views_to_circuit_for_gpu_batch_execution_result(
1206 &mut self,
1207 circuit: &mut EpistemicCircuit,
1208 provider: &CudaKernelProvider,
1209 evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
1210 ) -> Result<Vec<CircuitUpdate>> {
1211 epistemic_prob_trace_transaction!(self, {
1212 let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
1213 provider,
1214 evidence,
1215 "epistemic probabilistic incremental circuit batch production",
1216 )?;
1217
1218 let mut updates = Vec::with_capacity(accepted.len());
1219 for evidence in accepted {
1220 updates.push(self.apply_accepted_world_view_to_circuit(circuit, evidence)?);
1221 }
1222 Ok(updates)
1223 })
1224 }
1225
1226 fn accepted_world_views_from_gpu_batch_execution_evidence(
1227 &mut self,
1228 provider: &CudaKernelProvider,
1229 evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
1230 construct: &str,
1231 ) -> Result<Vec<AcceptedWorldViewEvidence>> {
1232 if evidence.batch.results.is_empty() {
1233 return Err(XlogError::UnsupportedEpistemicConstruct {
1234 construct: construct.to_string(),
1235 context: "probabilistic batch gating requires at least one accepted GPU component"
1236 .to_string(),
1237 });
1238 }
1239 if evidence.assumptions_by_component.len() != evidence.batch.results.len() {
1240 return Err(XlogError::UnsupportedEpistemicConstruct {
1241 construct: construct.to_string(),
1242 context: format!(
1243 "assumption group count {} does not match GPU batch component count {}",
1244 evidence.assumptions_by_component.len(),
1245 evidence.batch.results.len()
1246 ),
1247 });
1248 }
1249 let batch_trace = evidence.batch.trace;
1250 if batch_trace.component_count != evidence.batch.results.len()
1251 || batch_trace.gpu_runtime_component_executions != evidence.batch.results.len()
1252 || batch_trace.cpu_recomposition_steps != 0
1253 || batch_trace.cpu_candidate_enumerations != 0
1254 || batch_trace.cpu_world_view_validations != 0
1255 || batch_trace.cpu_solver_search_fallbacks != 0
1256 || batch_trace.cpu_probability_recomputations != 0
1257 || batch_trace.tracked_dtoh_calls != 0
1258 || batch_trace.tracked_htod_calls != 0
1259 || batch_trace.tracked_data_plane_htod_calls != 0
1260 || batch_trace.per_candidate_host_round_trips != 0
1261 || batch_trace.violated_constraint_relations != 0
1262 || !batch_trace.aggregate_kernel_timing.is_recorded()
1263 {
1264 return Err(XlogError::UnsupportedEpistemicConstruct {
1265 construct: construct.to_string(),
1266 context: format!(
1267 "accepted GPU batch evidence requires complete GPU component execution and \
1268 zero CPU/host fallback counters outside bounded launch metadata plus \
1269 aggregate CUDA-event timing, got \
1270 components={}/{}, recomposition={}, cpu_candidates={}, cpu_world_views={}, \
1271 cpu_solver_search={}, cpu_probability_recompute={}, dtoh_calls={}, \
1272 htod_calls={}, data_plane_htod_calls={}, launch_metadata_htod_calls={}, \
1273 round_trips={}, constraint_violations={}, aggregate_timing_recorded={}",
1274 batch_trace.gpu_runtime_component_executions,
1275 batch_trace.component_count,
1276 batch_trace.cpu_recomposition_steps,
1277 batch_trace.cpu_candidate_enumerations,
1278 batch_trace.cpu_world_view_validations,
1279 batch_trace.cpu_solver_search_fallbacks,
1280 batch_trace.cpu_probability_recomputations,
1281 batch_trace.tracked_dtoh_calls,
1282 batch_trace.tracked_htod_calls,
1283 batch_trace.tracked_data_plane_htod_calls,
1284 batch_trace.tracked_launch_metadata_htod_calls,
1285 batch_trace.per_candidate_host_round_trips,
1286 batch_trace.violated_constraint_relations,
1287 batch_trace.aggregate_kernel_timing.is_recorded()
1288 ),
1289 });
1290 }
1291 evidence.batch.require_trace_matches_components(construct)?;
1292
1293 let mut accepted = Vec::with_capacity(evidence.batch.results.len());
1294 for (result, assumptions) in evidence
1295 .batch
1296 .results
1297 .iter()
1298 .zip(evidence.assumptions_by_component.iter())
1299 {
1300 accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
1301 provider,
1302 result,
1303 (*assumptions).to_vec(),
1304 )?);
1305 }
1306
1307 self.trace.accepted_gpu_batch_evidence_consumed = Self::checked_trace_counter_add(
1308 self.trace.accepted_gpu_batch_evidence_consumed,
1309 1,
1310 "accepted_gpu_batch_evidence_consumed",
1311 )?;
1312 self.trace.accepted_gpu_batch_component_evidence_consumed =
1313 Self::checked_trace_counter_add(
1314 self.trace.accepted_gpu_batch_component_evidence_consumed,
1315 accepted.len() as u64,
1316 "accepted_gpu_batch_component_evidence_consumed",
1317 )?;
1318
1319 Ok(accepted)
1320 }
1321
1322 #[cfg(feature = "host-io")]
1323 fn record_conditioned_evidence_counts(
1324 &mut self,
1325 counts: EpistemicProbConditionedEvidenceCounts,
1326 path: EpistemicProbConditionedEvidencePath,
1327 ) -> Result<()> {
1328 macro_rules! add_counter {
1329 ($field:ident, $delta:expr) => {
1330 self.trace.$field =
1331 Self::checked_trace_counter_add(self.trace.$field, $delta, stringify!($field))?;
1332 };
1333 }
1334
1335 add_counter!(accepted_conditioned_world_view_evidence_consumed, 1);
1336 add_counter!(gpu_conditioned_evidence_facts, counts.total as u64);
1337 add_counter!(
1338 gpu_conditioned_nonzero_arity_evidence_facts,
1339 counts.nonzero_arity as u64
1340 );
1341 self.trace.gpu_conditioned_max_evidence_arity = self
1342 .trace
1343 .gpu_conditioned_max_evidence_arity
1344 .max(counts.max_arity);
1345 add_counter!(
1346 gpu_conditioned_negative_evidence_facts,
1347 counts.negative as u64
1348 );
1349 match path {
1350 EpistemicProbConditionedEvidencePath::Source => {
1351 add_counter!(accepted_source_conditioned_world_view_evidence_consumed, 1);
1352 add_counter!(gpu_source_conditioned_evidence_facts, counts.total as u64);
1353 add_counter!(
1354 gpu_source_conditioned_nonzero_arity_evidence_facts,
1355 counts.nonzero_arity as u64
1356 );
1357 self.trace.gpu_source_conditioned_max_evidence_arity = self
1358 .trace
1359 .gpu_source_conditioned_max_evidence_arity
1360 .max(counts.max_arity);
1361 add_counter!(
1362 gpu_source_conditioned_negative_evidence_facts,
1363 counts.negative as u64
1364 );
1365 add_counter!(
1366 gpu_source_conditioned_know_evidence_facts,
1367 counts.know as u64
1368 );
1369 add_counter!(
1370 gpu_source_conditioned_possible_evidence_facts,
1371 counts.possible as u64
1372 );
1373 add_counter!(
1374 gpu_source_conditioned_not_known_evidence_facts,
1375 counts.not_known as u64
1376 );
1377 add_counter!(
1378 gpu_source_conditioned_not_possible_evidence_facts,
1379 counts.not_possible as u64
1380 );
1381 }
1382 EpistemicProbConditionedEvidencePath::Program => {
1383 add_counter!(accepted_program_conditioned_world_view_evidence_consumed, 1);
1384 add_counter!(gpu_program_conditioned_evidence_facts, counts.total as u64);
1385 add_counter!(
1386 gpu_program_conditioned_nonzero_arity_evidence_facts,
1387 counts.nonzero_arity as u64
1388 );
1389 self.trace.gpu_program_conditioned_max_evidence_arity = self
1390 .trace
1391 .gpu_program_conditioned_max_evidence_arity
1392 .max(counts.max_arity);
1393 add_counter!(
1394 gpu_program_conditioned_negative_evidence_facts,
1395 counts.negative as u64
1396 );
1397 add_counter!(
1398 gpu_program_conditioned_know_evidence_facts,
1399 counts.know as u64
1400 );
1401 add_counter!(
1402 gpu_program_conditioned_possible_evidence_facts,
1403 counts.possible as u64
1404 );
1405 add_counter!(
1406 gpu_program_conditioned_not_known_evidence_facts,
1407 counts.not_known as u64
1408 );
1409 add_counter!(
1410 gpu_program_conditioned_not_possible_evidence_facts,
1411 counts.not_possible as u64
1412 );
1413 }
1414 }
1415 add_counter!(gpu_conditioned_know_evidence_facts, counts.know as u64);
1416 add_counter!(
1417 gpu_conditioned_possible_evidence_facts,
1418 counts.possible as u64
1419 );
1420 add_counter!(
1421 gpu_conditioned_not_known_evidence_facts,
1422 counts.not_known as u64
1423 );
1424 add_counter!(
1425 gpu_conditioned_not_possible_evidence_facts,
1426 counts.not_possible as u64
1427 );
1428 Ok(())
1429 }
1430
1431 fn record_accepted_gpu_production_path_events_since(
1432 &mut self,
1433 events_before: u64,
1434 ) -> Result<()> {
1435 let events_after = self.trace.checked_gpu_production_path_events()?;
1436 let delta = events_after.checked_sub(events_before).ok_or_else(|| {
1437 XlogError::UnsupportedEpistemicConstruct {
1438 construct: "epistemic probabilistic production trace accounting".to_string(),
1439 context: format!(
1440 "accepted GPU probability production events decreased from {events_before} to \
1441 {events_after}"
1442 ),
1443 }
1444 })?;
1445 self.trace.accepted_gpu_production_path_events = Self::checked_trace_counter_add(
1446 self.trace.accepted_gpu_production_path_events,
1447 delta,
1448 "accepted_gpu_production_path_events",
1449 )?;
1450 Ok(())
1451 }
1452
1453 pub fn compile_source_with_accepted_world_view(
1455 &mut self,
1456 source: &str,
1457 evidence: &AcceptedWorldViewEvidence,
1458 ) -> Result<ExactDdnnfProgram> {
1459 epistemic_prob_trace_transaction!(self, {
1460 self.require_accepted_evidence(evidence)?;
1461 let production_events_before = self.trace.checked_gpu_production_path_events()?;
1462 let program = ExactDdnnfProgram::compile_source_with_gpu(source, self.config)?;
1463 require_gpu_exact_backend(&program, "epistemic probabilistic source exact compile")?;
1464 checked_prob_trace_counter_inc!(self, gpu_exact_source_compiles);
1465 self.record_accepted_gpu_production_path_events_since(production_events_before)?;
1466 self.record_accepted_evidence(evidence)?;
1467 self.trace.require_zero_cpu_recompute()?;
1468 Ok(program)
1469 })
1470 }
1471
1472 pub fn compile_source_with_gpu_execution_result(
1474 &mut self,
1475 source: &str,
1476 provider: &CudaKernelProvider,
1477 result: &EpistemicGpuExecutionResult,
1478 assumptions: Vec<EpistemicAssumption>,
1479 ) -> Result<ExactDdnnfProgram> {
1480 let evidence =
1481 AcceptedWorldViewEvidence::from_gpu_execution_result(provider, result, assumptions)?;
1482 self.compile_source_with_accepted_world_view(source, &evidence)
1483 }
1484
1485 pub fn compile_source_for_gpu_execution_results(
1487 &mut self,
1488 source: &str,
1489 provider: &CudaKernelProvider,
1490 evidence_records: &[EpistemicProbGpuExecutionEvidence<'_>],
1491 ) -> Result<Vec<ExactDdnnfProgram>> {
1492 epistemic_prob_trace_transaction!(self, {
1493 if evidence_records.is_empty() {
1494 return Err(XlogError::UnsupportedEpistemicConstruct {
1495 construct: "epistemic probabilistic source exact compile batch".to_string(),
1496 context:
1497 "batched source exact compile requires at least one accepted GPU result"
1498 .to_string(),
1499 });
1500 }
1501
1502 let mut accepted = Vec::with_capacity(evidence_records.len());
1503 for record in evidence_records {
1504 accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
1505 provider,
1506 record.result,
1507 record.assumptions.to_vec(),
1508 )?);
1509 }
1510
1511 let mut programs = Vec::with_capacity(accepted.len());
1512 for evidence in &accepted {
1513 programs.push(self.compile_source_with_accepted_world_view(source, evidence)?);
1514 }
1515 Ok(programs)
1516 })
1517 }
1518
1519 pub fn compile_source_for_gpu_batch_execution_result(
1521 &mut self,
1522 source: &str,
1523 provider: &CudaKernelProvider,
1524 evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
1525 ) -> Result<Vec<ExactDdnnfProgram>> {
1526 epistemic_prob_trace_transaction!(self, {
1527 let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
1528 provider,
1529 evidence,
1530 "epistemic probabilistic source exact compile batch production",
1531 )?;
1532
1533 let mut programs = Vec::with_capacity(accepted.len());
1534 for evidence in &accepted {
1535 programs.push(self.compile_source_with_accepted_world_view(source, evidence)?);
1536 }
1537 Ok(programs)
1538 })
1539 }
1540
1541 pub fn compile_program_with_accepted_world_view(
1543 &mut self,
1544 program: &Program,
1545 evidence: &AcceptedWorldViewEvidence,
1546 ) -> Result<ExactDdnnfProgram> {
1547 epistemic_prob_trace_transaction!(self, {
1548 self.require_accepted_evidence(evidence)?;
1549 let production_events_before = self.trace.checked_gpu_production_path_events()?;
1550 let exact = ExactDdnnfProgram::compile_from_program(program, self.config)?;
1551 require_gpu_exact_backend(
1552 &exact,
1553 "epistemic probabilistic parsed-program exact compile",
1554 )?;
1555 checked_prob_trace_counter_inc!(self, gpu_exact_program_compiles);
1556 self.record_accepted_gpu_production_path_events_since(production_events_before)?;
1557 self.record_accepted_evidence(evidence)?;
1558 self.trace.require_zero_cpu_recompute()?;
1559 Ok(exact)
1560 })
1561 }
1562
1563 pub fn compile_program_with_gpu_execution_result(
1565 &mut self,
1566 program: &Program,
1567 provider: &CudaKernelProvider,
1568 result: &EpistemicGpuExecutionResult,
1569 assumptions: Vec<EpistemicAssumption>,
1570 ) -> Result<ExactDdnnfProgram> {
1571 let evidence =
1572 AcceptedWorldViewEvidence::from_gpu_execution_result(provider, result, assumptions)?;
1573 self.compile_program_with_accepted_world_view(program, &evidence)
1574 }
1575
1576 pub fn compile_program_for_gpu_execution_results(
1578 &mut self,
1579 program: &Program,
1580 provider: &CudaKernelProvider,
1581 evidence_records: &[EpistemicProbGpuExecutionEvidence<'_>],
1582 ) -> Result<Vec<ExactDdnnfProgram>> {
1583 epistemic_prob_trace_transaction!(self, {
1584 if evidence_records.is_empty() {
1585 return Err(XlogError::UnsupportedEpistemicConstruct {
1586 construct: "epistemic probabilistic parsed-program exact compile batch"
1587 .to_string(),
1588 context: "batched parsed-program exact compile requires at least one accepted GPU result"
1589 .to_string(),
1590 });
1591 }
1592
1593 let mut accepted = Vec::with_capacity(evidence_records.len());
1594 for record in evidence_records {
1595 accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
1596 provider,
1597 record.result,
1598 record.assumptions.to_vec(),
1599 )?);
1600 }
1601
1602 let mut programs = Vec::with_capacity(accepted.len());
1603 for evidence in &accepted {
1604 programs.push(self.compile_program_with_accepted_world_view(program, evidence)?);
1605 }
1606 Ok(programs)
1607 })
1608 }
1609
1610 pub fn compile_program_for_gpu_batch_execution_result(
1612 &mut self,
1613 program: &Program,
1614 provider: &CudaKernelProvider,
1615 evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
1616 ) -> Result<Vec<ExactDdnnfProgram>> {
1617 epistemic_prob_trace_transaction!(self, {
1618 let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
1619 provider,
1620 evidence,
1621 "epistemic probabilistic parsed-program exact compile batch production",
1622 )?;
1623
1624 let mut programs = Vec::with_capacity(accepted.len());
1625 for evidence in &accepted {
1626 programs.push(self.compile_program_with_accepted_world_view(program, evidence)?);
1627 }
1628 Ok(programs)
1629 })
1630 }
1631
1632 #[cfg(feature = "host-io")]
1634 pub fn compile_and_evaluate_source_with_accepted_world_view(
1635 &mut self,
1636 source: &str,
1637 evidence: &AcceptedWorldViewEvidence,
1638 ) -> Result<ExactResult> {
1639 epistemic_prob_trace_transaction!(self, {
1640 self.require_accepted_evidence(evidence)?;
1641 let production_events_before = self.trace.checked_gpu_production_path_events()?;
1642 let program = ExactDdnnfProgram::compile_source_with_gpu(source, self.config)?;
1643 require_gpu_exact_backend(
1644 &program,
1645 "epistemic probabilistic source exact compile/evaluate",
1646 )?;
1647 checked_prob_trace_counter_inc!(self, gpu_exact_source_compiles);
1648 let result = program.evaluate()?;
1649 checked_prob_trace_counter_inc!(self, gpu_exact_query_evaluations);
1650 checked_prob_trace_counter_inc!(self, gpu_source_exact_query_evaluations);
1651 checked_prob_trace_counter_inc!(self, gpu_knowledge_compilation_end_to_end_runs);
1652 checked_prob_trace_counter_inc!(self, gpu_source_knowledge_compilation_end_to_end_runs);
1653 self.record_accepted_gpu_production_path_events_since(production_events_before)?;
1654 self.record_accepted_evidence(evidence)?;
1655 self.trace.require_zero_cpu_recompute()?;
1656 Ok(result)
1657 })
1658 }
1659
1660 #[cfg(feature = "host-io")]
1662 pub fn compile_and_evaluate_source_with_gpu_execution_result(
1663 &mut self,
1664 source: &str,
1665 provider: &CudaKernelProvider,
1666 result: &EpistemicGpuExecutionResult,
1667 assumptions: Vec<EpistemicAssumption>,
1668 ) -> Result<ExactResult> {
1669 let evidence =
1670 AcceptedWorldViewEvidence::from_gpu_execution_result(provider, result, assumptions)?;
1671 self.compile_and_evaluate_source_with_accepted_world_view(source, &evidence)
1672 }
1673
1674 #[cfg(feature = "host-io")]
1676 pub fn compile_and_evaluate_source_for_gpu_execution_results(
1677 &mut self,
1678 source: &str,
1679 provider: &CudaKernelProvider,
1680 evidence_records: &[EpistemicProbGpuExecutionEvidence<'_>],
1681 ) -> Result<Vec<ExactResult>> {
1682 epistemic_prob_trace_transaction!(self, {
1683 if evidence_records.is_empty() {
1684 return Err(XlogError::UnsupportedEpistemicConstruct {
1685 construct: "epistemic probabilistic production batch".to_string(),
1686 context:
1687 "batched knowledge compilation requires at least one accepted GPU result"
1688 .to_string(),
1689 });
1690 }
1691
1692 let mut accepted = Vec::with_capacity(evidence_records.len());
1693 for record in evidence_records {
1694 accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
1695 provider,
1696 record.result,
1697 record.assumptions.to_vec(),
1698 )?);
1699 }
1700
1701 let mut results = Vec::with_capacity(accepted.len());
1702 for evidence in &accepted {
1703 results.push(
1704 self.compile_and_evaluate_source_with_accepted_world_view(source, evidence)?,
1705 );
1706 }
1707 Ok(results)
1708 })
1709 }
1710
1711 #[cfg(feature = "host-io")]
1713 pub fn compile_and_evaluate_source_for_gpu_batch_execution_result(
1714 &mut self,
1715 source: &str,
1716 provider: &CudaKernelProvider,
1717 evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
1718 ) -> Result<Vec<ExactResult>> {
1719 epistemic_prob_trace_transaction!(self, {
1720 let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
1721 provider,
1722 evidence,
1723 "epistemic probabilistic batch production",
1724 )?;
1725
1726 let mut results = Vec::with_capacity(accepted.len());
1727 for evidence in &accepted {
1728 results.push(
1729 self.compile_and_evaluate_source_with_accepted_world_view(source, evidence)?,
1730 );
1731 }
1732 Ok(results)
1733 })
1734 }
1735
1736 #[cfg(feature = "host-io")]
1738 pub fn compile_and_evaluate_conditioned_source_with_accepted_world_view(
1739 &mut self,
1740 source: &str,
1741 evidence: &AcceptedWorldViewEvidence,
1742 ) -> Result<ExactResult> {
1743 epistemic_prob_trace_transaction!(self, {
1744 let program = parse_program(source)?;
1745 let provenance = extract_from_program(&program)?;
1746 self.compile_and_evaluate_conditioned_program_with_path(
1747 &program,
1748 &provenance,
1749 evidence,
1750 EpistemicProbConditionedEvidencePath::Source,
1751 "epistemic probabilistic conditioned source exact compile/evaluate",
1752 )
1753 })
1754 }
1755
1756 #[cfg(feature = "host-io")]
1758 pub fn compile_and_evaluate_conditioned_source_with_gpu_execution_result(
1759 &mut self,
1760 source: &str,
1761 provider: &CudaKernelProvider,
1762 result: &EpistemicGpuExecutionResult,
1763 assumptions: Vec<EpistemicAssumption>,
1764 ) -> Result<ExactResult> {
1765 epistemic_prob_trace_transaction!(self, {
1766 let auto_derived = assumptions.is_empty();
1767 let evidence = AcceptedWorldViewEvidence::from_gpu_execution_result(
1768 provider,
1769 result,
1770 assumptions,
1771 )?;
1772 let program = parse_program(source)?;
1773 let provenance = extract_from_program(&program)?;
1774 let filtered_evidence;
1775 let evidence = if auto_derived {
1776 filtered_evidence =
1777 evidence_with_provenance_backed_assumptions(&evidence, &provenance)?;
1778 &filtered_evidence
1779 } else {
1780 &evidence
1781 };
1782 self.compile_and_evaluate_conditioned_program_with_path(
1783 &program,
1784 &provenance,
1785 evidence,
1786 EpistemicProbConditionedEvidencePath::Source,
1787 "epistemic probabilistic conditioned source exact compile/evaluate",
1788 )
1789 })
1790 }
1791
1792 #[cfg(feature = "host-io")]
1794 pub fn compile_and_evaluate_conditioned_source_for_gpu_execution_results(
1795 &mut self,
1796 source: &str,
1797 provider: &CudaKernelProvider,
1798 evidence_records: &[EpistemicProbGpuExecutionEvidence<'_>],
1799 ) -> Result<Vec<ExactResult>> {
1800 epistemic_prob_trace_transaction!(self, {
1801 if evidence_records.is_empty() {
1802 return Err(XlogError::UnsupportedEpistemicConstruct {
1803 construct: "epistemic probabilistic conditioned production batch".to_string(),
1804 context: "batched conditioned knowledge compilation requires at least one accepted GPU result"
1805 .to_string(),
1806 });
1807 }
1808
1809 let mut accepted = Vec::with_capacity(evidence_records.len());
1810 for record in evidence_records {
1811 accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
1812 provider,
1813 record.result,
1814 record.assumptions.to_vec(),
1815 )?);
1816 }
1817
1818 let program = parse_program(source)?;
1819 let provenance = extract_from_program(&program)?;
1820 let mut results = Vec::with_capacity(accepted.len());
1821 for (record, evidence) in evidence_records.iter().zip(accepted.iter()) {
1822 let filtered_evidence;
1823 let evidence = if record.assumptions.is_empty() {
1824 filtered_evidence =
1825 evidence_with_provenance_backed_assumptions(evidence, &provenance)?;
1826 &filtered_evidence
1827 } else {
1828 evidence
1829 };
1830 results.push(self.compile_and_evaluate_conditioned_program_with_path(
1831 &program,
1832 &provenance,
1833 evidence,
1834 EpistemicProbConditionedEvidencePath::Source,
1835 "epistemic probabilistic conditioned source exact compile/evaluate",
1836 )?);
1837 }
1838 Ok(results)
1839 })
1840 }
1841
1842 #[cfg(feature = "host-io")]
1844 pub fn compile_and_evaluate_conditioned_source_for_gpu_batch_execution_result(
1845 &mut self,
1846 source: &str,
1847 provider: &CudaKernelProvider,
1848 evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
1849 ) -> Result<Vec<ExactResult>> {
1850 epistemic_prob_trace_transaction!(self, {
1851 let auto_derived_by_component = evidence
1852 .assumptions_by_component
1853 .iter()
1854 .map(|assumptions| assumptions.is_empty())
1855 .collect::<Vec<_>>();
1856 let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
1857 provider,
1858 evidence,
1859 "epistemic probabilistic batch production",
1860 )?;
1861
1862 let program = parse_program(source)?;
1863 let provenance = extract_from_program(&program)?;
1864 let mut results = Vec::with_capacity(accepted.len());
1865 for (auto_derived, evidence) in auto_derived_by_component.iter().zip(accepted.iter()) {
1866 let filtered_evidence;
1867 let evidence = if *auto_derived {
1868 filtered_evidence =
1869 evidence_with_provenance_backed_assumptions(evidence, &provenance)?;
1870 &filtered_evidence
1871 } else {
1872 evidence
1873 };
1874 results.push(self.compile_and_evaluate_conditioned_program_with_path(
1875 &program,
1876 &provenance,
1877 evidence,
1878 EpistemicProbConditionedEvidencePath::Source,
1879 "epistemic probabilistic conditioned source exact compile/evaluate",
1880 )?);
1881 }
1882 Ok(results)
1883 })
1884 }
1885
1886 #[cfg(feature = "host-io")]
1888 pub fn compile_and_evaluate_conditioned_source_with_grads_with_accepted_world_view(
1889 &mut self,
1890 source: &str,
1891 evidence: &AcceptedWorldViewEvidence,
1892 ) -> Result<ExactResultWithGrads> {
1893 epistemic_prob_trace_transaction!(self, {
1894 let program = parse_program(source)?;
1895 let provenance = extract_from_program(&program)?;
1896 self.compile_and_evaluate_conditioned_program_with_grads_with_path(
1897 &program,
1898 &provenance,
1899 evidence,
1900 EpistemicProbConditionedEvidencePath::Source,
1901 "epistemic probabilistic conditioned source exact gradient",
1902 )
1903 })
1904 }
1905
1906 #[cfg(feature = "host-io")]
1908 pub fn compile_and_evaluate_conditioned_source_with_grads_with_gpu_execution_result(
1909 &mut self,
1910 source: &str,
1911 provider: &CudaKernelProvider,
1912 result: &EpistemicGpuExecutionResult,
1913 assumptions: Vec<EpistemicAssumption>,
1914 ) -> Result<ExactResultWithGrads> {
1915 epistemic_prob_trace_transaction!(self, {
1916 let auto_derived = assumptions.is_empty();
1917 let evidence = AcceptedWorldViewEvidence::from_gpu_execution_result(
1918 provider,
1919 result,
1920 assumptions,
1921 )?;
1922 let program = parse_program(source)?;
1923 let provenance = extract_from_program(&program)?;
1924 let filtered_evidence;
1925 let evidence = if auto_derived {
1926 filtered_evidence =
1927 evidence_with_provenance_backed_assumptions(&evidence, &provenance)?;
1928 &filtered_evidence
1929 } else {
1930 &evidence
1931 };
1932 self.compile_and_evaluate_conditioned_program_with_grads_with_path(
1933 &program,
1934 &provenance,
1935 evidence,
1936 EpistemicProbConditionedEvidencePath::Source,
1937 "epistemic probabilistic conditioned source exact gradient",
1938 )
1939 })
1940 }
1941
1942 #[cfg(feature = "host-io")]
1944 pub fn compile_and_evaluate_conditioned_source_with_grads_for_gpu_execution_results(
1945 &mut self,
1946 source: &str,
1947 provider: &CudaKernelProvider,
1948 evidence_records: &[EpistemicProbGpuExecutionEvidence<'_>],
1949 ) -> Result<Vec<ExactResultWithGrads>> {
1950 epistemic_prob_trace_transaction!(self, {
1951 if evidence_records.is_empty() {
1952 return Err(XlogError::UnsupportedEpistemicConstruct {
1953 construct: "epistemic probabilistic conditioned gradient production batch"
1954 .to_string(),
1955 context: "batched conditioned gradient compilation requires at least one accepted GPU result"
1956 .to_string(),
1957 });
1958 }
1959
1960 let mut accepted = Vec::with_capacity(evidence_records.len());
1961 for record in evidence_records {
1962 accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
1963 provider,
1964 record.result,
1965 record.assumptions.to_vec(),
1966 )?);
1967 }
1968
1969 let program = parse_program(source)?;
1970 let provenance = extract_from_program(&program)?;
1971 let mut results = Vec::with_capacity(accepted.len());
1972 for (record, evidence) in evidence_records.iter().zip(accepted.iter()) {
1973 let filtered_evidence;
1974 let evidence = if record.assumptions.is_empty() {
1975 filtered_evidence =
1976 evidence_with_provenance_backed_assumptions(evidence, &provenance)?;
1977 &filtered_evidence
1978 } else {
1979 evidence
1980 };
1981 results.push(
1982 self.compile_and_evaluate_conditioned_program_with_grads_with_path(
1983 &program,
1984 &provenance,
1985 evidence,
1986 EpistemicProbConditionedEvidencePath::Source,
1987 "epistemic probabilistic conditioned source exact gradient",
1988 )?,
1989 );
1990 }
1991 Ok(results)
1992 })
1993 }
1994
1995 #[cfg(feature = "host-io")]
1997 pub fn compile_and_evaluate_conditioned_source_with_grads_for_gpu_batch_execution_result(
1998 &mut self,
1999 source: &str,
2000 provider: &CudaKernelProvider,
2001 evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
2002 ) -> Result<Vec<ExactResultWithGrads>> {
2003 epistemic_prob_trace_transaction!(self, {
2004 let auto_derived_by_component = evidence
2005 .assumptions_by_component
2006 .iter()
2007 .map(|assumptions| assumptions.is_empty())
2008 .collect::<Vec<_>>();
2009 let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
2010 provider,
2011 evidence,
2012 "epistemic probabilistic batch production",
2013 )?;
2014
2015 let program = parse_program(source)?;
2016 let provenance = extract_from_program(&program)?;
2017 let mut results = Vec::with_capacity(accepted.len());
2018 for (auto_derived, evidence) in auto_derived_by_component.iter().zip(accepted.iter()) {
2019 let filtered_evidence;
2020 let evidence = if *auto_derived {
2021 filtered_evidence =
2022 evidence_with_provenance_backed_assumptions(evidence, &provenance)?;
2023 &filtered_evidence
2024 } else {
2025 evidence
2026 };
2027 results.push(
2028 self.compile_and_evaluate_conditioned_program_with_grads_with_path(
2029 &program,
2030 &provenance,
2031 evidence,
2032 EpistemicProbConditionedEvidencePath::Source,
2033 "epistemic probabilistic conditioned source exact gradient",
2034 )?,
2035 );
2036 }
2037 Ok(results)
2038 })
2039 }
2040
2041 #[cfg(feature = "host-io")]
2042 fn compile_and_evaluate_conditioned_program_with_path(
2043 &mut self,
2044 program: &Program,
2045 provenance: &Provenance,
2046 evidence: &AcceptedWorldViewEvidence,
2047 path: EpistemicProbConditionedEvidencePath,
2048 backend_context: &'static str,
2049 ) -> Result<ExactResult> {
2050 self.require_accepted_evidence(evidence)?;
2051 let production_events_before = self.trace.checked_gpu_production_path_events()?;
2052 let (program, evidence_counts) = condition_program_with_accepted_evidence_using_provenance(
2053 program, provenance, evidence,
2054 )?;
2055 let exact = ExactDdnnfProgram::compile_from_program(&program, self.config)?;
2056 require_gpu_exact_backend(&exact, backend_context)?;
2057 match path {
2058 EpistemicProbConditionedEvidencePath::Source => {
2059 checked_prob_trace_counter_inc!(self, gpu_exact_source_compiles);
2060 }
2061 EpistemicProbConditionedEvidencePath::Program => {
2062 checked_prob_trace_counter_inc!(self, gpu_exact_program_compiles);
2063 }
2064 }
2065 self.record_conditioned_evidence_counts(evidence_counts, path)?;
2066 let result = exact.evaluate()?;
2067 checked_prob_trace_counter_inc!(self, gpu_exact_query_evaluations);
2068 checked_prob_trace_counter_inc!(self, gpu_knowledge_compilation_end_to_end_runs);
2069 match path {
2070 EpistemicProbConditionedEvidencePath::Source => {
2071 checked_prob_trace_counter_inc!(self, gpu_source_exact_query_evaluations);
2072 checked_prob_trace_counter_inc!(
2073 self,
2074 gpu_source_knowledge_compilation_end_to_end_runs
2075 );
2076 }
2077 EpistemicProbConditionedEvidencePath::Program => {
2078 checked_prob_trace_counter_inc!(self, gpu_program_exact_query_evaluations);
2079 checked_prob_trace_counter_inc!(
2080 self,
2081 gpu_program_knowledge_compilation_end_to_end_runs
2082 );
2083 }
2084 }
2085 self.record_accepted_gpu_production_path_events_since(production_events_before)?;
2086 self.record_accepted_evidence(evidence)?;
2087 self.trace.require_zero_cpu_recompute()?;
2088 Ok(result)
2089 }
2090
2091 #[cfg(feature = "host-io")]
2092 fn compile_and_evaluate_conditioned_program_with_grads_with_path(
2093 &mut self,
2094 program: &Program,
2095 provenance: &Provenance,
2096 evidence: &AcceptedWorldViewEvidence,
2097 path: EpistemicProbConditionedEvidencePath,
2098 backend_context: &'static str,
2099 ) -> Result<ExactResultWithGrads> {
2100 self.require_accepted_evidence(evidence)?;
2101 let production_events_before = self.trace.checked_gpu_production_path_events()?;
2102 let (program, evidence_counts) = condition_program_with_accepted_evidence_using_provenance(
2103 program, provenance, evidence,
2104 )?;
2105 let exact = ExactDdnnfProgram::compile_from_program(&program, self.config)?;
2106 require_gpu_exact_backend(&exact, backend_context)?;
2107 match path {
2108 EpistemicProbConditionedEvidencePath::Source => {
2109 checked_prob_trace_counter_inc!(self, gpu_exact_source_compiles);
2110 }
2111 EpistemicProbConditionedEvidencePath::Program => {
2112 checked_prob_trace_counter_inc!(self, gpu_exact_program_compiles);
2113 }
2114 }
2115 self.record_conditioned_evidence_counts(evidence_counts, path)?;
2116 let result = exact.evaluate_gpu_with_grads()?;
2117 let origin = match path {
2118 EpistemicProbConditionedEvidencePath::Source => ExactProgramOrigin::Source,
2119 EpistemicProbConditionedEvidencePath::Program => ExactProgramOrigin::Program,
2120 };
2121 self.record_gpu_exact_gradient_evaluation_for_origin(origin)?;
2122 checked_prob_trace_counter_inc!(self, gpu_knowledge_compilation_end_to_end_runs);
2123 match path {
2124 EpistemicProbConditionedEvidencePath::Source => {
2125 checked_prob_trace_counter_inc!(self, gpu_source_conditioned_gradient_evaluations);
2126 checked_prob_trace_counter_inc!(
2127 self,
2128 gpu_source_knowledge_compilation_end_to_end_runs
2129 );
2130 }
2131 EpistemicProbConditionedEvidencePath::Program => {
2132 checked_prob_trace_counter_inc!(self, gpu_program_conditioned_gradient_evaluations);
2133 checked_prob_trace_counter_inc!(
2134 self,
2135 gpu_program_knowledge_compilation_end_to_end_runs
2136 );
2137 }
2138 }
2139 self.record_accepted_gpu_production_path_events_since(production_events_before)?;
2140 self.record_accepted_evidence(evidence)?;
2141 self.trace.require_zero_cpu_recompute()?;
2142 Ok(result)
2143 }
2144
2145 #[cfg(feature = "host-io")]
2147 pub fn compile_and_evaluate_conditioned_program_with_accepted_world_view(
2148 &mut self,
2149 program: &Program,
2150 evidence: &AcceptedWorldViewEvidence,
2151 ) -> Result<ExactResult> {
2152 epistemic_prob_trace_transaction!(self, {
2153 let provenance = extract_from_program(program)?;
2154 self.compile_and_evaluate_conditioned_program_with_path(
2155 program,
2156 &provenance,
2157 evidence,
2158 EpistemicProbConditionedEvidencePath::Program,
2159 "epistemic probabilistic conditioned parsed-program exact compile/evaluate",
2160 )
2161 })
2162 }
2163
2164 #[cfg(feature = "host-io")]
2166 pub fn compile_and_evaluate_conditioned_program_with_gpu_execution_result(
2167 &mut self,
2168 program: &Program,
2169 provider: &CudaKernelProvider,
2170 result: &EpistemicGpuExecutionResult,
2171 assumptions: Vec<EpistemicAssumption>,
2172 ) -> Result<ExactResult> {
2173 epistemic_prob_trace_transaction!(self, {
2174 let auto_derived = assumptions.is_empty();
2175 let evidence = AcceptedWorldViewEvidence::from_gpu_execution_result(
2176 provider,
2177 result,
2178 assumptions,
2179 )?;
2180 let provenance = extract_from_program(program)?;
2181 let filtered_evidence;
2182 let evidence = if auto_derived {
2183 filtered_evidence =
2184 evidence_with_provenance_backed_assumptions(&evidence, &provenance)?;
2185 &filtered_evidence
2186 } else {
2187 &evidence
2188 };
2189 self.compile_and_evaluate_conditioned_program_with_path(
2190 program,
2191 &provenance,
2192 evidence,
2193 EpistemicProbConditionedEvidencePath::Program,
2194 "epistemic probabilistic conditioned parsed-program exact compile/evaluate",
2195 )
2196 })
2197 }
2198
2199 #[cfg(feature = "host-io")]
2201 pub fn compile_and_evaluate_conditioned_program_for_gpu_execution_results(
2202 &mut self,
2203 program: &Program,
2204 provider: &CudaKernelProvider,
2205 evidence_records: &[EpistemicProbGpuExecutionEvidence<'_>],
2206 ) -> Result<Vec<ExactResult>> {
2207 epistemic_prob_trace_transaction!(self, {
2208 if evidence_records.is_empty() {
2209 return Err(XlogError::UnsupportedEpistemicConstruct {
2210 construct: "epistemic probabilistic conditioned production batch".to_string(),
2211 context: "batched conditioned program compilation requires at least one accepted GPU result"
2212 .to_string(),
2213 });
2214 }
2215
2216 let mut accepted = Vec::with_capacity(evidence_records.len());
2217 for record in evidence_records {
2218 accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
2219 provider,
2220 record.result,
2221 record.assumptions.to_vec(),
2222 )?);
2223 }
2224
2225 let provenance = extract_from_program(program)?;
2226 let mut results = Vec::with_capacity(accepted.len());
2227 for (record, evidence) in evidence_records.iter().zip(accepted.iter()) {
2228 let filtered_evidence;
2229 let evidence = if record.assumptions.is_empty() {
2230 filtered_evidence =
2231 evidence_with_provenance_backed_assumptions(evidence, &provenance)?;
2232 &filtered_evidence
2233 } else {
2234 evidence
2235 };
2236 results.push(self.compile_and_evaluate_conditioned_program_with_path(
2237 program,
2238 &provenance,
2239 evidence,
2240 EpistemicProbConditionedEvidencePath::Program,
2241 "epistemic probabilistic conditioned parsed-program exact compile/evaluate",
2242 )?);
2243 }
2244 Ok(results)
2245 })
2246 }
2247
2248 #[cfg(feature = "host-io")]
2250 pub fn compile_and_evaluate_conditioned_program_for_gpu_batch_execution_result(
2251 &mut self,
2252 program: &Program,
2253 provider: &CudaKernelProvider,
2254 evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
2255 ) -> Result<Vec<ExactResult>> {
2256 epistemic_prob_trace_transaction!(self, {
2257 let auto_derived_by_component = evidence
2258 .assumptions_by_component
2259 .iter()
2260 .map(|assumptions| assumptions.is_empty())
2261 .collect::<Vec<_>>();
2262 let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
2263 provider,
2264 evidence,
2265 "epistemic probabilistic batch production",
2266 )?;
2267
2268 let provenance = extract_from_program(program)?;
2269 let mut results = Vec::with_capacity(accepted.len());
2270 for (auto_derived, evidence) in auto_derived_by_component.iter().zip(accepted.iter()) {
2271 let filtered_evidence;
2272 let evidence = if *auto_derived {
2273 filtered_evidence =
2274 evidence_with_provenance_backed_assumptions(evidence, &provenance)?;
2275 &filtered_evidence
2276 } else {
2277 evidence
2278 };
2279 results.push(self.compile_and_evaluate_conditioned_program_with_path(
2280 program,
2281 &provenance,
2282 evidence,
2283 EpistemicProbConditionedEvidencePath::Program,
2284 "epistemic probabilistic conditioned parsed-program exact compile/evaluate",
2285 )?);
2286 }
2287 Ok(results)
2288 })
2289 }
2290
2291 #[cfg(feature = "host-io")]
2293 pub fn compile_and_evaluate_conditioned_program_with_grads_with_accepted_world_view(
2294 &mut self,
2295 program: &Program,
2296 evidence: &AcceptedWorldViewEvidence,
2297 ) -> Result<ExactResultWithGrads> {
2298 epistemic_prob_trace_transaction!(self, {
2299 let provenance = extract_from_program(program)?;
2300 self.compile_and_evaluate_conditioned_program_with_grads_with_path(
2301 program,
2302 &provenance,
2303 evidence,
2304 EpistemicProbConditionedEvidencePath::Program,
2305 "epistemic probabilistic conditioned parsed-program exact gradient",
2306 )
2307 })
2308 }
2309
2310 #[cfg(feature = "host-io")]
2312 pub fn compile_and_evaluate_conditioned_program_with_grads_with_gpu_execution_result(
2313 &mut self,
2314 program: &Program,
2315 provider: &CudaKernelProvider,
2316 result: &EpistemicGpuExecutionResult,
2317 assumptions: Vec<EpistemicAssumption>,
2318 ) -> Result<ExactResultWithGrads> {
2319 epistemic_prob_trace_transaction!(self, {
2320 let auto_derived = assumptions.is_empty();
2321 let evidence = AcceptedWorldViewEvidence::from_gpu_execution_result(
2322 provider,
2323 result,
2324 assumptions,
2325 )?;
2326 let provenance = extract_from_program(program)?;
2327 let filtered_evidence;
2328 let evidence = if auto_derived {
2329 filtered_evidence =
2330 evidence_with_provenance_backed_assumptions(&evidence, &provenance)?;
2331 &filtered_evidence
2332 } else {
2333 &evidence
2334 };
2335 self.compile_and_evaluate_conditioned_program_with_grads_with_path(
2336 program,
2337 &provenance,
2338 evidence,
2339 EpistemicProbConditionedEvidencePath::Program,
2340 "epistemic probabilistic conditioned parsed-program exact gradient",
2341 )
2342 })
2343 }
2344
2345 #[cfg(feature = "host-io")]
2347 pub fn compile_and_evaluate_conditioned_program_with_grads_for_gpu_execution_results(
2348 &mut self,
2349 program: &Program,
2350 provider: &CudaKernelProvider,
2351 evidence_records: &[EpistemicProbGpuExecutionEvidence<'_>],
2352 ) -> Result<Vec<ExactResultWithGrads>> {
2353 epistemic_prob_trace_transaction!(self, {
2354 if evidence_records.is_empty() {
2355 return Err(XlogError::UnsupportedEpistemicConstruct {
2356 construct: "epistemic probabilistic conditioned gradient production batch"
2357 .to_string(),
2358 context: "batched conditioned program gradient compilation requires at least one accepted GPU result"
2359 .to_string(),
2360 });
2361 }
2362
2363 let mut accepted = Vec::with_capacity(evidence_records.len());
2364 for record in evidence_records {
2365 accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
2366 provider,
2367 record.result,
2368 record.assumptions.to_vec(),
2369 )?);
2370 }
2371
2372 let provenance = extract_from_program(program)?;
2373 let mut results = Vec::with_capacity(accepted.len());
2374 for (record, evidence) in evidence_records.iter().zip(accepted.iter()) {
2375 let filtered_evidence;
2376 let evidence = if record.assumptions.is_empty() {
2377 filtered_evidence =
2378 evidence_with_provenance_backed_assumptions(evidence, &provenance)?;
2379 &filtered_evidence
2380 } else {
2381 evidence
2382 };
2383 results.push(
2384 self.compile_and_evaluate_conditioned_program_with_grads_with_path(
2385 program,
2386 &provenance,
2387 evidence,
2388 EpistemicProbConditionedEvidencePath::Program,
2389 "epistemic probabilistic conditioned parsed-program exact gradient",
2390 )?,
2391 );
2392 }
2393 Ok(results)
2394 })
2395 }
2396
2397 #[cfg(feature = "host-io")]
2399 pub fn compile_and_evaluate_conditioned_program_with_grads_for_gpu_batch_execution_result(
2400 &mut self,
2401 program: &Program,
2402 provider: &CudaKernelProvider,
2403 evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
2404 ) -> Result<Vec<ExactResultWithGrads>> {
2405 epistemic_prob_trace_transaction!(self, {
2406 let auto_derived_by_component = evidence
2407 .assumptions_by_component
2408 .iter()
2409 .map(|assumptions| assumptions.is_empty())
2410 .collect::<Vec<_>>();
2411 let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
2412 provider,
2413 evidence,
2414 "epistemic probabilistic batch production",
2415 )?;
2416
2417 let provenance = extract_from_program(program)?;
2418 let mut results = Vec::with_capacity(accepted.len());
2419 for (auto_derived, evidence) in auto_derived_by_component.iter().zip(accepted.iter()) {
2420 let filtered_evidence;
2421 let evidence = if *auto_derived {
2422 filtered_evidence =
2423 evidence_with_provenance_backed_assumptions(evidence, &provenance)?;
2424 &filtered_evidence
2425 } else {
2426 evidence
2427 };
2428 results.push(
2429 self.compile_and_evaluate_conditioned_program_with_grads_with_path(
2430 program,
2431 &provenance,
2432 evidence,
2433 EpistemicProbConditionedEvidencePath::Program,
2434 "epistemic probabilistic conditioned parsed-program exact gradient",
2435 )?,
2436 );
2437 }
2438 Ok(results)
2439 })
2440 }
2441
2442 #[cfg(feature = "host-io")]
2444 pub fn compile_and_evaluate_program_with_accepted_world_view(
2445 &mut self,
2446 program: &Program,
2447 evidence: &AcceptedWorldViewEvidence,
2448 ) -> Result<ExactResult> {
2449 epistemic_prob_trace_transaction!(self, {
2450 self.require_accepted_evidence(evidence)?;
2451 let production_events_before = self.trace.checked_gpu_production_path_events()?;
2452 let exact = ExactDdnnfProgram::compile_from_program(program, self.config)?;
2453 require_gpu_exact_backend(
2454 &exact,
2455 "epistemic probabilistic parsed-program exact compile/evaluate",
2456 )?;
2457 checked_prob_trace_counter_inc!(self, gpu_exact_program_compiles);
2458 let result = exact.evaluate()?;
2459 checked_prob_trace_counter_inc!(self, gpu_exact_query_evaluations);
2460 checked_prob_trace_counter_inc!(self, gpu_program_exact_query_evaluations);
2461 checked_prob_trace_counter_inc!(self, gpu_knowledge_compilation_end_to_end_runs);
2462 checked_prob_trace_counter_inc!(
2463 self,
2464 gpu_program_knowledge_compilation_end_to_end_runs
2465 );
2466 self.record_accepted_gpu_production_path_events_since(production_events_before)?;
2467 self.record_accepted_evidence(evidence)?;
2468 self.trace.require_zero_cpu_recompute()?;
2469 Ok(result)
2470 })
2471 }
2472
2473 #[cfg(feature = "host-io")]
2475 pub fn compile_and_evaluate_program_with_gpu_execution_result(
2476 &mut self,
2477 program: &Program,
2478 provider: &CudaKernelProvider,
2479 result: &EpistemicGpuExecutionResult,
2480 assumptions: Vec<EpistemicAssumption>,
2481 ) -> Result<ExactResult> {
2482 let evidence =
2483 AcceptedWorldViewEvidence::from_gpu_execution_result(provider, result, assumptions)?;
2484 self.compile_and_evaluate_program_with_accepted_world_view(program, &evidence)
2485 }
2486
2487 #[cfg(feature = "host-io")]
2489 pub fn compile_and_evaluate_program_for_gpu_execution_results(
2490 &mut self,
2491 program: &Program,
2492 provider: &CudaKernelProvider,
2493 evidence_records: &[EpistemicProbGpuExecutionEvidence<'_>],
2494 ) -> Result<Vec<ExactResult>> {
2495 epistemic_prob_trace_transaction!(self, {
2496 if evidence_records.is_empty() {
2497 return Err(XlogError::UnsupportedEpistemicConstruct {
2498 construct: "epistemic probabilistic parsed-program production batch"
2499 .to_string(),
2500 context: "batched parsed-program knowledge compilation requires at least one accepted GPU result"
2501 .to_string(),
2502 });
2503 }
2504
2505 let mut accepted = Vec::with_capacity(evidence_records.len());
2506 for record in evidence_records {
2507 accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
2508 provider,
2509 record.result,
2510 record.assumptions.to_vec(),
2511 )?);
2512 }
2513
2514 let mut results = Vec::with_capacity(accepted.len());
2515 for evidence in &accepted {
2516 results.push(
2517 self.compile_and_evaluate_program_with_accepted_world_view(program, evidence)?,
2518 );
2519 }
2520 Ok(results)
2521 })
2522 }
2523
2524 #[cfg(feature = "host-io")]
2526 pub fn compile_and_evaluate_program_for_gpu_batch_execution_result(
2527 &mut self,
2528 program: &Program,
2529 provider: &CudaKernelProvider,
2530 evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
2531 ) -> Result<Vec<ExactResult>> {
2532 epistemic_prob_trace_transaction!(self, {
2533 let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
2534 provider,
2535 evidence,
2536 "epistemic probabilistic batch production",
2537 )?;
2538
2539 let mut results = Vec::with_capacity(accepted.len());
2540 for evidence in &accepted {
2541 results.push(
2542 self.compile_and_evaluate_program_with_accepted_world_view(program, evidence)?,
2543 );
2544 }
2545 Ok(results)
2546 })
2547 }
2548
2549 pub fn encode_source_pir_cnf_with_accepted_world_view(
2551 &mut self,
2552 source: &str,
2553 provider: &Arc<CudaKernelProvider>,
2554 evidence: &AcceptedWorldViewEvidence,
2555 ) -> Result<EpistemicProbPirCnfEvidence> {
2556 epistemic_prob_trace_transaction!(self, {
2557 self.require_accepted_evidence(evidence)?;
2558 let program = parse_program(source)?;
2559 let base_provenance = extract_from_program(&program)?;
2560 self.encode_program_pir_cnf_with_base_provenance(
2561 &program,
2562 &base_provenance,
2563 provider,
2564 evidence,
2565 EpistemicProbPirCnfPath::Source,
2566 )
2567 })
2568 }
2569
2570 pub fn encode_source_pir_cnf_with_gpu_execution_result(
2572 &mut self,
2573 source: &str,
2574 provider: &Arc<CudaKernelProvider>,
2575 result: &EpistemicGpuExecutionResult,
2576 assumptions: Vec<EpistemicAssumption>,
2577 ) -> Result<EpistemicProbPirCnfEvidence> {
2578 epistemic_prob_trace_transaction!(self, {
2579 let auto_derived = assumptions.is_empty();
2580 let evidence = AcceptedWorldViewEvidence::from_gpu_execution_result(
2581 provider,
2582 result,
2583 assumptions,
2584 )?;
2585 let program = parse_program(source)?;
2586 let base_provenance = extract_from_program(&program)?;
2587 let filtered_evidence;
2588 let evidence = if auto_derived {
2589 filtered_evidence =
2590 evidence_with_provenance_backed_assumptions(&evidence, &base_provenance)?;
2591 &filtered_evidence
2592 } else {
2593 &evidence
2594 };
2595 self.encode_program_pir_cnf_with_base_provenance(
2596 &program,
2597 &base_provenance,
2598 provider,
2599 evidence,
2600 EpistemicProbPirCnfPath::Source,
2601 )
2602 })
2603 }
2604
2605 pub fn encode_source_pir_cnf_for_gpu_execution_results(
2607 &mut self,
2608 source: &str,
2609 provider: &Arc<CudaKernelProvider>,
2610 evidence_records: &[EpistemicProbGpuExecutionEvidence<'_>],
2611 ) -> Result<Vec<EpistemicProbPirCnfEvidence>> {
2612 epistemic_prob_trace_transaction!(self, {
2613 if evidence_records.is_empty() {
2614 return Err(XlogError::UnsupportedEpistemicConstruct {
2615 construct: "epistemic probabilistic source PIR/CNF production batch"
2616 .to_string(),
2617 context:
2618 "batched source PIR/CNF encoding requires at least one accepted GPU result"
2619 .to_string(),
2620 });
2621 }
2622
2623 let mut accepted = Vec::with_capacity(evidence_records.len());
2624 for record in evidence_records {
2625 accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
2626 provider,
2627 record.result,
2628 record.assumptions.to_vec(),
2629 )?);
2630 }
2631
2632 let program = parse_program(source)?;
2633 let base_provenance = extract_from_program(&program)?;
2634 let mut results = Vec::with_capacity(accepted.len());
2635 for (record, evidence) in evidence_records.iter().zip(accepted.iter()) {
2636 let filtered_evidence;
2637 let evidence = if record.assumptions.is_empty() {
2638 filtered_evidence =
2639 evidence_with_provenance_backed_assumptions(evidence, &base_provenance)?;
2640 &filtered_evidence
2641 } else {
2642 evidence
2643 };
2644 results.push(self.encode_program_pir_cnf_with_base_provenance(
2645 &program,
2646 &base_provenance,
2647 provider,
2648 evidence,
2649 EpistemicProbPirCnfPath::Source,
2650 )?);
2651 }
2652 Ok(results)
2653 })
2654 }
2655
2656 pub fn encode_source_pir_cnf_for_gpu_batch_execution_result(
2658 &mut self,
2659 source: &str,
2660 provider: &Arc<CudaKernelProvider>,
2661 evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
2662 ) -> Result<Vec<EpistemicProbPirCnfEvidence>> {
2663 epistemic_prob_trace_transaction!(self, {
2664 let auto_derived_by_component = evidence
2665 .assumptions_by_component
2666 .iter()
2667 .map(|assumptions| assumptions.is_empty())
2668 .collect::<Vec<_>>();
2669 let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
2670 provider.as_ref(),
2671 evidence,
2672 "epistemic probabilistic source PIR/CNF batch production",
2673 )?;
2674
2675 let program = parse_program(source)?;
2676 let base_provenance = extract_from_program(&program)?;
2677 let mut results = Vec::with_capacity(accepted.len());
2678 for (auto_derived, evidence) in auto_derived_by_component.iter().zip(accepted.iter()) {
2679 let filtered_evidence;
2680 let evidence = if *auto_derived {
2681 filtered_evidence =
2682 evidence_with_provenance_backed_assumptions(evidence, &base_provenance)?;
2683 &filtered_evidence
2684 } else {
2685 evidence
2686 };
2687 results.push(self.encode_program_pir_cnf_with_base_provenance(
2688 &program,
2689 &base_provenance,
2690 provider,
2691 evidence,
2692 EpistemicProbPirCnfPath::Source,
2693 )?);
2694 }
2695 Ok(results)
2696 })
2697 }
2698
2699 pub fn encode_program_pir_cnf_with_accepted_world_view(
2701 &mut self,
2702 program: &Program,
2703 provider: &Arc<CudaKernelProvider>,
2704 evidence: &AcceptedWorldViewEvidence,
2705 ) -> Result<EpistemicProbPirCnfEvidence> {
2706 epistemic_prob_trace_transaction!(self, {
2707 self.require_accepted_evidence(evidence)?;
2708 let base_provenance = extract_from_program(program)?;
2709 self.encode_program_pir_cnf_with_base_provenance(
2710 program,
2711 &base_provenance,
2712 provider,
2713 evidence,
2714 EpistemicProbPirCnfPath::Program,
2715 )
2716 })
2717 }
2718
2719 pub fn encode_program_pir_cnf_with_gpu_execution_result(
2721 &mut self,
2722 program: &Program,
2723 provider: &Arc<CudaKernelProvider>,
2724 result: &EpistemicGpuExecutionResult,
2725 assumptions: Vec<EpistemicAssumption>,
2726 ) -> Result<EpistemicProbPirCnfEvidence> {
2727 epistemic_prob_trace_transaction!(self, {
2728 let auto_derived = assumptions.is_empty();
2729 let evidence = AcceptedWorldViewEvidence::from_gpu_execution_result(
2730 provider,
2731 result,
2732 assumptions,
2733 )?;
2734 let base_provenance = extract_from_program(program)?;
2735 let filtered_evidence;
2736 let evidence = if auto_derived {
2737 filtered_evidence =
2738 evidence_with_provenance_backed_assumptions(&evidence, &base_provenance)?;
2739 &filtered_evidence
2740 } else {
2741 &evidence
2742 };
2743 self.encode_program_pir_cnf_with_base_provenance(
2744 program,
2745 &base_provenance,
2746 provider,
2747 evidence,
2748 EpistemicProbPirCnfPath::Program,
2749 )
2750 })
2751 }
2752
2753 pub fn encode_program_pir_cnf_for_gpu_execution_results(
2755 &mut self,
2756 program: &Program,
2757 provider: &Arc<CudaKernelProvider>,
2758 evidence_records: &[EpistemicProbGpuExecutionEvidence<'_>],
2759 ) -> Result<Vec<EpistemicProbPirCnfEvidence>> {
2760 epistemic_prob_trace_transaction!(self, {
2761 if evidence_records.is_empty() {
2762 return Err(XlogError::UnsupportedEpistemicConstruct {
2763 construct: "epistemic probabilistic parsed-program PIR/CNF production batch"
2764 .to_string(),
2765 context:
2766 "batched parsed-program PIR/CNF encoding requires at least one accepted GPU result"
2767 .to_string(),
2768 });
2769 }
2770
2771 let mut accepted = Vec::with_capacity(evidence_records.len());
2772 for record in evidence_records {
2773 accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
2774 provider,
2775 record.result,
2776 record.assumptions.to_vec(),
2777 )?);
2778 }
2779
2780 let base_provenance = extract_from_program(program)?;
2781 let mut results = Vec::with_capacity(accepted.len());
2782 for (record, evidence) in evidence_records.iter().zip(accepted.iter()) {
2783 let filtered_evidence;
2784 let evidence = if record.assumptions.is_empty() {
2785 filtered_evidence =
2786 evidence_with_provenance_backed_assumptions(evidence, &base_provenance)?;
2787 &filtered_evidence
2788 } else {
2789 evidence
2790 };
2791 results.push(self.encode_program_pir_cnf_with_base_provenance(
2792 program,
2793 &base_provenance,
2794 provider,
2795 evidence,
2796 EpistemicProbPirCnfPath::Program,
2797 )?);
2798 }
2799 Ok(results)
2800 })
2801 }
2802
2803 pub fn encode_program_pir_cnf_for_gpu_batch_execution_result(
2805 &mut self,
2806 program: &Program,
2807 provider: &Arc<CudaKernelProvider>,
2808 evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
2809 ) -> Result<Vec<EpistemicProbPirCnfEvidence>> {
2810 epistemic_prob_trace_transaction!(self, {
2811 let auto_derived_by_component = evidence
2812 .assumptions_by_component
2813 .iter()
2814 .map(|assumptions| assumptions.is_empty())
2815 .collect::<Vec<_>>();
2816 let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
2817 provider.as_ref(),
2818 evidence,
2819 "epistemic probabilistic parsed-program PIR/CNF batch production",
2820 )?;
2821
2822 let base_provenance = extract_from_program(program)?;
2823 let mut results = Vec::with_capacity(accepted.len());
2824 for (auto_derived, evidence) in auto_derived_by_component.iter().zip(accepted.iter()) {
2825 let filtered_evidence;
2826 let evidence = if *auto_derived {
2827 filtered_evidence =
2828 evidence_with_provenance_backed_assumptions(evidence, &base_provenance)?;
2829 &filtered_evidence
2830 } else {
2831 evidence
2832 };
2833 results.push(self.encode_program_pir_cnf_with_base_provenance(
2834 program,
2835 &base_provenance,
2836 provider,
2837 evidence,
2838 EpistemicProbPirCnfPath::Program,
2839 )?);
2840 }
2841 Ok(results)
2842 })
2843 }
2844
2845 #[cfg(feature = "host-io")]
2847 pub fn evaluate(
2848 &mut self,
2849 program: &ExactDdnnfProgram,
2850 evidence: &AcceptedWorldViewEvidence,
2851 ) -> Result<ExactResult> {
2852 epistemic_prob_trace_transaction!(self, {
2853 self.require_accepted_evidence(evidence)?;
2854 let production_events_before = self.trace.checked_gpu_production_path_events()?;
2855 require_gpu_exact_backend(program, "epistemic probabilistic exact query evaluation")?;
2856 let result = program.evaluate()?;
2857 self.record_gpu_exact_query_evaluation(program)?;
2858 self.record_accepted_gpu_production_path_events_since(production_events_before)?;
2859 self.record_accepted_evidence(evidence)?;
2860 self.trace.require_zero_cpu_recompute()?;
2861 Ok(result)
2862 })
2863 }
2864
2865 #[cfg(feature = "host-io")]
2867 pub fn evaluate_with_gpu_execution_result(
2868 &mut self,
2869 program: &ExactDdnnfProgram,
2870 provider: &CudaKernelProvider,
2871 result: &EpistemicGpuExecutionResult,
2872 assumptions: Vec<EpistemicAssumption>,
2873 ) -> Result<ExactResult> {
2874 let evidence =
2875 AcceptedWorldViewEvidence::from_gpu_execution_result(provider, result, assumptions)?;
2876 self.evaluate(program, &evidence)
2877 }
2878
2879 #[cfg(feature = "host-io")]
2881 pub fn evaluate_for_gpu_execution_results(
2882 &mut self,
2883 program: &ExactDdnnfProgram,
2884 provider: &CudaKernelProvider,
2885 evidence_records: &[EpistemicProbGpuExecutionEvidence<'_>],
2886 ) -> Result<Vec<ExactResult>> {
2887 epistemic_prob_trace_transaction!(self, {
2888 if evidence_records.is_empty() {
2889 return Err(XlogError::UnsupportedEpistemicConstruct {
2890 construct: "epistemic probabilistic query evaluation production batch"
2891 .to_string(),
2892 context: "batched query evaluation requires at least one accepted GPU result"
2893 .to_string(),
2894 });
2895 }
2896
2897 let mut accepted = Vec::with_capacity(evidence_records.len());
2898 for record in evidence_records {
2899 accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
2900 provider,
2901 record.result,
2902 record.assumptions.to_vec(),
2903 )?);
2904 }
2905
2906 let mut results = Vec::with_capacity(accepted.len());
2907 for evidence in &accepted {
2908 results.push(self.evaluate(program, evidence)?);
2909 }
2910 Ok(results)
2911 })
2912 }
2913
2914 #[cfg(feature = "host-io")]
2916 pub fn evaluate_for_gpu_batch_execution_result(
2917 &mut self,
2918 program: &ExactDdnnfProgram,
2919 provider: &CudaKernelProvider,
2920 evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
2921 ) -> Result<Vec<ExactResult>> {
2922 epistemic_prob_trace_transaction!(self, {
2923 let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
2924 provider,
2925 evidence,
2926 "epistemic probabilistic query evaluation batch production",
2927 )?;
2928
2929 let mut results = Vec::with_capacity(accepted.len());
2930 for evidence in &accepted {
2931 results.push(self.evaluate(program, evidence)?);
2932 }
2933 Ok(results)
2934 })
2935 }
2936
2937 #[cfg(feature = "host-io")]
2939 pub fn evaluate_gpu_with_grads(
2940 &mut self,
2941 program: &ExactDdnnfProgram,
2942 evidence: &AcceptedWorldViewEvidence,
2943 ) -> Result<ExactResultWithGrads> {
2944 epistemic_prob_trace_transaction!(self, {
2945 self.require_accepted_evidence(evidence)?;
2946 let production_events_before = self.trace.checked_gpu_production_path_events()?;
2947 require_gpu_exact_backend(
2948 program,
2949 "epistemic probabilistic exact gradient evaluation",
2950 )?;
2951 let result = program.evaluate_gpu_with_grads()?;
2952 self.record_gpu_exact_gradient_evaluation(program)?;
2953 self.record_accepted_gpu_production_path_events_since(production_events_before)?;
2954 self.record_accepted_evidence(evidence)?;
2955 self.trace.require_zero_cpu_recompute()?;
2956 Ok(result)
2957 })
2958 }
2959
2960 #[cfg(feature = "host-io")]
2962 pub fn evaluate_gpu_with_grads_with_gpu_execution_result(
2963 &mut self,
2964 program: &ExactDdnnfProgram,
2965 provider: &CudaKernelProvider,
2966 result: &EpistemicGpuExecutionResult,
2967 assumptions: Vec<EpistemicAssumption>,
2968 ) -> Result<ExactResultWithGrads> {
2969 let evidence =
2970 AcceptedWorldViewEvidence::from_gpu_execution_result(provider, result, assumptions)?;
2971 self.evaluate_gpu_with_grads(program, &evidence)
2972 }
2973
2974 #[cfg(feature = "host-io")]
2976 pub fn evaluate_gpu_with_grads_for_gpu_execution_results(
2977 &mut self,
2978 program: &ExactDdnnfProgram,
2979 provider: &CudaKernelProvider,
2980 evidence_records: &[EpistemicProbGpuExecutionEvidence<'_>],
2981 ) -> Result<Vec<ExactResultWithGrads>> {
2982 epistemic_prob_trace_transaction!(self, {
2983 if evidence_records.is_empty() {
2984 return Err(XlogError::UnsupportedEpistemicConstruct {
2985 construct: "epistemic probabilistic gradient evaluation production batch"
2986 .to_string(),
2987 context:
2988 "batched gradient evaluation requires at least one accepted GPU result"
2989 .to_string(),
2990 });
2991 }
2992
2993 let mut accepted = Vec::with_capacity(evidence_records.len());
2994 for record in evidence_records {
2995 accepted.push(AcceptedWorldViewEvidence::from_gpu_execution_result(
2996 provider,
2997 record.result,
2998 record.assumptions.to_vec(),
2999 )?);
3000 }
3001
3002 let mut results = Vec::with_capacity(accepted.len());
3003 for evidence in &accepted {
3004 results.push(self.evaluate_gpu_with_grads(program, evidence)?);
3005 }
3006 Ok(results)
3007 })
3008 }
3009
3010 #[cfg(feature = "host-io")]
3012 pub fn evaluate_gpu_with_grads_for_gpu_batch_execution_result(
3013 &mut self,
3014 program: &ExactDdnnfProgram,
3015 provider: &CudaKernelProvider,
3016 evidence: EpistemicProbGpuBatchExecutionEvidence<'_>,
3017 ) -> Result<Vec<ExactResultWithGrads>> {
3018 epistemic_prob_trace_transaction!(self, {
3019 let accepted = self.accepted_world_views_from_gpu_batch_execution_evidence(
3020 provider,
3021 evidence,
3022 "epistemic probabilistic gradient evaluation batch production",
3023 )?;
3024
3025 let mut results = Vec::with_capacity(accepted.len());
3026 for evidence in &accepted {
3027 results.push(self.evaluate_gpu_with_grads(program, evidence)?);
3028 }
3029 Ok(results)
3030 })
3031 }
3032
3033 fn consume_accepted_evidence(&mut self, evidence: &AcceptedWorldViewEvidence) -> Result<()> {
3034 self.require_accepted_evidence(evidence)?;
3035 self.record_accepted_evidence(evidence)?;
3036 self.trace.require_zero_cpu_recompute()
3037 }
3038
3039 fn require_accepted_evidence(&self, evidence: &AcceptedWorldViewEvidence) -> Result<()> {
3040 if evidence.world_count() == 0 {
3041 return Err(XlogError::UnsupportedEpistemicConstruct {
3042 construct: "accepted world-view evidence".to_string(),
3043 context: "probabilistic production path requires a non-empty accepted world view"
3044 .to_string(),
3045 });
3046 }
3047 if evidence.gpu_epistemic_mode().is_none() {
3048 return Err(XlogError::UnsupportedEpistemicConstruct {
3049 construct: "accepted world-view evidence".to_string(),
3050 context: "probabilistic production path requires GPU execution evidence; CPU \
3051 world-view evidence is oracle-only"
3052 .to_string(),
3053 });
3054 }
3055 self.trace.require_zero_cpu_recompute()
3056 }
3057
3058 fn record_accepted_evidence(&mut self, evidence: &AcceptedWorldViewEvidence) -> Result<()> {
3059 self.trace.accepted_world_view_evidence_consumed = Self::checked_trace_counter_add(
3060 self.trace.accepted_world_view_evidence_consumed,
3061 1,
3062 "accepted_world_view_evidence_consumed",
3063 )?;
3064 match evidence.gpu_epistemic_mode() {
3065 Some(EirEpistemicMode::G91) => {
3066 self.trace.accepted_g91_world_view_evidence_consumed =
3067 Self::checked_trace_counter_add(
3068 self.trace.accepted_g91_world_view_evidence_consumed,
3069 1,
3070 "accepted_g91_world_view_evidence_consumed",
3071 )?;
3072 }
3073 Some(EirEpistemicMode::Faeel) => {
3074 self.trace.accepted_faeel_world_view_evidence_consumed =
3075 Self::checked_trace_counter_add(
3076 self.trace.accepted_faeel_world_view_evidence_consumed,
3077 1,
3078 "accepted_faeel_world_view_evidence_consumed",
3079 )?;
3080 }
3081 None => {}
3082 }
3083 self.trace.accepted_evidence_assumptions_consumed = Self::checked_trace_counter_add(
3084 self.trace.accepted_evidence_assumptions_consumed,
3085 evidence.assumption_count() as u64,
3086 "accepted_evidence_assumptions_consumed",
3087 )?;
3088 self.trace
3089 .accepted_gpu_nonzero_arity_evidence_assumptions_consumed =
3090 Self::checked_trace_counter_add(
3091 self.trace
3092 .accepted_gpu_nonzero_arity_evidence_assumptions_consumed,
3093 evidence.nonzero_arity_assumption_count() as u64,
3094 "accepted_gpu_nonzero_arity_evidence_assumptions_consumed",
3095 )?;
3096 if evidence.max_assumption_arity() > u32::MAX as usize {
3097 return Err(XlogError::ResourceExhausted {
3098 context: "accepted GPU probability evidence max arity".to_string(),
3099 estimated_bytes: evidence.max_assumption_arity() as u64,
3100 budget_bytes: u32::MAX as u64,
3101 });
3102 }
3103 self.trace.accepted_gpu_max_evidence_arity_consumed = self
3104 .trace
3105 .accepted_gpu_max_evidence_arity_consumed
3106 .max(evidence.max_assumption_arity() as u32);
3107 self.trace.accepted_gpu_tuple_key_column_reads_consumed = Self::checked_trace_counter_add(
3108 self.trace.accepted_gpu_tuple_key_column_reads_consumed,
3109 evidence.gpu_tuple_key_column_reads() as u64,
3110 "accepted_gpu_tuple_key_column_reads_consumed",
3111 )?;
3112 self.trace.accepted_gpu_final_tuple_row_filters_consumed = Self::checked_trace_counter_add(
3113 self.trace.accepted_gpu_final_tuple_row_filters_consumed,
3114 evidence.gpu_final_tuple_row_filters() as u64,
3115 "accepted_gpu_final_tuple_row_filters_consumed",
3116 )?;
3117 self.trace
3118 .accepted_gpu_final_tuple_negated_row_filters_consumed =
3119 Self::checked_trace_counter_add(
3120 self.trace
3121 .accepted_gpu_final_tuple_negated_row_filters_consumed,
3122 evidence.gpu_final_tuple_negated_row_filters() as u64,
3123 "accepted_gpu_final_tuple_negated_row_filters_consumed",
3124 )?;
3125 self.trace
3126 .accepted_gpu_row_specific_membership_row_capacity_consumed =
3127 Self::checked_trace_counter_add(
3128 self.trace
3129 .accepted_gpu_row_specific_membership_row_capacity_consumed,
3130 evidence.gpu_row_specific_membership_row_capacity() as u64,
3131 "accepted_gpu_row_specific_membership_row_capacity_consumed",
3132 )?;
3133 self.trace
3134 .accepted_gpu_row_filter_fallback_row_capacity_consumed =
3135 Self::checked_trace_counter_add(
3136 self.trace
3137 .accepted_gpu_row_filter_fallback_row_capacity_consumed,
3138 evidence.gpu_row_filter_fallback_row_capacity() as u64,
3139 "accepted_gpu_row_filter_fallback_row_capacity_consumed",
3140 )?;
3141 self.trace
3142 .accepted_gpu_constraint_relations_checked_consumed = Self::checked_trace_counter_add(
3143 self.trace
3144 .accepted_gpu_constraint_relations_checked_consumed,
3145 evidence.gpu_checked_constraint_relations() as u64,
3146 "accepted_gpu_constraint_relations_checked_consumed",
3147 )?;
3148 self.trace
3149 .accepted_gpu_constraint_row_count_device_reads_consumed =
3150 Self::checked_trace_counter_add(
3151 self.trace
3152 .accepted_gpu_constraint_row_count_device_reads_consumed,
3153 evidence.gpu_constraint_row_count_device_reads() as u64,
3154 "accepted_gpu_constraint_row_count_device_reads_consumed",
3155 )?;
3156 Ok(())
3157 }
3158
3159 fn encode_program_pir_cnf_with_base_provenance(
3160 &mut self,
3161 program: &Program,
3162 base_provenance: &Provenance,
3163 provider: &Arc<CudaKernelProvider>,
3164 evidence: &AcceptedWorldViewEvidence,
3165 path: EpistemicProbPirCnfPath,
3166 ) -> Result<EpistemicProbPirCnfEvidence> {
3167 self.require_accepted_evidence(evidence)?;
3168 let conditioned_provenance = if evidence.assumptions().is_empty() {
3169 None
3170 } else {
3171 let conditioned_program = condition_program_with_available_evidence_using_provenance(
3172 program,
3173 base_provenance,
3174 evidence,
3175 )?;
3176 Some(extract_from_program(&conditioned_program)?)
3177 };
3178 let provenance = conditioned_provenance.as_ref().unwrap_or(base_provenance);
3179 self.encode_provenance_pir_cnf_with_accepted_world_view(
3180 provenance, provider, evidence, path,
3181 )
3182 }
3183
3184 fn encode_provenance_pir_cnf_with_accepted_world_view(
3185 &mut self,
3186 provenance: &Provenance,
3187 provider: &Arc<CudaKernelProvider>,
3188 evidence: &AcceptedWorldViewEvidence,
3189 path: EpistemicProbPirCnfPath,
3190 ) -> Result<EpistemicProbPirCnfEvidence> {
3191 self.require_accepted_evidence(evidence)?;
3192 let production_events_before = self.trace.checked_gpu_production_path_events()?;
3193 let roots = production_pir_roots(provenance)?;
3194 if roots.is_empty() {
3195 return Err(XlogError::UnsupportedEpistemicConstruct {
3196 construct: "accepted probabilistic PIR/CNF production path".to_string(),
3197 context: "GPU PIR/CNF evidence requires at least one query, evidence, or probabilistic variable root".to_string(),
3198 });
3199 }
3200 let gpu_pir = GpuPirGraph::from_host(&provenance.pir, provider)?;
3201 checked_prob_trace_counter_inc!(self, gpu_pir_graph_uploads);
3202 match path {
3203 EpistemicProbPirCnfPath::Source => {
3204 checked_prob_trace_counter_inc!(self, gpu_source_pir_graph_uploads);
3205 }
3206 EpistemicProbPirCnfPath::Program => {
3207 checked_prob_trace_counter_inc!(self, gpu_program_pir_graph_uploads);
3208 }
3209 }
3210 let gpu_roots = GpuPirRoots::from_host(&roots, provider)?;
3211 let encoding = encode_cnf_gpu(&gpu_pir, &gpu_roots, provider)?;
3212 checked_prob_trace_counter_inc!(self, gpu_cnf_encodes);
3213 match path {
3214 EpistemicProbPirCnfPath::Source => {
3215 checked_prob_trace_counter_inc!(self, gpu_source_cnf_encodes);
3216 }
3217 EpistemicProbPirCnfPath::Program => {
3218 checked_prob_trace_counter_inc!(self, gpu_program_cnf_encodes);
3219 }
3220 }
3221 let pir_cnf_evidence = EpistemicProbPirCnfEvidence {
3222 pir_nodes: provenance.pir.len(),
3223 root_count: roots.len(),
3224 cnf_var_cap: encoding.cnf.var_cap,
3225 cnf_clause_cap: encoding.cnf.clause_cap,
3226 cnf_lit_cap: encoding.cnf.lit_cap,
3227 };
3228 self.record_accepted_gpu_production_path_events_since(production_events_before)?;
3229 self.record_accepted_evidence(evidence)?;
3230 self.trace.require_zero_cpu_recompute()?;
3231 Ok(pir_cnf_evidence)
3232 }
3233}
3234
3235fn require_gpu_exact_backend(program: &ExactDdnnfProgram, construct: &'static str) -> Result<()> {
3236 if !program.uses_gpu_production_backend() {
3237 return Err(XlogError::UnsupportedEpistemicConstruct {
3238 construct: construct.to_string(),
3239 context:
3240 "production probability metrics require a compiled GPU-native Decision-DNNF exact/provenance/PIR/CNF backend; \
3241 empty roots and count-lift-only evaluation cannot satisfy accepted epistemic probability reuse"
3242 .to_string(),
3243 });
3244 }
3245 Ok(())
3246}
3247
3248#[cfg(feature = "host-io")]
3249#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
3250struct EpistemicProbConditionedEvidenceCounts {
3251 total: usize,
3252 nonzero_arity: usize,
3253 max_arity: u32,
3254 negative: usize,
3255 know: usize,
3256 possible: usize,
3257 not_known: usize,
3258 not_possible: usize,
3259}
3260
3261fn condition_program_with_available_evidence_using_provenance(
3262 program: &Program,
3263 base_provenance: &Provenance,
3264 evidence: &AcceptedWorldViewEvidence,
3265) -> Result<Program> {
3266 if evidence.assumptions().is_empty() {
3267 return Ok(program.clone());
3268 }
3269
3270 let mut program = program.clone();
3271 let mut applied = 0usize;
3272 for assumption in evidence.assumptions() {
3273 validate_conditioned_assumption_shape(assumption)?;
3274 let Some(atom) = conditioned_evidence_atom_for_assumption(base_provenance, assumption)
3275 else {
3276 return Err(XlogError::UnsupportedEpistemicConstruct {
3277 construct: "accepted probabilistic PIR/CNF evidence conditioning".to_string(),
3278 context: format!(
3279 "accepted {} PIR/CNF evidence for {}/{} has no provenance formula; partial \
3280 world-view evidence cannot satisfy production conditioning metrics",
3281 assumption.evidence_literal(),
3282 assumption.predicate,
3283 assumption.arity
3284 ),
3285 });
3286 };
3287 program.evidence.push(Evidence {
3288 atom,
3289 value: assumption.value,
3290 });
3291 applied += 1;
3292 }
3293
3294 if applied == 0 {
3295 return Err(XlogError::UnsupportedEpistemicConstruct {
3296 construct: "accepted probabilistic PIR/CNF evidence conditioning".to_string(),
3297 context: "PIR/CNF encoding requires at least one accepted epistemic assumption to match existing probabilistic provenance"
3298 .to_string(),
3299 });
3300 }
3301
3302 Ok(program)
3303}
3304
3305#[cfg(feature = "host-io")]
3306fn condition_program_with_accepted_evidence_using_provenance(
3307 program: &Program,
3308 provenance: &Provenance,
3309 evidence: &AcceptedWorldViewEvidence,
3310) -> Result<(Program, EpistemicProbConditionedEvidenceCounts)> {
3311 if evidence.assumptions().is_empty() {
3312 return Err(XlogError::UnsupportedEpistemicConstruct {
3313 construct: "accepted probabilistic evidence conditioning".to_string(),
3314 context: "conditioned exact path requires at least one accepted epistemic assumption"
3315 .to_string(),
3316 });
3317 }
3318
3319 let mut counts = EpistemicProbConditionedEvidenceCounts::default();
3320 for assumption in evidence.assumptions() {
3321 validate_conditioned_assumption_shape(assumption)?;
3322 record_conditioned_assumption_counts(&mut counts, assumption);
3323 }
3324 let mut program = program.clone();
3325 for assumption in evidence.assumptions() {
3326 let Some(atom) = conditioned_evidence_atom_for_assumption(provenance, assumption) else {
3327 return Err(XlogError::UnsupportedEpistemicConstruct {
3328 construct: "accepted probabilistic evidence conditioning".to_string(),
3329 context: format!(
3330 "accepted {} exact evidence for {}/{} has no provenance formula; \
3331 vacuous evidence cannot satisfy production conditioning metrics",
3332 assumption.evidence_literal(),
3333 assumption.predicate,
3334 assumption.arity
3335 ),
3336 });
3337 };
3338 program.evidence.push(Evidence {
3339 atom,
3340 value: assumption.value,
3341 });
3342 }
3343
3344 Ok((program, counts))
3345}
3346
3347fn validate_conditioned_assumption_shape(assumption: &EpistemicAssumption) -> Result<()> {
3348 if assumption.arity == 0 {
3349 if !assumption.terms.is_empty() {
3350 return Err(XlogError::UnsupportedEpistemicConstruct {
3351 construct: "accepted probabilistic evidence conditioning".to_string(),
3352 context: format!(
3353 "zero-arity exact evidence must not carry tuple terms, got {}/{}",
3354 assumption.predicate, assumption.arity
3355 ),
3356 });
3357 }
3358 } else if assumption.terms.len() != assumption.arity {
3359 return Err(XlogError::UnsupportedEpistemicConstruct {
3360 construct: "accepted probabilistic evidence conditioning".to_string(),
3361 context: format!(
3362 "nonzero exact evidence conditioning requires {} concrete tuple terms, got {} for {}/{}",
3363 assumption.arity,
3364 assumption.terms.len(),
3365 assumption.predicate,
3366 assumption.arity
3367 ),
3368 });
3369 }
3370 Ok(())
3371}
3372
3373#[cfg(feature = "host-io")]
3374fn record_conditioned_assumption_counts(
3375 counts: &mut EpistemicProbConditionedEvidenceCounts,
3376 assumption: &EpistemicAssumption,
3377) {
3378 counts.total += 1;
3379 if assumption.arity > 0 {
3380 counts.nonzero_arity += 1;
3381 counts.max_arity = counts.max_arity.max(assumption.arity as u32);
3382 }
3383 if !assumption.value {
3384 counts.negative += 1;
3385 }
3386 match (assumption.kind, assumption.value) {
3387 (EpistemicAssumptionKind::Know, true) => counts.know += 1,
3388 (EpistemicAssumptionKind::Possible, true) => counts.possible += 1,
3389 (EpistemicAssumptionKind::Know, false) => counts.not_known += 1,
3390 (EpistemicAssumptionKind::Possible, false) => counts.not_possible += 1,
3391 }
3392}
3393
3394fn evidence_term_variants(term: &EpistemicEvidenceTerm) -> Vec<(Value, Term)> {
3395 match term {
3396 EpistemicEvidenceTerm::Integer(value) => vec![(Value::I64(*value), Term::Integer(*value))],
3397 EpistemicEvidenceTerm::String(value) => {
3398 let symbol_id = symbol::intern(value);
3399 vec![
3400 (Value::String(value.clone()), Term::String(value.clone())),
3401 (Value::Symbol(symbol_id), Term::Symbol(symbol_id)),
3402 ]
3403 }
3404 EpistemicEvidenceTerm::Symbol(value) => {
3405 let string_value = symbol::resolve(*value);
3406 vec![
3407 (Value::Symbol(*value), Term::Symbol(*value)),
3408 (
3409 Value::String(string_value.clone()),
3410 Term::String(string_value),
3411 ),
3412 ]
3413 }
3414 }
3415}
3416
3417fn conditioned_evidence_atom_for_assumption(
3418 provenance: &Provenance,
3419 assumption: &EpistemicAssumption,
3420) -> Option<Atom> {
3421 if assumption.terms.is_empty() {
3422 if provenance
3423 .query_formula(&assumption.predicate, &[])
3424 .is_some()
3425 {
3426 return Some(Atom {
3427 predicate: assumption.predicate.clone(),
3428 terms: Vec::new(),
3429 });
3430 }
3431 return None;
3432 }
3433
3434 let variants = assumption
3435 .terms
3436 .iter()
3437 .map(evidence_term_variants)
3438 .collect::<Vec<_>>();
3439 let mut values = Vec::with_capacity(variants.len());
3440 let mut terms = Vec::with_capacity(variants.len());
3441 conditioned_evidence_atom_from_variants(
3442 provenance,
3443 assumption,
3444 &variants,
3445 0,
3446 &mut values,
3447 &mut terms,
3448 )
3449}
3450
3451fn conditioned_evidence_atom_from_variants(
3452 provenance: &Provenance,
3453 assumption: &EpistemicAssumption,
3454 variants: &[Vec<(Value, Term)>],
3455 index: usize,
3456 values: &mut Vec<Value>,
3457 terms: &mut Vec<Term>,
3458) -> Option<Atom> {
3459 if index == variants.len() {
3460 if provenance
3461 .query_formula(&assumption.predicate, values)
3462 .is_some()
3463 {
3464 return Some(Atom {
3465 predicate: assumption.predicate.clone(),
3466 terms: terms.clone(),
3467 });
3468 }
3469 return None;
3470 }
3471
3472 for (value, term) in &variants[index] {
3473 values.push(value.clone());
3474 terms.push(term.clone());
3475 if let Some(atom) = conditioned_evidence_atom_from_variants(
3476 provenance,
3477 assumption,
3478 variants,
3479 index + 1,
3480 values,
3481 terms,
3482 ) {
3483 return Some(atom);
3484 }
3485 values.pop();
3486 terms.pop();
3487 }
3488 None
3489}
3490
3491fn assumption_has_provenance_formula(
3492 provenance: &Provenance,
3493 assumption: &EpistemicAssumption,
3494) -> bool {
3495 conditioned_evidence_atom_for_assumption(provenance, assumption).is_some()
3496}
3497
3498fn evidence_with_provenance_backed_assumptions(
3499 evidence: &AcceptedWorldViewEvidence,
3500 provenance: &Provenance,
3501) -> Result<AcceptedWorldViewEvidence> {
3502 let assumptions = evidence
3503 .assumptions()
3504 .iter()
3505 .filter(|assumption| assumption_has_provenance_formula(provenance, assumption))
3506 .cloned()
3507 .collect::<Vec<_>>();
3508 if assumptions.is_empty() {
3509 return Err(XlogError::UnsupportedEpistemicConstruct {
3510 construct: "accepted probabilistic PIR/CNF evidence conditioning".to_string(),
3511 context: "PIR/CNF encoding requires at least one accepted epistemic assumption to match existing probabilistic provenance"
3512 .to_string(),
3513 });
3514 }
3515 Ok(evidence.with_assumptions(assumptions))
3516}
3517
3518fn production_pir_roots(provenance: &Provenance) -> Result<Vec<PirNodeId>> {
3519 let mut roots = BTreeSet::new();
3520
3521 for (atom, value) in &provenance.evidence {
3522 if let Some(id) = provenance.query_formula(&atom.predicate, &atom.args) {
3523 roots.insert(id);
3524 } else if *value {
3525 return Err(XlogError::Execution(format!(
3526 "Exact inference error: evidence atom is never derivable: {}",
3527 atom.predicate
3528 )));
3529 }
3530 }
3531
3532 for atom in &provenance.queries {
3533 if let Some(id) = provenance.query_formula(&atom.predicate, &atom.args) {
3534 roots.insert(id);
3535 }
3536 }
3537
3538 for (idx, node) in provenance.pir.nodes().iter().enumerate() {
3539 if matches!(
3540 node,
3541 PirNode::Decision { .. } | PirNode::Lit { .. } | PirNode::NegLit { .. }
3542 ) {
3543 roots.insert(PirNodeId::from_u32(idx as u32));
3544 }
3545 }
3546
3547 Ok(roots.into_iter().collect())
3548}