Skip to content

Commit

Permalink
Fixing bug of lalrpop and adding new features; bumping version to 0.1.9
Browse files Browse the repository at this point in the history
  • Loading branch information
Liby99 committed Apr 24, 2023
1 parent 3724ac6 commit d35f3bf
Show file tree
Hide file tree
Showing 44 changed files with 860 additions and 104 deletions.
8 changes: 5 additions & 3 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# latest
# (Latest) v0.1.9, Apr 24, 2023

- Fixed a bug so that NaN would not appear in the value computation
- Fixed a bug in `scallopy` where disjunctive facts are not processed correctly
- Supporting (partial) disjunctive Datalog
- Fixed custom provenance's default implementations and dispatcher fallback
- Adding new negation syntax to `exists` and `forall` expression
- Multiple bugs fixed

# v0.1.8, Mar 27, 2023

Expand Down
2 changes: 1 addition & 1 deletion core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "scallop-core"
version = "0.1.8"
version = "0.1.9"
authors = ["Ziyang Li <[email protected]>"]
edition = "2018"

Expand Down
40 changes: 0 additions & 40 deletions core/src/common/input_tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,46 +50,6 @@ impl Default for DynamicInputTag {
}
}

pub trait StaticInputTag: Sized {
fn from_dynamic_input_tag(_: &DynamicInputTag) -> Option<Self>;
}

impl<T> StaticInputTag for T {
default fn from_dynamic_input_tag(_: &DynamicInputTag) -> Option<Self> {
None
}
}

impl StaticInputTag for bool {
fn from_dynamic_input_tag(t: &DynamicInputTag) -> Option<Self> {
match t {
DynamicInputTag::Bool(b) => Some(b.clone()),
_ => None,
}
}
}

impl StaticInputTag for f64 {
fn from_dynamic_input_tag(t: &DynamicInputTag) -> Option<Self> {
match t {
DynamicInputTag::Float(f) => Some(f.clone()),
DynamicInputTag::ExclusiveFloat(f, _) => Some(f.clone()),
_ => None,
}
}
}

impl StaticInputTag for (f64, Option<usize>) {
fn from_dynamic_input_tag(t: &DynamicInputTag) -> Option<Self> {
match t {
DynamicInputTag::Exclusive(i) => Some((1.0, Some(i.clone()))),
DynamicInputTag::Float(f) => Some((f.clone(), None)),
DynamicInputTag::ExclusiveFloat(f, u) => Some((f.clone(), Some(u.clone()))),
_ => None,
}
}
}

impl std::str::FromStr for DynamicInputTag {
type Err = ParseInputTagError;

Expand Down
4 changes: 2 additions & 2 deletions core/src/compiler/front/grammar.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,14 @@ match {
// Literals
r"[a-zA-Z][a-zA-Z_0-9]*" => name,
r"-?[0-9]+" => int,
r"-?\d+(\.\d+)(e-?\d+)?" => float,
r"-?[0-9]+(\.[0-9]+)(e-?[0-9]+)?" => float,
r#""[^"]*""# => string,
r#"t"[^"]*""# => date_time_string,
r#"d"[^"]*""# => duration_string,
r#"'[^']*'"# => character,

// Comments and Whitespaces
r"\s*" => { },
r"[ \n\r]*" => { },
r"//[^\n\r]*[\n\r]*" => { },
r"/\*([^\*]*\*+[^\*/])*([^\*]*\*+|[^\*])*\*/" => { },
}
Expand Down
17 changes: 17 additions & 0 deletions core/src/integrate/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,23 @@ impl<Prov: Provenance, P: PointerFamily> IntegrateContext<Prov, P> {
}
}

pub fn clone_with_new_provenance<Prov2: Provenance>(&self, new_prov: Prov2) -> IntegrateContext<Prov2, P>
where
Prov2::InputTag: ConvertFromInputTag<Prov::InputTag>,
{
IntegrateContext {
options: self.options.clone(),
front_ctx: self.front_ctx.clone(),
internal: InternalIntegrateContext {
prov_ctx: new_prov,
runtime_env: self.internal.runtime_env.clone(),
ram_program: self.internal.ram_program.clone(),
exec_ctx: self.internal.exec_ctx.clone_with_new_provenance::<Prov2>(),
},
front_has_changed: true,
}
}

pub fn provenance_context(&self) -> &Prov {
&self.internal.prov_ctx
}
Expand Down
16 changes: 16 additions & 0 deletions core/src/runtime/database/extensional/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,22 @@ impl<Prov: Provenance> ExtensionalDatabase<Prov> {
}
}

