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

// Verify Figure 1.

// 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    "topologies.h"


// IsPosetKFG() checks whether adding (o,p) to the partial order represented by
// kfg_ordering[m] fails to produce a partial order or is equivalent to an edge in the
// extender diagram.  In either case 0 is returned; 1 is returned if and only if (o,p)
// belongs to the extender diagram.  IsPosetKF() is similar.

int IsPosetKFG(KFGenum *kfgop, int m, int **adj, int **orig, int **tc, int o, int p);
int IsPosetKF(KFenum *kfop, int m, int **adj, int **orig, int **tc, int o, int p);

int main(int argc, const char * argv[])
{
    FILE       *input;
    uint32_t   *point_closures, **sets;
    int         j, k, m, ordering = 0, space = 0;
    int         kfg_extender[13] = {0};
    int      ***kfg_ordering, ***kf_ordering;
    int       **orig, **tc, **ac, **tr;
    char      **set_kfg, **set_kf;
    KFGenum     kfg_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,34,35,36,37,38,39};
    KFGenum    *kfgop = &kfg_key;
    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     *kfop = &kf_key;

// The 12 global orderings of KFG each occur in some space of cardinality 6.

    int         spacesize = 6;

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

    KFG        *kfg = CreateKFG(spacesize);
    KZ         *kz = CreateKZ(spacesize);

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

// For n = 1 to 40 set_kfg[n] stores the label of sets[a][n] where a is an arbitrary set.

    KFGlabels(set_kfg);

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

    KFlabels(set_kf);

// kfg_ordering[][][] stores the 12 global orderings of KFG.
// The purpose of the while loop below is to obtain these orderings.

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

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

    sets = (uint32_t **)malloc(40 * sizeof(uint32_t *));
    if (sets==0)
    {
        printf("\nCould not allocate space for sets.\n");
        exit(0);
    }
    for (j=0; j<40; j++)
    {
        sets[j] = (uint32_t *)malloc((one<<spacesize) * sizeof(uint32_t));
        if (sets[j]==0)
        {
            printf("\nCould not allocate space for sets[%d].\n", j);
            exit(0);
        }
        for (k=0; k<(one<<spacesize); k++) sets[j][k] = 0;
    }

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

    input = fopen("6-spaces.txt", "r");
    if (input==0)
    {
        printf("\nCould not open file 6-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);
    }

// Find and store the 12 global orderings of KFG in the kfg_ordering[][][] array.

    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]);

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

        ComputeKFG(kfg,spacesize,point_closures);

// Find the global ordering of KFG that X satisfies.

        ordering = KFGOrdering(kz,kfg,spacesize,point_closures);

// #    index to KFGOrdering()
// -    ----------------------
// 1    D
// 2    P
// 3    EO 1 (fb <= id not true)
// 4    ED 1 (fb <= id not true)
// 5    OU 1 (fbg <= id not true)
// 6    GE 1 (bg <= aibi not true)
// 7    KD 1 (fbg <= id not true)
// 8    EO 2 (fb <= id true)
// 9    ED 2 (fb <= id true)
// 10   OU 2 (fbg <= id true)
// 11   GE 2 (bg <= aibi true)
// 12   KD 2 (fbg <= id true)

// Compute and store the ordering itself in the adjacency matrix
// kfg_ordering[ordering][][].

        if (!kfg_extender[ordering])    // Just perform once for each global ordering.
        {

// Copy KFG(A) into sets[][] so loops can be used to find all inequalities.

            CopyKFGarray(sets, kfg, spacesize);

            for (j=0; j<40; j++)
                for (k=0; k<40; k++)
                {
                    if (OpSubset(sets[j],sets[k],spacesize)) kfg_ordering[ordering][j][k] = 1;
                }
            kfg_extender[ordering] = 1; // Just perform once for each global ordering.
        }
        space++;                        // Advance the while loop counter.
    }

// Verify that each ordering occurred.

    for (m=1; m<13; m++) 
    {
        if (!kfg_extender[m])
        {
            printf("Error: kfg_ordering[%d] did not occur\n", m);
            exit(0);
        }
    }

// We verify Figure 1(ii) by printing all edges in the transitive reduction of
// kfg_ordering[6][][] up to left duality (Figure 1(i) follows immediately).

    printf("\n\nAll edges in Figure 1(ii):\n\n");
    getTransitiveReduction(kfg_ordering[6], orig, tc, ac, tr, 40);

// For all o,p in KFG the inequality ao < p is impossible and ao < ap is the left dual of
// p < o, so we assume the left side of the inequality is in KFG.

    for (j=0; j<20; j++)
        for (k=0; k<40; k++)
        {

// We exclude left duals of b < 1 and dashed lines in Figure 1(ii).

            if (j == kfgop->_zero && k == kfgop->_ab) continue;     // left dual of b < 1
            if (j == kfgop->_f && k == kfgop->_ai) continue;        // left dual of i < af
            if (j == kfgop->_fbi && k == kfgop->_aibi) continue;    // left dual of ibi < afbi
            if (j == kfgop->_bif && k == kfgop->_aibi) continue;    // left dual of ibi < abif
            if (j == kfgop->_if && k == kfgop->_abi) continue;      // left dual of bi < aif
            if (j == kfgop->_fb && k == kfgop->_aib) continue;      // left dual of ib < afb
            if (j == kfgop->_ff && k == kfgop->_aif) continue;      // left dual of if < aff

            if (tr[j][k]) printf("%s < %s\n", set_kfg[j], set_kfg[k]);
        }

// We extract the nine global orderings of KF from the kfg_ordering[][][] array.

    for (m=0; m<10; m++) ExtractKFfromKFG(kf_ordering[m], kfg_ordering[m]);

