1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
use crate::{gp::GpDefinitions, Cstr, Obj, ObjDirection};
use core::{fmt::Debug, iter::Chain, slice::Iter};
use mop_common::TraitCfg;
use num_traits::{Bounded, NumCast};

#[derive(Debug)]
pub struct MinCstrsRslts<CI> {
  cstrs: CI,
}

impl<CI> MinCstrsRslts<CI> {
  pub fn new(cstrs: CI) -> Self {
    Self { cstrs }
  }
}

impl<'a, C> MinCstrsRslts<Iter<'a, C>> {
  pub fn from_gp_hcs<D, HCS, OS, SCS>(defs: &'a GpDefinitions<D, HCS, OS, SCS>) -> Self
  where
    HCS: AsRef<[C]>,
  {
    Self { cstrs: defs.hard_cstrs.as_ref().iter() }
  }
}

impl<'a, C> MinCstrsRslts<Chain<Iter<'a, C>, Iter<'a, C>>> {
  pub fn from_gp_hcs_and_scs<D, HCS, OS, SCS>(defs: &'a GpDefinitions<D, HCS, OS, SCS>) -> Self
  where
    HCS: AsRef<[C]>,
    SCS: AsRef<[C]>,
  {
    let hci = defs.hard_cstrs.as_ref().iter();
    let sci = defs.soft_cstrs.as_ref().iter();
    Self { cstrs: hci.chain(sci) }
  }
}

impl<C, CI, OR, S> Obj<OR, S> for MinCstrsRslts<CI>
where
  C: Cstr<S>,
  CI: Clone + Iterator<Item = C> + TraitCfg,
  OR: Bounded + NumCast,
{
  fn obj_direction(&self) -> ObjDirection {
    ObjDirection::Min
  }

  fn result(&self, s: &S) -> OR {
    let sum: usize = self.cstrs.clone().map(|cstr| cstr.violations(s)).sum();
    OR::from(sum).unwrap_or_else(OR::max_value)
  }
}

impl<'a, C, CI, OR, S> From<&'a MinCstrsRslts<CI>> for &'a dyn Obj<OR, S>
where
  C: Cstr<S>,
  CI: Clone + Iterator<Item = C> + TraitCfg,
  OR: Bounded + NumCast,
{
  fn from(f: &'a MinCstrsRslts<CI>) -> Self {
    f
  }
}