https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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
17using namespace libMesh;
18
19namespace 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 */
25template <class T>
27{
28public:
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
46protected:
48 const std::size_t _n_rows;
49 const std::size_t _n_cols;
50
51private:
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
64template <typename T>
65CartesianProduct<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
80template <typename T>
81std::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
91template <typename T>
92std::vector<T>
93CartesianProduct<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
101template <typename T>
102T
103CartesianProduct<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
110template <typename T>
111std::size_t
112CartesianProduct<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 */
123template <class T, class W>
125{
126public:
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
136private:
139};
140
141template <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
153template <typename T, typename W>
154std::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
163template <typename T, typename W>
164W
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::size_t numRows() const
Total number of rows in the complete matrix.
std::deque< unsigned int > _moduli
const std::size_t _n_rows
Number of rows/columns.
static std::size_t computeRowCount(const std::vector< std::vector< T > > &items)
Helper to compute the rows in initialization list to allow _n_rows to be const.
CartesianProduct(const std::vector< std::vector< T > > &items)
std::vector< T > computeRow(std::size_t row) const
Compute specified row of Cartesian product matrix.
std::vector< std::vector< T > > computeMatrix() const
Compute the complete Cartesian product matrix.
T computeValue(std::size_t row, std::size_t col) const
Compute specific value, given row and column, of the Cartesian product matrix.
const std::vector< std::vector< T > > _items
Data used to create Cartesian product use a copy because a temporary can be supplied,...
std::deque< unsigned int > _denomenators
Containers for lazy Cartesian product calculation.
std::size_t numCols() const
Total number of columns in the complete matrix.
std::vector< W > computeWeightVector() const
Compute complete vector of weights.
W computeWeight(std::size_t row) const
Compute specific weight value, given row.
const CartesianProduct< W > _weight
Data used to create Cartesian product; use a copy because a temporary can be supplied.
WeightedCartesianProduct(const std::vector< std::vector< T > > &items, const std::vector< std::vector< W > > &weights)
Enum for batch type in stochastic tools MultiApp.
The following methods are specializations for using the Parallel::packed_range_* routines for a vecto...
uint8_t dof_id_type