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

// Examples of spaces satisfying the 12 global orderings on KFG.

// 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;
    int       **closures, **base;
    int         j, k, ordering = 0, max_spacesize = 11;
    char      **spacetype;

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

    KFG        *kfg = CreateKFG(max_spacesize);
    KZ         *kz = CreateKZ(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;
    }

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

    for (j=0; j<13; 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 1");
    strcpy(spacetype[4],"ED 1");
    strcpy(spacetype[5],"OU 1");
    strcpy(spacetype[6],"GE 1");
    strcpy(spacetype[7],"KD 1");
    strcpy(spacetype[8],"EO 2");
    strcpy(spacetype[9],"ED 2");
    strcpy(spacetype[10],"OU 2");
    strcpy(spacetype[11],"GE 2");
    strcpy(spacetype[12],"KD 2");

    printf("Global orderings of KFG for minimal spaces:\n");

// The minimal Kuratowski space X with base {{w}, {x,y}, {w,x,y,z}} is GE 2.

    static const int ge[4][4] = {
                                {1,0,0,0},
                                {0,1,1,0},
                                {0,1,1,0},
                                {1,1,1,1}};

    for (j=0; j<4; j++) memcpy(base[j],ge[j],sizeof(ge[j]));

    ordering = BaseToKFGOrdering(kz,kfg,base,closures,point_closures,4);

    printf("%s, ", spacetype[ordering]);

// The space X with base {{v}, {w}, {v,w,x}, {y,z}} is KD 2.

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

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

    ordering = BaseToKFGOrdering(kz,kfg,base,closures,point_closures,5);

    printf("%s, ", spacetype[ordering]);

// The space X with base {{x,y}, {x,y,z}} is ED 2.

    static const int ed[3][3] = {
                                {1,1,0},
                                {1,1,0},
                                {1,1,1}};

    for (j=0; j<3; j++) memcpy(base[j],ed[j],sizeof(ed[j]));

    ordering = BaseToKFGOrdering(kz,kfg,base,closures,point_closures,3);

    printf("%s, ", spacetype[ordering]);

// The space X with base {{x}, {y}, {x,y,z}} is OU 2.

    static const int ou[3][3] = {
                                {1,0,0},
                                {0,1,0},
                                {1,1,1}};

    for (j=0; j<3; j++) memcpy(base[j],ou[j],sizeof(ou[j]));

    ordering = BaseToKFGOrdering(kz,kfg,base,closures,point_closures,3);

    printf("%s, ", spacetype[ordering]);

// The Sierpinski space X with base {{x}, {x,y}} is EO 2.

    static const int eo[2][2] = {
                                {1,0},
                                {1,1}};

    for (j=0; j<2; j++) memcpy(base[j],eo[j],sizeof(eo[j]));

    ordering = BaseToKFGOrdering(kz,kfg,base,closures,point_closures,2);

    printf("%s, ", spacetype[ordering]);

// The minimal indiscrete space X with base {{x,y}} is P.

    static const int p[2][2] = {
                                {1,1},
                                {1,1}};

    for (j=0; j<2; j++) memcpy(base[j],p[j],sizeof(p[j]));

    ordering = BaseToKFGOrdering(kz,kfg,base,closures,point_closures,2);

    printf("%s, ", spacetype[ordering]);

// The singleton space X with base {{x}} is D.

    static const int d[1][1] = {
                                {1}};

    for (j=0; j<1; j++) memcpy(base[j],d[j],sizeof(d[j]));

    ordering = BaseToKFGOrdering(kz,kfg,base,closures,point_closures,1);

    printf("%s\n\nOther global orderings of KFG that occur:\n", spacetype[ordering]);

// The space X with base {{w,x}, {w,x,y,z}} is ED 1.

    static const int edone[4][4] = {
                                {1,1,0,0},
                                {1,1,0,0},
                                {1,1,1,1},
                                {1,1,1,1}};

    for (j=0; j<4; j++) memcpy(base[j],edone[j],sizeof(edone[j]));

    ordering = BaseToKFGOrdering(kz,kfg,base,closures,point_closures,4);

    printf("%s, ", spacetype[ordering]);

// The space X with base {{x}, {x,y}, {x,y,z}} is EO 1.

    static const int eoone[3][3] = {
                                {1,0,0},
                                {1,1,0},
                                {1,1,1}};

    for (j=0; j<3; j++) memcpy(base[j],eoone[j],sizeof(eoone[j]));

    ordering = BaseToKFGOrdering(kz,kfg,base,closures,point_closures,3);

    printf("%s, ", spacetype[ordering]);

// The space X with base {{w}, {x}, {w,x,y,z}} is OU 1.

    static const int ouone[4][4] = {
                                {1,0,0,0},
                                {0,1,0,0},
                                {1,1,1,1},
                                {1,1,1,1}};

    for (j=0; j<4; j++) memcpy(base[j],ouone[j],sizeof(ouone[j]));

    ordering = BaseToKFGOrdering(kz,kfg,base,closures,point_closures,4);

    printf("%s, ", spacetype[ordering]);

// The space X with base {{u}, {v}, {u,w}, {u,v,w,x}, {y,z}} is KD 1.

    static const int kdone[6][6] = {
                                {1,0,0,0,0,0},
                                {0,1,0,0,0,0},
                                {1,0,1,0,0,0},
                                {1,1,1,1,0,0},
                                {0,0,0,0,1,1},
                                {0,0,0,0,1,1}};

    for (j=0; j<6; j++) memcpy(base[j],kdone[j],sizeof(kdone[j]));

    ordering = BaseToKFGOrdering(kz,kfg,base,closures,point_closures,6);

    printf("%s,\nR under the usual topology is GE 1\n", spacetype[ordering]);

    for (j=0; j<max_spacesize; j++)
    {
        free(base[j]);
        free(closures[j]);
    }
    free(base);
    free(closures);
    free(point_closures);
    for (j=0; j<13; j++) free(spacetype[j]);
    free(spacetype);
    FreeKFG(kfg);
    FreeKZ(kz);
    printf("\n");
    return EXIT_SUCCESS;
}
