https://mooseframework.inl.gov
CartesianProduct.h
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 #pragma once
10 #include "MooseError.h"
11 #include <numeric>
12 #include <vector>
13 #include <deque>
14 #include "libmesh/libmesh_common.h"
15 
16 using namespace libMesh;
17 
18 namespace StochasticTools
19 {
20 /* Compute the Cartesian Product of the supplied vectors.
21  * http://phrogz.net/lazy-cartesian-product
22  * https://github.com/iamtheburd/lazy-cartesian-product-python/blob/master/LazyCartesianProduct.py
23  */
24 template <class T>
26 {
27 public:
28  CartesianProduct(const std::vector<std::vector<T>> & items);
29 
31  std::vector<std::vector<T>> computeMatrix() const;
32 
34  std::vector<T> computeRow(std::size_t row) const;
35 
37  T computeValue(std::size_t row, std::size_t col) const;
38 
40  std::size_t numRows() const { return _n_rows; }
41 
43  std::size_t numCols() const { return _n_cols; }
44 
45 protected:
47  const std::size_t _n_rows;
48  const std::size_t _n_cols;
49 
50 private:
53  const std::vector<std::vector<T>> _items;
54 
56  std::deque<unsigned int> _denomenators;
57  std::deque<unsigned int> _moduli;
58 
60  static std::size_t computeRowCount(const std::vector<std::vector<T>> & items);
61 };
62 
63 template <typename T>
64 CartesianProduct<T>::CartesianProduct(const std::vector<std::vector<T>> & items)
65  : _n_rows(computeRowCount(items)), _n_cols(items.size()), _items(items)
66 {
67  dof_id_type d = 1;
68  for (typename std::vector<std::vector<T>>::const_reverse_iterator iter = _items.rbegin();
69  iter != _items.rend();
70  ++iter)
71  {
72  std::size_t n = iter->size();
73  _denomenators.push_front(d);
74  _moduli.push_front(n);
75  d *= n;
76  }
77 }
78 
79 template <typename T>
80 std::vector<std::vector<T>>
82 {
83  std::vector<std::vector<T>> output(_n_rows, std::vector<T>(_n_cols));
84  for (std::size_t row = 0; row < _n_rows; ++row)
85  for (std::size_t col = 0; col < _n_cols; ++col)
86  output[row][col] = computeValue(row, col);
87  return output;
88 }
89 
90 template <typename T>
91 std::vector<T>
92 CartesianProduct<T>::computeRow(std::size_t row) const
93 {
94  std::vector<T> output(_n_cols);
95  for (std::size_t col = 0; col < _n_cols; ++col)
96  output[col] = computeValue(row, col);
97  return output;
98 }
99 
100 template <typename T>
101 T
102 CartesianProduct<T>::computeValue(std::size_t row, std::size_t col) const
103 {
104  mooseAssert(row < _n_rows, "Row index out of range.");
105  mooseAssert(col < _n_cols, "Column index out of range.");
106  return _items[col][(row / _denomenators[col]) % _moduli[col]];
107 }
108 
109 template <typename T>
110 std::size_t
111 CartesianProduct<T>::computeRowCount(const std::vector<std::vector<T>> & items)
112 {
113  std::size_t n_rows = 1;
114  for (const auto & inner : items)
115  n_rows *= inner.size();
116  return n_rows;
117 }
118 
119 /*
120  * Add ability to compute weighting values with the Cartesian Product
121  */
122 template <class T, class W>
124 {
125 public:
126  WeightedCartesianProduct(const std::vector<std::vector<T>> & items,
127  const std::vector<std::vector<W>> & weights);
128 
130  std::vector<W> computeWeightVector() const;
131 
133  W computeWeight(std::size_t row) const;
134 
135 private:
138 };
139 
140 template <typename T, typename W>
142  const std::vector<std::vector<T>> & items, const std::vector<std::vector<W>> & weights)
143  : CartesianProduct<T>(items), _weight(weights)
144 {
145  mooseAssert(items.size() == weights.size(),
146  "The supplied items and weights must be the same size.");
147  for (std::size_t i = 0; i < items.size(); ++i)
148  mooseAssert(items[i].size() == weights[i].size(),
149  "Internal vector of the supplied items and weights must be the same size.");
150 }
151 
152 template <typename T, typename W>
153 std::vector<W>
155 {
156  std::vector<W> output(this->_n_rows);
157  for (std::size_t i = 0; i < output.size(); ++i)
158  output[i] = computeWeight(i);
159  return output;
160 }
161 
162 template <typename T, typename W>
163 W
165 {
166  std::vector<W> vec = _weight.computeRow(row);
167  return std::accumulate(vec.begin(), vec.end(), static_cast<W>(1), std::multiplies<W>());
168 }
169 } // namespace
std::deque< unsigned int > _denomenators
Containers for lazy Cartesian product calculation.
W computeWeight(std::size_t row) const
Compute specific weight value, given row.
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...
Enum for batch type in stochastic tools MultiApp.
std::deque< unsigned int > _moduli
const CartesianProduct< W > _weight
Data used to create Cartesian product; use a copy because a temporary can be supplied.
const std::size_t _n_rows
Number of rows/columns.
const std::vector< std::vector< T > > _items
Data used to create Cartesian product use a copy because a temporary can be supplied, as is the case in the CartesianProductSampler.
std::size_t numCols() const
Total number of columns in the complete matrix.
std::size_t numRows() const
Total number of rows in the complete matrix.
std::vector< W > computeWeightVector() const
Compute complete vector of weights.
uint8_t dof_id_type