Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
ansumanbanerjee
@ansumanbanerjee
I have downloaded mpp, however, when I try cmake --build . I face the error "Could not load cache"
I am unable to proceed further
Please help
Andrew Corrigan
@andrewcorrigan

Couldn't find a chat room, for questions about Obake. Asking here:
Is checking for a monomial that is 1 best accomplished via:

   return m.get_value() == 0;

Or is this using internal implementation details and subject to break?

More generally, could you please offer some pointers on accessing the symbols and exponents of a monomial in Obake? With your help, in Piranha, I accessed a monomial (as a polynomial):

const auto& container = polynomial._container();
const auto& args = polynomial.get_symbol_set();
const auto& monomial = container.begin()->m_key;

for(auto i : range(monomial.size()))
{
    std::cout << "exponent = " << monomial[i] << std::endl;
    std::cout << "symbol = " << args[i].get_name() << std::endl;
}

What would the equivalent be in Obake directly on the monomial type (since the monomials of a polynomial are monomials in Obake)?

Francesco Biscani
@bluescarni

obake has a specialised primitive for detecting monomials which are equivalent to one. It is called key_is_one() and you can see some examples of its usage here:

https://github.com/bluescarni/obake/blob/master/test/polynomials_d_packed_monomial_00.cpp#L229

Like all monomial-related primitives, you need to pass also the symbol set as last argument. E.g.,

using monomial_t = packed_monomial<unsigned long>;

symbol_set s{"x", "y", "z"};

monomial_t m{0, 0, 0};

assert(key_is_one(m, s));
Regarding the second question, you can access polynomial terms in obake as-if an obake polynomial was a dictionary in which the keys are the monomials and the values are the coefficients. I.e., you can iterate over the polynomial terms like this (assuming p is a polynomial object):
for (const auto &[m, cf] : p) {
   // In here "m" is a const reference to the monomial,
   // "cf" a const reference to its coefficient.
}
Francesco Biscani
@bluescarni
At the moment there is no unified API (i.e., an API valid for all monomial classes) to access the exponents of a monomial (I plan to add it). This means that currently the only way of extracting the exponents is to invoke functions which are specific to the monomial type in use. For instance, in case of packed_monomial, you need first to extract the packed exponents via the get_value() member function, and then you can unpack this value using facilities from the k_packing.hpp header.
For instance:
using monomial_t = packed_monomial<unsigned long>;

monomial_t m{1, 2, 3};

k_unpacker<unsigned long> ku(m.get_value(), 3);
unsigned long tmp;
ku >> tmp;
std::cout << "The first exponent is: " << tmp << '\n';
ku >> tmp;
std::cout << "The second exponent is: " << tmp << '\n';
ku >> tmp;
std::cout << "The third exponent is: " << tmp << '\n';
Andrew Corrigan
@andrewcorrigan
Thank you. In your last example, if I obtain a monomial from a polynomial (like in the range-based for loop above) rather than constructing the monomial and knowing its size a priori (3 in your example), how do I deduce its size, in order to know how much exponents to extract? Would it be the size of p.get_symbol_set()? Does the unpacker report exponents in the same order as p.get_symbol_set()?
Francesco Biscani
@bluescarni
Yes and yes. The API for monomials is supposed to be used in conjunction with the symbol set of the polynomial to which a monomial belongs. This makes it possible to avoid storing directly in the monomial a bunch of information that would be needlessly duplicated across all the monomials of a polynomial.
Andrew Corrigan
@andrewcorrigan
got it, thanks
Francesco Biscani
@bluescarni
sure np
Andrew Corrigan
@andrewcorrigan

In terms of builds, one thing wasn't clear to me: I see that you have a very nice modern CMake build infrastructure for Obake, mp++ and other dependencies. In my projects, I try to include all dependencies in one parent project, and then build them all hierarchically via add_subdirectory. I've been modifying your CMake file as follows:

# mp++.
# NOTE: put the minimum version in a variable
# so that we can re-use it in the config-file package
# machinery below.
#set (_OBAKE_MIN_MPPP_VERSION 0.17)
#find_package(mp++ REQUIRED)
#if(${mp++_VERSION} VERSION_LESS ${_OBAKE_MIN_MPPP_VERSION})
#    message(FATAL_ERROR "The minimum mp++ version required by obake is ${_OBAKE_MIN_MPPP_VERSION}, but version ${mp++_VERSION} was found instead.")
#endif()

