-
Notifications
You must be signed in to change notification settings - Fork 0
Adds functions to generate matrices #246
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| /* | ||
| * Copyright 2026 NWChemEx-Project | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| #pragma once | ||
| #include <cstdint> | ||
| #include <random> | ||
| #include <tensorwrapper/tensor/tensor.hpp> | ||
|
|
||
| namespace tensorwrapper::generate { | ||
|
|
||
| /** @brief Adds clamped normal noise to each element of @p matrix. | ||
| * | ||
| * Draws `delta ~ Normal(0, t)` and clamps to `[-t, t]` before adding to each | ||
| * element. When @p t is zero the input is copied unchanged. | ||
| * | ||
| * @param[in] matrix The tensor to perturb. | ||
| * @param[in] t Non-negative noise scale (standard deviation and clamp bound). | ||
| * @param[in,out] gen Random number generator used for the normal draws. | ||
| * | ||
| * @return A new tensor with the same shape as @p matrix. | ||
| * | ||
| * @throw std::invalid_argument if @p t is negative. | ||
| */ | ||
| Tensor add_noise(const Tensor& matrix, double t, std::mt19937& gen); | ||
|
|
||
| /** @brief Overload of add_noise that creates its own RNG from @p seed. | ||
| * | ||
| * @param[in] matrix The tensor to perturb. | ||
| * @param[in] t Non-negative noise scale (standard deviation and clamp bound). | ||
| * @param[in] seed Seed for the internal random number generator. A value of | ||
| * zero selects a non-deterministic seed. | ||
| * | ||
| * @return A new tensor with the same shape as @p matrix. | ||
| * | ||
| * @throw std::invalid_argument if @p t is negative. | ||
| */ | ||
| Tensor add_noise(const Tensor& matrix, double t, std::uint64_t seed = 42); | ||
|
|
||
| } // namespace tensorwrapper::generate |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| /* | ||
| * Copyright 2026 NWChemEx-Project | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| #pragma once | ||
| #include <tensorwrapper/generate/add_noise.hpp> | ||
| #include <tensorwrapper/generate/generate_eigen_system.hpp> | ||
| #include <tensorwrapper/generate/generate_eigenvalues.hpp> | ||
| #include <tensorwrapper/generate/generate_utils.hpp> | ||
| #include <tensorwrapper/generate/identity_matrix.hpp> | ||
| #include <tensorwrapper/generate/random_orthogonal_matrix.hpp> | ||
|
|
||
| /** @brief Namespace for utilities that generate synthetic tensors and matrices. | ||
| * | ||
| * The functions in this namespace create reproducible test matrices, | ||
| * eigenvalue | ||
| * spectra, and related quantities for unit testing and benchmarking. | ||
| */ | ||
| namespace tensorwrapper::generate {} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| /* | ||
| * Copyright 2026 NWChemEx-Project | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| #pragma once | ||
| #include <cstddef> | ||
| #include <tensorwrapper/generate/generate_utils.hpp> | ||
| #include <tensorwrapper/tensor/tensor.hpp> | ||
|
|
||
| namespace tensorwrapper::generate { | ||
|
|
||
| /** @brief A symmetric matrix together with its eigen-decomposition. | ||
| * | ||
| * The member @p matrix satisfies @f$M = Q D Q^T@f$ where @p eigenvectors is | ||
| * @f$Q@f$ and @p eigenvalues holds the diagonal entries of @f$D@f$. | ||
| */ | ||
| struct EigenSystem { | ||
| /// Dimension of the square matrix. | ||
| std::size_t n = 0; | ||
| /// Rank-1 tensor of length @p n containing the eigenvalues. | ||
| Tensor eigenvalues; | ||
| /// Rank-2 tensor of shape `(n, n)` whose columns are the eigenvectors. | ||
| Tensor eigenvectors; | ||
| /// Rank-2 tensor of shape `(n, n)` representing the symmetric matrix. | ||
| Tensor matrix; | ||
| }; | ||
|
|
||
| /** @brief Generates a reproducible symmetric matrix and its | ||
| * eigen-decomposition. | ||
| * | ||
| * Constructs @f$M = Q D Q^T@f$ where @f$D@f$ is built from eigenvalues | ||
| * generated according to @p spec and @f$Q@f$ is a random orthogonal matrix. | ||
| * | ||
| * @param[in] spec Parameters controlling the matrix dimension, spectrum, and | ||
| * random seed. | ||
| * | ||
| * @return An @ref EigenSystem populated with @p spec.n, the eigenvalues, | ||
| * eigenvectors, and the assembled matrix. | ||
| * | ||
| * @throw std::invalid_argument if @p spec.n is outside `[1, kMaxMatrixDim]`. | ||
| */ | ||
| EigenSystem generate_eigen_system(const SymmetricMatrixSpec& spec); | ||
|
|
||
| } // namespace tensorwrapper::generate | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| /* | ||
| * Copyright 2026 NWChemEx-Project | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| #pragma once | ||
| #include <random> | ||
| #include <tensorwrapper/generate/generate_utils.hpp> | ||
| #include <tensorwrapper/tensor/tensor.hpp> | ||
|
|
||
| namespace tensorwrapper::generate { | ||
|
|
||
| /** @brief Generates a sorted rank-1 tensor of eigenvalues from @p spec. | ||
| * | ||
| * The spectrum spans | ||
| * @f$[\texttt{spec.min\_eigenvalue}, | ||
| * \texttt{spec.min\_eigenvalue} \times \texttt{spec.condition\_number}]@f$ | ||
| * using the spacing strategy given by @p spec.spacing. | ||
| * | ||
| * @param[in] spec Parameters controlling the eigenvalue distribution. | ||
| * @param[in,out] gen Random number generator used when @p spec.spacing | ||
| * requires random draws. | ||
| * | ||
| * @return A rank-1 tensor of length @p spec.n containing the eigenvalues in | ||
| * ascending order. | ||
| * | ||
| * @throw std::invalid_argument if @p spec.n is outside `[1, kMaxMatrixDim]` or | ||
| * if @p spec.spacing is invalid. | ||
| */ | ||
| Tensor generate_eigenvalues(const SymmetricMatrixSpec& spec, std::mt19937& gen); | ||
|
|
||
| } // namespace tensorwrapper::generate |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| /* | ||
| * Copyright 2026 NWChemEx-Project | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| #pragma once | ||
| #include <cstdint> | ||
| #include <random> | ||
| #include <stdexcept> | ||
|
|
||
| namespace tensorwrapper::generate { | ||
|
ryanmrichard marked this conversation as resolved.
|
||
|
|
||
| /// Maximum supported dimension for generated square matrices. | ||
| constexpr std::size_t kMaxMatrixDim = 10; | ||
|
|
||
| /** @brief Specifies how eigenvalues are distributed between the endpoints. | ||
| * | ||
| * Each spacing mode fills the interval | ||
| * @f$[\lambda_{\min}, \lambda_{\max}]@f$ with @f$n@f$ eigenvalues, where | ||
| * @f$\lambda_{\max} = \lambda_{\min} \times@f$ the condition number. | ||
| */ | ||
| enum class EigenvalueSpacing { | ||
| /// Uniform spacing with @f$\Delta\lambda = (\lambda_{\max} - | ||
| /// \lambda_{\min}) / (n - 1)@f$. | ||
| Linear, | ||
| /// Uniform spacing in log space with | ||
| /// @f$\Delta\log\lambda = \log(\lambda_{\max} / \lambda_{\min}) / (n - | ||
| /// 1)@f$. | ||
| Logarithmic, | ||
| /// Eigenvalues are grouped into clusters of width @p cluster_width that are | ||
| /// separated by @f$(\lambda_{\max} - \lambda_{\min}) / (n_{\text{clusters}} | ||
| /// - 1)@f$. | ||
| Clustered, | ||
| /// Same cluster centers as @ref Clustered, but all eigenvalues in a cluster | ||
| /// are identical. | ||
| Degenerate | ||
| }; | ||
|
|
||
| /** @brief Parameters controlling the generation of a symmetric test matrix. | ||
| * | ||
| * The resulting matrix has eigenvalues in | ||
| * @f$[\texttt{min\_eigenvalue}, | ||
| * \texttt{min\_eigenvalue} \times \texttt{condition\_number}]@f$ with the | ||
| * spacing determined by @p spacing. | ||
| */ | ||
| struct SymmetricMatrixSpec { | ||
| /// Dimension of the square matrix. | ||
| std::size_t n = 2; | ||
| /// Ratio of the largest to smallest eigenvalue. | ||
| double condition_number = 10.0; | ||
| /// Smallest eigenvalue in the spectrum. | ||
| double min_eigenvalue = 1.0; | ||
| /// Strategy used to distribute eigenvalues between the endpoints. | ||
| EigenvalueSpacing spacing = EigenvalueSpacing::Linear; | ||
| /// Number of eigenvalue clusters when @p spacing is @ref Clustered or | ||
| /// @ref Degenerate. | ||
| std::size_t n_clusters = 1; | ||
| /// Half-width of each cluster when @p spacing is @ref Clustered. | ||
| double cluster_width = 1e-6; | ||
| /// Seed for random number generation. A value of zero selects a | ||
| /// non-deterministic seed. | ||
| std::uint64_t seed = 42; | ||
| }; | ||
|
|
||
| /** @brief Creates a Mersenne Twister RNG from @p seed. | ||
| * | ||
| * @param[in] seed The seed value. When zero, a seed is drawn from | ||
| * `std::random_device`. | ||
| * | ||
| * @return A `std::mt19937` generator initialized with @p seed. | ||
| */ | ||
| inline std::mt19937 make_rng(std::uint64_t seed) { | ||
| if(seed == 0) { | ||
| std::random_device rd; | ||
| return std::mt19937(rd()); | ||
| } | ||
| return std::mt19937(static_cast<std::mt19937::result_type>(seed)); | ||
| } | ||
|
|
||
| /** @brief Validates that @p n is an allowed matrix dimension. | ||
| * | ||
| * @param[in] n The dimension to validate. | ||
| * | ||
| * @throw std::invalid_argument if @p n is not in `[1, kMaxMatrixDim]`. | ||
| */ | ||
| inline void require_valid_n(std::size_t n) { | ||
| if(n < 1 || n > kMaxMatrixDim) { | ||
| throw std::invalid_argument("n must be in [1, kMaxMatrixDim]"); | ||
| } | ||
| } | ||
|
|
||
| } // namespace tensorwrapper::generate | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| /* | ||
| * Copyright 2026 NWChemEx-Project | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| #pragma once | ||
| #include <cstddef> | ||
| #include <tensorwrapper/generate/generate_utils.hpp> | ||
| #include <tensorwrapper/utilities/diagonal_matrix.hpp> | ||
| #include <tensorwrapper/utilities/make_tensor.hpp> | ||
| #include <vector> | ||
|
|
||
| namespace tensorwrapper::generate { | ||
|
|
||
| /** @brief Creates an @p n x @p n identity matrix. | ||
| * | ||
| * @param[in] n Matrix dimension. Must be in `[1, kMaxMatrixDim]`. | ||
| * | ||
| * @return A rank-2 tensor with ones on the diagonal and zeros elsewhere. | ||
| * | ||
| * @throw std::invalid_argument if @p n is outside the allowed range. | ||
| */ | ||
| inline Tensor identity_matrix(std::size_t n) { | ||
| require_valid_n(n); | ||
| std::vector<double> values(n, 1.0); | ||
| auto values_tensor = utilities::make_tensor({n}, values); | ||
| return utilities::diagonal_matrix(values_tensor); | ||
| } | ||
|
|
||
| } // namespace tensorwrapper::generate |
37 changes: 37 additions & 0 deletions
37
include/tensorwrapper/generate/random_orthogonal_matrix.hpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| /* | ||
| * Copyright 2026 NWChemEx-Project | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| #pragma once | ||
| #include <random> | ||
| #include <tensorwrapper/tensor/tensor.hpp> | ||
|
|
||
| namespace tensorwrapper::generate { | ||
|
|
||
| /** @brief Creates a random @p n x @p n orthogonal matrix. | ||
| * | ||
| * Draws entries from a standard normal distribution and applies Householder QR | ||
| * factorization to obtain an orthogonal matrix @f$Q@f$. | ||
| * | ||
| * @param[in] n Matrix dimension. Must be in `[1, kMaxMatrixDim]`. | ||
| * @param[in,out] gen Random number generator used for the normal draws. | ||
| * | ||
| * @return A rank-2 tensor whose columns form an orthonormal basis. | ||
| * | ||
| * @throw std::invalid_argument if @p n is outside the allowed range. | ||
| */ | ||
| Tensor random_orthogonal_matrix(std::size_t n, std::mt19937& gen); | ||
|
ryanmrichard marked this conversation as resolved.
|
||
|
|
||
| } // namespace tensorwrapper::generate | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.