<commit_before>#include "../kontsevich_graph_series.hpp"
#include "../kontsevich_graph_operator.hpp"
#include "../util/partitions.hpp"
#include "../util/factorial.hpp"
#include <ginac/ginac.h>
#include <iostream>
#include <vector>
#include <fstream>
#include <limits>
using namespace std;
using namespace GiNaC;

size_t order = 4;

int main()
{
    map< size_t, set<KontsevichGraph> > relevants;
    map<KontsevichGraph, ex> weights;
    cout << "Reading in known graphs and their weights...";
    ifstream weights_file("data/known_weights.txt");
    weights_file.ignore(numeric_limits<streamsize>::max(), '\n'); // ignore first line with column headers
    KontsevichGraph graph;
    int numerator, denominator;
    char slash;
    while (weights_file >> graph >> numerator >> slash >> denominator)
    {
        ex weight = numerator/(ex)denominator;
        weights[graph] = weight;
        relevants[graph.internal()].insert(graph);
    }
    cout << " done." << endl;
    cout << "Listing relevant graphs (prime, positive differential order, nonzero, modulo mirror images) at order " << order << "...";
    cout.flush();
    relevants[order] = KontsevichGraph::graphs(order, 2, true, true,
                    [](KontsevichGraph g) -> bool
                    {
                        return g.positive_differential_order() && g.is_prime() && !g.is_zero();
                    });
    cout << " done." << endl;
    cout << "Making a table of primes and weights...";
    map< size_t, vector<KontsevichGraph> > primes;
    size_t weight_count = 0;
    for (size_t n = 1; n <= order; ++n)
    {
        primes[n].reserve(2*relevants[n].size());
        for (KontsevichGraph g : relevants[n])
        {
            if (n == order)
                weights[g] = symbol("w_" + to_string(weight_count++));
            primes[n].push_back(g);
            KontsevichGraph mirror = g.mirror_image();
            if (g.abs() != mirror.abs())
            {
                weights[mirror] = weights[g];
                if (n % 2 == 1)
                    weights[mirror] *= -1;
                primes[n].push_back(mirror);
            }
        }
    }
    cout << " done." << endl;
    cout << "Constructing star product at order";
    KontsevichGraphSeries<ex> star_product;
    star_product[0] = KontsevichGraphSum<ex> { { 1, KontsevichGraph(0, 2, {}) } };
    for (size_t n = 1; n <= order; ++n)
    {
        cout << " " << n << ",";
        cout.flush();
        ex major_coeff = 1/(ex)factorial(n);
        Partitions partitions(n);
        for (auto partition = partitions.begin(); partition != partitions.end(); ++partition)
        {
            // count multiplicities of parts
            std::map<size_t, std::vector<size_t> > multiplicity;
            for (size_t i = 0; i != (*partition).size(); ++i)
                multiplicity[(*partition)[i]].push_back(i);
            // ignore multiplicity 1
            for (auto part : *partition)
                if (multiplicity[part].size() == 1)
                    multiplicity.erase(part);

            std::vector<size_t> prime_sizes((*partition).size());
            for (size_t i = 0; i != (*partition).size(); ++i)
                prime_sizes[i] = primes[(*partition)[i]].size();
            CartesianProduct decompositions(prime_sizes);
            for (auto decomposition = decompositions.begin(); decomposition != decompositions.end(); ++decomposition)
            {
                bool accept = true;
                for (auto& part : multiplicity)
                {
                    size_t prev = 0;
                    for (auto& idx : part.second) // when drawing from multiple equal sets
                    {
                        size_t current = (*decomposition)[idx];
                        if (current < prev) // accept only non-decreasing indices, to avoid duplicates
                            accept = false;
                        prev = current;
                    }
                }
                if (!accept)
                    continue;

                KontsevichGraph composite(0, 2, {});
                ex coeff = major_coeff;
                for (size_t i = 0; i != (*partition).size(); ++i)
                {
                    composite *= primes[(*partition)[i]][(*decomposition)[i]];
                    coeff *= weights[primes[(*partition)[i]][(*decomposition)[i]]];
                }
                coeff *= composite.multiplicity();
                star_product[n] += KontsevichGraphSum<ex>({ { coeff, composite} });
            }
        }
        // TODO: n is not yet considered a partition of n, so treat it separately for now:
        for (KontsevichGraph prime : primes[n])
        {
            star_product[n] += KontsevichGraphSum<ex>({ { major_coeff * weights[prime] * prime.multiplicity(), prime } });
        }
    }
    cout << " done:" << endl;
    cout << star_product << "\n";
    cout << "Number of terms in star product:\n";
    for (size_t n = 0; n <= order; ++n)
    {
        cout << "h^" << n << ": " << star_product[n].size() << " total\n";
        for (std::vector<size_t> indegrees : star_product[n].in_degrees())
        {
            for (size_t j = 0; j != indegrees.size(); ++j)
                cout << indegrees[j] << " ";
            cout << ": " << star_product[n][indegrees].size() << "\n";
        }
    }
    cout << "Computing associator...";
    cout.flush();
    KontsevichGraphSeries<ex> arg = { { 0, { { 1, KontsevichGraph(0, 1, {}) } }} };
    KontsevichGraphSeries<ex> assoc = star_product({ arg, star_product }) - star_product({ star_product, arg });
    cout << endl;
    cout << "Reducing associator...";
    cout.flush();
    assoc.reduce();
    cout << endl;
    cout << "Number of terms in associator:\n";
    for (size_t n = 0; n <= order; ++n)
    {
        cout << "h^" << n << ":\n";
        cout << assoc[n].size() << " total\n";
        for (std::vector<size_t> indegrees : assoc[n].in_degrees())
        {
            for (size_t j = 0; j != indegrees.size(); ++j)
                cout << indegrees[j] << " ";
            cout << ": " << assoc[n][indegrees].size() << "\n";<commit_msg>Change sign in associator to agree with SAGE.<commit_after>#include "../kontsevich_graph_series.hpp"
#include "../kontsevich_graph_operator.hpp"
#include "../util/partitions.hpp"
#include "../util/factorial.hpp"
#include <ginac/ginac.h>
#include <iostream>
#include <vector>
#include <fstream>
#include <limits>
using namespace std;
using namespace GiNaC;

size_t order = 4;

int main()
{
    map< size_t, set<KontsevichGraph> > relevants;
    map<KontsevichGraph, ex> weights;
    cout << "Reading in known graphs and their weights...";
    ifstream weights_file("data/known_weights.txt");
    weights_file.ignore(numeric_limits<streamsize>::max(), '\n'); // ignore first line with column headers
    KontsevichGraph graph;
    int numerator, denominator;
    char slash;
    while (weights_file >> graph >> numerator >> slash >> denominator)
    {
        ex weight = numerator/(ex)denominator;
        weights[graph] = weight;
        relevants[graph.internal()].insert(graph);
    }
    cout << " done." << endl;
    cout << "Listing relevant graphs (prime, positive differential order, nonzero, modulo mirror images) at order " << order << "...";
    cout.flush();
    relevants[order] = KontsevichGraph::graphs(order, 2, true, true,
                    [](KontsevichGraph g) -> bool
                    {
                        return g.positive_differential_order() && g.is_prime() && !g.is_zero();
                    });
    cout << " done." << endl;
    cout << "Making a table of primes and weights...";
    map< size_t, vector<KontsevichGraph> > primes;
    size_t weight_count = 0;
    for (size_t n = 1; n <= order; ++n)
    {
        primes[n].reserve(2*relevants[n].size());
        for (KontsevichGraph g : relevants[n])
        {
            if (n == order)
                weights[g] = symbol("w_" + to_string(weight_count++));
            primes[n].push_back(g);
            KontsevichGraph mirror = g.mirror_image();
            if (g.abs() != mirror.abs())
            {
                weights[mirror] = weights[g];
                if (n % 2 == 1)
                    weights[mirror] *= -1;
                primes[n].push_back(mirror);
            }
        }
    }
    cout << " done." << endl;
    cout << "Constructing star product at order";
    KontsevichGraphSeries<ex> star_product;
    star_product[0] = KontsevichGraphSum<ex> { { 1, KontsevichGraph(0, 2, {}) } };
    for (size_t n = 1; n <= order; ++n)
    {
        cout << " " << n << ",";
        cout.flush();
        ex major_coeff = 1/(ex)factorial(n);
        Partitions partitions(n);
        for (auto partition = partitions.begin(); partition != partitions.end(); ++partition)
        {
            // count multiplicities of parts
            std::map<size_t, std::vector<size_t> > multiplicity;
            for (size_t i = 0; i != (*partition).size(); ++i)
                multiplicity[(*partition)[i]].push_back(i);
            // ignore multiplicity 1
            for (auto part : *partition)
                if (multiplicity[part].size() == 1)
                    multiplicity.erase(part);

            std::vector<size_t> prime_sizes((*partition).size());
            for (size_t i = 0; i != (*partition).size(); ++i)
                prime_sizes[i] = primes[(*partition)[i]].size();
            CartesianProduct decompositions(prime_sizes);
            for (auto decomposition = decompositions.begin(); decomposition != decompositions.end(); ++decomposition)
            {
                bool accept = true;
                for (auto& part : multiplicity)
                {
                    size_t prev = 0;
                    for (auto& idx : part.second) // when drawing from multiple equal sets
                    {
                        size_t current = (*decomposition)[idx];
                        if (current < prev) // accept only non-decreasing indices, to avoid duplicates
                            accept = false;
                        prev = current;
                    }
                }
                if (!accept)
                    continue;

                KontsevichGraph composite(0, 2, {});
                ex coeff = major_coeff;
                for (size_t i = 0; i != (*partition).size(); ++i)
                {
                    composite *= primes[(*partition)[i]][(*decomposition)[i]];
                    coeff *= weights[primes[(*partition)[i]][(*decomposition)[i]]];
                }
                coeff *= composite.multiplicity();
                star_product[n] += KontsevichGraphSum<ex>({ { coeff, composite} });
            }
        }
        // TODO: n is not yet considered a partition of n, so treat it separately for now:
        for (KontsevichGraph prime : primes[n])
        {
            star_product[n] += KontsevichGraphSum<ex>({ { major_coeff * weights[prime] * prime.multiplicity(), prime } });
        }
    }
    cout << " done:" << endl;
    cout << star_product << "\n";
    cout << "Number of terms in star product:\n";
    for (size_t n = 0; n <= order; ++n)
    {
        cout << "h^" << n << ": " << star_product[n].size() << " total\n";
        for (std::vector<size_t> indegrees : star_product[n].in_degrees())
        {
            for (size_t j = 0; j != indegrees.size(); ++j)
                cout << indegrees[j] << " ";
            cout << ": " << star_product[n][indegrees].size() << "\n";
        }
    }
    cout << "Computing associator...";
    cout.flush();
    KontsevichGraphSeries<ex> arg = { { 0, { { 1, KontsevichGraph(0, 1, {}) } }} };
    KontsevichGraphSeries<ex> assoc = star_product({ star_product, arg }) - star_product({ arg, star_product });
    cout << endl;
    cout << "Reducing associator...";
    cout.flush();
    assoc.reduce();
    cout << endl;
    cout << "Number of terms in associator:\n";
    for (size_t n = 0; n <= order; ++n)
    {
        cout << "h^" << n << ":\n";
        cout << assoc[n].size() << " total\n";
        for (std::vector<size_t> indegrees : assoc[n].in_degrees())
        {
            for (size_t j = 0; j != indegrees.size(); ++j)
                cout << indegrees[j] << " ";
            cout << ": " << assoc[n][indegrees].size() << "\n";
{'fraction_non_alphanumeric': 0.15549967553536664, 'fraction_numerical': 0.004866969500324465, 'mean_word_length': 1.926418229290292, 'pattern_counts': {'":': 8, '<': 237, '<?xml version=': 0, '>': 65, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '913988', 'n_tokens_mistral': 3836, 'n_tokens_neox': 3647, 'n_words': 872}