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
64
65
66
67
68
69
70
71
72
73
use crate::{gp::Gp, Obj, ObjDirection};
use cl_traits::Storage;
use core::{
  iter::Sum,
  ops::{Add, Div},
  slice::Iter,
};
use mop_common::TraitCfg;
use num_traits::One;

#[derive(Debug)]
pub struct MinWeightedSum<OI, WI> {
  objs: OI,
  weights: WI,
}

impl<OI, WI> MinWeightedSum<OI, WI> {
  pub fn new<CS, D, OR, S>(objs: OI, weights: WI) -> Self {
    Self { objs, weights }
  }
}

impl<'a, O, WI> MinWeightedSum<Iter<'a, O>, WI> {
  pub fn from_gp<D, HCRS, HCS, ORS, OS, SCRS, SCS, SS>(
    mp: &'a Gp<D, HCRS, HCS, ORS, OS, SCRS, SCS, SS>,
    weights: WI,
  ) -> Self
  where
    OS: AsRef<[O]> + Storage<Item = O>,
  {
    Self { objs: mp.defs().objs().as_ref().iter(), weights }
  }
}

impl<O, OR, OI, S, WI> Obj<OR, S> for MinWeightedSum<OI, WI>
where
  O: Obj<OR, S>,
  OR: Add<Output = OR> + Div<Output = OR> + One + Sum,
  OI: Clone + Iterator<Item = O> + TraitCfg,
  WI: Clone + Iterator<Item = OR> + TraitCfg,
{
  fn obj_direction(&self) -> ObjDirection {
    ObjDirection::Min
  }

  fn result(&self, s: &S) -> OR {
    self
      .objs
      .clone()
      .zip(self.weights.clone())
      .map(|(o, w)| {
        let result = o.result(s);
        let transformed = match o.obj_direction() {
          ObjDirection::Max => OR::one() / (OR::one() + result),
          ObjDirection::Min => result,
        };
        transformed * w
      })
      .sum()
  }
}

impl<'a, O, OR, OI, S, WI> From<&'a MinWeightedSum<OI, WI>> for &'a dyn Obj<OR, S>
where
  O: Obj<OR, S>,
  OR: Add<Output = OR> + Div<Output = OR> + One + Sum,
  OI: Clone + Iterator<Item = O> + TraitCfg,
  WI: Clone + Iterator<Item = OR> + TraitCfg,
{
  fn from(f: &'a MinWeightedSum<OI, WI>) -> Self {
    f
  }
}