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

// Find all border psi-numbers.

// 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, set;
    int         j, k, psi, space = 0;
    int       **border_psi;

// The smallest space cardinality that suffices is 8.

    int         spacesize = 8;

// These structs store KFG(A) and KFZ(A) for all A in X.

    KFG        *kfg = CreateKFG(spacesize);
    KFZ        *kfz = CreateKFZ(spacesize);

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

// The input file contains all nonhomeomorphic spaces on 8 points.

    input = fopen("8-spaces.txt", "r");
    if (input==0)
    {
        printf("\nCould not open file 8-spaces.txt.\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 lists the closure of every singleton.  (These integers can
// alternatively be interpreted as smallest open neighborhoods.  Either interpretation
// yields all nonhomeomorphic spaces of cardinality = spacesize at the file level, but a
// given line does not in general yield the same space.)

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

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

// We compute KFG(A) for every A in X and store the result in kfg.

        ComputeKFG(kfg,spacesize,point_closures);

// We need KFZ(A) to get psi(A), so we extract it from KFG(A).

        CopyKFZfromKFG(kfz,kfg,spacesize);

// We compute psi(A), psi(gA) for all A in X. 

        for (set=0; set<(one<<spacesize); set++)
        {
            psi = Psi(set,spacesize,kfz);
            border_psi[psi][Psi(kfg->_g[set],spacesize,kfz)] = 1;
        }

// Advance the while counter.

        space++;
    }

// For each psi-number we print all border psi-numbers that occurred.

    printf("\n psi(A)\tpsi(gA)\n ------\t-------");

    for (j=1; j<71; j++)
    {
        printf("\n   %d\t ", j);
        for (k=1; k<71; k++)
            if (border_psi[j][k]) printf("%d ", k);
    }
    printf("\n\n");

    fclose(input);
    for (j=0; j<71; j++) free(border_psi[j]);
    free(border_psi);
    free(point_closures);
    FreeKFG(kfg);
    FreeKFZ(kfz);
    printf("\n");
    return EXIT_SUCCESS;
}