pub fn clone_with_new_provenance<Prov2: Provenance>(&self) -> ExtensionalDatabase<Prov2>
where
Prov2::InputTag: ConvertFromInputTag<Prov::InputTag>,
{
ExtensionalDatabase {
type_check: self.type_check,
disjunction_count: self.disjunction_count,
relation_types: self.relation_types.clone(),
extensional_relations: self.extensional_relations.iter().map(|(pred, rel)| {
let new_rel = rel.clone_with_new_provenance();
(pred.clone(), new_rel)
}).collect(),
internalized: false,
}
}

pub fn with_relation_types<I>(types: I) -> Self
where
I: Iterator<Item = (String, TupleType)>,
Expand Down
17 changes: 17 additions & 0 deletions core/src/runtime/database/extensional/relation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,23 @@ impl<Prov: Provenance> ExtensionalRelation<Prov> {
}
}

pub fn clone_with_new_provenance<Prov2: Provenance>(&self) -> ExtensionalRelation<Prov2>
where
Prov2::InputTag: ConvertFromInputTag<Prov::InputTag>,
{
ExtensionalRelation {
program_facts: self.program_facts.clone(),
internalized_program_facts: false,
dynamic_input: self.dynamic_input.clone(),
static_input: self.static_input.iter().map(|(tag, tuple)| {
let new_tag = tag.as_ref().and_then(|tag| ConvertFromInputTag::from_input_tag(tag.clone()));
(new_tag, tuple.clone())
}).collect(),
internal: DynamicCollection::empty(),
internalized: false,
}
}

pub fn has_program_facts(&self) -> bool {
!self.program_facts.is_empty()
}
Expand Down
6 changes: 6 additions & 0 deletions core/src/runtime/database/intentional/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ impl<Prov: Provenance, Ptr: PointerFamily> IntentionalDatabase<Prov, Ptr> {
}
}

/// Clone the intentional database into a new one with a different provenance.
/// The new database will be empty.
pub fn clone_with_new_provenance<Prov2: Provenance>(&self) -> IntentionalDatabase<Prov2, Ptr> {
IntentionalDatabase::new()
}

/// Create an intentional database from dynamic collections
pub fn from_dynamic_collections<I>(iter: I) -> Self
where
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate::common::expr::*;
use crate::common::foreign_predicate::*;
use crate::common::input_tag::*;
use crate::runtime::provenance::*;

use super::*;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::common::foreign_predicate::*;
use crate::common::input_tag::*;
use crate::common::value::*;
use crate::common::tuple::*;
use crate::runtime::provenance::*;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::common::foreign_predicate::*;
use crate::common::input_tag::*;
use crate::common::expr::*;
use crate::common::tuple::*;
use crate::common::value::*;
Expand Down
12 changes: 12 additions & 0 deletions core/src/runtime/dynamic/incremental.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,18 @@ impl<Prov: Provenance, Ptr: PointerFamily> DynamicExecutionContext<Prov, Ptr> {
}
}

pub fn clone_with_new_provenance<Prov2: Provenance>(&self) -> DynamicExecutionContext<Prov2, Ptr>
where
Prov2::InputTag: ConvertFromInputTag<Prov::InputTag>,
{
DynamicExecutionContext {
options: self.options.clone(),
program: self.program.clone(),
edb: self.edb.clone_with_new_provenance::<Prov2>(),
idb: self.idb.clone_with_new_provenance::<Prov2>(),
}
}

pub fn set_non_incremental(&mut self) {
self.options.incremental_maintain = false;
}
Expand Down
36 changes: 36 additions & 0 deletions core/src/runtime/provenance/common/input_tags/boolean.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use crate::common::input_tag::*;

use super::*;

impl StaticInputTag for bool {
fn from_dynamic_input_tag(t: &DynamicInputTag) -> Option<Self> {
match t {
DynamicInputTag::Bool(b) => Some(b.clone()),
_ => None,
}
}
}

impl ConvertFromInputTag<()> for bool {
fn from_input_tag(_: ()) -> Option<Self> { None }
}

impl ConvertFromInputTag<bool> for bool {
fn from_input_tag(t: bool) -> Option<Self> { Some(t) }
}

impl ConvertFromInputTag<usize> for bool {
fn from_input_tag(t: usize) -> Option<Self> { Some(t > 0) }
}

impl ConvertFromInputTag<f32> for bool {
fn from_input_tag(t: f32) -> Option<Self> { Some(t > 0.0) }
}

impl ConvertFromInputTag<f64> for bool {
fn from_input_tag(t: f64) -> Option<Self> { Some(t > 0.0) }
}

impl<T: Clone + 'static> ConvertFromInputTag<InputDiffProb<T>> for bool {
fn from_input_tag(t: InputDiffProb<T>) -> Option<Self> { Some(t.0 > 0.0) }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub trait ConvertFromInputTag<X: Sized>: Sized {
fn from_input_tag(t: X) -> Option<Self>;
}
45 changes: 45 additions & 0 deletions core/src/runtime/provenance/common/input_tags/float.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use crate::common::input_tag::*;

use super::*;

