// main.c
// Copyright (C) 2023 Mark Bowron

// Produce header file local_orderings_496.h

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.


#include    <stdio.h>
#include    <stdlib.h>
#include    <inttypes.h>
#include    <stdbool.h>
#include    <string.h>
#include    "set_operators.h"
#include    "set_families.h"
#include    "set_relations.h"
#include    "collapses.h"


int main(int argc, const char * argv[])
{
    FILE       *input;
    uint32_t  **kf_array, *point_closures, set;
    int      ***inequalities;
    int         flag = 0, count = 0, j, k, m, space = 0, spacesize = 10;

// This struct stores KF(A) for all A in X.

    KF         *kf = CreateKF(spacesize);

// The input file contains all spaces up to homeomorphism.

    input = fopen("10-spaces_all_decimal.txt", "r");
    if (input==0)
    {
        printf("\nCould not open spaces file.\n");
        exit(0);
    }

    inequalities = (int ***)malloc(500 * sizeof(int **));
    if (inequalities==0)
    {
        printf("\nCould not allocate space for inequalities.\n");
        exit(0);
    }
    for (j=0; j<500; j++)
    {
        inequalities[j] = (int **)malloc(34 * sizeof(int *));
        if (inequalities[j]==0)
        {
            printf("\nCould not allocate space for inequalities[%d].\n", j);
            exit(0);
        }
        for (k=0; k<34; k++)
        {
            inequalities[j][k] = (int *)malloc(34 * sizeof(int));
            if (inequalities[j][k]==0)
            {
                printf("\nCould not allocate space for inequalities[%d][%d].\n", j, k);
                exit(0);
            }
            for (m=0; m<34; m++) inequalities[j][k][m] = 0;
        }
    }

    kf_array = (uint32_t **)malloc(34 * sizeof(uint32_t *));
    if (kf_array==0)
    {
        printf("\nCould not allocate space for kf_array.\n");
        exit(0);
    }
    for (j=0; j<34; j++)
    {
        kf_array[j] = (uint32_t *)malloc((one<<spacesize) * sizeof(uint32_t));
        if (kf_array[j]==0)
        {
            printf("\nCould not allocate space for kf_array[%d].\n", j);
            exit(0);
        }
        for (k=0; k<(one<<spacesize); k++) kf_array[j][k] = 0;
    }

// Sets are represented by unsigned 32-bit integers with leading zeros.

    point_closures = (uint32_t *)malloc(spacesize * sizeof(uint32_t));
    if (point_closures==0)
    {
        printf("\nCould not allocate space for point_closures.\n");
        exit(0);
    }
    for (j=0; j<spacesize; j++) point_closures[j] = 0;

    while (space < spaces[spacesize])
    {

// This program interprets each line of input as closures of singletons.
// Alternatively, we could interpret each line as smallest open neighborhoods.
// Either interpretation yields all nonhomeomorphic 10-spaces, but any given line
// does not in general produce homeomorphic spaces under the two interpretations.

// Read the current line of input into the point_closures array.

        for (j=0; j<spacesize; j++) fscanf(input, "%" PRIu32, &point_closures[j]);

        ComputeKF(kf,spacesize,point_closures);
        CopyKFarray(kf_array,kf,spacesize);

// Use the local ordering on the empty set to initialize inequalities[count].

        if (!space)
        {
            for (j=0; j<34; j++)
                for (k=0; k<34; k++)
                    if (Subset(kf_array[j][0],kf_array[k][0])) inequalities[count][j][k] = 1;
            count++;
        }

        for (set=1; set<(one<<spacesize); set++)
        {
            for (j=0; j<34; j++)
                for (k=0; k<34; k++)
                    inequalities[count][j][k] = 0;
            for (j=0; j<34; j++)
                for (k=0; k<34; k++)
                    if (Subset(kf_array[j][set],kf_array[k][set])) inequalities[count][j][k] = 1;
            for (m=0; m<count; m++)
            {
                for (j=0; j<34; j++)
                {
                    k = 0;
                    while (k < 34)
                    {
                        if (inequalities[count][j][k] != inequalities[m][j][k]) break;
                        k++;
                    }
                    if (k < 34)
                    {
                        flag = 1;
                        break;
                    }
                }
                if (flag)
                {
                    flag = 0;
                    continue;
                }
                break;  // if we get to here it means the local ordering is not new
            }
            if (m == count) count++;
        }
        space++;
    }

// Print local_orderings_496.h

    printf("// local_orderings_496.h\n");
    printf("// Copyright (C) 2023 Mark Bowron\n\n");
    printf("// All local orderings on the GE monoid.\n\n");
    printf("// This program is free software: you can redistribute it and/or modify\n");
    printf("// it under the terms of the GNU General Public License as published by\n");
    printf("// the Free Software Foundation, either version 3 of the License, or\n");
    printf("// (at your option) any later version.\n\n");
    printf("// This program is distributed in the hope that it will be useful,\n");
    printf("// but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
    printf("// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n");
    printf("// GNU General Public License for more details.\n\n");
    printf("static const int local_orderings_on_kf[496][34][34] = {\n");

    j = 0;
    while (j<count)
    {
        printf("{");
        for (k=0; k<33; k++)
        {
            printf("{");
            for (m=0; m<33; m++) printf("%d,", inequalities[j][k][m]);
            printf("%d},", inequalities[j][k][33]);
        }
        printf("{");
        for (m=0; m<33; m++) printf("%d,", inequalities[j][33][m]);
        if (j<count-1) printf("%d}},\n", inequalities[j][33][33]);
        else printf("%d}}};\n\n", inequalities[j][33][33]);
        j++;
    }

    fclose(input);
    free(point_closures);
    for (j=0; j<500; j++)
    {
        for (k=0; k<34; k++) free(inequalities[j][k]);
        free(inequalities[j]);
    }
    free(inequalities);
    for (j=0; j<34; j++) free(kf_array[j]);
    free(kf_array);
    FreeKF(kf);
    printf("\n\n");
    return EXIT_SUCCESS;
}
