pub struct ConjunctiveQueryFoldability { /* private fields */ }Expand description
The Conjunctive Query Foldability problem.
Given a finite domain D, a set of relation symbols with fixed arities,
distinguished variables X, undistinguished variables Y, and two
conjunctive queries Q1 and Q2 (over X ∪ Y ∪ D), this problem asks:
does there exist a substitution σ: Y → X ∪ Y ∪ D that maps every atom
of Q1 to an atom of Q2?
This is equivalent to the query containment problem for conjunctive queries and is NP-complete (Chandra & Merlin, 1977; Garey & Johnson A4 SR30).
§Representation
- Each undistinguished variable
Y[i]is a configuration variable whose value encodes its substitution target:0..domain_size→Constant(v)domain_size..domain_size+num_distinguished→Distinguished(v - domain_size)domain_size+num_distinguished..→Undistinguished(v - domain_size - num_distinguished)
- The problem is satisfiable iff applying
σto all atoms of Q1 yields exactly the multiset (treated as a set) of atoms in Q2.
§Example
use problemreductions::models::misc::{ConjunctiveQueryFoldability, Term};
use problemreductions::{Problem, Solver, BruteForce};
// Q1: R(x, u) ∧ R(u, u) Q2: R(x, x) (single atom; duplicates are irrelevant)
// σ: u → x (index = domain_size + 0 = 0) folds Q1 to Q2
let problem = ConjunctiveQueryFoldability::new(
0, 1, 1,
vec![2],
vec![
(0, vec![Term::Distinguished(0), Term::Undistinguished(0)]),
(0, vec![Term::Undistinguished(0), Term::Undistinguished(0)]),
],
vec![
(0, vec![Term::Distinguished(0), Term::Distinguished(0)]),
],
);
let solver = BruteForce::new();
let solution = solver.find_witness(&problem);
assert!(solution.is_some());Implementations§
Source§impl ConjunctiveQueryFoldability
impl ConjunctiveQueryFoldability
Sourcepub fn new(
domain_size: usize,
num_distinguished: usize,
num_undistinguished: usize,
relation_arities: Vec<usize>,
query1_conjuncts: Vec<(usize, Vec<Term>)>,
query2_conjuncts: Vec<(usize, Vec<Term>)>,
) -> Self
pub fn new( domain_size: usize, num_distinguished: usize, num_undistinguished: usize, relation_arities: Vec<usize>, query1_conjuncts: Vec<(usize, Vec<Term>)>, query2_conjuncts: Vec<(usize, Vec<Term>)>, ) -> Self
Create a new ConjunctiveQueryFoldability instance.
§Arguments
domain_size– Number of domain constants|D|.num_distinguished– Number of distinguished variables|X|.num_undistinguished– Number of undistinguished variables|Y|.relation_arities– Arity of each relation symbol.query1_conjuncts– Atoms of Q1 as(relation_index, args)pairs.query2_conjuncts– Atoms of Q2 as(relation_index, args)pairs.
§Panics
Panics if:
- Any atom references a relation index out of range.
- Any atom has the wrong number of arguments for its relation’s arity.
- Any
Constant(i)hasi >= domain_size. - Any
Distinguished(i)hasi >= num_distinguished. - Any
Undistinguished(i)hasi >= num_undistinguished.
Sourcepub fn domain_size(&self) -> usize
pub fn domain_size(&self) -> usize
Returns the size of the finite domain D.
Sourcepub fn num_distinguished(&self) -> usize
pub fn num_distinguished(&self) -> usize
Returns the number of distinguished variables X.
Sourcepub fn num_undistinguished(&self) -> usize
pub fn num_undistinguished(&self) -> usize
Returns the number of undistinguished variables Y.
Sourcepub fn num_conjuncts_q1(&self) -> usize
pub fn num_conjuncts_q1(&self) -> usize
Returns the number of conjuncts (atoms) in Q1.
Sourcepub fn num_conjuncts_q2(&self) -> usize
pub fn num_conjuncts_q2(&self) -> usize
Returns the number of conjuncts (atoms) in Q2.
Sourcepub fn num_relations(&self) -> usize
pub fn num_relations(&self) -> usize
Returns the number of relation symbols.
Sourcepub fn relation_arities(&self) -> &[usize]
pub fn relation_arities(&self) -> &[usize]
Returns the arities of the relation symbols.
Sourcepub fn query1_conjuncts(&self) -> &[(usize, Vec<Term>)]
pub fn query1_conjuncts(&self) -> &[(usize, Vec<Term>)]
Returns the atoms (conjuncts) of query Q1.
Sourcepub fn query2_conjuncts(&self) -> &[(usize, Vec<Term>)]
pub fn query2_conjuncts(&self) -> &[(usize, Vec<Term>)]
Returns the atoms (conjuncts) of query Q2.
Trait Implementations§
Source§impl Clone for ConjunctiveQueryFoldability
impl Clone for ConjunctiveQueryFoldability
Source§fn clone(&self) -> ConjunctiveQueryFoldability
fn clone(&self) -> ConjunctiveQueryFoldability
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for ConjunctiveQueryFoldability
impl Debug for ConjunctiveQueryFoldability
Source§impl<'de> Deserialize<'de> for ConjunctiveQueryFoldability
impl<'de> Deserialize<'de> for ConjunctiveQueryFoldability
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl Problem for ConjunctiveQueryFoldability
impl Problem for ConjunctiveQueryFoldability
Source§fn dims(&self) -> Vec<usize>
fn dims(&self) -> Vec<usize>
Returns the configuration space dimensions.
Each of the num_undistinguished variables can map to any element of
D ∪ X ∪ Y, giving domain_size + num_distinguished + num_undistinguished
choices per variable. When num_undistinguished == 0 the vector is empty
(Q1 contains no variables to substitute; the problem is trivially decided
by checking set equality of Q1 and Q2 at evaluation time).
Source§fn evaluate(&self, config: &[usize]) -> Or
fn evaluate(&self, config: &[usize]) -> Or
Evaluate whether configuration config represents a folding of Q1 into Q2.
Returns true iff applying the substitution encoded by config to every
atom of Q1 produces exactly the set of atoms in Q2.
Source§const NAME: &'static str = "ConjunctiveQueryFoldability"
const NAME: &'static str = "ConjunctiveQueryFoldability"
Source§fn variant() -> Vec<(&'static str, &'static str)>
fn variant() -> Vec<(&'static str, &'static str)>
Source§fn num_variables(&self) -> usize
fn num_variables(&self) -> usize
Source§fn problem_type() -> ProblemType
fn problem_type() -> ProblemType
impl DeclaredVariant for ConjunctiveQueryFoldability
Auto Trait Implementations§
impl Freeze for ConjunctiveQueryFoldability
impl RefUnwindSafe for ConjunctiveQueryFoldability
impl Send for ConjunctiveQueryFoldability
impl Sync for ConjunctiveQueryFoldability
impl Unpin for ConjunctiveQueryFoldability
impl UnsafeUnpin for ConjunctiveQueryFoldability
impl UnwindSafe for ConjunctiveQueryFoldability
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Conv for T
impl<T> Conv for T
Source§impl<T> DynProblem for T
impl<T> DynProblem for T
Source§fn evaluate_dyn(&self, config: &[usize]) -> String
fn evaluate_dyn(&self, config: &[usize]) -> String
Source§fn evaluate_json(&self, config: &[usize]) -> Value
fn evaluate_json(&self, config: &[usize]) -> Value
Source§fn serialize_json(&self) -> Value
fn serialize_json(&self) -> Value
Source§fn problem_name(&self) -> &'static str
fn problem_name(&self) -> &'static str
Problem::NAME).Source§fn num_variables_dyn(&self) -> usize
fn num_variables_dyn(&self) -> usize
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.