Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/cmake.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:
-DSEQUANT_SKIP_LONG_TESTS=${{ matrix.valgrind || matrix.sanitize }}
-DSEQUANT_COMPILE_DOC_EXAMPLES=${{ !matrix.valgrind }}
-DSEQUANT_PYTHON=${{ !matrix.valgrind && !matrix.sanitize }}
-DSEQUANT_ASSERT_BEHAVIOR=THROW
-DSEQUANT_ASSERT_BEHAVIOR=${{ matrix.valgrind && 'IGNORE' || 'THROW' }}
steps:
- uses: actions/checkout@v6

Expand Down Expand Up @@ -140,4 +140,4 @@ jobs:
if: ${{ matrix.valgrind }}
working-directory: ${{github.workspace}}/build
shell: bash
run: valgrind --error-exitcode=1 --leak-check=full ./tests/unit/unit_tests-sequant
run: valgrind --error-exitcode=1 --leak-check=full ./tests/unit/unit_tests-sequant '~[valgrind_skip]'
37 changes: 29 additions & 8 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,21 @@ add_feature_info(SEQUANT_CONTEXT_MANIPULATION_THREADSAFE SEQUANT_CONTEXT_MANIPUL
# Prerequisites
##########################

# Apple Clang 16 and earlier do not correctly implement P0522R0
# (relaxed matching of template template arguments), which SeQuant requires
if (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" AND
CMAKE_CXX_COMPILER_VERSION VERSION_LESS 17)
message(FATAL_ERROR "SeQuant requires Apple Clang 17 or later (found ${CMAKE_CXX_COMPILER_VERSION}). "
"Upgrade Xcode or use a different compiler (e.g., LLVM Clang from Homebrew).")
endif()

include(CheckCXXFeatures)
if (PROJECT_IS_TOP_LEVEL)
vgkit_check_libcxx_linker_mismatch(MODIFY_GLOBAL_FLAGS)
else()
vgkit_check_libcxx_linker_mismatch()
endif()

if (PROJECT_IS_TOP_LEVEL AND NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
Expand All @@ -189,9 +204,8 @@ if ((${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" AND
set_target_properties(TBB::tbb PROPERTIES IMPORTED_GLOBAL TRUE)
endif (ENABLE_TBB)
endif ()
# check of <execution> header is usable
include(CheckCXXFeatures)
check_cxx_execution_header(SEQUANT)
# check if <execution> header is usable
vgkit_check_cxx_execution_header(SEQUANT)

# Ranges-V3
include(FindOrFetchRangeV3)
Expand Down Expand Up @@ -425,11 +439,14 @@ set(SeQuant_eval_src

# Optimize sources (depends on eval)
set(SeQuant_optimize_src
SeQuant/core/eval/optimize.hpp
SeQuant/core/eval/optimize/common_subexpression_elimination.hpp
SeQuant/core/eval/optimize/fusion.cpp
SeQuant/core/eval/optimize/fusion.hpp
SeQuant/core/eval/optimize/optimize.cpp
SeQuant/core/optimize/common_subexpression_elimination.hpp
SeQuant/core/optimize/fusion.cpp
SeQuant/core/optimize/fusion.hpp
SeQuant/core/optimize/optimize.cpp
SeQuant/core/optimize/optimize.hpp
SeQuant/core/optimize/single_term.hpp
SeQuant/core/optimize/sum.cpp
SeQuant/core/optimize/sum.hpp
)

# Export sources (depends on eval)
Expand Down Expand Up @@ -752,6 +769,9 @@ configure_package_config_file(cmake/sequant-config.cmake.in
PATH_VARS CMAKE_INSTALL_PREFIX SEQUANT_INSTALL_BINDIR
SEQUANT_INSTALL_INCLUDEDIR SEQUANT_INSTALL_LIBDIR
SEQUANT_INSTALL_DOCDIR SEQUANT_INSTALL_CMAKEDIR)
# Copy CheckCXXFeatures.cmake to build dir so sequant-config.cmake can find it
configure_file("${vg_cmake_kit_SOURCE_DIR}/modules/CheckCXXFeatures.cmake"
"${PROJECT_BINARY_DIR}/CheckCXXFeatures.cmake" COPYONLY)

## Install config, version, and target files
install(EXPORT sequant
Expand All @@ -762,6 +782,7 @@ install(EXPORT sequant
install(FILES
"${PROJECT_BINARY_DIR}/sequant-config.cmake"
"${PROJECT_BINARY_DIR}/sequant-config-version.cmake"
"${vg_cmake_kit_SOURCE_DIR}/modules/CheckCXXFeatures.cmake"
DESTINATION "${SEQUANT_INSTALL_CMAKEDIR}"
COMPONENT sequant-config)
add_custom_target_subproject(sequant install-config
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#include <string>
#include <unordered_map>

namespace sequant {
namespace sequant::opt {

namespace cse {

Expand Down Expand Up @@ -382,6 +382,6 @@ void eliminate_common_subexpressions(VectorLike &expr_trees,
replacer.perform_replacements();
}

} // namespace sequant
} // namespace sequant::opt

#endif // SEQUANT_COMMON_SUBEXPRESSION_ELIMINATION_HPP
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include <SeQuant/core/eval/optimize/fusion.hpp>
#include <SeQuant/core/optimize/fusion.hpp>

#include <SeQuant/core/complex.hpp>
#include <SeQuant/core/container.hpp>
Expand Down
File renamed without changes.
108 changes: 108 additions & 0 deletions SeQuant/core/optimize/optimize.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#include <SeQuant/core/binary_node.hpp>
#include <SeQuant/core/complex.hpp>
#include <SeQuant/core/container.hpp>
#include <SeQuant/core/eval/eval_expr.hpp>
#include <SeQuant/core/expr.hpp>
#include <SeQuant/core/hash.hpp>
#include <SeQuant/core/optimize/optimize.hpp>
#include <SeQuant/core/optimize/single_term.hpp>
#include <SeQuant/core/optimize/sum.hpp>
#include <SeQuant/core/utility/indices.hpp>
#include <SeQuant/core/utility/macros.hpp>

#include <range/v3/algorithm/all_of.hpp>
#include <range/v3/iterator/basic_iterator.hpp>
#include <range/v3/range/access.hpp>
#include <range/v3/range/conversion.hpp>
#include <range/v3/view/tail.hpp>
#include <range/v3/view/transform.hpp>
#include <range/v3/view/view.hpp>
Comment thread
evaleev marked this conversation as resolved.

#include <cstddef>
#include <type_traits>
#include <utility>

namespace sequant {

namespace opt {

///
/// \param expr Expression to be optimized.
/// \param idxsz An invocable object that maps an Index object to size.
/// \param reorder_sum If true, the summands are reordered so that terms with
/// common sub-expressions appear closer to each other.
/// \return Optimized expression for lower evaluation cost.
template <typename IdxToSize, typename = std::enable_if_t<std::is_invocable_r_v<
size_t, IdxToSize, const Index&>>>
ExprPtr optimize(ExprPtr const& expr, IdxToSize const& idx2size,
bool reorder_sum) {
using ranges::views::transform;
if (expr->is<Product>()) {
if (ranges::all_of(*expr, [](auto&& x) {
return x->template is<Tensor>() || x->template is<Variable>();
}))
return opt::single_term_opt(expr->as<Product>(), idx2size);
else {
auto const& prod = expr->as<Product>();

container::svector<ExprPtr> non_tensors(prod.size());
container::svector<ExprPtr> new_factors;

for (auto i = 0; i < prod.size(); ++i) {
auto&& f = prod.factor(i);
if (f.is<Tensor>() || f.is<Variable>())
new_factors.emplace_back(f);
else {
non_tensors[i] = f;
auto target_idxs = get_unique_indices(f);
new_factors.emplace_back(
ex<Tensor>(L"I_" + std::to_wstring(i), bra(target_idxs.bra),
ket(target_idxs.ket), aux(target_idxs.aux)));
}
}

auto result = opt::single_term_opt(
Product(prod.scalar(), new_factors, Product::Flatten::No), idx2size);

auto replacer = [&non_tensors](ExprPtr& out) {
if (!out->is<Tensor>()) return;
auto const& tnsr = out->as<Tensor>();
auto&& label = tnsr.label();
if (label.at(0) == L'I' && label.at(1) == L'_') {
size_t suffix = std::stoi(std::wstring(label.data() + 2));
out = non_tensors[suffix].clone();
}
};

result->visit(replacer, /* atoms_only = */ true);
return result;
}
} else if (expr->is<Sum>()) {
auto smands = *expr | transform([&idx2size](auto&& s) {
return optimize(s, idx2size, /* reorder_sum= */ false);
}) | ranges::to_vector;
auto sum = Sum{smands.begin(), smands.end()};
return reorder_sum ? ex<Sum>(opt::reorder(sum)) : ex<Sum>(std::move(sum));
} else
return expr->clone();
}

} // namespace opt

ExprPtr optimize(ExprPtr const& expr, bool reorder_sum) {
return opt::optimize(
expr, [](Index const& ix) { return ix.space().approximate_size(); },
reorder_sum);
}

ResultExpr& optimize(ResultExpr& expr, bool reorder_sum) {
expr.expression() = optimize(expr.expression(), reorder_sum);

return expr;
}

ResultExpr& optimize(ResultExpr&& expr, bool reorder_sum) {
return optimize(expr, reorder_sum);
}

} // namespace sequant
41 changes: 41 additions & 0 deletions SeQuant/core/optimize/optimize.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#ifndef SEQUANT_OPTIMIZE_OPTIMIZE_HPP
#define SEQUANT_OPTIMIZE_OPTIMIZE_HPP

#include <SeQuant/core/expr_fwd.hpp>

namespace sequant {

///
/// Optimize the expression using IndexSpace::approximate_size() for reference
/// index extent.
///
/// \param expr Expression to be optimized.
/// \param reorder_sum If true, the summands are reordered so that terms with
/// common sub-expressions appear closer to each other.
/// True by default.
/// \return Optimized expression for lower evaluation cost.
ExprPtr optimize(ExprPtr const& expr, bool reorder_sum = true);

/// Optimize the expression using IndexSpace::approximate_size() for reference
/// index extent.
///
/// \param expr Expression to be optimized.
/// \param reorder_sum If true, the summands are reordered so that terms with
/// common sub-expressions appear closer to each other.
/// True by default.
/// \return Optimized expression for lower evaluation cost.
ResultExpr& optimize(ResultExpr& expr, bool reorder_sum = true);

/// Optimize the expression using IndexSpace::approximate_size() for reference
/// index extent.
///
/// \param expr Expression to be optimized.
/// \param reorder_sum If true, the summands are reordered so that terms with
/// common sub-expressions appear closer to each other.
/// True by default.
/// \return Optimized expression for lower evaluation cost.
[[nodiscard]] ResultExpr& optimize(ResultExpr&& expr, bool reorder_sum = true);

} // namespace sequant

#endif // SEQUANT_OPTIMIZE_OPTIMIZE_HPP
Loading