#data-fusion #fusion #function #toolbox #belief

furtif-core

Flexible User-oriented Rusted Toolbox for Information Fusion: a data fusion toolbox based on asynchronous and interacting processes, particularly focused on belief functions fusion

4 releases

0.1.2 Mar 4, 2024
0.1.1 Feb 26, 2024
0.1.0 Feb 21, 2024
0.0.0 Nov 13, 2023

#2158 in Rust patterns

30 downloads per month

LGPL-3.0

290KB
3.5K SLoC

This is part of Furtif project

furtif-core contains core components for implementing furtif application

Notes:

About version 0.1.2:

  • CombiLattice is deprecated and replaced by EnumLattice
  • Dependencies are updated

Documentation is generated under the hypothesis that feature silx is enabled, which is default configuration

By default, feature silx is enabled, which means:

  • Serialization/deserialization (serde and rkyv) and archive (rkyv) features are enabled
  • silx-types is enabled, so that f64slx, u128slx, u32slx replace the native types f64, u128, u32

Type aliasing and casting are implemented in the types module and depend on whether or not the silx-types feature is enabled

Purpose

Furtif offers a generic implementation in Rust of functionalities for manipulating belief functions and merging them. This crate includes:

  • Traits defining the notion of lattice and its variants
    • Two types of lattices are implemented
      • Powerset
      • Taxonomy
  • Tools for transforming between different forms of belief functions
  • The notion of referee functions is implemented, thus enabling:
    • the ability to generically define fusion rules
    • the design of generic engines for computing fused assignments
      • Presently, an exact computation method with pruning is proposed

Furtif is designed from the outset to work asynchronously, interacting with the Silx library. This feature is enabled by default, but can be deselected in Cargo.toml by applying option default-features = false on furtif-core

Main features of furtif-core are:

  • default : feature silx is enabled
  • silx : makes furtif-core compatible with silx:
    • Features silx-types, serde and rkyv are enabled
  • serde : implements serde serialization/deserialization for some types
  • rkyv : implements rkyv serialization/zero-copy deserialization for some types
  • silx-types : builds implementations with silx types
    • Silx types f64slx, u128slx, u32slx are used instead of native types f64, u128, u32, in order to implement lattices, elements and assignments

Furtif remains a project under development. The current version can work as silx-independent (by applying option default-features = false on furtif-core) or as silx-integrated crate, the latter allowing it to operate in the asynchronous silx environment.
Further enhancements are envisaged, such as the implementation of Mex modules for Matlab or Octave. In addition, we have some developments in view concerning belief functions.

To start with, the following silx-independent example gives a minimalist overview of the library's features. Other examples, especially silx-integrated, are also available on the project's github.

Minimalist example (Dempster-Shafer fusion)

Cargo.toml

[package]
name = "silx_furtif_dst"
version = "0.1.2"
edition = "2021"

[dependencies]
furtif-core = { version = "0.1.2", default-features = false }

main.rs

use furtif_core::{
    structs::{DiscountedFuser, EnumRule, Powerset},
    traits::{ComplementedLattice, DiscountedFusion, IterableLattice, Lattice},
};

/// Furtif: a simple fusion of 2 masses by Dempster-Shafer rule 
pub fn main() -> Result<(),String> {
    // build a powerset generated by `A` `B` and `C`
    let powerset = Powerset::new_with_label(
        &["A".to_string(), "B".to_string(), "C".to_string()], 128
    )?;
    // List of elements in the powerset (non-decreasing for the inclusion ordering)
    println!("==== Elements -------------");
    let powerset = powerset.set_iterators();
    for e in powerset.bottom_to_top()? {
        println!("{e} -> {}", powerset.to_string(&e)?);
    }
    // Some boolean operations and results
    // * `powerset.join(...)` is the disjunction operator
    // * `powerset.not(...)` is the boolean negation
    // * `powerset.meet(...)` is the conjunction operator
    println!("\n==== operators -------------");
    let a = powerset.from_str("A")?;
    let b = powerset.from_str("B")?;
    let aub = powerset.join(&a,&b)?;
    let not_a = powerset.not(&a)?;
    let aub_n_not_a = powerset.meet(&aub, &not_a)?;
    println!("aub: {} -> {}", aub, powerset.to_string(&aub)?);
    println!("not_a: {} -> {}", not_a, powerset.to_string(&not_a)?);
    println!("aub_n_not_a: {} -> {}", aub_n_not_a, powerset.to_string(&aub_n_not_a)?);
    println!("\n==== assignments -------------");
    // Construction of two basic belief assignments
    let c = powerset.from_str("C")?;
    let buc = not_a;
    let cua = powerset.not(&b)?;
    let m1 = powerset.assignment()
        + (a, 3.0) + (aub, 3.0) + (buc, 4.0) + ();
    let m2 = powerset.assignment()
        + (c, 2.0) + (aub, 3.0) + (cua, 5.0) + ();
    println!("m1 -> {m1}");
    println!("m2 -> {m2}");
    // Computation of Dempster-Shafer fusion
    let engine = DiscountedFuser::new(512..=1024);
    let (fused,z) = engine.fuse(&powerset, &EnumRule::DempsterShafer,&[&m1,&m2])?;
    println!("fused / DS -> {fused}");
    println!("z -> {z:.3}");
    Ok(())
}

Typical output

==== Elements -------------
0 -> 4 -> C
1 -> A
2 -> B
5 -> A | C
6 -> B | C
3 -> A | B
7 -> ==== operators -------------
aub: 3 -> A | B
not_a: 6 -> B | C
aub_n_not_a: 2 -> B

==== assignments -------------
m1 -> [ 6 -> 0.4000, 3 -> 0.3000, 1 -> 0.3000, ]
m2 -> [ 3 -> 0.3000, 5 -> 0.5000, 4 -> 0.2000, ]
fused / DS -> [ 3 -> 0.1023, 4 -> 0.3182, 1 -> 0.4432, 2 -> 0.1364, ]
z -> 0.120

Dependencies

~1.6–9MB
~80K SLoC