Skip to content

Commit

Permalink
Merge 08dafae into b272762
Browse files Browse the repository at this point in the history
  • Loading branch information
nimar committed Jun 25, 2022
2 parents b272762 + 08dafae commit cad5b38
Show file tree
Hide file tree
Showing 9 changed files with 172 additions and 34 deletions.
11 changes: 0 additions & 11 deletions .github/actions-rs/grcov.yml

This file was deleted.

8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ jobs:
CARGO_INCREMENTAL: '0'
RUSTFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off'
RUSTDOCFLAGS: '-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off'
- name: Download grcov v0.8.2
- name: Download grcov v0.8.10
run: |
wget https://github.com/mozilla/grcov/releases/download/v0.8.2/grcov-linux-x86_64.tar.bz2
tar xjf grcov-linux-x86_64.tar.bz2
wget https://github.com/mozilla/grcov/releases/download/v0.8.10/grcov-x86_64-unknown-linux-gnu.tar.bz2
tar xjf grcov-x86_64-unknown-linux-gnu.tar.bz2
- name: Run grcov
run: ./grcov . --binary-path ./target/debug -s . --ignore="/*" --ignore="ferric/examples/*" -t lcov --branch > lcov.info
run: ./grcov . --binary-path ./target/debug -s . --ignore="/*" --ignore="ferric/examples/*" --ignore="ferric/tests/*" --excl-br-start "#\[test\]" --excl-start "#\[test\]" --excl-br-line "panic!" --excl-line "panic!" -t lcov --branch --ignore-not-existing > lcov.info
- name: Coveralls upload
uses: coverallsapp/github-action@master
with:
Expand Down
18 changes: 14 additions & 4 deletions .vscode/coverage
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,20 @@ cargo clean
rm lcov.info
rm -fr coverage
export CARGO_INCREMENTAL=0
# removing "-Zpanic_abort_tests -Cpanic=abort" since they don't quite work
export RUSTFLAGS="-Zprofile -Ccodegen-units=1 -Cinline-threshold=0 -Clink-dead-code -Coverflow-checks=off"
cargo +nightly build --verbose $CARGO_OPTIONS
cargo +nightly test --all-features --no-fail-fast --verbose $CARGO_OPTIONS

