Skip to content

Commit 9247bb6

Browse files
authored
FFI for WMC with complex numbers (#191)
* FFI for complex-valued WMC * Remove dupe bdd_num_recursive_calls
1 parent 2ccf991 commit 9247bb6

File tree

3 files changed

+120
-1
lines changed

3 files changed

+120
-1
lines changed

src/ffi.rs

+53-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::os::raw::c_char;
22
use std::{collections::HashMap, ffi::CStr};
33

44
use crate::repr::DDNNFPtr;
5-
use crate::util::semirings::{RealSemiring, Semiring};
5+
use crate::util::semirings::{Complex, RealSemiring, Semiring};
66
use crate::{
77
builder::{bdd::RobddBuilder, cache::AllIteTable, BottomUpBuilder},
88
constants::primes,
@@ -270,12 +270,27 @@ pub unsafe extern "C" fn bdd_wmc(
270270
DDNNFPtr::unsmoothed_wmc(&(*bdd), &(*wmc)).0
271271
}
272272

273+
#[no_mangle]
274+
#[allow(clippy::missing_safety_doc)]
275+
pub unsafe extern "C" fn bdd_wmc_complex(
276+
bdd: *mut BddPtr<'static>,
277+
wmc: *mut WmcParams<Complex>,
278+
) -> Complex {
279+
DDNNFPtr::unsmoothed_wmc(&(*bdd), &(*wmc))
280+
}
281+
273282
#[no_mangle]
274283
#[allow(clippy::missing_safety_doc)]
275284
pub unsafe extern "C" fn new_wmc_params_f64() -> *mut WmcParams<RealSemiring> {
276285
Box::into_raw(Box::new(WmcParams::new(HashMap::from([]))))
277286
}
278287

288+
#[no_mangle]
289+
#[allow(clippy::missing_safety_doc)]
290+
pub unsafe extern "C" fn new_wmc_params_complex() -> *mut WmcParams<Complex> {
291+
Box::into_raw(Box::new(WmcParams::new(HashMap::from([]))))
292+
}
293+
279294
#[no_mangle]
280295
#[allow(clippy::missing_safety_doc)]
281296
pub unsafe extern "C" fn wmc_param_f64_set_weight(
@@ -287,6 +302,17 @@ pub unsafe extern "C" fn wmc_param_f64_set_weight(
287302
(*weights).set_weight(VarLabel::new(var), RealSemiring(low), RealSemiring(high))
288303
}
289304

305+
#[no_mangle]
306+
#[allow(clippy::missing_safety_doc)]
307+
pub unsafe extern "C" fn wmc_param_complex_set_weight(
308+
weights: *mut WmcParams<Complex>,
309+
var: u64,
310+
low: Complex,
311+
high: Complex,
312+
) {
313+
(*weights).set_weight(VarLabel::new(var), low, high)
314+
}
315+
290316
#[repr(C)]
291317
#[derive(Clone, Copy)]
292318
pub struct WeightF64(pub f64, pub f64);
@@ -312,3 +338,29 @@ pub unsafe extern "C" fn weight_f64_lo(w: WeightF64) -> f64 {
312338
pub unsafe extern "C" fn weight_f64_hi(w: WeightF64) -> f64 {
313339
w.1
314340
}
341+
342+
#[repr(C)]
343+
#[derive(Clone, Copy)]
344+
pub struct WeightComplex(pub Complex, pub Complex);
345+
346+
#[no_mangle]
347+
#[allow(clippy::missing_safety_doc)]
348+
pub unsafe extern "C" fn wmc_param_complex_var_weight(
349+
weights: *mut WmcParams<Complex>,
350+
var: u64,
351+
) -> WeightComplex {
352+
let (l, h) = (*weights).var_weight(VarLabel::new(var));
353+
WeightComplex(*l, *h)
354+
}
355+
356+
#[no_mangle]
357+
#[allow(clippy::missing_safety_doc)]
358+
pub unsafe extern "C" fn weight_complex_lo(w: WeightComplex) -> Complex {
359+
w.0
360+
}
361+
362+
#[no_mangle]
363+
#[allow(clippy::missing_safety_doc)]
364+
pub unsafe extern "C" fn weight_complex_hi(w: WeightComplex) -> Complex {
365+
w.1
366+
}

src/util/semirings/complex.rs

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
use super::semiring_traits::*;
2+
use std::{
3+
fmt::{self, Display, Formatter},
4+
ops::{Add, Mul, Sub},
5+
};
6+
7+
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize)]
8+
#[repr(C)]
9+
pub struct Complex {
10+
pub re: f64,
11+
pub im: f64,
12+
}
13+
14+
impl Display for Complex {
15+
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
16+
if self.im >= 0. {
17+
write!(f, "{}+{}i", self.re, self.im)
18+
} else {
19+
write!(f, "{}{}i", self.re, self.im)
20+
}
21+
}
22+
}
23+
24+
impl Add<Complex> for Complex {
25+
type Output = Self;
26+
27+
fn add(self, rhs: Complex) -> Self::Output {
28+
Self {
29+
re: self.re + rhs.re,
30+
im: self.im + rhs.im,
31+
}
32+
}
33+
}
34+
35+
impl Mul<Complex> for Complex {
36+
type Output = Self;
37+
38+
fn mul(self, rhs: Complex) -> Self::Output {
39+
Self {
40+
re: self.re * rhs.re - self.im * rhs.im,
41+
im: self.re * rhs.im + self.im * rhs.re,
42+
}
43+
}
44+
}
45+
46+
impl Sub<Complex> for Complex {
47+
type Output = Self;
48+
49+
fn sub(self, rhs: Complex) -> Self::Output {
50+
Self {
51+
re: self.re - rhs.re,
52+
im: self.im - rhs.im,
53+
}
54+
}
55+
}
56+
57+
impl Semiring for Complex {
58+
fn one() -> Self {
59+
Self { re: 1.0, im: 0.0 }
60+
}
61+
62+
fn zero() -> Self {
63+
Self { re: 0.0, im: 0.0 }
64+
}
65+
}

src/util/semirings/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
mod boolean;
2+
mod complex;
23
mod expectation;
34
mod finitefield;
45
mod rational;
@@ -7,6 +8,7 @@ mod semiring_traits;
78
mod tropical;
89

910
pub use self::boolean::*;
11+
pub use self::complex::*;
1012
pub use self::expectation::*;
1113
pub use self::finitefield::*;
1214
pub use self::rational::*;

0 commit comments

Comments
 (0)