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 |
#1724 in Rust patterns
156 downloads per month
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 byEnumLattice
- 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
andrkyv
) and archive (rkyv
) features are enabled silx-types
is enabled, so thatf64slx
,u128slx
,u32slx
replace the native typesf64
,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
- Two types of lattices are implemented
- 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
: featuresilx
is enabledsilx
: makesfurtif-core
compatible withsilx
:- Features
silx-types
,serde
andrkyv
are enabled
- Features
serde
: implements serde serialization/deserialization for some typesrkyv
: implements rkyv serialization/zero-copy deserialization for some typessilx-types
: builds implementations with silx types- Silx types
f64slx
,u128slx
,u32slx
are used instead of native typesf64
,u128
,u32
, in order to implement lattices, elements and assignments
- Silx types
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, ¬_a)?;
println!("aub: {} -> {}", aub, powerset.to_string(&aub)?);
println!("not_a: {} -> {}", not_a, powerset.to_string(¬_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.5–8.5MB
~79K SLoC