// Compute the extenders of all possible global orderings on KF and KFG.

    for (m=1; m<10; m++)
    {
        if (m < 5 || m > 7) printf("\n\nKF extender for %s spaces:\n\n", kfg_type[m]);
        else
        {
            if (m == 5) printf("\n\nKF extender for OU spaces:\n\n");
            if (m == 6) printf("\n\nKF extender for GE spaces:\n\n");
            if (m == 7) printf("\n\nKF extender for KD spaces:\n\n");
        }
        for (j=0; j<34; j++)
            for (k=0; k<34; k++)
            {
                if (!kf_ordering[m][j][k])
                {

// IsPoset() does the heavy lifting.

                    if (IsPosetKF(kfop,m,kf_ordering[m],orig,tc,j,k)) printf("%s < %s\n", set_kf[j], set_kf[k]);
                }
            }
    }
    for (m=1; m<13; m++)
    {
        printf("\n\nKFG extender for %s spaces:\n\n", kfg_type[m]);
        for (j=0; j<40; j++)
            for (k=0; k<40; k++)
            {
                if (!kfg_ordering[m][j][k])
                {
                    if (IsPosetKFG(kfgop,m,kfg_ordering[m],orig,tc,j,k)) printf("%s < %s\n", set_kfg[j], set_kfg[k]);
                }
            }
    }

    fclose(input);
    for (j=0; j<40; j++) free(set_kfg[j]);
    for (j=0; j<34; j++) free(set_kf[j]);
    free(set_kfg);
    free(set_kf);
    for (j=0; j<13; j++)
    {
        for (k=0; k<40; k++) free(kfg_ordering[j][k]);
        free(kfg_ordering[j]);
        for (k=0; k<34; k++) free(kf_ordering[j][k]);
        free(kf_ordering[j]);
    }
    free(kfg_ordering);
    free(kf_ordering);
    for (j=0; j<40; j++)
    {
        free(sets[j]);
        free(orig[j]);
        free(tc[j]);
        free(ac[j]);
        free(tr[j]);
    }
    free(sets);
    free(orig);
    free(tc);
    free(ac);
    free(tr);
    free(point_closures);
    FreeKFG(kfg);
    FreeKZ(kz);
    printf("\n");
    return EXIT_SUCCESS;
}


// IsPosetKFG() first checks whether adding (o,p) to the partial order represented by
// kfg_ordering[m] results in a partial order.  It returns 0 if not or if (o,p) is
// equivalent to an edge in the extender diagram; otherwise it returns 1.