add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/mppp")

Is there a way I could have a parent project that includes both Obake and mp++ via add_subdirectory, where I instead leave your Obake CMakeLists.txt unmodified and find_package(mp++ REQUIRED) detects that mp++is being configured/built as part of the same project?

Andrew Corrigan
@andrewcorrigan
if that's just not supported, no problem
Francesco Biscani
@bluescarni
I am not really up to speed with CMake subprojects. The build systems of mp++ and obake are made with installation into a prefix in mind, a-la classical Unix way or even conda. Is the problem here that finding mp++ fails?
Andrew Corrigan
@andrewcorrigan
yes. That's fine, since this is not your intended usage, the answer is probably that I should just comment out the find_package lines. No big deal
Francesco Biscani
@bluescarni
Well I was thinking... what find_package() ultimately does is to create an mp++::mp++ imported target. Perhaps you can try to write:
if(NOT TARGET mp++::mp++)
  set (_OBAKE_MIN_MPPP_VERSION 0.17)
  find_package(mp++ REQUIRED)
  if(${mp++_VERSION} VERSION_LESS ${_OBAKE_MIN_MPPP_VERSION})
      message(FATAL_ERROR "The minimum mp++ version required by obake is ${_OBAKE_MIN_MPPP_VERSION}, but version ${mp++_VERSION} was found instead.")
  endif()
endif()
and see what happens?
this assumes that you have already found mp++ somewhere before...
I don't really know how this sort of inclusion of subprojects is properly done in CMake
Andrew Corrigan
@andrewcorrigan
nice
I'll play around with it and see if I can come up with something that supports both approaches
Francesco Biscani
@bluescarni
ok, sounds good
how does it work with the install targets in a subproject though? You just don't use them I presume?
Andrew Corrigan
@andrewcorrigan
I think I commented those out as well
Andrew Corrigan
@andrewcorrigan
would it make sense to support automatic conversion from std::map<std::string, Value> to obake::symbol_map<Value>?
Francesco Biscani
@bluescarni
I try to avoid automatic conversions unless absolutely necessary. You should be able to construct a map from a symbol_set (and vice-versa) using the constructors from ranges though?
Andrew Corrigan
@andrewcorrigan
fyi, on my system the default setting of -Werror for debug builds triggers errors from included TBB headers.
Francesco Biscani
@bluescarni
Can you report the compiler output? I am assuming this is clang on OSX?
Andrew Corrigan
@andrewcorrigan
correct
Andrew Corrigan
@andrewcorrigan
I still owe you the compiler output. To be clear, these are warnings from TBB, not Obake.
Francesco Biscani
@bluescarni
@andrewcorrigan thanks for the report! Today it's a holiday over here, so I won't be able to reply until the evening.
Regarding the compiler output, it might be possible to suppress the tbb warnings with some pragmas
Andrew Corrigan
@andrewcorrigan
I spent some time trying to reproduce the warnings, but haven't been able to. I'm sorry, I'll report back as soon as it happens again. Also, thanks for any help with the issue I raised.
Francesco Biscani
@bluescarni
@andrewcorrigan I managed to squeeze in some debug time in the afternoon. I think the issue you reported is a bug in the polynomial integration function, I have opened a PR with a tentative solution.
Andrew Corrigan
@andrewcorrigan
thanks! looks good
I'm testing my application and a lot of things are working the same as Piranha, however for certain cases, I see errors like the below. Would you have any hints on what to do about this?
# 2 | :0 | decltype(series_default_in_place_addsub_algorithm<true, obake::series<obake::polynomials::packed_monomial<unsigned long long, void>, mppp::rational<1ul>, obake::polynomials::tag, void>&&&, obake::series<obake::polynomials::packed_monomial<unsigned long long, void>, mppp::rational<1ul>, obake::polynomials::tag, void>&&>.second)::type obake::detail::series_default_in_place_addsub_impl<true, obake::series<obake::polynomials::packed_monomial<unsigned long long, void>, mppp::rational<1ul>, obake::polynomials::tag, void>&, obake::series<obake::polynomials::packed_monomial<unsigned long long, void>, mppp::rational<1ul>, obake::polynomials::tag, void> >(obake::series<obake::polynomials::packed_monomial<unsigned long long, void>, mppp::rational<1ul>, obake::polynomials::tag, void>&&&, obake::series<obake::polynomials::packed_monomial<unsigned long long, void>, mppp::rational<1ul>, obake::polynomials::tag, void>&&)
# 1 | :0 | void obake::detail::series_sym_extender<obake::series<obake::polynomials::packed_monomial<unsigned long long, void>, mppp::rational<1ul>, obake::polynomials::tag, void>, obake::series<obake::polynomials::packed_monomial<unsigned long long, void>, mppp::rational<1ul>, obake::polynomials::tag, void>&>(obake::series<obake::polynomials::packed_monomial<unsigned long long, void>, mppp::rational<1ul>, obake::polynomials::tag, void>&, obake::series<obake::polynomials::packed_monomial<unsigned long long, void>, mppp::rational<1ul>, obake::polynomials::tag, void>&&&, boost::container::flat_map<unsigned long, boost::container::flat_set<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, void>, std::__1::less<unsigned long>, void> const&)
# 0 | :0 | obake::polynomials::packed_monomial<unsigned long long, std::__1::enable_if<is_k_packable_v<unsigned long long>, void>::type> obake::polynomials::key_merge_symbols<unsigned long long>(obake::polynomials::packed_monomial<unsigned long long, std::__1::enable_if<is_k_packable_v<unsigned long long>, void>::type> const&, boost::container::flat_map<unsigned long, boost::container::flat_set<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, void>, std::__1::less<unsigned long>, void> const&, boost::container::flat_set<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::less<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >, void> const&)

