proto_vulcan/relation/clpfd/
infd.rs

1use crate::engine::Engine;
2use crate::goal::{AnyGoal, GoalCast, InferredGoal};
3use crate::lterm::LTerm;
4use crate::operator::conj::InferredConj;
5use crate::relation::clpfd::domfd::DomFd;
6use crate::state::FiniteDomain;
7use crate::user::User;
8use std::ops::RangeInclusive;
9
10/// Associates the same domain to multiple variables
11pub fn infd<U, E, G>(u: LTerm<U, E>, domain: &[isize]) -> InferredGoal<U, E, G>
12where
13    U: User,
14    E: Engine<U>,
15    G: AnyGoal<U, E>,
16{
17    if u.is_list() {
18        let goals = u
19            .iter()
20            .map(|v| DomFd::new(v.clone(), FiniteDomain::from(domain)).cast_into())
21            .collect();
22        InferredConj::from_vec(goals)
23    } else {
24        DomFd::new(u, FiniteDomain::from(domain))
25    }
26}
27
28pub fn infdrange<U, E, G>(u: LTerm<U, E>, domain: &RangeInclusive<isize>) -> InferredGoal<U, E, G>
29where
30    U: User,
31    E: Engine<U>,
32    G: AnyGoal<U, E>,
33{
34    if u.is_list() {
35        let goals = u
36            .iter()
37            .map(|v| DomFd::new(v.clone(), FiniteDomain::from(domain)).cast_into())
38            .collect();
39        InferredConj::from_vec(goals)
40    } else {
41        DomFd::new(u, FiniteDomain::from(domain))
42    }
43}
44
45#[cfg(test)]
46mod tests {
47    use super::infd;
48    use crate::prelude::*;
49
50    #[test]
51    fn test_infd_1() {
52        let query = proto_vulcan_query!(|q| {
53            |x, y| {
54                q == [x, y],
55                infd([x, y], &[1]),
56            }
57        });
58        let mut iter = query.run();
59        assert_eq!(iter.next().unwrap().q, lterm!([1, 1]));
60        assert!(iter.next().is_none());
61    }
62
63    #[test]
64    fn test_infd_2() {
65        let query = proto_vulcan_query!(|q| {
66            infd(q, &[1, 2, 3, 4]),
67        });
68        let mut iter = query.run();
69        assert_eq!(iter.next().unwrap().q, 1);
70        assert_eq!(iter.next().unwrap().q, 2);
71        assert_eq!(iter.next().unwrap().q, 3);
72        assert_eq!(iter.next().unwrap().q, 4);
73        assert!(iter.next().is_none());
74    }
75
76    #[test]
77    fn test_infd_3() {
78        let query = proto_vulcan_query!(|q| {
79            infd(q, &[1, 2]),
80            q != 1,
81        });
82        let mut iter = query.run();
83        assert_eq!(iter.next().unwrap().q, 2);
84        assert!(iter.next().is_none());
85    }
86
87    #[test]
88    fn test_infd_4() {
89        let query = proto_vulcan_query!(|q| {
90            |x| {
91                infd([x, q], &[1, 2]),
92                q != 1,
93                x == q,
94            }
95        });
96        let mut iter = query.run();
97        assert_eq!(iter.next().unwrap().q, 2);
98        assert!(iter.next().is_none());
99    }
100
101    #[test]
102    fn test_infd_5() {
103        let query = proto_vulcan_query!(|x, y, z| {
104            infd(x, &[1, 2, 3]),
105            infd(y, &[3, 4, 5]),
106            x == y,
107            infd(z, &[1, 3, 5, 7, 8]),
108            infd(z, &[5, 6]),
109            z == 5,
110        });
111        let mut iter = query.run();
112        let result = iter.next().unwrap();
113        assert_eq!(result.x, 3);
114        assert_eq!(result.y, 3);
115        assert_eq!(result.z, 5);
116        assert!(iter.next().is_none());
117    }
118
119    #[test]
120    fn test_infd_6() {
121        let query = proto_vulcan_query!(|x, y, z| {
122            infd(x, &[1, 2, 3]),
123            infd(y, &[3, 4, 5]),
124            x == y,
125            infd(z, &[1, 3, 5, 7, 8]),
126            infd(z, &[5, 6]),
127            z == x,
128        });
129        let mut iter = query.run();
130        assert!(iter.next().is_none());
131    }
132
133    #[test]
134    fn test_infd_7() {
135        let query = proto_vulcan_query!(|q| {
136            |x| {
137                infd(x, &[1, 2]),
138                infd(q, &[5])
139            }
140        });
141        let mut iter = query.run();
142        assert_eq!(iter.next().unwrap().q, 5);
143        assert!(iter.next().is_none());
144    }
145
146    #[test]
147    fn test_infd_8() {
148        let query = proto_vulcan_query!(|q| {
149            infd(q, &[1, 2]),
150            q == true
151        });
152        let mut iter = query.run();
153        assert!(iter.next().is_none());
154    }
155
156    #[test]
157    fn test_infd_9() {
158        let query = proto_vulcan_query!(|q| {
159            q == true,
160            infd(q, &[1, 2]),
161        });
162        let mut iter = query.run();
163        assert!(iter.next().is_none());
164    }
165}