int IsPosetKFG(KFGenum *kfgop, int m, int **adj, int **orig, int **tc, int o, int p)
{
    int q, r;

// To leave adj[][] = kfg_ordering[m][] undisturbed, we copy it to the orig array.

    matrixCopy(adj,orig,40);

// We know orig[o][p] = 0 since otherwise IsPosetKFG() would not have been called.
// Our first task is to check whether changing it to 1 yields a partial order.

    orig[o][p] = 1;

// Since (q,r) may exist such that q = o and r = p we also need to set orig[q][r] = 1 for
// all such (q,r).

    for (q=0; q<40; q++)
    {
        if (orig[o][q] && orig[q][o])
        {
            for (r=0; r<40; r++)
            {
                if (orig[r][p] && orig[p][r]) orig[q][r] = 1;
            }
        }
    }

// To determine whether these changes yield a partial order, we compare orig[][] with the
// transitive closure of a copy of it stored in the tc[][] array.

    matrixCopy(orig,tc,40);
    Warshall(tc,40);

    if (matrixEqual(orig,tc,40))    // (o,p) is in the extender
    {

// We only return 1 if (o,p) appears explicitly as an edge in the extender diagram.
// For efficiency, we ignore the global ordering and check, in decreasing order of
// frequency, every edge that appears at least once in some extender diagram.
// If we never find a match it means the extender diagram for kfg_ordering[m] is
// incomplete, in which case the program exits with an error.

        if (adj[o][kfgop->_i] && adj[kfgop->_i][o] && adj[kfgop->_ai][p] && adj[p][kfgop->_ai])//   i < ai
        {
            if (o == kfgop->_i && p == kfgop->_ai) return 1;
            return 0;
        }
        if (adj[o][kfgop->_ab] && adj[kfgop->_ab][o] && adj[kfgop->_b][p] && adj[p][kfgop->_b])//   ab < b
        {
            if (o == kfgop->_ab && p == kfgop->_b) return 1;
            return 0;
        }

// If X is discrete the function should have now returned a value.
// We mark the completion of each global ordering like this:

//---------- D ----------

        if (adj[o][kfgop->_if] && adj[kfgop->_if][o] && adj[kfgop->_id][p] && adj[p][kfgop->_id])// if < id
        {
            if (o == kfgop->_if && p == kfgop->_id) return 1;
            return 0;
        }
        if (adj[o][kfgop->_a] && adj[kfgop->_a][o] && adj[kfgop->_aif][p] && adj[p][kfgop->_aif])// a(if < id) = (a < aif)
        {
            return 0;
        }
        if (adj[o][kfgop->_if] && adj[kfgop->_if][o] && adj[kfgop->_aif][p] && adj[p][kfgop->_aif])// if < aif
        {
            if (o == kfgop->_if && p == kfgop->_aif) return 1;
            return 0;
        }
        if (adj[o][kfgop->_g] && adj[kfgop->_g][o] && adj[kfgop->_ag][p] && adj[p][kfgop->_ag])// g < ag
        {
            if (o == kfgop->_g && p == kfgop->_ag) return 1;
            return 0;
        }

//---------- P ----------

        if (adj[o][kfgop->_fi] && adj[kfgop->_fi][o] && adj[kfgop->_afi][p] && adj[p][kfgop->_afi])// fi < afi
        {
            if (o == kfgop->_fi && p == kfgop->_afi) return 1;
            return 0;
        }
        if (adj[o][kfgop->_fb] && adj[kfgop->_fb][o] && adj[kfgop->_afb][p] && adj[p][kfgop->_afb])// fb < afb
        {
            if (o == kfgop->_fb && p == kfgop->_afb) return 1;
            return 0;
        }

//---------- EO 2 ----------

        if (adj[o][kfgop->_if] && adj[kfgop->_if][o] && adj[kfgop->_ag][p] && adj[p][kfgop->_ag])// if < ag
        {
            if (o == kfgop->_if && p == kfgop->_ag) return 1;
            return 0;
        }
        if (adj[o][kfgop->_g] && adj[kfgop->_g][o] && adj[kfgop->_aif][p] && adj[p][kfgop->_aif])// a(if < ag) = (g < aif)
        {
            return 0;
        }

//---------- ED 2 ----------

        if (adj[o][kfgop->_fi] && adj[kfgop->_fi][o] && adj[kfgop->_id][p] && adj[p][kfgop->_id])// fi < id
        {
            if (o == kfgop->_fi && p == kfgop->_id) return 1;
            return 0;
        }
        if (adj[o][kfgop->_a] && adj[kfgop->_a][o] && adj[kfgop->_afi][p] && adj[p][kfgop->_afi])// a(fi < id) = (a < afi)
        {
            return 0;
        }
        if (adj[o][kfgop->_fb] && adj[kfgop->_fb][o] && adj[kfgop->_id][p] && adj[p][kfgop->_id])// fb < id
        {
            if (o == kfgop->_fb && p == kfgop->_id) return 1;
            return 0;
        }
        if (adj[o][kfgop->_a] && adj[kfgop->_a][o] && adj[kfgop->_afb][p] && adj[p][kfgop->_afb])// a(fb < id) = (a < afb)
        {
            return 0;
        }
        if (adj[o][kfgop->_fi] && adj[kfgop->_fi][o] && adj[kfgop->_bg][p] && adj[p][kfgop->_bg])// fi < bg
        {
            if (o == kfgop->_fi && p == kfgop->_bg) return 1;
            return 0;
        }
        if (adj[o][kfgop->_abg] && adj[kfgop->_abg][o] && adj[kfgop->_afi][p] && adj[p][kfgop->_afi])// a(fi < bg) = (abg < afi)
        {
            return 0;
        }
        if (adj[o][kfgop->_g] && adj[kfgop->_g][o] && adj[kfgop->_afi][p] && adj[p][kfgop->_afi])// g < afi
        {
            if (o == kfgop->_g && p == kfgop->_afi) return 1;
            return 0;
        }
        if (adj[o][kfgop->_fi] && adj[kfgop->_fi][o] && adj[kfgop->_ag][p] && adj[p][kfgop->_ag])// a(g < afi) = (fi < ag)
        {
            return 0;
        }
        if (adj[o][kfgop->_g] && adj[kfgop->_g][o] && adj[kfgop->_afb][p] && adj[p][kfgop->_afb])// g < afb
        {
            if (o == kfgop->_g && p == kfgop->_afb) return 1;
            return 0;
        }
        if (adj[o][kfgop->_fb] && adj[kfgop->_fb][o] && adj[kfgop->_ag][p] && adj[p][kfgop->_ag])// a(g < afb) = (fb < ag)
        {
            return 0;
        }

//---------- EO 1 ----------

        if (adj[o][kfgop->_fi] && adj[kfgop->_fi][o] && adj[kfgop->_afbg][p] && adj[p][kfgop->_afbg])// fi < afbg
        {
            if (o == kfgop->_fi && p == kfgop->_afbg) return 1;
            return 0;
        }
        if (adj[o][kfgop->_fbg] && adj[kfgop->_fbg][o] && adj[kfgop->_afi][p] && adj[p][kfgop->_afi])// a(fi < afbg) = (fbg < afi)
        {
            return 0;
        }

//---------- ED 1 ----------

        if (adj[o][kfgop->_fib] && adj[kfgop->_fib][o] && adj[kfgop->_id][p] && adj[p][kfgop->_id])// fib < id
        {
            if (o == kfgop->_fib && p == kfgop->_id) return 1;
            return 0;
        }
        if (adj[o][kfgop->_a] && adj[kfgop->_a][o] && adj[kfgop->_afib][p] && adj[p][kfgop->_afib])// a(fib < id) = (a < afib)
        {
            return 0;
        }
        if (adj[o][kfgop->_fib] && adj[kfgop->_fib][o] && adj[kfgop->_afib][p] && adj[p][kfgop->_afib])// fib < afib
        {
            if (o == kfgop->_fib && p == kfgop->_afib) return 1;
            return 0;
        }
        if (adj[o][kfgop->_ibi] && adj[kfgop->_ibi][o] && adj[kfgop->_id][p] && adj[p][kfgop->_id])// ibi < id
        {
            if (o == kfgop->_ibi && p == kfgop->_id) return 1;
            return 0;
        }
        if (adj[o][kfgop->_a] && adj[kfgop->_a][o] && adj[kfgop->_aibi][p] && adj[p][kfgop->_aibi])// a(ibi < id) = (a < aibi)
        {
            return 0;
        }
        if (adj[o][kfgop->_ibi] && adj[kfgop->_ibi][o] && adj[kfgop->_afi][p] && adj[p][kfgop->_afi])// ibi < afi
        {
            if (o == kfgop->_ibi && p == kfgop->_afi) return 1;
            return 0;
        }
        if (adj[o][kfgop->_fi] && adj[kfgop->_fi][o] && adj[kfgop->_aibi][p] && adj[p][kfgop->_aibi])// a(ibi < afi) = (fi < aibi)
        {
            return 0;
        }
        if (adj[o][kfgop->_g] && adj[kfgop->_g][o] && adj[kfgop->_bib][p] && adj[p][kfgop->_bib])// g < bib
        {
            if (o == kfgop->_g && p == kfgop->_bib) return 1;
            return 0;
        }
        if (adj[o][kfgop->_abib] && adj[kfgop->_abib][o] && adj[kfgop->_ag][p] && adj[p][kfgop->_ag])// a(g < bib) = (abib < ag)
        {
            return 0;
        }
        if (adj[o][kfgop->_g] && adj[kfgop->_g][o] && adj[kfgop->_afib][p] && adj[p][kfgop->_afib])// g < afib
        {
            if (o == kfgop->_g && p == kfgop->_afib) return 1;
            return 0;
        }
        if (adj[o][kfgop->_fib] && adj[kfgop->_fib][o] && adj[kfgop->_ag][p] && adj[p][kfgop->_ag])// a(g < afib) = (fib < ag)
        {
            return 0;
        }

//---------- OU 2 ----------

        if (adj[o][kfgop->_fb] && adj[kfgop->_fb][o] && adj[kfgop->_bib][p] && adj[p][kfgop->_bib])// fb < bib
        {
            if (o == kfgop->_fb && p == kfgop->_bib) return 1;
            return 0;
        }
        if (adj[o][kfgop->_abib] && adj[kfgop->_abib][o] && adj[kfgop->_afb][p] && adj[p][kfgop->_afb])// a(fb < bib) = (abib < afb)
        {
            return 0;
        }
        if (adj[o][kfgop->_g] && adj[kfgop->_g][o] && adj[kfgop->_aibi][p] && adj[p][kfgop->_aibi])// g < aibi
        {
            if (o == kfgop->_g && p == kfgop->_aibi) return 1;
            return 0;
        }
        if (adj[o][kfgop->_ibi] && adj[kfgop->_ibi][o] && adj[kfgop->_ag][p] && adj[p][kfgop->_ag])// a(g < aibi) = (ibi < ag)
        {
            return 0;
        }
        if (adj[o][kfgop->_fib] && adj[kfgop->_fib][o] && adj[kfgop->_bg][p] && adj[p][kfgop->_bg])// fib < bg
        {
            if (o == kfgop->_fib && p == kfgop->_bg) return 1;
            return 0;
        }
        if (adj[o][kfgop->_abg] && adj[kfgop->_abg][o] && adj[kfgop->_afib][p] && adj[p][kfgop->_afib])// a(fib < bg) = (abg < afib)
        {
            return 0;
        }
        if (adj[o][kfgop->_bg] && adj[kfgop->_bg][o] && adj[kfgop->_id][p] && adj[p][kfgop->_id])// bg < id
        {
            if (o == kfgop->_bg && p == kfgop->_id) return 1;
            return 0;
        }
        if (adj[o][kfgop->_a] && adj[kfgop->_a][o] && adj[kfgop->_abg][p] && adj[p][kfgop->_abg])// a(bg < id) = (a < abg)
        {
            return 0;
        }

//---------- OU 1 ----------

        if (adj[o][kfgop->_fib] && adj[kfgop->_fib][o] && adj[kfgop->_afbg][p] && adj[p][kfgop->_afbg])// fib < afbg
        {
            if (o == kfgop->_fib && p == kfgop->_afbg) return 1;
            return 0;
        }
        if (adj[o][kfgop->_fbg] && adj[kfgop->_fbg][o] && adj[kfgop->_afib][p] && adj[p][kfgop->_afib])// a(fib < afbg) = (fbg < afib)
        {
            return 0;
        }
        if (adj[o][kfgop->_fbg] && adj[kfgop->_fbg][o] && adj[kfgop->_bib][p] && adj[p][kfgop->_bib])// fbg < bib
        {
            if (o == kfgop->_fbg && p == kfgop->_bib) return 1;
            return 0;
        }
        if (adj[o][kfgop->_abib] && adj[kfgop->_abib][o] && adj[kfgop->_afbg][p] && adj[p][kfgop->_afbg])// a(fbg < bib) = (abib < afbg)
        {
            return 0;
        }
        if (adj[o][kfgop->_fbg] && adj[kfgop->_fbg][o] && adj[kfgop->_afbg][p] && adj[p][kfgop->_afbg])// fbg < afbg
        {
            if (o == kfgop->_fbg && p == kfgop->_afbg) return 1;
            return 0;
        }

//---------- KD 2 ----------

        if (adj[o][kfgop->_fbg] && adj[kfgop->_fbg][o] && adj[kfgop->_id][p] && adj[p][kfgop->_id])// fbg < id
        {
            if (o == kfgop->_fbg && p == kfgop->_id) return 1;
            return 0;
        }
        if (adj[o][kfgop->_a] && adj[kfgop->_a][o] && adj[kfgop->_afbg][p] && adj[p][kfgop->_afbg])// a(fbg < id) = (a < afbg)
        {
            return 0;
        }
        if (adj[o][kfgop->_g] && adj[kfgop->_g][o] && adj[kfgop->_afbg][p] && adj[p][kfgop->_afbg])// g < afbg
        {
            if (o == kfgop->_g && p == kfgop->_afbg) return 1;
            return 0;
        }
        if (adj[o][kfgop->_fbg] && adj[kfgop->_fbg][o] && adj[kfgop->_ag][p] && adj[p][kfgop->_ag])// a(g < afbg) = (fbg < ag)
        {
            return 0;
        }
        if (adj[o][kfgop->_ibi] && adj[kfgop->_ibi][o] && adj[kfgop->_afbg][p] && adj[p][kfgop->_afbg])// ibi < afbg
        {
            if (o == kfgop->_ibi && p == kfgop->_afbg) return 1;
            return 0;
        }
        if (adj[o][kfgop->_fbg] && adj[kfgop->_fbg][o] && adj[kfgop->_aibi][p] && adj[p][kfgop->_aibi])// a(ibi < afbg) = (fbg < aibi)
        {
            return 0;
        }

//---------- KD 1 ----------

        if (adj[o][kfgop->_fib] && adj[kfgop->_fib][o] && adj[kfgop->_bi][p] && adj[p][kfgop->_bi])// fib < bi
        {
            if (o == kfgop->_fib && p == kfgop->_bi) return 1;
            return 0;
        }
        if (adj[o][kfgop->_abi] && adj[kfgop->_abi][o] && adj[kfgop->_afib][p] && adj[p][kfgop->_afib])// a(fib < bi) = (abi < afib)
        {
            return 0;
        }
        if (adj[o][kfgop->_fif] && adj[kfgop->_fif][o] && adj[kfgop->_bi][p] && adj[p][kfgop->_bi])// fif < bi
        {
            if (o == kfgop->_fif && p == kfgop->_bi) return 1;
            return 0;
        }
        if (adj[o][kfgop->_abi] && adj[kfgop->_abi][o] && adj[kfgop->_afif][p] && adj[p][kfgop->_afif])// a(fif < bi) = (abi < afif)
        {
            return 0;
        }
        if (adj[o][kfgop->_fif] && adj[kfgop->_fif][o] && adj[kfgop->_aib][p] && adj[p][kfgop->_aib])// fif < aib
        {
            if (o == kfgop->_fif && p == kfgop->_aib) return 1;
            return 0;
        }
        if (adj[o][kfgop->_ib] && adj[kfgop->_ib][o] && adj[kfgop->_afif][p] && adj[p][kfgop->_afif])// a(fif < aib) = (ib < afif)
        {
            return 0;
        }
        if (adj[o][kfgop->_fif] && adj[kfgop->_fif][o] && adj[kfgop->_id][p] && adj[p][kfgop->_id])// fif < id
        {
            if (o == kfgop->_fif && p == kfgop->_id) return 1;
            return 0;
        }
        if (adj[o][kfgop->_a] && adj[kfgop->_a][o] && adj[kfgop->_afif][p] && adj[p][kfgop->_afif])// a(fif < id) = (a < afif)
        {
            return 0;
        }
        if (adj[o][kfgop->_fif] && adj[kfgop->_fif][o] && adj[kfgop->_afib][p] && adj[p][kfgop->_afib])// fif < afib
        {
            if (o == kfgop->_fif && p == kfgop->_afib) return 1;
            return 0;
        }
        if (adj[o][kfgop->_fib] && adj[kfgop->_fib][o] && adj[kfgop->_afif][p] && adj[p][kfgop->_afif])// a(fif < afib) = (fib < afif)
        {
            return 0;
        }
        if (adj[o][kfgop->_fif] && adj[kfgop->_fif][o] && adj[kfgop->_afbi][p] && adj[p][kfgop->_afbi])// fif < afbi
        {
            if (o == kfgop->_fif && p == kfgop->_afbi) return 1;
            return 0;
        }
        if (adj[o][kfgop->_fbi] && adj[kfgop->_fbi][o] && adj[kfgop->_afif][p] && adj[p][kfgop->_afif])// a(fif < afbi) = (fbi < afif)
        {
            return 0;
        }
        if (adj[o][kfgop->_fbi] && adj[kfgop->_fbi][o] && adj[kfgop->_id][p] && adj[p][kfgop->_id])// fbi < id
        {
            if (o == kfgop->_fbi && p == kfgop->_id) return 1;
            return 0;
        }
        if (adj[o][kfgop->_a] && adj[kfgop->_a][o] && adj[kfgop->_afbi][p] && adj[p][kfgop->_afbi])// a(fbi < id) = (a < afbi)
        {
            return 0;
        }
        if (adj[o][kfgop->_fbi] && adj[kfgop->_fbi][o] && adj[kfgop->_aib][p] && adj[p][kfgop->_aib])// fbi < aib
        {
            if (o == kfgop->_fbi && p == kfgop->_aib) return 1;
            return 0;
        }
        if (adj[o][kfgop->_ib] && adj[kfgop->_ib][o] && adj[kfgop->_afbi][p] && adj[p][kfgop->_afbi])// a(fbi < aib) = (ib < afbi)
        {
            return 0;
        }
        if (adj[o][kfgop->_fib] && adj[kfgop->_fib][o] && adj[kfgop->_afbi][p] && adj[p][kfgop->_afbi])// fib < afbi
        {
            if (o == kfgop->_fib && p == kfgop->_afbi) return 1;
            return 0;
        }
        if (adj[o][kfgop->_fbi] && adj[kfgop->_fbi][o] && adj[kfgop->_afib][p] && adj[p][kfgop->_afib])// a(fib < afbi) = (fbi < afib)
        {
            return 0;
        }
        if (adj[o][kfgop->_fif] && adj[kfgop->_fif][o] && adj[kfgop->_afif][p] && adj[p][kfgop->_afif])// fif < afif
        {
            if (o == kfgop->_fif && p == kfgop->_afif) return 1;
            return 0;
        }
        if (adj[o][kfgop->_fbi] && adj[kfgop->_fbi][o] && adj[kfgop->_afbi][p] && adj[p][kfgop->_afbi])// fbi < afbi
        {
            if (o == kfgop->_fbi && p == kfgop->_afbi) return 1;
            return 0;
        }
        if (adj[o][kfgop->_g] && adj[kfgop->_g][o] && adj[kfgop->_afbi][p] && adj[p][kfgop->_afbi])// g < afbi
        {
            if (o == kfgop->_g && p == kfgop->_afbi) return 1;
            return 0;
        }
        if (adj[o][kfgop->_fbi] && adj[kfgop->_fbi][o] && adj[kfgop->_ag][p] && adj[p][kfgop->_ag])// a(g < afbi) = (fbi < ag)
        {
            return 0;
        }
        if (adj[o][kfgop->_g] && adj[kfgop->_g][o] && adj[kfgop->_afif][p] && adj[p][kfgop->_afif])// g < afif
        {
            if (o == kfgop->_g && p == kfgop->_afif) return 1;
            return 0;
        }
        if (adj[o][kfgop->_fif] && adj[kfgop->_fif][o] && adj[kfgop->_ag][p] && adj[p][kfgop->_ag])// a(g < afif) = (fif < ag)
        {
            return 0;
        }
        if (adj[o][kfgop->_fbi] && adj[kfgop->_fbi][o] && adj[kfgop->_bg][p] && adj[p][kfgop->_bg])// fbi < bg
        {
            if (o == kfgop->_fbi && p == kfgop->_bg) return 1;
            return 0;
        }
        if (adj[o][kfgop->_abg] && adj[kfgop->_abg][o] && adj[kfgop->_afbi][p] && adj[p][kfgop->_afbi])// a(fbi < bg) = (abg < afbi)
        {
            return 0;
        }

// If the function did not return a value our extender diagram is incomplete.

        printf("\n\nError: %d < %d showed up in the extender of kfg_ordering[%d].\n\n", o, p, m);
        exit(0);
    }
    return 0;// adding (o,p) did not result in a partial order.
}