grcov . --binary-path ./target/debug -s . --ignore="/*" --ignore="ferric/examples/*" -t lcov --branch --ignore-not-existing > lcov.info
export RUSTDOCFLAGS="-Cpanic=abort"
# the following flag makes cargo build work with nightly mode and we don't need the `+nightly` flag any more
export RUSTC_BOOTSTRAP=1
cargo build
cargo test --all-features --no-fail-fast
# excluding coverage of all test files and unit test sections in files, also excluding panic! macros
grcov . --binary-path ./target/debug -s . --ignore="/*" --ignore="ferric/examples/*" --ignore="ferric/tests/*" \
--excl-br-start "#\[test\]" --excl-start "#\[test\]" \
--excl-br-line "panic!" --excl-line "panic!" -t lcov --branch --ignore-not-existing > lcov.info
genhtml -o coverage --branch-coverage --show-details --highlight --ignore-errors source --legend lcov.info
cargo clean
unset RUSTFLAGS
unset RUSTDOCFLAGS
unset RUSTC_BOOTSTRAP
unset CARGO_INCREMENTAL
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"livePreview.defaultPreviewPath": "/coverage/ferric/src/core/index.html"
}
14 changes: 14 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,20 @@
"isDefault": true
}
},
{
"label": "documentation",
"type": "shell",
"command": "cargo",
"args": [
"doc",
"--open",
"--no-deps",
],
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "run test",
"type": "shell",
Expand Down
31 changes: 16 additions & 15 deletions ferric-macros/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ pub fn codegen(ir: ModelIR) -> TokenStream {
let use_stmt = quote! {use #use_expr};
use_stmts.push(use_stmt);
}
// additional use statements needed for code generation
use_stmts.push(quote! {use ferric::FeOption});

// for all let <variable name> statements
let mut var_idents = Vec::<Ident>::new(); // <variable name>
let mut var_idents = Vec::<Ident>::new(); // var_<variable name>
let mut var_type_idents = Vec::<Ident>::new(); // <variable's type name>
let mut var_init_idents = Vec::<Ident>::new(); // initialized_<variable name>
let mut var_eval_idents = Vec::<Ident>::new(); // eval_<variable name>
let mut var_eval_dist_idents = Vec::<Ident>::new(); // evaldist_<variable name>
let mut eval_dist_exprs = Vec::<TokenStream>::new(); // expression for evaldist_<variable name>
Expand All @@ -41,8 +42,6 @@ pub fn codegen(ir: ModelIR) -> TokenStream {
let var_ident = format_ident!("var_{}", &variable.var_ident);
var_idents.push(var_ident.clone());
var_type_idents.push(variable.type_ident.clone());
let init_var = format_ident!("initialized_{}", &variable.var_ident);
var_init_idents.push(init_var.clone());
let eval_var = format_ident!("eval_{}", &variable.var_ident);
var_eval_idents.push(eval_var.clone());
let eval_dist_var = format_ident!("evaldist_{}", &variable.var_ident);
Expand All @@ -51,7 +50,7 @@ pub fn codegen(ir: ModelIR) -> TokenStream {
let modified_eval_dist_dep = replace(quote! {#eval_dist_dep}, &ir.variables);
eval_dist_exprs.push(modified_eval_dist_dep);
// if this variable is being queried then we need to store these
// generate tokens in query-specific lists
// generated tokens in query-specific lists
if variable.is_queried {
query_idents.push(variable.var_ident.clone());
query_type_idents.push(variable.type_ident.clone());
Expand All @@ -72,10 +71,14 @@ pub fn codegen(ir: ModelIR) -> TokenStream {
#use_stmts;
)*

// all the queried variables are fields in the `Sample` struct
pub struct Sample {
#(pub #query_idents: #query_type_idents, )*
#(
pub #query_idents: #query_type_idents,
)*
}

// all the observed variables are fields in the `Model` struct
pub struct Model {
#(
pub #obs_idents: #obs_type_idents,
Expand All @@ -95,8 +98,7 @@ pub fn codegen(ir: ModelIR) -> TokenStream {

pub struct World<R> {
rng: R,
#(#var_idents: #var_type_idents, )*
#(#var_init_idents: bool, )*
#(#var_idents: FeOption<#var_type_idents>, )*
#(#obs_obs_idents: #obs_type_idents, )*
}

Expand All @@ -112,15 +114,14 @@ pub fn codegen(ir: ModelIR) -> TokenStream {
pub fn new(rng: R, #(#obs_idents: #obs_type_idents,)*) -> World<R> {
World {
rng: rng,
#(#var_idents: Default::default(), )*
#(#var_init_idents: false, )*
#(#var_idents: FeOption::Unknown, )*
#(#obs_obs_idents: #obs_idents, )*
}
}

pub fn reset(&mut self) {
#(
self.#var_init_idents = false;
self.#var_idents = FeOption::Unknown;
)*
}

Expand All @@ -142,12 +143,12 @@ pub fn codegen(ir: ModelIR) -> TokenStream {

#(
pub fn #var_eval_idents(&mut self) -> #var_type_idents {
if !self.#var_init_idents {
if self.#var_idents.is_unknown() {
let dist = self.#var_eval_dist_idents();
self.#var_idents = dist.sample(&mut self.rng);
self.#var_init_idents = true;
self.#var_idents = FeOption::Known(dist.sample(&mut self.rng));
}
self.#var_idents
// TODO: handle the case when the value is Null
self.#var_idents.unwrap()
}

pub fn #var_eval_dist_idents(&mut self) -> Box<dyn ferric::distributions::Distribution<R, Domain=#var_type_idents>> {
Expand Down
111 changes: 111 additions & 0 deletions ferric/src/core/feoption.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright 2022 The Ferric AI Project Developers
//! Optional value of a Ferric random variable.
//!
//! Type [`FeOption`] represents an potential value for a random variable:
//! every [`FeOption`] is either [`Known`] and contains a value, or [`Null`], or
//! [`Unknown`]. Note that a [`Null`] value is technically a case where the value is known.
//!
#[derive(Copy, Clone)]
pub enum FeOption<T> {
Null,
Unknown,
Known(T),
}

use FeOption::{Known, Null, Unknown};

impl<T> FeOption<T> {
/// Returns `true` if the FeOption is a [`Null`] value.
///
/// # Examples
///
/// ```
/// # use ferric::*;
/// let x: FeOption<u32> = Null;
/// assert_eq!(x.is_null(), true);
///
/// let x: FeOption<u32> = Known(2);
/// assert_eq!(x.is_null(), false);
///
/// let x: FeOption<u32> = Unknown;
/// assert_eq!(x.is_null(), false);
/// ```
#[inline]
pub const fn is_null(&self) -> bool {
matches!(*self, Null)
}

/// Returns `true` if the FeOption is an [`Unknown`] value.
///
/// # Examples
///
/// ```
/// # use ferric::*;
/// let x: FeOption<u32> = Unknown;
/// assert_eq!(x.is_unknown(), true);
///
/// let x: FeOption<u32> = Known(2);
/// assert_eq!(x.is_unknown(), false);
///
/// let x: FeOption<u32> = Null;
/// assert_eq!(x.is_unknown(), false);
/// ```
#[inline]
pub const fn is_unknown(&self) -> bool {
matches!(*self, Unknown)
}

/// Returns `true` if the FeOption is a [`Known`] value.
///
/// # Examples
///
/// ```
/// # use ferric::*;
/// let x: FeOption<u32> = Known(2);
/// assert_eq!(x.is_known(), true);
///
/// let x: FeOption<u32> = Null;
/// assert_eq!(x.is_known(), false);
///
/// let x: FeOption<u32> = Unknown;
/// assert_eq!(x.is_known(), false);
/// ```
#[inline]
pub const fn is_known(&self) -> bool {
matches!(*self, Known(_))
}

/// Returns the contained [`Known`] value, consuming the `self` value.
///
/// # Panics
///
/// Panics if the self value equals [`Unknown`] or [`Null`].
///
/// # Examples
///
/// ```
/// # use ferric::*;
/// let x = Known("air");
/// assert_eq!(x.unwrap(), "air");
/// ```
///
/// ```should_panic
/// # use ferric::*;
/// let x: FeOption<&str> = Null;
/// assert_eq!(x.unwrap(), "air"); // fails
/// ```
///
/// ```should_panic
/// # use ferric::*;
/// let x: FeOption<&str> = Unknown;
/// assert_eq!(x.unwrap(), "air"); // fails
/// ```
#[inline]
pub fn unwrap(self) -> T {
match self {
Known(val) => val,
Null => panic!("called `FeOption::unwrap()` on a `Null` value"),
Unknown => panic!("called `FeOption::unwrap()` on an `Unknown` value"),
}
}
}
5 changes: 5 additions & 0 deletions ferric/src/core/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Copyright 2022 The Ferric AI Project Developers
mod feoption;

// Re-exports
pub use self::feoption::FeOption;
5 changes: 5 additions & 0 deletions ferric/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,9 @@
pub use ferric_macros::make_model;

// Public modules
pub mod core;
pub mod distributions;

// re-export FeOption and its variants
pub use self::core::FeOption;
pub use FeOption::{Known, Null, Unknown};

0 comments on commit cad5b38

Please sign in to comment.