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

// Verify non-blank entries in Table 12 of arXiv preprint.

// 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"
#include    "local_orderings_496.h"


int main(int argc, const char * argv[])
{
    int       **optional, **equals, psi_number[496] = {0}, present[11] = {0};
    int         j, k, m, initialized;
    KFenum      kf_key = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,
                            21,22,23,24,25,26,27,28,29,30,31,32,33};
    KFenum     *kf = &kf_key;

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

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

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

// Get the psi-number for each local ordering on KF.

    for (j=0; j<496; j++)
    {
        for (k=0; k<34; k++)
            for (m=0; m<34; m++)
                equals[k][m] = 0;
        for (k=0; k<33; k++)
            for (m=k+1; m<34; m++)
            {
                if (local_orderings_on_kf[j][k][m]*local_orderings_on_kf[j][m][k])
                {
                    equals[k][m] = 1;
                    equals[m][k] = 1;
                }
            }
        psi_number[j] = PsiArray(equals,kf);
    }

// For each psi-number from 1 to 50, test the 11 inequalities for optionality.

    for (j=1; j<51; j++)
    {
        initialized = 0;
        for (k=0; k<11; k++) present[k] = 0;
        for (k=0; k<496; k++)
        {
            if (initialized)
            {
                if (psi_number[k] == j)
                {

// An inequality is optional if and only if its initial presence/absence changes.

                    if (present[0])
                    {
                        if (!local_orderings_on_kf[k][kf->_fbi][kf->_fib]) optional[0][j] = 1;
                    }
                    else if (local_orderings_on_kf[k][kf->_fbi][kf->_fib]) optional[0][j] = 1;


                    if (present[1])
                    {
                        if (!local_orderings_on_kf[k][kf->_fif][kf->_fbi]) optional[1][j] = 1;
                    }
                    else if (local_orderings_on_kf[k][kf->_fif][kf->_fbi]) optional[1][j] = 1;


                    if (present[2])
                    {
                        if (!local_orderings_on_kf[k][kf->_fib][kf->_fif]) optional[2][j] = 1;
                    }
                    else if (local_orderings_on_kf[k][kf->_fib][kf->_fif]) optional[2][j] = 1;


                    if (present[3])
                    {
                        if (!local_orderings_on_kf[k][kf->_bi][kf->_ib]) optional[3][j] = 1;
                    }
                    else if (local_orderings_on_kf[k][kf->_bi][kf->_ib]) optional[3][j] = 1;


                    if (present[4])
                    {
                        if (!local_orderings_on_kf[k][kf->_fif][kf->_ib]) optional[4][j] = 1;
                    }
                    else if (local_orderings_on_kf[k][kf->_fif][kf->_ib]) optional[4][j] = 1;


                    if (present[5])
                    {
                        if (!local_orderings_on_kf[k][kf->_id][kf->_ib]) optional[5][j] = 1;
                    }
                    else if (local_orderings_on_kf[k][kf->_id][kf->_ib]) optional[5][j] = 1;


                    if (present[6])
                    {
                        if (!local_orderings_on_kf[k][kf->_fbi][kf->_id]) optional[6][j] = 1;
                    }
                    else if (local_orderings_on_kf[k][kf->_fbi][kf->_id]) optional[6][j] = 1;


                    if (present[7])
                    {
                        if (!local_orderings_on_kf[k][kf->_fif][kf->_id]) optional[7][j] = 1;
                    }
                    else if (local_orderings_on_kf[k][kf->_fif][kf->_id]) optional[7][j] = 1;


                    if (present[8])
                    {
                        if (!local_orderings_on_kf[k][kf->_fib][kf->_id]) optional[8][j] = 1;
                    }
                    else if (local_orderings_on_kf[k][kf->_fib][kf->_id]) optional[8][j] = 1;


                    if (present[9])
                    {
                        if (!local_orderings_on_kf[k][kf->_fb][kf->_id]) optional[9][j] = 1;
                    }
                    else if (local_orderings_on_kf[k][kf->_fb][kf->_id]) optional[9][j] = 1;


                    if (present[10])
                    {
                        if (!local_orderings_on_kf[k][kf->_ff][kf->_id]) optional[10][j] = 1;
                    }
                    else if (local_orderings_on_kf[k][kf->_ff][kf->_id]) optional[10][j] = 1;
                }
            }
            else if (psi_number[k] == j)
            {
                initialized = 1;
                if (local_orderings_on_kf[k][kf->_fbi][kf->_fib])   present[0] = 1;
                if (local_orderings_on_kf[k][kf->_fif][kf->_fbi])   present[1] = 1;
                if (local_orderings_on_kf[k][kf->_fib][kf->_fif])   present[2] = 1;
                if (local_orderings_on_kf[k][kf->_bi][kf->_ib])     present[3] = 1;
                if (local_orderings_on_kf[k][kf->_fif][kf->_ib])    present[4] = 1;
                if (local_orderings_on_kf[k][kf->_id][kf->_ib])     present[5] = 1;
                if (local_orderings_on_kf[k][kf->_fbi][kf->_id])    present[6] = 1;
                if (local_orderings_on_kf[k][kf->_fif][kf->_id])    present[7] = 1;
                if (local_orderings_on_kf[k][kf->_fib][kf->_id])    present[8] = 1;
                if (local_orderings_on_kf[k][kf->_fb][kf->_id])     present[9] = 1;
                if (local_orderings_on_kf[k][kf->_ff][kf->_id])     present[10] = 1;
            }
        }
    }

// Print the results as they appear in Table 12 of arXiv preprint.

    for (k=0; k<11; k++)
    {
        for (j=1; j<51; j++)
        {
            if (optional[k][j]) printf("%d", j-(j/10)*10);
            else printf(" ");
        }
        printf("\n");
    }

    for (k=0; k<11; k++) free(optional[k]);
    free(optional);
    for (k=0; k<34; k++) free(equals[k]);
    free(equals);
    printf("\n");
    return EXIT_SUCCESS;
}
