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

// All 70 psi-numbers occur in four resolvable spaces of cardinality 11.

// 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, *psi_number, phi;
    int         j, k, max_spacesize = 11;

// Allocate memory for the structs that store KFG(A), KFZ(A), and KZ(A) for all A in X.

    KFZ        *kfz = CreateKFZ(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);
    }

    psi_number = (int *)malloc(71 * sizeof(int));
    if (psi_number==0)
    {
        printf("\nCould not allocate space for psi_number.\n");
        exit(0);
    }
    for (j=0; j<71; j++) psi_number[j] = 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;
    }

// Every psi-number occurs in at least one of the following four resolvable 11-spaces.

// Base {{p,q}, {r,s}, {t,u}, {v,w}, {p,q,r,s,x}, {v,w,y}, {p,q,t,u,v,w,y,z}}:

    static const int sp_one[11][11] = {
                                {1,1,0,0,0,0,0,0,0,0,0},
                                {1,1,0,0,0,0,0,0,0,0,0},
                                {0,0,1,1,0,0,0,0,0,0,0},
                                {0,0,1,1,0,0,0,0,0,0,0},
                                {0,0,0,0,1,1,0,0,0,0,0},
                                {0,0,0,0,1,1,0,0,0,0,0},
                                {0,0,0,0,0,0,1,1,0,0,0},
                                {0,0,0,0,0,0,1,1,0,0,0},
                                {1,1,1,1,0,0,0,0,1,0,0},
                                {0,0,0,0,0,0,1,1,0,1,0},
                                {1,1,0,0,1,1,1,1,0,1,1}};

    for (j=0; j<11; j++) memcpy(base[j],sp_one[j],sizeof(sp_one[j]));
    
    printf("\n\nnontrivial psi-numbers generated by T_1:\n");

    BaseToPsiNumbers(kfz,base,closures,point_closures,psi_number,11);

// Base {{p,q}, {r,s}, {t,u}, {v,w}, {r,s,x}, {v,w,y}, {t,u,v,w,y,z}}:

    static const int sp_two[11][11] = {
                                {1,1,0,0,0,0,0,0,0,0,0},
                                {1,1,0,0,0,0,0,0,0,0,0},
                                {0,0,1,1,0,0,0,0,0,0,0},
                                {0,0,1,1,0,0,0,0,0,0,0},
                                {0,0,0,0,1,1,0,0,0,0,0},
                                {0,0,0,0,1,1,0,0,0,0,0},
                                {0,0,0,0,0,0,1,1,0,0,0},
                                {0,0,0,0,0,0,1,1,0,0,0},
                                {0,0,1,1,0,0,0,0,1,0,0},
                                {0,0,0,0,0,0,1,1,0,1,0},
                                {0,0,0,0,1,1,1,1,0,1,1}};

    for (j=0; j<11; j++) memcpy(base[j],sp_two[j],sizeof(sp_two[j]));
    
    printf("\n\nnontrivial psi-numbers generated by T_2:\n");

    BaseToPsiNumbers(kfz,base,closures,point_closures,psi_number,11);

// Base {{p,q}, {r,s}, {t,u}, {p,q,r,s,t,u,v}, {p,q,r,s,w}, {p,q,x}, {r,s,y}, {t,u,z}}:

    static const int sp_three[11][11] = {
                                {1,1,0,0,0,0,0,0,0,0,0},
                                {1,1,0,0,0,0,0,0,0,0,0},
                                {0,0,1,1,0,0,0,0,0,0,0},
                                {0,0,1,1,0,0,0,0,0,0,0},
                                {0,0,0,0,1,1,0,0,0,0,0},
                                {0,0,0,0,1,1,0,0,0,0,0},
                                {1,1,1,1,1,1,1,0,0,0,0},
                                {1,1,1,1,0,0,0,1,0,0,0},
                                {1,1,0,0,0,0,0,0,1,0,0},
                                {0,0,1,1,0,0,0,0,0,1,0},
                                {0,0,0,0,1,1,0,0,0,0,1}};

    for (j=0; j<11; j++) memcpy(base[j],sp_three[j],sizeof(sp_three[j]));
    
    printf("\n\nnontrivial psi-numbers generated by T_3:\n");

    BaseToPsiNumbers(kfz,base,closures,point_closures,psi_number,11);

// Base {{p,q}, {r,s}, {t,u}, {p,q,r,s,v}, {p,q,t,u,w}, {p,q,x}, {r,s,t,u,y}, {r,s,z}}:

    static const int sp_four[11][11] = {
                                {1,1,0,0,0,0,0,0,0,0,0},
                                {1,1,0,0,0,0,0,0,0,0,0},
                                {0,0,1,1,0,0,0,0,0,0,0},
                                {0,0,1,1,0,0,0,0,0,0,0},
                                {0,0,0,0,1,1,0,0,0,0,0},
                                {0,0,0,0,1,1,0,0,0,0,0},
                                {1,1,1,1,0,0,1,0,0,0,0},
                                {1,1,0,0,1,1,0,1,0,0,0},
                                {1,1,0,0,0,0,0,0,1,0,0},
                                {0,0,1,1,1,1,0,0,0,1,0},
                                {0,0,1,1,0,0,0,0,0,0,1}};

    for (j=0; j<11; j++) memcpy(base[j],sp_four[j],sizeof(sp_four[j]));
    
    printf("\n\nnontrivial psi-numbers generated by T_4:\n");

    BaseToPsiNumbers(kfz,base,closures,point_closures,psi_number,11);

// The space X with base {{q}, {r}, {s}, {t,u}, {v,w}, {q,x}, {r,s,y}, {q,v,w,x,z}}
// admits all 30 phi-numbers.

    static const int all_phi[10][10] = {
                                {1,0,0,0,0,0,0,0,0,0},
                                {0,1,0,0,0,0,0,0,0,0},
                                {0,0,1,0,0,0,0,0,0,0},
                                {0,0,0,1,1,0,0,0,0,0},
                                {0,0,0,1,1,0,0,0,0,0},
                                {0,0,0,0,0,1,1,0,0,0},
                                {0,0,0,0,0,1,1,0,0,0},
                                {1,0,0,0,0,0,0,1,0,0},
                                {0,1,1,0,0,0,0,0,1,0},
                                {1,0,0,0,0,1,1,1,0,1}};

    for (j=0; j<10; j++) memcpy(base[j],all_phi[j],sizeof(all_phi[j]));

    BaseToPhiNumbers(kz,base,closures,point_closures,psi_number,10);

    for (phi=1; phi<30; phi++)
    {
        if (!psi_number[phi])
        {
            printf("Error: phi-number %d not found.\n",phi);
            break;
        }
    }

// Since all phi-numbers occur, the value of phi is 30 when the for loop ends.

    if (phi == 30) printf("\n\nAll 30 phi-numbers occur.\n");

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