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