How to define a finite topological space? I want to develop a simple way to define topologies on finite sets
$X=\{1,2,\dots,n\}$ for computational experiments. 

Does any function $c:X\to \mathcal P(X)$, such that $x\in c(x)$,
  define a closure operator on $X$?

The idea is that $c$ should define a closure operator by
$$\mathrm{cl}(\{x_1,\cdots,x_m\})=\overline{\{x_1,\cdots,x_m\}}=\bigcup_{k=1}^{m} c(x_k)$$
 A: You need an additional property to guarantee that the closure operator will be idempotent. Requiring
$$x \in c(y) \Rightarrow c(x) \subseteq c(y)$$
in addition to  $x \in c(x)$ is necessary and sufficient.
A: It's sufficient to define a relation $x \le y$, the specialisation order, (so just a subset of $X^2$), which is a pre-order, so $x \le x$ for all $x$,and $x \le y$ and $y \le z$ implies $x \le z$. ($\le$ is reflexive and transitive).
This relation is defined in a topological space by $x \le y$ iff $x \in \overline{\{y\}}$. But if we start with a preorder $\le$, we can define a topology: $\overline{\{y\}}$ is then defined by $\downarrow y = \{x \in X: x \le y\}$ and $\overline{A} = \cup_{x \in A}\downarrow x$. 
The set of finite topological spaces is just the set of finite pre-orders.
A: No. First of all, it must be a function $c\colon\mathcal{P}(X)\longrightarrow\mathcal{P}(X)$. Besides, it must satisfy these conditions:


*

*$A\in\mathcal{P}(X)\Longrightarrow A\subset c(A)$;

*$A,B\in\mathcal{P}(X)\wedge A\subset B\Longrightarrow c(A)\subset c(B)$;

*$A\in\mathcal{P}(X)\Longrightarrow c\bigl(c(A)\bigr)=c(A)$.

A: If you want a simple way to define finite topological spaces, the simplest ones are nothing more that a chain of inclusions:
$\emptyset \subset A_1 \subset A_2 \dots \subset A_n ( = X) $
The ${A_i}^{'}s$ are your closed sets.
This doesn't describe all topologies on $X$ , but it may be useful for your experiments.
A: 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;
}

A: Starting with an arbitrary function $c:X\to\mathcal P(X)$ such that $\forall x\in X:x\in c(x)$, this should be an algorithm to transform $c$ to a function that defines a closure operator, due to the accepted answer:
$0:\quad$ $\mathrm{ready}\leftarrow\mathrm{true}$
$1:\quad$ $i\leftarrow 1$
$2:\quad$ $j\leftarrow 1$
$3:\quad$ if $i\in c(j)$ and $c(i)\cap c(j)\neq c(i)$ then $c(j)\leftarrow c(j)\cup c(i)$ ; $\mathrm{ready}\leftarrow\mathrm{false}$
$4:\quad$ $j\leftarrow j+1$
$5:\quad$ if $j\leq n$ then goto $3$
$6:\quad$ $i\leftarrow i+1$
$7:\quad$ if $i\leq n$ then goto $2$
$8:\quad$ if not ready then goto $0$  
