Creativistic Philosophy: Exploring the Limits of Formalization, #3–Patterns and Algorithms.
By Andreas Keller
***
Creativistic Philosophy: Exploring the Limits of Formalization, #3–Patterns and Algorithms[ii]
1. Introduction
The idea that mathematics can be used to describe parts of reality originated in antiquity,[iii] but it only took a central role during what is called the “scientific revolution” in the 17th century, especially with Newton’s Principia Mathematica.[iv] Following this example, natural philosophers, who later, in the 1830s, started calling themselves “scientists,” learned to create mathematical theories describing ever larger parts of physical reality.
This general approach enabled them to compute many aspects of the systems at hand. Often, at the center of such theories there are systems of equations. However, it is not always easy to do the calculations, or “solve” the equations. In many cases, methods to solve the equations are not known or sometimes can even be shown not to exist. Scientists often have to be content with simplified models and approximate solutions. So, are there limits to what can be computed and what can be formalized?
The answer is actually “yes.” Formalization and calculation have their limits, and I will suggest that the boundary between the “exact sciences” on the one hand and philosophy and less exact (and more philosophical) academic subjects on the other essentially runs along these boundaries of formalizability.
But exploring that topic will be the subject of a later installment. Before I look into the relationship between exact science and philosophy, I want to explore the topic of computability with simple examples, so that we can get a more exact, but at the same time intuitive, understanding about what these limits are.
2. Limits of Formalization — Exploring Simple Examples
In this and the following instalments, we will first look at something simple: the set of natural numbers. I will first explore simple computable properties, or predicates, of natural numbers, like “odd,” “even,” “prime,” etc. Subsequently, we will expand this investigation and look at computable functions that map natural numbers to natural numbers. Later, we will see how what we have learnt this way can be applied to computable functions that have arbitrary types of data as inputs and outputs. To do so, we will look at what is called “Gödel numbers,” by which arbitrary data can be coded as natural numbers. This will enable us to apply the insights gained to things like learning algorithms, LLMs (“large language models”) and other AI systems.
Only very little mathematical knowledge is required to understand these considerations. I am going to explain things in small steps. For readers who are familiar with mathematics and skilled in it, the presentation may be too simple in places and therefore perhaps boring at times, but I want it to be understandable for as many potential readers as possible. Schoolchildren who are just learning mathematics should be able to follow the reasoning.
I am going to use the notions of “formal theory” or “algorithm” interchangeably. You can think of an algorithm as a computer program, an app, written in some programming language.
The set of natural numbers appears simple. We generate these numbers by counting. We start with 1, and for each number, we can produce its successor: from 1 we count to 2, from 2 to 3, and so-on.
We can assign properties to numbers. For example, we can say that a number is odd, that it is even, that it is smaller than another number, etc. It seems easy to write a program that produces statements about natural numbers. For example, we could write a program that tells us whether a number given to it as an input is even. For example, if we represent the numbers in the normal decimal notation, as a string of digits, we can just look at the last digit. If it is one of the digits 0, 2, 4, 6, or 8, the number is even.
Such an algorithm can give us one of two values, “true,” if the input is an even number, and “false” if it is not. It could produce statements like “1 is not even,” “2 is even,” etc. Another version of such an algorithm could give us some more compact notation like 1f, 2t, 3f, 4t, etc. (where the number represents the input, f the result “false” and t the result “true”), or it could just only produce the output values f and t, producing an output sequence “ftftftft…” for the input sequence 1, 2, 3, 4, etc. In a way, the programs producing these different outputs are equivalent since one of them could easily be turned into the other.
We can go one step further and write a program that fills a table: In the first column, every number that can be divided (without remainder) by 1 is marked with “true.” Well, that is every number. In the second column, every number that is divisible by 2 is marked with “true” (this column describes the even numbers). In the third column, every number divisible by 3 is marked with true, etc.
In the following graphic, the truth value “true” is represented by black rectangles, “false” by white ones. The dots indicate that the table continues, i.e. we can generate as many additional lines and columns as we want and as our resources, like time and storage space, allow.
Somebody who has learnt to write programs can easily write a program that will fill such a table. We can start in the upper left corner, with the “1,1”-rectangle. Then we could fill the two adjacent rectangles “2,1” (that is the one below the first one) and “1,2” (first line, second column), then we continue with “3,1”, “2,2”, and “1,3”, and so-on. The following graphic shows in which sequence the fields will be filled:
Using such a method we can fill the table as far as we want. There are other possible ways to go through all fields of such a table systematically, but in any case, this method works.
Each of the columns of this table represents a predicate on natural numbers. More specifically, a predicate with one variable: x is divisible by 1 (column 1), x is divisible by 2 (column 2), x is divisible by 3 (column 3), and so-on. We can also view the whole table as representing a predicate with two variables “x is divisible by y.”
We can think of an algorithm that can fill this table as an algorithm that enumerates the predicates that are represented by the columns. Since it will sooner or later fill every field of the table, it can compute all of these predicates, so these are not just predicates on the natural numbers, they are also computable predicates.[v] We can, therefore, take the table algorithm and derive algorithms for calculating each column from it. It can thus be viewed as (or be turned into) an algorithm that enumerates algorithms for each column.[vi]
What we can see in the table is that the algorithm produces a pattern. Each of the columns can also be viewed as a pattern. If you know how to program in one of the common programming languages, you will probably be able to write a program producing this table with less than a page of program code. The algorithm can be formulated as a finite text, i.e. a string of symbols (letters, numbers, special characters) in a programming language. So, it contains a finite — and in this simple case, small — amount of information. We can think of the length of this program text as a measure for the complexity of the pattern. I will come back to that idea in a later instalment.
It is possible to represent the whole table as a string of symbols in some notation as well. We could, for example, write the line- and column numbers in decimal notation, separated by a comma, and then the letter “t” for true or “f” for false. So, for each field of the table, we can have something like “1,1,t”, “2,1,t”, “1,2,f”, “3,1,t”, “2,2,t”, “1,3,f” and so-on. If we assume a standard way to go through all fields of the table, like the one described above, we can write this just as a string of letters representing the truth values assigned to the fields of the table in the order we go through them, like “ttfttftfff…” and so-on.
If we let the algorithm run for some time and fill in the table more and more, the total amount of data it generates will, at some point, become larger than the algorithm’s own length as a program text. We can then view the algorithm generating this data as a compressed description of this data.
Data compression requires that the data contains some regularity. It must be, in some more or less complex way, patterned or repetitive. In the algorithm describing this regularity, this repetitiveness will show up in the form of loops[vii] that go through the same sequence of operations repeatedly.
Let us summarize a number of insights we could get out of this simple example and hint at some further ideas that will be explored in later installments:
- An algorithm describes a pattern.
- An algorithm contains a finite amount of information. Viewed as a text in a programming language, it has a finite length.
- A short algorithm can produce an output that is much longer than itself (in fact, an arbitrarily long output) by means of loops or other programming language constructs that enable it to go through the same operations repeatedly. This results in the data generated by it to show regularities, i.e. to be patterned.
- An algorithm can be viewed as a compressed form of the data it produces or “describes” (if the amount of data produced is larger than the size of the algorithm).
- We could think of the compression of the data into the algorithm as a process of folding or rolling up the data, resulting in the loop structure of the algorithm. Conversely, we can imagine the generation of data by the running program as an unfolding or rolling out that leaves the output data as a track.
- The algorithm can be viewed as a description of the pattern or regularity of the generated data. We can think of it as knowledge describing that data.
- An algorithm producing a table like the one in the example can be viewed as producing an enumeration (i.e. a numbered sequence) of algorithms for the functions described by each column (in this case, simple one-variable predicates).
In the next installment, we will see that if we have such a table of predicates (or an algorithm producing such a table) and we are given another predicate or set of predicates (e.g., described by another algorithm), we can merge such a predicate or set of predicates into the existing table, i.e. produce a (perhaps more complex) algorithm that produces a more complex pattern containing all columns from both initial sets.
This leads to the question whether it is possible to construct an algorithm that is universal, i.e. that contains all possible computable predicates merged into one super-table or super-pattern. I will introduce a simple trick, called “diagonalization,” by which we can always produce a new predicate (column) not contained in a given table. Using that, we will see that a universal table or algorithm cannot exist, i.e., it is not possible to enumerate all the computable predicates with a single algorithm. Since the fields of such a table represent simple statements about natural numbers, like “2 is even” or “19 is divisible by 3,” this means it is not possible to derive all computable true statements (and only these) about natural numbers by means of a single algorithm. We are going to see that every such algorithm is incomplete, i.e., there are always more true and computable statements about the natural numbers than can be calculated by any single algorithm or can be derived within any single formal theory.
As we shall see later, this result points towards the limits of formalizability and the limits of artificial intelligence.
REFERENCES
(Keller, 2025). Keller, A. “Creativistic Philosophy: Exploring the Limits of Formalization, #2. — From Astrology to ‘Artificial Intelligence’” Against Professional Philosophy. 17 August. Available online at URL = <https://againstprofphil.org/2025/08/17/creativistic-philosophy-exploring-the-limits-of-formalization-2-from-astrology-to-artificial-intelligence/>.
(Smith, 2024) Smith, G. “Newton’s Philosophiae Naturalis Principia Mathematica.” In E.N. Zalta and U. Nodelman (eds.), The Stanford Encyclopedia of Philosophy. Winter Edition. Available online at URL = <https://plato.stanford.edu/archives/win2024/entries/newton-principia/>.
(Wikimedia, 2006) Wikimedia. “Various Spirograph Designs.”Avaliable online at URL = <https://commons.wikimedia.org/wiki/File:Various_Spirograph_Designs.jpg>.
NOTES
[i] The image shows various patterns produced with a Spirograph, a toy from the era before personal computers became available. The Spirograph can be used as a metaphor for algorithms that produce patterns — and can, of course, be simulated by computer programs.
[ii] © Andreas Keller 2025. All rights reserved, including the right to use this text or sections or translations thereof as training data or part of training data of AI systems or machine learning systems. Using this work or parts thereof as training data or part of training data of an AI system or machine learning system requires prior written permission by the author.
[iii] See also (Keller, 2025).
[iv] (Smith, 2024).
[v] In later installments, we will see that predicates that are not computable can actually be defined.
[vi] We can easily produce an algorithm for the column with a certain column number n (e.g., n = 5) by wrapping a small program around the table algorithm that lets it run and that only output those results that have the column number 5, discarding all other outputs. This would be a very inefficient solution and there are smarter ways of doing this, but it would always work.
[vii] Or some other equivalent notion, like “recursivity,” depending on the programming language, but these technical details don’t need to concern us here.
***
AGAINST PROFESSIONAL PHILOSOPHY REDUX 1036
Mr Nemo, W, X, Y, & Z, Monday 8 September 2025
Against Professional Philosophy is a sub-project of the online mega-project Philosophy Without Borders, which is home-based on Patreon here.
Please consider becoming a patron!
