Search code examples
c++mathpolynomial-math

Combinations of n-th degree monomials in C++


So I have to generate a vector of monomials. Here is how I did it for up to 3 dimensions for an arbitrary order:

#include <iostream>
#include <vector>
using namespace std;

int main() {
    int dim = 3; 
    int order = 2;
    std::vector<std::vector<int>> powers;

    for (int ord = 0; ord <= order; ord++) {
        if (dim == 1) {
            powers.push_back({ord});
        } else if (dim == 2) {
            for (int i = 0; i < ord + 1; i++) {
                powers.push_back({i, ord - i});
            }
        } else if (dim == 3) {
            for (int i = 0; i < ord + 1; i++) {
                for (int j = 0; j < ord + 1 - i; j++) {
                    powers.push_back({i, j, ord - i - j});
                }
            }
        } else if (dim == 4){
            for (int i = 0; i < ord + 1; i++) {
                for (int j = 0; j < ord + 1 - i; j++) {
                    for (int k = 0; k < ord + 1 - i - j; k++) {
                        powers.push_back({i, j, k, ord - i - j - k});
                    }
                }
            }
        } else {
            // "Monomials of dimension >= 4 not supported."
        }
    }
    cout << "Finished!" << endl;
    return 0;
}

Now my goal is to support N dimensions and N-th monomials order. Any ideas on how to extend the code above to N dimensional spaces? I don't see an easy way to implement that above. I was thinking about using combinatorics and somehow eliminating the extra terms, but I am not sure about the speed.

EDIT (Expected output): For given input order = 2 and dim = 3 the expected output is (not necessary in that order):

000
001
002
010
011
020
100
101
110
200

for order = 1 and dim = 3:

000
001
010
100

and for order = 2 and dim = 2:

00
01
10
11
02
20

Solution

  • This is a classic recursive function:

    Each time you have to chose the order of the current variable x_1 (lets say i), and then you remain with all the possibilities for monomial with degree ord - i on n -1 variables.

    The (working) code, is as follows:

       std::vector<std::vector<int>> getAllMonomials(int order, int dimension) {
        std::vector<std::vector<int>> to_return;
        if (1 == dimension) {
            for (int i = 0 ; i <= order; i++){
                to_return.push_back({i});
            }
            return to_return;
        }
    
        for (int i = 0 ; i <= order; i++) {
            std::vector<std::vector<int>> all_options_with_this_var_at_degree_i = getAllMonomials(order - i, dimension - 1);
            for (int j = 0; j < all_options_with_this_var_at_degree_i.size(); j++) {
                all_options_with_this_var_at_degree_i.at(j).insert(all_options_with_this_var_at_degree_i.at(j).begin(), i);
            }
            to_return.insert(to_return.end(), all_options_with_this_var_at_degree_i.begin(), all_options_with_this_var_at_degree_i.end());
    
        }
        return to_return;
    }