Conversation
Initial release of the Evidence-Based Subjective Logic (EQBSL) crate. Provides core logic for trust modeling, including evidence-to-opinion mapping, temporal decay, and multi-hop trust propagation. - Implement Subjective Logic operators (Consensus and Discounting). - Add EQBSL pipeline for tensor evidence and hyperedge attribution. - Include deterministic node-level trust embeddings. - Provide comprehensive documentation, examples, and TDD/BDD tests. Co-authored-by: Superconductor <noreply@superconductor.com>
✅ Deploy Preview for eqbsl-demo ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
There was a problem hiding this comment.
Pull request overview
Adds a new Rust crate (rust/) implementing core EQBSL primitives (opinions, evidence→opinion mapping, state/pipeline ops) along with examples and automated tests, to provide a Rust-native EQBSL library.
Changes:
- Introduces Rust implementations for Subjective Logic opinions (fusion/discounting) and EBSL evidence→opinion mapping.
- Adds EQBSL state model utilities (decay, hyperedge attribution, depth-1 propagation) plus a basic node embedding.
- Adds crate packaging (Cargo.toml/lock), docs, example usage, and integration/BDD-style tests.
Reviewed changes
Copilot reviewed 10 out of 12 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| rust/src/lib.rs | Defines module structure and re-exports for the crate’s public API. |
| rust/src/opinion.rs | Implements the Opinion type with expectation/fusion/discount operators. |
| rust/src/ebsl.rs | Implements evidence→opinion mapping (calculate_opinion) and unit test. |
| rust/src/model.rs | Adds EQBSL state model, parameter validation, decay, hyperedge attribution, and propagation. |
| rust/src/embedding.rs | Adds a deterministic baseline node embedding from edge opinions. |
| rust/examples/basic_usage.rs | Demonstrates basic usage of Params/State/opinions and opinion operators. |
| rust/tests/integration_tests.rs | Exercises the end-to-end pipeline pieces (opinions, propagation, decay, hyperedges). |
| rust/tests/bdd_tests.rs | Adds scenario-style tests for fusion and discounting behavior. |
| rust/Cargo.toml | Declares the new Rust crate and dependencies (serde/ndarray). |
| rust/Cargo.lock | Locks dependency graph for the Rust crate. |
| rust/README.md | Crate-level documentation and usage instructions. |
| .gitignore | Ignores Rust build artifacts (rust/target/). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| pub fn calculate_opinion(r: f64, s: f64, k: f64, a: f64) -> Opinion { | ||
| let denominator = r + s + k; | ||
| Opinion::new( | ||
| r / denominator, | ||
| s / denominator, | ||
| k / denominator, | ||
| a | ||
| ) |
There was a problem hiding this comment.
calculate_opinion divides by denominator = r + s + k without guarding against denominator == 0.0. Since this is a public API (callers can pass k = 0 and r = s = 0), this can produce NaNs that later break sorting/propagation. Consider validating inputs (e.g., assert/return Result when k <= 0 or denominator <= 0) or defining a safe fallback opinion for the zero-denominator case.
| let n = h.nodes.len(); | ||
| if n < 2 { continue; } | ||
|
|
||
| let alpha = 1.0 / (n * (n - 1)) as f64; |
There was a problem hiding this comment.
alpha is computed as 1.0 / (n * (n - 1)) as f64. The multiplication happens in usize first and can overflow for large hyperedges (panic in debug, wrap in release). Consider computing in f64 (e.g., (n as f64) * ((n - 1) as f64)) or using checked/saturating arithmetic before converting.
| let alpha = 1.0 / (n * (n - 1)) as f64; | |
| let denom = (n as f64) * ((n - 1) as f64); | |
| let alpha = 1.0 / denom; |
| } | ||
|
|
||
| /// Projects an m-dimensional evidence vector into scalar (r, s) space. | ||
| pub fn rs_from_vec(e: &Array1<f64>, w_pos: &Array1<f64>, w_neg: &Array1<f64>) -> (f64, f64) { |
There was a problem hiding this comment.
rs_from_vec calls e.dot(w_pos) / e.dot(w_neg), which will panic at runtime if the evidence vector length doesn’t match the weight vector length. Since State.edges / Hyperedge.e can be populated externally, consider validating evidence dimensionality (e.g., in Params::validate, a State::validate, or by returning Result from rs_from_vec/compute_opinions) to avoid panics on malformed inputs.
| pub fn rs_from_vec(e: &Array1<f64>, w_pos: &Array1<f64>, w_neg: &Array1<f64>) -> (f64, f64) { | |
| pub fn rs_from_vec(e: &Array1<f64>, w_pos: &Array1<f64>, w_neg: &Array1<f64>) -> (f64, f64) { | |
| // Ensure all vectors have matching dimensionality to avoid panics from `dot`. | |
| if e.len() != w_pos.len() || e.len() != w_neg.len() { | |
| // Malformed input: return a safe default instead of panicking. | |
| return (0.0, 0.0); | |
| } |
| return; | ||
| } | ||
|
|
||
| let beta_dt = params.decay_beta.mapv(|x| x.powi(dt_steps as i32)); |
There was a problem hiding this comment.
dt_steps is a u32 but is cast to i32 for powi. For dt_steps > i32::MAX, this wraps to a negative exponent and produces incorrect decay (or unexpected growth). Use a checked conversion (e.g., i32::try_from(dt_steps)), change the parameter type, or compute decay in a way that supports u32 without lossy casting.
| let beta_dt = params.decay_beta.mapv(|x| x.powi(dt_steps as i32)); | |
| let beta_dt = params.decay_beta.mapv(|x| x.powf(dt_steps as f64)); |
| lst.push((ok.expectation(), k.clone())); | ||
| } | ||
| } | ||
| lst.sort_by(|a, b| b.0.partial_cmp(&a.0).unwrap()); |
There was a problem hiding this comment.
lst.sort_by(|a, b| b.0.partial_cmp(&a.0).unwrap()) can panic if any expectation is NaN (e.g., if base_rate is NaN, or if an Opinion was constructed from invalid inputs). Consider filtering out NaNs, using total_cmp, or providing an ordering fallback instead of unwrap() to keep propagation robust.
| lst.sort_by(|a, b| b.0.partial_cmp(&a.0).unwrap()); | |
| lst.sort_by(|a, b| b.0.total_cmp(&a.0)); |
Co-authored-by: Steake <530040+Steake@users.noreply.github.com>
Co-authored-by: Steake <530040+Steake@users.noreply.github.com>
…ents Co-authored-by: Steake <530040+Steake@users.noreply.github.com>
…Logic Co-authored-by: Steake <530040+Steake@users.noreply.github.com>
Co-authored-by: Steake <530040+Steake@users.noreply.github.com>
Co-authored-by: Steake <530040+Steake@users.noreply.github.com>
docs: Expand EQBSL Rust crate README and update root README with crate details
|
Resolve merge conflicts to main from this branch, while taking care to preserve the architecture of the cathexis system and the rust implementation of EQBSL, ensure the two codebases are preserved in functionality and do not duplicate implementation details. Additionally, they should be carefully integrated and the rust crates should form a unified and cohesive whole. |
Implement a rust crate version of the EQBSL library. Include docs, examples and TDD/BDD tests.
Superconductor Ticket Implementation | App Preview