Skip to content

Implement Rust crate version of EQBSL library with docs, examples, and tests#17

Open
Steake wants to merge 10 commits intomainfrom
implement-rust-crate-version-of-eqbsl-library-with-docs-examples-and-tests-Wn9PR9JC77fh
Open

Implement Rust crate version of EQBSL library with docs, examples, and tests#17
Steake wants to merge 10 commits intomainfrom
implement-rust-crate-version-of-eqbsl-library-with-docs-examples-and-tests-Wn9PR9JC77fh

Conversation

@Steake
Copy link
Owner

@Steake Steake commented Feb 25, 2026

Implement a rust crate version of the EQBSL library. Include docs, examples and TDD/BDD tests.


Superconductor Ticket Implementation | App Preview

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>
Copilot AI review requested due to automatic review settings February 25, 2026 00:04
@netlify
Copy link

netlify bot commented Feb 25, 2026

Deploy Preview for eqbsl-demo ready!

Name Link
🔨 Latest commit 3c1036b
🔍 Latest deploy log https://app.netlify.com/projects/eqbsl-demo/deploys/69b3a6382f18ec0008d3cba9
😎 Deploy Preview https://deploy-preview-17--eqbsl-demo.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +19 to +26
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
)
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
let n = h.nodes.len();
if n < 2 { continue; }

let alpha = 1.0 / (n * (n - 1)) as f64;
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
let alpha = 1.0 / (n * (n - 1)) as f64;
let denom = (n as f64) * ((n - 1) as f64);
let alpha = 1.0 / denom;

Copilot uses AI. Check for mistakes.
}

/// 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) {
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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);
}

Copilot uses AI. Check for mistakes.
return;
}

let beta_dt = params.decay_beta.mapv(|x| x.powi(dt_steps as i32));
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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));

Copilot uses AI. Check for mistakes.
lst.push((ok.expectation(), k.clone()));
}
}
lst.sort_by(|a, b| b.0.partial_cmp(&a.0).unwrap());
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
lst.sort_by(|a, b| b.0.partial_cmp(&a.0).unwrap());
lst.sort_by(|a, b| b.0.total_cmp(&a.0));

Copilot uses AI. Check for mistakes.
Copy link
Owner Author

@Steake Steake left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot Please include mermaid diagrams. Please make read me considerably more useful and include examples Inc. real world examples

@Steake Steake self-assigned this Feb 25, 2026
@Steake
Copy link
Owner Author

Steake commented Feb 25, 2026

@copilot Please include mermaid diagrams. Please make read me considerably more useful and include examples Inc. real world examples

@copilot

Copy link
Contributor

Copilot AI commented Feb 25, 2026

@Steake I've opened a new pull request, #18, to work on those changes. Once the pull request is ready, I'll request review from you.

Copilot AI and others added 8 commits February 25, 2026 01:28
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
@Steake Steake closed this Mar 13, 2026
@Steake Steake reopened this Mar 13, 2026
@Steake
Copy link
Owner Author

Steake commented Mar 13, 2026

@copilot

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.

Copy link
Contributor

Copilot AI commented Mar 13, 2026

@Steake I've opened a new pull request, #22, to work on those changes. Once the pull request is ready, I'll request review from you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants