The easiest way to define topologies is to read them from a list. Complete lists of inequivalent (non-homeomorphic) topological spaces on $n$ points for $2\leq n\leq7$ and $T_0$ topological spaces on 8 and 9 points can be found here:
https://www.mathtransit.com/finite_topological_spaces.php
The C program below can be used to get more spaces. It calculates the transitive closure of a reflexive relation using Warshall's algorithm. A good introduction to this subject can be found here:
https://www.jstor.org/stable/2689890
#include <stdio.h>
#include <stdlib.h>
unsigned long closure(unsigned long *cl, unsigned long set);
unsigned long complement(unsigned long set);
unsigned long interior(unsigned long *cl, unsigned long set);
unsigned long maxbits = (unsigned long) (8*sizeof(unsigned long)); // sizeof() returns byte count
unsigned long *twopower; // twopower[i] = 2^i
int spacesize; // cardinality of topological space
int main(int argc, const char **argv)
{
twopower = (unsigned long *)malloc(maxbits * sizeof(unsigned long));
if (twopower == 0)
{
printf("\nCould not allocate space for twopower array.\n");
exit(0);
}
twopower[0] = 1;
for (int k=1; k<maxbits; k++) twopower[k] = 2*twopower[k-1];
spacesize = 10;
if (spacesize > maxbits)
{
printf("\nSpace cardinality cannot exceed maxbits.\n");
exit(0);
}
int **adjacency_matrix, row, col;
adjacency_matrix = (int **)malloc(spacesize * sizeof(int *));
if (adjacency_matrix==0)
{
printf("Could not allocate space for adjacency matrix.");
exit(0);
}
for (row=0; row<spacesize; row++)
{
adjacency_matrix[row] = (int *)malloc(spacesize * sizeof(int));
if (adjacency_matrix[row]==0)
{
printf("Could not allocate space for row %d.", row);
exit(0);
}
}
/*
* Randomly generate adjacency matrix of reflexive relation R:
*/
int discretion = 8; // higher discretion => more 0's
for (row=0; row<spacesize; row++)
for (col=0; col<spacesize; col++)
{
if (col == row) adjacency_matrix[row][col] = 1; // this makes R reflexive
else adjacency_matrix[row][col] = !(rand() % discretion);
}
/*
* Use Warshall's algorithm to get transitive closure of R (preserves reflexivity):
*/
int mid;
for (mid=0; mid<spacesize; mid++)
for (row=0; row<spacesize; row++)
for (col=0; col<spacesize; col++)
adjacency_matrix[row][col] = adjacency_matrix[row][col] || (adjacency_matrix[row][mid] && adjacency_matrix[mid][col]);
/*
* We now have the adjacency matrix of a preorder, i.e., topological space.
*
* Assuming space = {0,...,spacesize-1} and subsets are represented by bit strings of length spacesize,
* we define closure of singleton {x} as
*
* cl[x] = binary integer obtained by reversing row x (where rows are numbered 0,...,spacesize-1) of adjacency matrix.
*
* Reversing the bits gives us the nice property that point x belongs to set S iff S & 2^x = 2^x.
*
* Next we calculate cl[x] for x = 0,...,spacesize-1:
*/
unsigned long *cl;
cl = (unsigned long *)malloc(spacesize * sizeof(unsigned long));
if (cl==0)
{
printf("Could not allocate space for closures of singletons.");
exit(0);
}
for (row=0; row<spacesize; row++)
{
cl[row] = 0;
for (col=0; col<spacesize; col++)
cl[row] = cl[row] + adjacency_matrix[row][col] * twopower[col];
}
/*
* [do experiments here]
*/
free(cl);
for (row=0; row<spacesize; row++) free(adjacency_matrix[row]);
free(adjacency_matrix);
free(twopower);
return EXIT_SUCCESS;
}
unsigned long closure(unsigned long *cl, unsigned long set)
{
int i;
unsigned long closure = 0;
for (i=0; i<spacesize; i++)
if (set & twopower[i]) closure = closure | cl[i];
return closure;
}
unsigned long complement(unsigned long set)
{
unsigned long complement, space = twopower[spacesize]-1;
complement = ~set & space;
return complement;
}
unsigned long interior(unsigned long *cl, unsigned long set)
{
unsigned long interior;
interior = closure(cl, set);
interior = complement(interior);
interior = closure(cl, interior);
return interior;
}