proto_vulcan/relation/clpfd/
infd.rs1use 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
10pub 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}