// IsPosetKF() first checks whether adding (o,p) to the partial order represented by
// kf_ordering[m] results in a partial order.  It returns 0 if not or if (o,p) is
// equivalent to an edge in the extender diagram; otherwise it returns 1.

int IsPosetKF(KFenum *kfop, int m, int **adj, int **orig, int **tc, int o, int p)
{
    int q, r;

// To leave adj[][] = kf_ordering[m][] undisturbed, we copy it to the orig array.

    matrixCopy(adj,orig,34);

// We know orig[o][p] = 0 since otherwise IsPosetKF() would not have been called.
// Our first task is to check whether changing it to 1 yields a partial order.

    orig[o][p] = 1;

// Since (q,r) may exist such that q = o and r = p we also need to set orig[q][r] = 1 for
// all such (q,r).

    for (q=0; q<34; q++)
    {
        if (orig[o][q] && orig[q][o])
        {
            for (r=0; r<34; r++)
            {
                if (orig[r][p] && orig[p][r]) orig[q][r] = 1;
            }
        }
    }

// To determine whether these changes yield a partial order, we compare orig[][] with the
// transitive closure of a copy of it stored in the tc[][] array.

    matrixCopy(orig,tc,34);
    Warshall(tc,34);

    if (matrixEqual(orig,tc,34))    // (o,p) is in the extender
    {

// We only return 1 if (o,p) appears explicitly as an edge in the extender diagram.
// For efficiency, we ignore the global ordering and check, in decreasing order of
// frequency, every edge that appears at least once in some extender diagram.
// If we never find a match it means the extender diagram for kf_ordering[m] is
// incomplete, in which case the program exits with an error.

        if (adj[o][kfop->_i] && adj[kfop->_i][o] && adj[kfop->_ai][p] && adj[p][kfop->_ai])//   i < ai
        {
            if (o == kfop->_i && p == kfop->_ai) return 1;
            return 0;
        }
        if (adj[o][kfop->_ab] && adj[kfop->_ab][o] && adj[kfop->_b][p] && adj[p][kfop->_b])//   ab < b
        {
            if (o == kfop->_ab && p == kfop->_b) return 1;
            return 0;
        }

// If X is discrete the function should have now returned a value.
// We mark the completion of each global ordering like this:

//---------- D ----------

        if (adj[o][kfop->_if] && adj[kfop->_if][o] && adj[kfop->_id][p] && adj[p][kfop->_id])// if < id
        {
            if (o == kfop->_if && p == kfop->_id) return 1;
            return 0;
        }
        if (adj[o][kfop->_a] && adj[kfop->_a][o] && adj[kfop->_aif][p] && adj[p][kfop->_aif])// a(if < id) = (a < aif)
        {
            return 0;
        }
        if (adj[o][kfop->_if] && adj[kfop->_if][o] && adj[kfop->_aif][p] && adj[p][kfop->_aif])// if < aif
        {
            if (o == kfop->_if && p == kfop->_aif) return 1;
            return 0;
        }
        if (adj[o][kfop->_if] && adj[kfop->_if][o] && adj[kfop->_a][p] && adj[p][kfop->_a])// if < a
        {
            if (o == kfop->_if && p == kfop->_a) return 1;
            return 0;
        }
        if (adj[o][kfop->_id] && adj[kfop->_id][o] && adj[kfop->_aif][p] && adj[p][kfop->_aif])// a(if < a) = (id < aif)
        {
            return 0;
        }

//---------- P ----------

        if (adj[o][kfop->_fi] && adj[kfop->_fi][o] && adj[kfop->_afi][p] && adj[p][kfop->_afi])// fi < afi
        {
            if (o == kfop->_fi && p == kfop->_afi) return 1;
            return 0;
        }
        if (adj[o][kfop->_fb] && adj[kfop->_fb][o] && adj[kfop->_afb][p] && adj[p][kfop->_afb])// fb < afb
        {
            if (o == kfop->_fb && p == kfop->_afb) return 1;
            return 0;
        }

//---------- EO 2 and ED 2 ----------

        if (adj[o][kfop->_fi] && adj[kfop->_fi][o] && adj[kfop->_id][p] && adj[p][kfop->_id])// fi < id
        {
            if (o == kfop->_fi && p == kfop->_id) return 1;
            return 0;
        }
        if (adj[o][kfop->_a] && adj[kfop->_a][o] && adj[kfop->_afi][p] && adj[p][kfop->_afi])// a(fi < id) = (a < afi)
        {
            return 0;
        }
        if (adj[o][kfop->_fb] && adj[kfop->_fb][o] && adj[kfop->_id][p] && adj[p][kfop->_id])// fb < id
        {
            if (o == kfop->_fb && p == kfop->_id) return 1;
            return 0;
        }
        if (adj[o][kfop->_a] && adj[kfop->_a][o] && adj[kfop->_afb][p] && adj[p][kfop->_afb])// a(fb < id) = (a < afb)
        {
            return 0;
        }
        if (adj[o][kfop->_fi] && adj[kfop->_fi][o] && adj[kfop->_a][p] && adj[p][kfop->_a])// fi < a
        {
            if (o == kfop->_fi && p == kfop->_a) return 1;
            return 0;
        }
        if (adj[o][kfop->_id] && adj[kfop->_id][o] && adj[kfop->_afi][p] && adj[p][kfop->_afi])// a(fi < a) = (id < afi)
        {
            return 0;
        }
        if (adj[o][kfop->_fb] && adj[kfop->_fb][o] && adj[kfop->_a][p] && adj[p][kfop->_a])// fb < a
        {
            if (o == kfop->_fb && p == kfop->_a) return 1;
            return 0;
        }
        if (adj[o][kfop->_id] && adj[kfop->_id][o] && adj[kfop->_afb][p] && adj[p][kfop->_afb])// a(fb < a) = (id < afb)
        {
            return 0;
        }

//---------- EO 1 and ED 1 ----------

        if (adj[o][kfop->_fib] && adj[kfop->_fib][o] && adj[kfop->_id][p] && adj[p][kfop->_id])// fib < id
        {
            if (o == kfop->_fib && p == kfop->_id) return 1;
            return 0;
        }
        if (adj[o][kfop->_a] && adj[kfop->_a][o] && adj[kfop->_afib][p] && adj[p][kfop->_afib])// a(fib < id) = (a < afib)
        {
            return 0;
        }
        if (adj[o][kfop->_fib] && adj[kfop->_fib][o] && adj[kfop->_afib][p] && adj[p][kfop->_afib])// fib < afib
        {
            if (o == kfop->_fib && p == kfop->_afib) return 1;
            return 0;
        }
        if (adj[o][kfop->_ibi] && adj[kfop->_ibi][o] && adj[kfop->_id][p] && adj[p][kfop->_id])// ibi < id
        {
            if (o == kfop->_ibi && p == kfop->_id) return 1;
            return 0;
        }
        if (adj[o][kfop->_a] && adj[kfop->_a][o] && adj[kfop->_aibi][p] && adj[p][kfop->_aibi])// a(ibi < id) = (a < aibi)
        {
            return 0;
        }
        if (adj[o][kfop->_ibi] && adj[kfop->_ibi][o] && adj[kfop->_afi][p] && adj[p][kfop->_afi])// ibi < afi
        {
            if (o == kfop->_ibi && p == kfop->_afi) return 1;
            return 0;
        }
        if (adj[o][kfop->_fi] && adj[kfop->_fi][o] && adj[kfop->_aibi][p] && adj[p][kfop->_aibi])// a(ibi < afi) = (fi < aibi)
        {
            return 0;
        }
        if (adj[o][kfop->_fib] && adj[kfop->_fib][o] && adj[kfop->_a][p] && adj[p][kfop->_a])// fib < a
        {
            if (o == kfop->_fib && p == kfop->_a) return 1;
            return 0;
        }
        if (adj[o][kfop->_id] && adj[kfop->_id][o] && adj[kfop->_afib][p] && adj[p][kfop->_afib])// a(fib < a) = (id < afib)
        {
            return 0;
        }

//---------- OU ----------

        if (adj[o][kfop->_fb] && adj[kfop->_fb][o] && adj[kfop->_bib][p] && adj[p][kfop->_bib])// fb < bib
        {
            if (o == kfop->_fb && p == kfop->_bib) return 1;
            return 0;
        }
        if (adj[o][kfop->_abib] && adj[kfop->_abib][o] && adj[kfop->_afb][p] && adj[p][kfop->_afb])// a(fb < bib) = (abib < afb)
        {
            return 0;
        }
        if (adj[o][kfop->_id] && adj[kfop->_id][o] && adj[kfop->_bib][p] && adj[p][kfop->_bib])// id < bib
        {
            if (o == kfop->_id && p == kfop->_bib) return 1;
            return 0;
        }
        if (adj[o][kfop->_abib] && adj[kfop->_abib][o] && adj[kfop->_a][p] && adj[p][kfop->_a])// a(id < bib) = (abib < a)
        {
            return 0;
        }

//---------- KD ----------

        if (adj[o][kfop->_fib] && adj[kfop->_fib][o] && adj[kfop->_bi][p] && adj[p][kfop->_bi])// fib < bi
        {
            if (o == kfop->_fib && p == kfop->_bi) return 1;
            return 0;
        }
        if (adj[o][kfop->_abi] && adj[kfop->_abi][o] && adj[kfop->_afib][p] && adj[p][kfop->_afib])// a(fib < bi) = (abi < afib)
        {
            return 0;
        }
        if (adj[o][kfop->_fif] && adj[kfop->_fif][o] && adj[kfop->_bi][p] && adj[p][kfop->_bi])// fif < bi
        {
            if (o == kfop->_fif && p == kfop->_bi) return 1;
            return 0;
        }
        if (adj[o][kfop->_abi] && adj[kfop->_abi][o] && adj[kfop->_afif][p] && adj[p][kfop->_afif])// a(fif < bi) = (abi < afif)
        {
            return 0;
        }
        if (adj[o][kfop->_fif] && adj[kfop->_fif][o] && adj[kfop->_aib][p] && adj[p][kfop->_aib])// fif < aib
        {
            if (o == kfop->_fif && p == kfop->_aib) return 1;
            return 0;
        }
        if (adj[o][kfop->_ib] && adj[kfop->_ib][o] && adj[kfop->_afif][p] && adj[p][kfop->_afif])// a(fif < aib) = (ib < afif)
        {
            return 0;
        }
        if (adj[o][kfop->_fif] && adj[kfop->_fif][o] && adj[kfop->_id][p] && adj[p][kfop->_id])// fif < id
        {
            if (o == kfop->_fif && p == kfop->_id) return 1;
            return 0;
        }
        if (adj[o][kfop->_a] && adj[kfop->_a][o] && adj[kfop->_afif][p] && adj[p][kfop->_afif])// a(fif < id) = (a < afif)
        {
            return 0;
        }
        if (adj[o][kfop->_fif] && adj[kfop->_fif][o] && adj[kfop->_afib][p] && adj[p][kfop->_afib])// fif < afib
        {
            if (o == kfop->_fif && p == kfop->_afib) return 1;
            return 0;
        }
        if (adj[o][kfop->_fib] && adj[kfop->_fib][o] && adj[kfop->_afif][p] && adj[p][kfop->_afif])// a(fif < afib) = (fib < afif)
        {
            return 0;
        }
        if (adj[o][kfop->_fif] && adj[kfop->_fif][o] && adj[kfop->_afbi][p] && adj[p][kfop->_afbi])// fif < afbi
        {
            if (o == kfop->_fif && p == kfop->_afbi) return 1;
            return 0;
        }
        if (adj[o][kfop->_fbi] && adj[kfop->_fbi][o] && adj[kfop->_afif][p] && adj[p][kfop->_afif])// a(fif < afbi) = (fbi < afif)
        {
            return 0;
        }
        if (adj[o][kfop->_fbi] && adj[kfop->_fbi][o] && adj[kfop->_id][p] && adj[p][kfop->_id])// fbi < id
        {
            if (o == kfop->_fbi && p == kfop->_id) return 1;
            return 0;
        }
        if (adj[o][kfop->_a] && adj[kfop->_a][o] && adj[kfop->_afbi][p] && adj[p][kfop->_afbi])// a(fbi < id) = (a < afbi)
        {
            return 0;
        }
        if (adj[o][kfop->_fbi] && adj[kfop->_fbi][o] && adj[kfop->_aib][p] && adj[p][kfop->_aib])// fbi < aib
        {
            if (o == kfop->_fbi && p == kfop->_aib) return 1;
            return 0;
        }
        if (adj[o][kfop->_ib] && adj[kfop->_ib][o] && adj[kfop->_afbi][p] && adj[p][kfop->_afbi])// a(fbi < aib) = (ib < afbi)
        {
            return 0;
        }
        if (adj[o][kfop->_fib] && adj[kfop->_fib][o] && adj[kfop->_afbi][p] && adj[p][kfop->_afbi])// fib < afbi
        {
            if (o == kfop->_fib && p == kfop->_afbi) return 1;
            return 0;
        }
        if (adj[o][kfop->_fbi] && adj[kfop->_fbi][o] && adj[kfop->_afib][p] && adj[p][kfop->_afib])// a(fib < afbi) = (fbi < afib)
        {
            return 0;
        }
        if (adj[o][kfop->_fif] && adj[kfop->_fif][o] && adj[kfop->_afif][p] && adj[p][kfop->_afif])// fif < afif
        {
            if (o == kfop->_fif && p == kfop->_afif) return 1;
            return 0;
        }
        if (adj[o][kfop->_fbi] && adj[kfop->_fbi][o] && adj[kfop->_afbi][p] && adj[p][kfop->_afbi])// fbi < afbi
        {
            if (o == kfop->_fbi && p == kfop->_afbi) return 1;
            return 0;
        }
        if (adj[o][kfop->_fib] && adj[kfop->_fib][o] && adj[kfop->_bif][p] && adj[p][kfop->_bif])// fib < bif
        {
            if (o == kfop->_fib && p == kfop->_bif) return 1;
            return 0;
        }
        if (adj[o][kfop->_abif] && adj[kfop->_abif][o] && adj[kfop->_afib][p] && adj[p][kfop->_afib])// a(fib < bif) = (abif < afib)
        {
            return 0;
        }
        if (adj[o][kfop->_fbi] && adj[kfop->_fbi][o] && adj[kfop->_bif][p] && adj[p][kfop->_bif])// fbi < bif
        {
            if (o == kfop->_fbi && p == kfop->_bif) return 1;
            return 0;
        }
        if (adj[o][kfop->_abif] && adj[kfop->_abif][o] && adj[kfop->_afbi][p] && adj[p][kfop->_afbi])// a(fbi < bif) = (abif < afbi)
        {
            return 0;
        }
        if (adj[o][kfop->_fif] && adj[kfop->_fif][o] && adj[kfop->_a][p] && adj[p][kfop->_a])// fif < a
        {
            if (o == kfop->_fif && p == kfop->_a) return 1;
            return 0;
        }
        if (adj[o][kfop->_id] && adj[kfop->_id][o] && adj[kfop->_afif][p] && adj[p][kfop->_afif])// a(fif < a) = (id < afif)
        {
            return 0;
        }
        if (adj[o][kfop->_fbi] && adj[kfop->_fbi][o] && adj[kfop->_a][p] && adj[p][kfop->_a])// fbi < a
        {
            if (o == kfop->_fbi && p == kfop->_a) return 1;
            return 0;
        }
        if (adj[o][kfop->_id] && adj[kfop->_id][o] && adj[kfop->_afbi][p] && adj[p][kfop->_afbi])// a(fbi < a) = (id < afbi)
        {
            return 0;
        }

// If the function did not return a value our extender diagram is incomplete.

        printf("\n\nError: %d < %d showed up in the extender of kf_ordering[%d].\n\n", o, p, m);
        exit(0);
    }
    return 0;// adding (o,p) did not result in a partial order.
}
