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 
11 #include "MooseError.h"
12 #include <numeric>
13 #include <vector>
14 #include <deque>
15 #include "libmesh/libmesh_common.h"
16 
17 using namespace libMesh;
18 
19 namespace StochasticTools
20 {
21 /* Compute the Cartesian Product of the supplied vectors.
22  * http://phrogz.net/lazy-cartesian-product
23  * https://github.com/iamtheburd/lazy-cartesian-product-python/blob/master/LazyCartesianProduct.py
24  */
25 template <class T>
27 {
28 public:
29  CartesianProduct(const std::vector<std::vector<T>> & items);
30 
32  std::vector<std::vector<T>> computeMatrix() const;
33 
35  std::vector<T> computeRow(std::size_t row) const;
36 
38  T computeValue(std::size_t row, std::size_t col) const;
39 
41  std::size_t numRows() const { return _n_rows; }
42 
44  std::size_t numCols() const { return _n_cols; }
45 
46 protected:
48  const std::size_t _n_rows;
49  const std::size_t _n_cols;
50 
51 private:
54  const std::vector<std::vector<T>> _items;
55 
57  std::deque<unsigned int> _denomenators;
58  std::deque<unsigned int> _moduli;
59 
61  static std::size_t computeRowCount(const std::vector<std::vector<T>> & items);
62 };
63 
64 template <typename T>
65 CartesianProduct<T>::CartesianProduct(const std::vector<std::vector<T>> & items)
66  : _n_rows(computeRowCount(items)), _n_cols(items.size()), _items(items)
67 {
68  dof_id_type d = 1;
69  for (typename std::vector<std::vector<T>>::const_reverse_iterator iter = _items.rbegin();
70  iter != _items.rend();
71  ++iter)
72  {
73  std::size_t n = iter->size();
74  _denomenators.push_front(d);
75  _moduli.push_front(n);
76  d *= n;
77  }
78 }
79 
80 template <typename T>
81 std::vector<std::vector<T>>
83 {
84  std::vector<std::vector<T>> output(_n_rows, std::vector<T>(_n_cols));
85  for (std::size_t row = 0; row < _n_rows; ++row)
86  for (std::size_t col = 0; col < _n_cols; ++col)
87  output[row][col] = computeValue(row, col);
88  return output;
89 }
90 
91 template <typename T>
92 std::vector<T>
93 CartesianProduct<T>::computeRow(std::size_t row) const
94 {
95  std::vector<T> output(_n_cols);
96  for (std::size_t col = 0; col < _n_cols; ++col)
97  output[col] = computeValue(row, col);
98  return output;
99 }
100 
101 template <typename T>
102 T
103 CartesianProduct<T>::computeValue(std::size_t row, std::size_t col) const
104 {
105  mooseAssert(row < _n_rows, "Row index out of range.");
106  mooseAssert(col < _n_cols, "Column index out of range.");
107  return _items[col][(row / _denomenators[col]) % _moduli[col]];
108 }
109 
110 template <typename T>
111 std::size_t
112 CartesianProduct<T>::computeRowCount(const std::vector<std::vector<T>> & items)
113 {
114  std::size_t n_rows = 1;
115  for (const auto & inner : items)
116  n_rows *= inner.size();
117  return n_rows;
118 }
119 
120 /*
121  * Add ability to compute weighting values with the Cartesian Product
122  */
123 template <class T, class W>
125 {
126 public:
127  WeightedCartesianProduct(const std::vector<std::vector<T>> & items,
128  const std::vector<std::vector<W>> & weights);
129 
131  std::vector<W> computeWeightVector() const;
132 
134  W computeWeight(std::size_t row) const;
135 
136 private:
139 };
140 
141 template <typename T, typename W>
143  const std::vector<std::vector<T>> & items, const std::vector<std::vector<W>> & weights)
144  : CartesianProduct<T>(items), _weight(weights)
145 {
146  mooseAssert(items.size() == weights.size(),
147  "The supplied items and weights must be the same size.");
148  for (std::size_t i = 0; i < items.size(); ++i)
149  mooseAssert(items[i].size() == weights[i].size(),
150  "Internal vector of the supplied items and weights must be the same size.");
151 }
152 
153 template <typename T, typename W>
154 std::vector<W>
156 {
157  std::vector<W> output(this->_n_rows);
158  for (std::size_t i = 0; i < output.size(); ++i)
159  output[i] = computeWeight(i);
160  return output;
161 }
162 
163 template <typename T, typename W>
164 W
166 {
167  std::vector<W> vec = _weight.computeRow(row);
168  return std::accumulate(vec.begin(), vec.end(), static_cast<W>(1), std::multiplies<W>());
169 }
170 } // namespace
const double T
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