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
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#[cfg(all(feature = "with-ndsparse", feature = "with-rand"))]
use cl_traits::{Array, ArrayWrapper, Push, Storage};
#[cfg(feature = "with-rand")]
use {
  cl_traits::create_array,
  core::ops::RangeInclusive,
  rand::{
    distributions::{uniform::SampleUniform, Distribution, Uniform},
    Rng,
  },
};

pub trait Domain<S> {
  type Error;

  fn is_empty(&self) -> bool {
    self.len() == 0
  }

  fn len(&self) -> usize;

  #[cfg(feature = "with-rand")]
  fn new_random_solution<R>(&self, rng: &mut R) -> Result<S, Self::Error>
  where
    R: Rng;

  #[cfg(feature = "with-rand")]
  fn set_rnd_domain<R>(&self, s: &mut S, idx: usize, rng: &mut R)
  where
    R: Rng;
}

#[cfg(feature = "with-rand")]
macro_rules! array_impls {
  ($($N:expr),+) => {
    $(
      impl<T> Domain<[T; $N]> for [RangeInclusive<T>; $N]
      where
        T: Copy + SampleUniform,
      {
        type Error = core::convert::Infallible;

        fn len(&self) -> usize {
          $N
        }

        fn new_random_solution<R>(&self, rng: &mut R) -> Result<[T; $N], Self::Error>
        where
          R: Rng,
        {
          Ok(create_array(|idx| {
            Uniform::from(*self[idx].start()..=*self[idx].end()).sample(rng)
          }))
        }

        fn set_rnd_domain<R>(&self, s: &mut [T; $N], idx: usize, rng: &mut R)
        where
          R: Rng,
        {
          let domain = &self[idx];
          let domain_value = Uniform::from(*domain.start()..=*domain.end()).sample(rng);
          s[idx] = domain_value;
        }
      }

      impl<T> Domain<arrayvec::ArrayVec<[T; $N]>> for arrayvec::ArrayVec<[RangeInclusive<T>; $N]>
      where
        T: Copy + SampleUniform,
      {
        type Error = core::convert::Infallible;

        fn len(&self) -> usize {
          self.len()
        }

        fn new_random_solution<R>(&self, rng: &mut R) -> Result<arrayvec::ArrayVec<[T; $N]>, Self::Error>
        where
          R: Rng,
        {
          let mut s = arrayvec::ArrayVec::new();
          for domain in self.iter() {
            s.push(Uniform::from(*domain.start()..=*domain.end()).sample(rng));
          }
          Ok(s)
        }

        fn set_rnd_domain<R>(&self, s: &mut arrayvec::ArrayVec<[T; $N]>, idx: usize, rng: &mut R)
        where
          R: Rng,
        {
          let domain = &self[idx];
          let domain_value = Uniform::from(*domain.start()..=*domain.end()).sample(rng);
          s[idx] = domain_value;
        }
      }

      #[cfg(feature = "with-ndsparse")]
      impl<DA, DATA, DS, IS, OS> Domain<ndsparse::csl::Csl<DA, DS, IS, OS>> for [RangeInclusive<DATA>; $N]
      where
        DA: Array<Item = usize> + Copy + Default,
        DATA: Copy + SampleUniform,
        DS: AsMut<[DATA]> + AsRef<[DATA]> + Default + Push<Input = DATA> + Storage<Item = DATA>,
        IS: AsMut<[usize]> + AsRef<[usize]> + Default + Push<Input = usize>,
        OS: AsMut<[usize]> + AsRef<[usize]> + Default + Push<Input = usize>,
        rand::distributions::Standard: Distribution<DATA>
      {
        type Error = crate::Error;

        fn len(&self) -> usize {
          self.as_ref().len()
        }

        fn new_random_solution<R>(&self, rng: &mut R) -> Result<ndsparse::csl::Csl<DA, DS, IS, OS>, Self::Error>
        where
          R: Rng,
        {
          let nnz = self.as_ref().len();
          let dims = ArrayWrapper::default();
          let mut array: DA = *dims;
          let iter = array.slice_mut().iter_mut();
          match nnz {
            0 => {}
            1 => iter.for_each(|dim| *dim = 1),
            _ => iter.for_each(|dim| *dim = rng.gen_range(1, nnz)),
          }
          Ok(ndsparse::csl::Csl::new_controlled_random_rand(dims, nnz, rng, |g, _| g.gen()).map_err(|_| crate::Error::Other("Error"))?)
        }

        fn set_rnd_domain<R>(&self, s: &mut ndsparse::csl::Csl<DA, DS, IS, OS>, idx: usize, rng: &mut R)
        where
          R: Rng,
        {
          let domain = &self[idx];
          let domain_value = Uniform::from(*domain.start()..=*domain.end()).sample(rng);
          s.data_mut()[idx] = domain_value;
        }
      }
    )+
  }
}

#[cfg(feature = "with-rand")]
array_impls!(
  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
);