Exception type   : std::overflow_error
Exception message: Invalid size specified in the constructor of a Kronecker packer for the type 'unsigned long long': the maximum possible size is 21, but a size of 22 was specified instead
Andrew Corrigan
@andrewcorrigan
Would I need d_packed_monomial instead? I'm not clear from the examples what reasonable template arguments would be. If this is the more appropriate data structure, how would I adapt the unpacking code above? Hope you're enjoying the holiday. Any help is appreciated.
Francesco Biscani
@bluescarni
Yes a d_packed_monomial does not have limits in the number of variables it can represent. The first template parameter, T, is the same as in packed_monomial. The second template parameter is the (approximate) number of bits you want to devote to each exponent. So for instance if you use NBits==8 and T an unsigned integral type, then each exponent will have a range of circa [0, 256] (it will be less than that in reality, but same order of magnitude).
A d_packed_monomial is kind of like a vector of packed_monomials
so the packing/unpacking is a bit more complicated
brb
Francesco Biscani
@bluescarni
From a d_packed_monomial, you can access the underlying vector of Ts via the _container() function. You can then proceed to unpack each T value as if it was the value in a packed_monomial. For instance:
using d_type = d_packed_monomial<unsigned long, 8>;
// This is the number of exponents packed in each unsigned long stored in a d_type.
// This is a compile-time constant.
constexpr auto psize = d_type::psize;

// Create a monomial.
d_type d{....};

// Print out all exponents.
for (const auto &n : d._container()) {
  k_unpacker<unsigned long> ku(n, psize);

  unsigned long tmp;
  for (auto j = 0u; j < psize; ++j) {
    ku >> tmp;
    std::cout << tmp << '\n';
  }
}
Note that like this it will print a number of exponents multiple of psize. That is, if psize is 8, then the code above will print either 8, 16, 24, 32, etc... exponents.
Even if in reality the actual number of exponents is not necessarily a multiple of 8.
So in actual code you need a bit more book-keeping on how to stop the inner for loop, but hopefully you get the gist.
Andrew Corrigan
@andrewcorrigan
thank you
where would I get the actual number of exponents from? would the polynomial containing the monomial give me the right size, as was the case with packed_monomial?
Francesco Biscani
@bluescarni
yes exactly. you can see an example of this in the function that computes the degree of a d_packed_monomial:
https://github.com/bluescarni/obake/blob/master/include/obake/polynomials/d_packed_monomial.hpp#L902
Andrew Corrigan
@andrewcorrigan
got it, thanks!