#ifndef OPMIN_META_H #define OPMIN_META_H #ifndef FASTOR_DONT_PERFORM_OP_MIN #include "tensor_meta.h" #include "einsum_meta.h" namespace Fastor { // Cost model for by-pair tensor contraction //------------------------------------------------------------------------------------------------------------// template struct pair_flop_cost; template struct pair_flop_cost,Index,Tensor,Tensor,std_ext::index_sequence> { static constexpr size_t ind0[sizeof...(Idx0)] = {Idx0... }; static constexpr size_t ind1[sizeof...(Idx1)] = {Idx1... }; static constexpr int nums1[sizeof...(Rest1)] = {Rest1... }; static constexpr size_t cost_tensor0 = pack_prod::value; static constexpr size_t remaining_cost = pack_prod::value; static constexpr size_t value = cost_tensor0*remaining_cost; using resulting_tensor = typename get_resuling_tensor,Index, Tensor,Tensor>::type; using resulting_index = typename get_resuling_index,Index, Tensor,Tensor>::type; }; template struct pair_flop_cost,Index<>,Tensor,Tensor,std_ext::index_sequence> { static constexpr size_t value = pack_prod::value; }; template struct pair_flop_cost,Index,Tensor,Tensor,std_ext::index_sequence> { static constexpr size_t value = pack_prod::value; }; template struct pair_flop_cost,Index<>,Tensor,Tensor,std_ext::index_sequence> { static constexpr size_t value = 1; }; //------------------------------------------------------------------------------------------------------------// // Cost of triplet tensor contraction (single evaluation) //------------------------------------------------------------------------------------------------------------// template struct single_evaluation_triplet_cost; template struct single_evaluation_triplet_cost,Index,Index, Tensor,Tensor,Tensor> { using concat_tensor_01 = typename no_of_loops_to_set,Index,Tensor,Tensor, typename std_ext::make_index_sequence::value>::type>::type; using concat_index_01 = typename no_of_loops_to_set,Index,Tensor,Tensor, typename std_ext::make_index_sequence::value>::type>::indices; static constexpr size_t value = pair_flop_cost,concat_tensor_01,Tensor, typename std_ext::make_index_sequence::type>::value; }; //------------------------------------------------------------------------------------------------------------// // Cost model for triplet tensor network contraction //------------------------------------------------------------------------------------------------------------// template struct triplet_flop_cost; template struct triplet_flop_cost,Index,Index, Tensor,Tensor,Tensor> { // Perform depth-first search //--------------------------------------------------------------------- // first two tensors contracted first using resulting_tensor_0 = typename get_resuling_tensor,Index, Tensor,Tensor>::type; using resulting_index_0 = typename get_resuling_index,Index, Tensor,Tensor>::type; static constexpr size_t flop_count_01_0 = pair_flop_cost,Index,Tensor,Tensor, typename std_ext::make_index_sequence::type>::value; static constexpr size_t flop_count_01_1 = pair_flop_cost,resulting_tensor_0,Tensor, typename std_ext::make_index_sequence::type>::value; static constexpr size_t flop_count_01 = flop_count_01_0 + flop_count_01_1; // first and last tensors contracted first using resulting_tensor_1 = typename get_resuling_tensor,Index, Tensor,Tensor>::type; using resulting_index_1 = typename get_resuling_index,Index, Tensor,Tensor>::type; static constexpr size_t flop_count_02_0 = pair_flop_cost,Index,Tensor,Tensor, typename std_ext::make_index_sequence::type>::value; static constexpr size_t flop_count_02_1 = pair_flop_cost,resulting_tensor_1,Tensor, typename std_ext::make_index_sequence::type>::value; static constexpr size_t flop_count_02 = flop_count_02_0 + flop_count_02_1; // second and last tensors contracted first using resulting_tensor_2 = typename get_resuling_tensor,Index, Tensor,Tensor>::type; using resulting_index_2 = typename get_resuling_index,Index, Tensor,Tensor>::type; static constexpr size_t flop_count_12_0 = pair_flop_cost,Index,Tensor,Tensor, typename std_ext::make_index_sequence::type>::value; static constexpr size_t flop_count_12_1 = pair_flop_cost,resulting_tensor_2,Tensor, typename std_ext::make_index_sequence::type>::value; static constexpr size_t flop_count_12 = flop_count_12_0 + flop_count_12_1; static constexpr size_t flop_count_012 = single_evaluation_triplet_cost,Index,Index, Tensor,Tensor,Tensor>::value; static constexpr size_t min_cost = meta_min::value; static constexpr int which_variant = meta_argmin::value; // this is the overall resulting tensor and index from overall triplet contraction using resulting_tensor = typename std::conditional< which_variant==0, typename get_resuling_tensor,resulting_tensor_0,Tensor>::type, typename std::conditional< which_variant==1, typename get_resuling_tensor,resulting_index_1,Tensor,resulting_tensor_1>::type, typename get_resuling_tensor,resulting_index_2,Tensor,resulting_tensor_2>::type >::type >::type; using resulting_index = typename std::conditional< which_variant==0, typename get_resuling_index,resulting_tensor_0,Tensor>::type, typename std::conditional< which_variant==1, typename get_resuling_index,resulting_index_1,Tensor,resulting_tensor_1>::type, typename get_resuling_index,resulting_index_2,Tensor,resulting_tensor_2>::type >::type >::type; }; //------------------------------------------------------------------------------------------------------------// // Cost model for quartet tensor network contraction //------------------------------------------------------------------------------------------------------------// template struct quartet_flop_cost; template struct quartet_flop_cost,Index,Index,Index, Tensor,Tensor,Tensor,Tensor> { // Perform depth-first search //--------------------------------------------------------------------- // first three tensors contracted first using triplet_cost_012 = triplet_flop_cost,Index,Index, Tensor,Tensor,Tensor>; using resulting_tensor_0 = typename triplet_cost_012::resulting_tensor; using resulting_index_0 = typename triplet_cost_012::resulting_index; static constexpr size_t flop_count_012 = triplet_cost_012::min_cost; static constexpr size_t flop_count_012_3 = pair_flop_cost,resulting_tensor_0,Tensor, typename std_ext::make_index_sequence::type>::value; static constexpr size_t flop_count_0 = flop_count_012 + flop_count_012_3; // first, second and last tensors contracted first using triplet_cost_013 = triplet_flop_cost,Index,Index, Tensor,Tensor,Tensor>; using resulting_tensor_1 = typename triplet_cost_013::resulting_tensor; using resulting_index_1 = typename triplet_cost_013::resulting_index; static constexpr size_t flop_count_013 = triplet_cost_013::min_cost; static constexpr size_t flop_count_013_2 = pair_flop_cost,resulting_tensor_1,Tensor, typename std_ext::make_index_sequence::type>::value; static constexpr size_t flop_count_1 = flop_count_013 + flop_count_013_2; // first, third and last tensors contracted first using triplet_cost_023 = triplet_flop_cost,Index,Index, Tensor,Tensor,Tensor>; using resulting_tensor_2 = typename triplet_cost_023::resulting_tensor; using resulting_index_2 = typename triplet_cost_023::resulting_index; static constexpr size_t flop_count_023 = triplet_cost_023::min_cost; static constexpr size_t flop_count_023_1 = pair_flop_cost,resulting_tensor_2,Tensor, typename std_ext::make_index_sequence::type>::value; static constexpr size_t flop_count_2 = flop_count_023 + flop_count_023_1; // last three tensors contracted first using triplet_cost_123 = triplet_flop_cost,Index,Index, Tensor,Tensor,Tensor>; using resulting_tensor_3 = typename triplet_cost_123::resulting_tensor; using resulting_index_3 = typename triplet_cost_123::resulting_index; static constexpr size_t flop_count_123 = triplet_cost_123::min_cost; static constexpr size_t flop_count_123_0 = pair_flop_cost,resulting_tensor_3,Tensor, typename std_ext::make_index_sequence::type>::value; static constexpr size_t flop_count_3 = flop_count_123 + flop_count_123_0; static constexpr size_t min_cost = meta_min::value; static constexpr int which_variant = meta_argmin::value; // this is the overall resulting tensor and index from overall quartet contraction using resulting_tensor = typename std::conditional< which_variant==0, typename get_resuling_tensor,resulting_tensor_0,Tensor>::type, typename std::conditional< which_variant==1, typename get_resuling_tensor,resulting_index_1,Tensor,resulting_tensor_1>::type, typename std::conditional< which_variant==2, typename get_resuling_tensor,resulting_index_2,Tensor,resulting_tensor_2>::type, typename get_resuling_tensor,resulting_index_3,Tensor,resulting_tensor_3>::type >::type >::type >::type; using resulting_index = typename std::conditional< which_variant==0, typename get_resuling_index,resulting_tensor_0,Tensor>::type, typename std::conditional< which_variant==1, typename get_resuling_index,resulting_index_1,Tensor,resulting_tensor_1>::type, typename std::conditional< which_variant==2, typename get_resuling_index,resulting_index_2,Tensor,resulting_tensor_2>::type, typename get_resuling_index,resulting_index_3,Tensor,resulting_tensor_3>::type >::type >::type >::type; }; //------------------------------------------------------------------------------------------------------------// // Cost model for quintet tensor contraction //------------------------------------------------------------------------------------------------------------// template struct quintet_flop_cost; template struct quintet_flop_cost,Index,Index,Index, Index, Tensor,Tensor,Tensor,Tensor,Tensor> { // Perform depth-first search //--------------------------------------------------------------------- // first four tensors contracted first using quartet_cost_0123 = quartet_flop_cost,Index,Index,Index, Tensor,Tensor,Tensor,Tensor>; using resulting_tensor_0 = typename quartet_cost_0123::resulting_tensor; using resulting_index_0 = typename quartet_cost_0123::resulting_index; static constexpr size_t flop_count_0123 = quartet_cost_0123::min_cost; static constexpr size_t flop_count_0123_4 = pair_flop_cost,resulting_tensor_0,Tensor, typename std_ext::make_index_sequence::type>::value; static constexpr size_t flop_count_0 = flop_count_0123 + flop_count_0123_4; // 1st, 2nd, 3rd, 5th tensors contracted first using quartet_cost_0124 = quartet_flop_cost,Index,Index,Index, Tensor,Tensor,Tensor,Tensor>; using resulting_tensor_1 = typename quartet_cost_0124::resulting_tensor; using resulting_index_1 = typename quartet_cost_0124::resulting_index; static constexpr size_t flop_count_0124 = quartet_cost_0124::min_cost; static constexpr size_t flop_count_0124_3 = pair_flop_cost,resulting_tensor_1,Tensor, typename std_ext::make_index_sequence::type>::value; static constexpr size_t flop_count_1 = flop_count_0124 + flop_count_0124_3; // 1st, 2nd, 4th, 5th tensors contracted first using quartet_cost_0134 = quartet_flop_cost,Index,Index,Index, Tensor,Tensor,Tensor,Tensor>; using resulting_tensor_2 = typename quartet_cost_0134::resulting_tensor; using resulting_index_2 = typename quartet_cost_0134::resulting_index; static constexpr size_t flop_count_0134 = quartet_cost_0134::min_cost; static constexpr size_t flop_count_0134_2 = pair_flop_cost,resulting_tensor_2,Tensor, typename std_ext::make_index_sequence::type>::value; static constexpr size_t flop_count_2 = flop_count_0134 + flop_count_0134_2; // 1st, 3rd, 4th, 5th tensors contracted first using quartet_cost_0234 = quartet_flop_cost,Index,Index,Index, Tensor,Tensor,Tensor,Tensor>; using resulting_tensor_3 = typename quartet_cost_0234::resulting_tensor; using resulting_index_3 = typename quartet_cost_0234::resulting_index; static constexpr size_t flop_count_0234 = quartet_cost_0234::min_cost; static constexpr size_t flop_count_0234_1 = pair_flop_cost,resulting_tensor_3,Tensor, typename std_ext::make_index_sequence::type>::value; static constexpr size_t flop_count_3 = flop_count_0234 + flop_count_0234_1; // last four tensors contracted first using quartet_cost_1234 = quartet_flop_cost,Index,Index,Index, Tensor,Tensor,Tensor,Tensor>; using resulting_tensor_4 = typename quartet_cost_1234::resulting_tensor; using resulting_index_4 = typename quartet_cost_1234::resulting_index; static constexpr size_t flop_count_1234 = quartet_cost_1234::min_cost; static constexpr size_t flop_count_1234_0 = pair_flop_cost,resulting_tensor_4,Tensor, typename std_ext::make_index_sequence::type>::value; static constexpr size_t flop_count_4 = flop_count_1234 + flop_count_1234_0; static constexpr size_t min_cost = meta_min::value; static constexpr int which_variant = meta_argmin::value; // this is the overall resulting tensor and index from overall quintet contraction using resulting_tensor = typename std::conditional< which_variant==0, typename get_resuling_tensor,resulting_tensor_0,Tensor>::type, typename std::conditional< which_variant==1, typename get_resuling_tensor,resulting_index_1,Tensor,resulting_tensor_1>::type, typename std::conditional< which_variant==2, typename get_resuling_tensor,resulting_index_2,Tensor,resulting_tensor_2>::type, typename std::conditional< which_variant==3, typename get_resuling_tensor,resulting_index_3,Tensor,resulting_tensor_3>::type, typename get_resuling_tensor,resulting_index_4,Tensor,resulting_tensor_4>::type >::type >::type >::type >::type; using resulting_index = typename std::conditional< which_variant==0, typename get_resuling_index,resulting_tensor_0,Tensor>::type, typename std::conditional< which_variant==1, typename get_resuling_index,resulting_index_1,Tensor,resulting_tensor_1>::type, typename std::conditional< which_variant==2, typename get_resuling_index,resulting_index_2,Tensor,resulting_tensor_2>::type, typename std::conditional< which_variant==3, typename get_resuling_index,resulting_index_3,Tensor,resulting_tensor_3>::type, typename get_resuling_index,resulting_index_4,Tensor,resulting_tensor_4>::type >::type >::type >::type >::type; }; //------------------------------------------------------------------------------------------------------------// // Cost model for sixtet tensor contraction //------------------------------------------------------------------------------------------------------------// template struct sixtet_flop_cost; template struct sixtet_flop_cost,Index,Index,Index, Index, Index, Tensor,Tensor,Tensor,Tensor,Tensor,Tensor> { // Perform depth-first search //--------------------------------------------------------------------- // first 5 tensors contracted first using quintet_cost_01234 = quintet_flop_cost,Index,Index,Index,Index, Tensor,Tensor,Tensor,Tensor,Tensor>; using resulting_tensor_0 = typename quintet_cost_01234::resulting_tensor; using resulting_index_0 = typename quintet_cost_01234::resulting_index; static constexpr size_t flop_count_01234 = quintet_cost_01234::min_cost; static constexpr size_t flop_count_01234_5 = pair_flop_cost,resulting_tensor_0,Tensor, typename std_ext::make_index_sequence::type>::value; static constexpr size_t flop_count_0 = flop_count_01234 + flop_count_01234_5; // 1st, 2nd, 3rd, 4th, 6th tensors contracted first using quintet_cost_01235 = quintet_flop_cost,Index,Index,Index,Index, Tensor,Tensor,Tensor,Tensor,Tensor>; using resulting_tensor_1 = typename quintet_cost_01235::resulting_tensor; using resulting_index_1 = typename quintet_cost_01235::resulting_index; static constexpr size_t flop_count_01235 = quintet_cost_01235::min_cost; static constexpr size_t flop_count_01235_4 = pair_flop_cost,resulting_tensor_1,Tensor, typename std_ext::make_index_sequence::type>::value; static constexpr size_t flop_count_1 = flop_count_01235 + flop_count_01235_4; // 1st, 2nd, 3rd, 5th, 6th tensors contracted first using quintet_cost_01245 = quintet_flop_cost,Index,Index,Index,Index, Tensor,Tensor,Tensor,Tensor,Tensor>; using resulting_tensor_2 = typename quintet_cost_01245::resulting_tensor; using resulting_index_2 = typename quintet_cost_01245::resulting_index; static constexpr size_t flop_count_01245 = quintet_cost_01235::min_cost; static constexpr size_t flop_count_01245_3 = pair_flop_cost,resulting_tensor_2,Tensor, typename std_ext::make_index_sequence::type>::value; static constexpr size_t flop_count_2 = flop_count_01245 + flop_count_01245_3; // 1st, 2nd, 4th, 5th, 6th tensors contracted first using quintet_cost_01345 = quintet_flop_cost,Index,Index,Index,Index, Tensor,Tensor,Tensor,Tensor,Tensor>; using resulting_tensor_3 = typename quintet_cost_01345::resulting_tensor; using resulting_index_3 = typename quintet_cost_01345::resulting_index; static constexpr size_t flop_count_01345 = quintet_cost_01235::min_cost; static constexpr size_t flop_count_01345_2 = pair_flop_cost,resulting_tensor_3,Tensor, typename std_ext::make_index_sequence::type>::value; static constexpr size_t flop_count_3 = flop_count_01345 + flop_count_01345_2; // 1st, 3rd, 4th, 5th, 6th tensors contracted first using quintet_cost_02345 = quintet_flop_cost,Index,Index,Index,Index, Tensor,Tensor,Tensor,Tensor,Tensor>; using resulting_tensor_4 = typename quintet_cost_02345::resulting_tensor; using resulting_index_4 = typename quintet_cost_02345::resulting_index; static constexpr size_t flop_count_02345 = quintet_cost_01235::min_cost; static constexpr size_t flop_count_02345_1 = pair_flop_cost,resulting_tensor_4,Tensor, typename std_ext::make_index_sequence::type>::value; static constexpr size_t flop_count_4 = flop_count_02345 + flop_count_02345_1; // last 5 tensors contracted first using quintet_cost_12345 = quintet_flop_cost,Index,Index,Index,Index, Tensor,Tensor,Tensor,Tensor,Tensor>; using resulting_tensor_5 = typename quintet_cost_12345::resulting_tensor; using resulting_index_5 = typename quintet_cost_12345::resulting_index; static constexpr size_t flop_count_12345 = quintet_cost_01235::min_cost; static constexpr size_t flop_count_12345_0 = pair_flop_cost,resulting_tensor_5,Tensor, typename std_ext::make_index_sequence::type>::value; static constexpr size_t flop_count_5 = flop_count_12345 + flop_count_12345_0; static constexpr size_t min_cost = meta_min::value; static constexpr int which_variant = meta_argmin::value; // this is the overall resulting tensor and index from overall sextet contraction using resulting_tensor = typename std::conditional< which_variant==0, typename get_resuling_tensor,resulting_tensor_0,Tensor>::type, typename std::conditional< which_variant==1, typename get_resuling_tensor,resulting_index_1,Tensor,resulting_tensor_1>::type, typename std::conditional< which_variant==2, typename get_resuling_tensor,resulting_index_2,Tensor,resulting_tensor_2>::type, typename std::conditional< which_variant==3, typename get_resuling_tensor,resulting_index_3,Tensor,resulting_tensor_3>::type, typename std::conditional< which_variant==4, typename get_resuling_tensor,resulting_index_4,Tensor,resulting_tensor_4>::type, typename get_resuling_tensor,resulting_index_5,Tensor,resulting_tensor_5>::type >::type >::type >::type >::type >::type; using resulting_index = typename std::conditional< which_variant==0, typename get_resuling_index,resulting_tensor_0,Tensor>::type, typename std::conditional< which_variant==1, typename get_resuling_index,resulting_index_1,Tensor,resulting_tensor_1>::type, typename std::conditional< which_variant==2, typename get_resuling_index,resulting_index_2,Tensor,resulting_tensor_2>::type, typename std::conditional< which_variant==3, typename get_resuling_index,resulting_index_3,Tensor,resulting_tensor_3>::type, typename std::conditional< which_variant==4, typename get_resuling_index,resulting_index_4,Tensor,resulting_tensor_4>::type, typename get_resuling_index,resulting_index_5,Tensor,resulting_tensor_5>::type >::type >::type >::type >::type >::type; }; //------------------------------------------------------------------------------------------------------------// // einsum helper to extract the resulting index and the resulting tensor //------------------------------------------------------------------------------------------------------------// template struct einsum_helper; template struct einsum_helper> { using resulting_index = typename contraction_impl, typename std_ext::make_index_sequence::type>::indices; using resulting_tensor = typename contraction_impl, typename std_ext::make_index_sequence::type>::type; }; template struct einsum_helper { using resulting_index = typename get_resuling_index::type; using resulting_tensor = typename get_resuling_tensor::type; }; template struct einsum_helper { using cost_model = triplet_flop_cost; using resulting_index = typename cost_model::resulting_index; using resulting_tensor = typename cost_model::resulting_tensor; }; template struct einsum_helper { using cost_model = quartet_flop_cost; using resulting_index = typename cost_model::resulting_index; using resulting_tensor = typename cost_model::resulting_tensor; }; template struct einsum_helper { using cost_model = quintet_flop_cost; using resulting_index = typename cost_model::resulting_index; using resulting_tensor = typename cost_model::resulting_tensor; }; template struct einsum_helper { using cost_model = sixtet_flop_cost; using resulting_index = typename cost_model::resulting_index; using resulting_tensor = typename cost_model::resulting_tensor; }; //------------------------------------------------------------------------------------------------------------// } // end of namespace Fastor #endif // FASTOR_DONT_PERFORM_OP_MIN #endif // OPMIN_META_H