april-tools / cirkit

a python framework to build, learn and reason about probabilistic circuits and tensor networks
https://cirkit-docs.readthedocs.io/en/latest/
GNU General Public License v3.0
80 stars 4 forks source link

Implement symbolic evidence operator #268

Closed loreloc closed 1 month ago

loreloc commented 2 months ago

Given a symbolic circuit $c$ we would like an operator called e.g. evidence such that it implements the observation of some variables symbolically.

This is useful to implement complex queries involving observation, e.g., the query checking the fairness of a regressor $f$ implemented as a circuit w.r.t. some sensitive Boolean variable $S$:

\mathbb{E}_{\mathbf{x}\sim p(\mathbf{X}\mid S=0)} [f(\mathbf{x},S=0)] - \mathbb{E}_{\mathbf{x}\sim p(\mathbf{X}\mid S=1)} [f(\mathbf{x},S=1)]
\frac{1}{p(S=0)} \int_{\mathrm{dom}(\mathbf{X})} p(\mathbf{x},S=0) f(\mathbf{x},S=0) \mathrm{d}\mathbf{x} - \frac{1}{p(S=1)} \int_{\mathrm{dom}(\mathbf{X})} p(\mathbf{x},S=1) f(\mathbf{x},S=1) \mathrm{d}\mathbf{x}

We should be able to implement this query with the following code:

p0 = integrate(evidence(p, obs={S: 0}))
p1 = integrate(evidence(p, obs={S: 1}))
ex = integrate(multiply(p, f, scope=Scope(X)))
ex0 = evidence(ex, obs={S: 0})
ex1 = evidence(ex, obs={S: 1})
circuit_p0 = compile(p0)
circuit_p1 = compile(p1)
circuit_ex0 = compile(ex0)
circuit_ex1 = compile(ex1)
result = (1.0 / circuit_p0()) * circuit_ex0() - (1.0 / circuit_p1()) * circuit_ex1()

Most importantly, the evidence operator must be implemented in a way such that it can be combined with circuit multiplications and integrations.