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

// Upper bounds are sharp in Corollaries 17 and 18.

// 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    <stdbool.h>
#include    <string.h>
#include    "set_operators.h"
#include    "set_families.h"
#include    "set_relations.h"
#include    "collapses.h"
#include    "topologies.h"


int main(int argc, const char * argv[])
{
    uint32_t   *point_closures, set;
    int       **closures, **base, psi_in_space[71] = {0};
    int         j, k, spacesize = 5, max_spacesize = 11;

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

    KFZ        *kfz = CreateKFZ(max_spacesize);

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

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

    base = (int **)malloc(max_spacesize * sizeof(int *));
    if (base==0)
    {
        printf("\nCould not allocate space for base.\n");
        exit(0);
    }

    closures = (int **)malloc(max_spacesize * sizeof(int *));
    if (closures==0)
    {
        printf("\nCould not allocate space for closures.\n");
        exit(0);
    }

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

// Input the space X with base {{v}, {v,w}, {x,y}, {v,x,y,z}}.

    static const int space[5][5] = {
                                {1,0,0,0,0},
                                {1,1,0,0,0},
                                {0,0,1,1,0},
                                {0,0,1,1,0},
                                {1,0,1,1,1}};

    for (j=0; j<5; j++) memcpy(base[j],space[j],sizeof(space[j]));

    BaseToPointClosures(base,closures,point_closures,spacesize);
    ComputeKFZ(kfz,spacesize,point_closures);

    for (set=0; set<(one<<spacesize); set++) psi_in_space[Psi(set,spacesize,kfz)] = 1;

    printf("\nAll psi-numbers < 49 in space with base {{v}, {v,w}, {x,y}, {v,x,y,z}}:\n\n");

    for (j=1; j<49; j++)
    {
        if (psi_in_space[j]) printf("%d ", j);
    }

    for (j=0; j<max_spacesize; j++)
    {
        free(base[j]);
        free(closures[j]);
    }
    free(base);
    free(closures);
    free(point_closures);
    FreeKFZ(kfz);
    printf("\n\n");
    return EXIT_SUCCESS;
}
