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

// Frequencies of the seven GE monoids up to homeomorphism.

// 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   *point_closures;
    int         j, k, monoid, spacesize = 8, space = 0;
    int         monoid_count[8] = {0};
    char      **spacetype;

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

    KZ         *kz = CreateKZ(spacesize);

    spacetype = (char **)malloc(13 * sizeof(char *));
    if (spacetype==0)
    {
        printf("\nCould not allocate space for spacetype.\n");
        exit(0);
    }

    for (j=0; j<8; j++)
    {
        spacetype[j] = (char *)malloc(11 * sizeof(char));
        if (spacetype[j]==0)
        {
            printf("\nCould not allocate space for spacetype[%d].\n", j);
            exit(0);
        }
        for (k=0; k<11; k++) spacetype[j][k] = 0;
    }

    strcpy(spacetype[1],"D");
    strcpy(spacetype[2],"P");
    strcpy(spacetype[3],"EO");
    strcpy(spacetype[4],"ED");
    strcpy(spacetype[5],"OU");
    strcpy(spacetype[6],"GE");
    strcpy(spacetype[7],"KD");

// Open the input file.

    switch (spacesize)
    {
        case 3:
            input = fopen("3-spaces.txt", "r");
            if (input==0)
            {
                printf("\nCould not open file 3-spaces.txt for input.\n");
                exit(0);
            }
            break;
        case 4:
            input = fopen("4-spaces.txt", "r");
            if (input==0)
            {
                printf("\nCould not open file 4-spaces.txt for input.\n");
                exit(0);
            }
            break;
        case 5:
            input = fopen("5-spaces.txt", "r");
            if (input==0)
            {
                printf("\nCould not open file 5-spaces.txt for input.\n");
                exit(0);
            }
            break;
        case 6:
            input = fopen("6-spaces.txt", "r");
            if (input==0)
            {
                printf("\nCould not open file 6-spaces.txt for input.\n");
                exit(0);
            }
            break;
        case 7:
            input = fopen("7-spaces.txt", "r");
            if (input==0)
            {
                printf("\nCould not open file 7-spaces.txt for input.\n");
                exit(0);
            }
            break;
        case 8:
            input = fopen("8-spaces.txt", "r");
            if (input==0)
            {
                printf("\nCould not open file 8-spaces.txt for input.\n");
                exit(0);
            }
            break;
        default:
            printf("\nError: input file not found.\n\n");
            exit(0);
    }

// Sets are represented by unsigned 32-bit binary integers with leading zeros.
// Assuming X = {0,1,...,n-1} the element k is in A iff the coefficient of 2^k in the
// binary integer representing A is 1 (i.e., the bits of the binary integer representing
// A are in reverse order compared to X).

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

    while (space < spaces[spacesize])
    {

// Each line of input has the closure of every singleton.  These can alternatively be
// regarded as smallest open neighborhoods.  Either interpretation yields all
// nonhomeomorphic spaces of cardinality = spacesize, but any given line does not
// in general produce the same space under the two.

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

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

// Compute KZ(A) for all A in X, find the GE monoid, increment the count, then repeat.

        ComputeKZ(kz,spacesize,point_closures);
        monoid = GE(kz,spacesize,point_closures);
        monoid_count[monoid]++;
        space++;                    // Advances the loop counter.
    }

// Print the counts.

    printf("\nSpace type counts:\n");
    for (j=1; j<8; j++) printf("\n%s:\t%d", spacetype[j], monoid_count[j]);
    printf("\n\n");

    fclose(input);
    for (j=0; j<8; j++) free(spacetype[j]);
    free(spacetype);
    free(point_closures);
    FreeKZ(kz);
}