impl StaticInputTag for f64 {
fn from_dynamic_input_tag(t: &DynamicInputTag) -> Option<Self> {
match t {
DynamicInputTag::Float(f) => Some(f.clone()),
DynamicInputTag::ExclusiveFloat(f, _) => Some(f.clone()),
_ => None,
}
}
}

impl ConvertFromInputTag<()> for f64 {
fn from_input_tag(_: ()) -> Option<Self> { None }
}

impl ConvertFromInputTag<bool> for f64 {
fn from_input_tag(t: bool) -> Option<Self> { Some(if t { 1.0 } else { 0.0 }) }
}

impl ConvertFromInputTag<usize> for f64 {
fn from_input_tag(t: usize) -> Option<Self> { Some(if t > 0 { 1.0 } else { 0.0 }) }
}

impl ConvertFromInputTag<Exclusion> for f64 {
fn from_input_tag(_: Exclusion) -> Option<Self> { None }
}

impl ConvertFromInputTag<f64> for f64 {
fn from_input_tag(t: f64) -> Option<Self> { Some(t) }
}

impl ConvertFromInputTag<InputExclusiveProb> for f64 {
fn from_input_tag(t: InputExclusiveProb) -> Option<Self> { Some(t.prob) }
}

impl<T: Clone + 'static> ConvertFromInputTag<InputDiffProb<T>> for f64 {
fn from_input_tag(t: InputDiffProb<T>) -> Option<Self> { Some(t.0) }
}

impl<T: Clone + 'static> ConvertFromInputTag<InputExclusiveDiffProb<T>> for f64 {
fn from_input_tag(t: InputExclusiveDiffProb<T>) -> Option<Self> { Some(t.prob) }
}
93 changes: 93 additions & 0 deletions core/src/runtime/provenance/common/input_tags/input_diff_prob.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
use crate::common::input_tag::*;

use super::*;

/// An input differentiable probability.
///
/// It contains two elements.
/// The first is an `f64` which represents the probability of the tag.
/// The second is an `Option<T>` which is the original differentiable object.
/// Note that if the second element is provided as `None` then it means we
/// do not treat the object as differentiable and thus we do not need to
/// back-propagate gradients into it.
/// In such case the probability is treated as a constant.
#[derive(Clone)]
pub struct InputDiffProb<T: Clone + 'static>(pub f64, pub Option<T>);

impl<T: Clone + 'static> std::fmt::Debug for InputDiffProb<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}

impl<T: Clone + 'static> From<(f64, Option<T>)> for InputDiffProb<T> {
fn from((p, t): (f64, Option<T>)) -> Self {
Self(p, t)
}
}

impl<T: Clone + 'static> StaticInputTag for InputDiffProb<T> {
fn from_dynamic_input_tag(t: &DynamicInputTag) -> Option<Self> {
match t {
DynamicInputTag::ExclusiveFloat(f, _) => Some(Self(f.clone(), None)),
DynamicInputTag::Float(f) => Some(Self(f.clone(), None)),
_ => None,
}
}
}

impl<T: Clone + 'static> ConvertFromInputTag<()> for InputDiffProb<T> {
fn from_input_tag(_: ()) -> Option<Self> {
None
}
}

impl<T: Clone + 'static> ConvertFromInputTag<bool> for InputDiffProb<T> {
fn from_input_tag(b: bool) -> Option<Self> {
if b {
None
} else {
Some(Self(0.0, None))
}
}
}

impl<T: Clone + 'static> ConvertFromInputTag<usize> for InputDiffProb<T> {
fn from_input_tag(u: usize) -> Option<Self> {
if u > 0 {
None
} else {
Some(Self(0.0, None))
}
}
}

impl<T: Clone + 'static> ConvertFromInputTag<Exclusion> for InputDiffProb<T> {
fn from_input_tag(_: Exclusion) -> Option<Self> {
None
}
}

impl<T: Clone + 'static> ConvertFromInputTag<f64> for InputDiffProb<T> {
fn from_input_tag(t: f64) -> Option<Self> {
Some(Self(t, None))
}
}

impl<T: Clone + 'static> ConvertFromInputTag<InputExclusiveProb> for InputDiffProb<T> {
fn from_input_tag(t: InputExclusiveProb) -> Option<Self> {
Some(Self(t.prob, None))
}
}

impl<T: Clone + 'static> ConvertFromInputTag<InputDiffProb<T>> for InputDiffProb<T> {
fn from_input_tag(t: InputDiffProb<T>) -> Option<Self> {
Some(t.clone())
}
}

impl<T: Clone + 'static> ConvertFromInputTag<InputExclusiveDiffProb<T>> for InputDiffProb<T> {
fn from_input_tag(t: InputExclusiveDiffProb<T>) -> Option<Self> {
Some(Self(t.prob, None))
}
}
Loading

0 comments on commit d35f3bf

Please sign in to comment.