pcp/search/branching/
enumerate.rs

1// Copyright 2015 Pierre Talbot (IRCAM)
2
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6
7//     http://www.apache.org/licenses/LICENSE-2.0
8
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use kernel::*;
16use search::branching::*;
17use search::branching::branch::*;
18use search::space::*;
19use term::*;
20use propagators::cmp::*;
21use concept::*;
22
23pub struct Enumerate;
24
25impl<VStore, CStore, R, Domain, Bound> Distributor<Space<VStore, CStore, R>, Bound> for Enumerate where
26  VStore: VStoreConcept<Item=Domain, Location=Identity<Domain>, Output=Domain> + 'static,
27  CStore: IntCStore<VStore>,
28  Domain: IntDomain<Item=Bound> + 'static,
29  Bound: IntBound + Copy + 'static,
30  R: FreezeSpace<VStore, CStore> + Snapshot<State=Space<VStore, CStore, R>>
31{
32  fn distribute(&mut self, space: Space<VStore, CStore, R>, var_idx: usize, val: Bound) ->
33    (<Space<VStore, CStore, R> as Freeze>::FrozenState, Vec<Branch<Space<VStore, CStore, R>>>)
34  {
35    // Note that `Copy` on `Bound` should not be mandatory.
36    // This is a problem generated by the Rust issue #28796, because we cannot box (and thus return) closures that contain moved values.
37    // This is also why we have redundant code in both branches, we can only pass value that can be copied to the closures (here `var_idx` and `val`).
38    Branch::distribute(space,
39      vec![
40        Box::new(move |space: &mut Space<VStore, CStore, R>| {
41          let x = Box::new(Identity::<Domain>::new(var_idx)) as Var<VStore>;
42          let v = Box::new(Constant::new(val)) as Var<VStore>;
43          let x_eq_v = XEqY::new(x.bclone(), v.bclone());
44          space.cstore.alloc(Box::new(x_eq_v));
45        }),
46        Box::new(move |space: &mut Space<VStore, CStore, R>| {
47          let x = Box::new(Identity::<Domain>::new(var_idx)) as Var<VStore>;
48          let v = Box::new(Constant::new(val)) as Var<VStore>;
49          let x_neq_v = XNeqY::new(x, v);
50          space.cstore.alloc(Box::new(x_neq_v));
51        })
52      ]
53    )
54  }
55}
56
57#[cfg(test)]
58mod test {
59  use super::*;
60  use search::branching::binary_split::test::test_distributor;
61  use search::branching::MinVal;
62
63  #[test]
64  fn binary_split_distribution() {
65    let vars = vec![(1,10),(2,4),(1,2)];
66    test_distributor(Enumerate, MinVal, 0,
67      vars.clone(),
68      vec![(1,1),(2,10)]
69    );
70    test_distributor(Enumerate, MinVal, 1,
71      vars.clone(),
72      vec![(2,2),(3,4)]
73    );
74    test_distributor(Enumerate, MinVal, 2,
75      vars.clone(),
76      vec![(1,1),(2,2)]
77    );
78  }
79
80  #[test]
81  #[should_panic]
82  fn binary_split_impossible_distribution() {
83    test_distributor(Enumerate, MinVal, 0,
84      vec![(1,1)],
85      vec![]
86    );
87  }
88
89  #[test]
90  #[should_panic]
91  fn binary_split_impossible_distribution_2() {
92    test_distributor(Enumerate, MinVal, 2,
93      vec![(1,5),(2,4),(4,4)],
94      vec![]
95    );
96  }
97}