use ark_ff::Field;
use ark_poly::DenseMultilinearExtension;
use ark_relations::gr1cs::{ConstraintSystem, Matrix};
use ark_std::{cfg_into_iter, cfg_iter};
#[cfg(feature = "parallel")]
use rayon::prelude::*;
use super::{Arith, Error};
use crate::{algebra::ops::poly::MLEHelper, circuits::Assignments};
pub trait CCS:
Arith + for<'a> From<&'a ConstraintSystem<Self::Field>> + From<ConstraintSystem<Self::Field>>
{
type Field: Field;
fn matrices(&self) -> &[Matrix<Self::Field>];
fn evaluate_ccs<const Q: usize>(
&self,
z: Assignments<Self::Field, impl AsRef<[Self::Field]> + Sync>,
multisets: [Vec<usize>; Q],
coefficients: [Self::Field; Q],
) -> Result<Vec<Self::Field>, Error> {
let cfg = self.config();
let matrices = self.matrices();
let public_len = z.public.as_ref().len();
let private_len = z.private.as_ref().len();
if public_len != cfg.n_public_inputs {
return Err(Error::MalformedAssignments(format!(
"The number of public inputs in R1CS ({}) does not match the length of the provided public inputs ({}).",
cfg.n_public_inputs, public_len
)));
}
if private_len != cfg.n_witnesses {
return Err(Error::MalformedAssignments(format!(
"The number of witnesses in R1CS ({}) does not match the length of the provided witnesses ({}).",
cfg.n_witnesses, private_len
)));
}
Ok(cfg_into_iter!(0..cfg.n_constraints)
.map(|row| {
multisets
.iter()
.zip(coefficients)
.map(|(s, c)| {
c * s
.iter()
.map(|&i| {
matrices[i][row]
.iter()
.map(|(val, col)| z[*col] * val)
.sum::<Self::Field>()
})
.product::<Self::Field>()
})
.sum()
})
.collect())
}
fn mles(
&self,
z: Assignments<Self::Field, impl AsRef<[Self::Field]> + Sync>,
) -> Vec<DenseMultilinearExtension<Self::Field>> {
self.matrices()
.iter()
.map(|matrix| {
DenseMultilinearExtension::from_evaluations(
&cfg_iter!(matrix)
.map(|row| row.iter().map(|(val, col)| z[*col] * val).sum())
.collect::<Vec<_>>(),
)
})
.collect()
}
}