Saturday, April 30, 2022

Visualising prime distributions with JavaFX

Let $n \in \mathbb{N}$ be a natural number greater then zero $n > 0$. Then by the fundamental theorem of arithmetic $n$ is associated to a multiset of prime factors. By the relative multiplicities of this multiset, this number is always associated to a prime distribution. We can display these prime distributions using JavaFX.
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.scene.chart.*;
import org.apache.commons.collections4.multiset.HashMultiSet;
import org.apache.commons.math3.primes.Primes;
import java.util.ArrayList;
import java.util.HashMap;

public class PrimeDistributionChart extends  Application {
    public HashMap primeDistribution(int n) {
        var factors = new HashMultiSet(Primes.primeFactors(n));
        double bigomega = (double) factors.size();
        var rval = new HashMap();

        for(var i : factors.entrySet()) {
            rval.put(i.getElement(), ((double) i.getCount()) / bigomega);
        }

        return rval;
    }

    public void start(Stage primaryStage) throws Exception {
        // this is the number to be factorised
        var initialNumber = 360;
       
        // create the prime distribution 
        var dist = primeDistribution(initialNumber);
        var dataCollection = new ArrayList();
        for(var i : dist.entrySet()) {
            var keyString = i.getKey().toString();
            var data = new PieChart.Data(keyString, i.getValue());
            dataCollection.add(data);
        }

        // make the prime distribution into a pie chart
        ObservableList pieChartData =
                FXCollections.observableArrayList(dataCollection);
        var chart = new PieChart(pieChartData);

        // put the pie chart in a stackpane
        var group = new StackPane();
        group.getChildren().add(chart);

        // set up the scene
        var scene = new Scene(group, 500,450);
        primaryStage.setScene(scene);
        primaryStage.setTitle("Prime distribution");
        primaryStage.show();

    }

    public static void main(String[] args) {
        launch(args);
    }
}

Here is an example of the prime distribution of three hundred and sixty: You can easily change this program to display the prime distribution of any non zero natural number.

Friday, April 29, 2022

Opening JavaFX hyperlinks in the browser

Suppose you have a hyperlink in your JavaFX application. Then you can make it clickable using the HostServices provided by JavaFX.
package application;
import javafx.application.Application;
import javafx.application.HostServices;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Hyperlink;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class HyperLinkExample extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {

        var linkLocation = "http://www.lisp-ai.blogspot.com";
        Hyperlink hp = new Hyperlink(linkLocation);
        var root = new StackPane();
        HostServices services = this.getHostServices();

        hp.setOnAction(new EventHandler() {
            @Override
            public void handle(ActionEvent actionEvent) {
                services.showDocument(linkLocation);
            }
        });

        root.getChildren().add(hp);
        Scene scene=new Scene(root,400,300);
        primaryStage.setScene(scene);
        primaryStage.setTitle("Clickable hyperlinks");
        primaryStage.show();

    }

}

The resulting JavaFX application looks like this: The idea of opening up a separate browser window for a hyperlink provides an alternative to using the JavaFX webview.

Thursday, April 28, 2022

Displaying the Locus ontology with Protege

An ontology of set systems with hundreds of computable classes and their inclusions is available on github. It looks like this when seen in Protege: An upper ontology based upon set theory would primarily be concerned with set systems like these and their relations to one another. I have concluded, however, that categorical logic and topos theory provide a better foundation for mathematical ontologies.

Tuesday, April 26, 2022

Using apache commons exec from Clojure

One of the strong points of Clojure is its ability to handle markup languages like HTML, so I figure why not demonstrate the apache commons exec library by opening up a browser window to display hiccup generated HTML.
(ns executor.core
  (:use (hiccup core))
  (:import [org.apache.commons.io FileUtils]
           [org.apache.commons.exec CommandLine DefaultExecutor]
           (java.io File)
           (java.nio.charset StandardCharsets)))

; hiccup generated html
(def page-data
  [:html
   [:head
    [:title "Group rings"]]
   [:body
    "Let G be a group and R a ring then R[G] is its group ring."]])

; store the html on the file system first
(defn ^File create-temp-file
  [html-data]

  (let [tmp (FileUtils/getTempDirectory)
        out-file (new File (str (.getPath tmp) "/out.html"))]
    (FileUtils/write out-file (html html-data) StandardCharsets/UTF_8)
    out-file))

; display the temp file in the browser
(defn display-temp-file
  [file]

  (let [cmdLine (new CommandLine "firefox")]
    (.addArgument cmdLine (.getPath file))
    (let [executor (new DefaultExecutor)]
      (.execute executor cmdLine))))

; Create a file and display it at the same time
(defn display-html
  [data]

  (display-temp-file (create-temp-file data)))

Another possibility is that you can display generated HTML using Swing. In either case, it is relatively easy to open up some kind of window to display an HTML document. Apache commons exec can be used to open up all kinds of processes from Clojure.

External links:
Apache commons exec

Sunday, April 24, 2022

Compilation of Java operators

When implementing a language on the JVM, inevitably you are going to want to implement a similar set of basic operators as those provided by the Java language. Most of these Java operators correspond one-to-one with their JVM counterparts, so in this post I will focus only on the interesting tidbits.

Addition

The addition operator is one interesting case where Java doesn't directly correspond to its underlying bytecode. In the case when you are adding two integers it does, but for Strings it produces a different command using invokedynamic instead.
class ArithmeticOperators {
	
	// special behaviour of addition
	public static int add(int n, int m) {
		return n + m;
	}
	
	public static String add(String n, String m) {
		return n + m;
	}

}
We are then going to be looking at compiled bytecode like this:
  public static int add(int, int);
    Code:
       0: iload_0
       1: iload_1
       2: iadd
       3: ireturn

  public static java.lang.String add(java.lang.String, java.lang.String);
    Code:
       0: aload_0
       1: aload_1
       2: invokedynamic #7,  0              // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
       7: areturn
This demonstrates that whilst addition operates normally on integers, it produces a special invokedynamic instruction on Strings using the java.lang.invoke.StringConcatFactory. This is a special change of Java 9 because before that it used StringBuilders as you would expect.

Bitwise not

There is no bitwise not operator on the JVM, so that is another case where there is a slight difference between language and bytecode.
class BitwiseOperators { 
	public static int bitwiseCompliment(int n) {
		return ~n;
	}   
}
Of course, we can get around this by using bitwise not with negative one which happens to be the largest bit set in the twos complement representation of integers.
  public static int bitwiseCompliment(int);
    Code:
       0: iload_0
       1: iconst_m1
       2: ixor
       3: ireturn
So thats pretty easy to get around using the bitwise xor operator. All the other bitwise operators like &, |, ^ all compile directly to their corresponding JVM opcodes: and, or, xor, etc. The only difference is that the static type information determines the exact opcode for the JVM type system.

Logical operators

There are no logical operators in the JVM instruction set. This is very easy to get around using conditional jump instructions like this.
class LogicalOperators {
	public static boolean logicalAnd(boolean x, boolean y) {
		return x && y;
	}
	
	public static boolean logicalOr(boolean x, boolean y) {
		return x || y;
	}
	
	public static boolean logicalNot(boolean x) {
		return !x;
	}
}
The ifeq operator in fact only checks if the top value on the stack is zero. So to implement logicalAnd we simply perform two checks on each value to see if they are zero, and in either case we return false and otherwise we return one. The logical or does the same thing but it checks for truth instead. The conditional jumps implement short-circuiting evaluation.
  public static boolean logicalAnd(boolean, boolean);
    Code:
       0: iload_0
       1: ifeq          12
       4: iload_1
       5: ifeq          12
       8: iconst_1
       9: goto          13
      12: iconst_0
      13: ireturn

  public static boolean logicalOr(boolean, boolean);
    Code:
       0: iload_0
       1: ifne          8
       4: iload_1
       5: ifeq          12
       8: iconst_1
       9: goto          13
      12: iconst_0
      13: ireturn

  public static boolean logicalNot(boolean);
    Code:
       0: iload_0
       1: ifne          8
       4: iconst_1
       5: goto          9
       8: iconst_0
       9: ireturn
So we can get around the lack of dedicated JVM opcodes for logical operators by using conditional jumps. The basic point is that the operators && and || are short circuiting so they need to be implemented using conditional jumps.

Assignment operators

The assignment operator = in the Java programming language is not as simple as you would think because it takes into account lvalues. Assignment operators can be compiled to putfield,putstatic,store, or astore depending upon the context.
import java.awt.Point;

class AssignmentOperators { 
	public static void assignment(Point[][] coll) {
		coll[0][0].x = 10;
	}
}
This modifies the value of the x field in the Point class by first getting the place in the array in which it is stored using aaload.
  public static void assignment(java.awt.Point[][]);
    Code:
       0: aload_0
       1: iconst_0
       2: aaload
       3: iconst_0
       4: aaload
       5: bipush        10
       7: putfield      #7                  // Field java/awt/Point.x:I
      10: return
So this demonstrates the lvalue support in the javac language compiler, which goes a long way to making Java as nice as it is to use. You have a unified interface which saves you from having to worry about the differences between global variables, local variables, array locations, and instance fields.

Relational operators

Instead of relational operators, the JVM has conditional jump opcodes like ifeq, ifne, ifgt, ifge, ifle, and iflt. There is a pretty straight forward translation from the relational operators to their JVM conditional jump instructions.

References:
String Concatenation with Invoke Dynamic

Saturday, April 23, 2022

Computing the totient function by prime factorisation

The totient function $\phi(x)$ could be implemented by using prime factorisation, rather then manually iterating through all the totatives of a number. Then the only issue is making sure that the prime factorisation algorithm is fast, but I think that is going to be pretty good since it comes from apache commons math.

import org.apache.commons.math3.primes.Primes;
import org.apache.commons.math3.util.ArithmeticUtils;
import org.apache.commons.collections4.multiset.HashMultiSet;
import java.util.ArrayList;

public class Totatives {

    public static boolean isCoprime(int n, int m) {
        return (ArithmeticUtils.gcd(n,m) == 1);
    }

    public static ArrayList totatives(int n) {
        var rval = new ArrayList();

        for(int i = 1; i <= n; i++) {
            if(isCoprime(i,n)) {
                rval.add(i);
            }
        }

        return rval;
    }

    public static int totativesCount(int n) {
        return totatives(n).size();
    }

    public static int eulersTotientFunction(int n) {
        if(n == 1) {
            return 1;
        }

        HashMultiSet m = new HashMultiSet(Primes.primeFactors(n));
        var s = m.entrySet();

        int rval = 1;

        for(var i : s) {
            int p = i.getElement();
            int k = i.getCount();
            rval *= (Math.pow(p,k)-Math.pow(p,k-1));
        }

        return rval;
    }

    public static void main(String[] args) {

        // test for equality
        for(int i = 1; i < 100; i++) {
            if(eulersTotientFunction(i) != totativesCount(i)) {
                System.out.println("Failed at: " + i);
            }
        }

    }

}

The one issue with the primeFactors method is that it outputs a List rather then a Multiset, so I like that we can call to the apache commons collections library to convert it into the appropriate multiset data type for our computations. Iterating over the entry set produces the primes and their multiplicities which is what we need to compute the totient function.

Sunday, April 17, 2022

Mutable versions of common data structures

Clojure encourages immutability and functional programming as a best practice. Nonetheless, you can still access mutable data structures using Clojure's Java interop facilities. Many of the distinctions between immutable and mutable data structures are first apparent in Java itself. For example, the distinction between immutable Strings and the more mutable StringBuilders.

Similarily, in Java all primitive data types are immutable. The mutable versions of these data types instead come from the apache commons lang module. So getting a grasp first of the difference between mutable and immutable data structures in Java will give you knowledge that that can transfer over to Clojure. This data structure knowledge will be summarized here.

Primitives

Mutable booleans:
The java.lang.Boolean class is a value type and it is therefore immutable. Therefore, in order to create a mutable boolean you should make use of apache commons lang.
; create a mutable boolean
(def mutable-boolean (new MutableBoolean))

; set the value of the mutable boolean to true
(.setValue mutable-boolean true)

; print out the value of the mutable boolean
(println (.getValue mutable-boolean))
The MutableBoolean class comes with setTrue and setFalse operators that don't take any extra arguments on the stack. An example of this usage is provided by the swap-boolean! operation.
(defn swap-boolean!
  [bool]

  (if (.isTrue bool)
    (.setFalse bool)
    (.setTrue bool)))
The basic swap operation isn't provided in the current version of apache commons lang, but as demonstrated above it isn't too hard for us to provide it ourselves.

Mutable numbers:
The other class of mutable primitives provided by apache commons lang are the mutable numbers. These come in many forms for each type of number in java.lang but right now we will mainly focus on mutable integers.
; create a mutable number
(def mutable-int (new MutableInt 0))

; perform arithmetic side effects on a number
(.add mutable-int 10)
(.subtract mutable-int 10)

; print out the value of the mutable integer
(.println (.getValue mutable-int))
In the previous section we define the swap-boolean! operation on mutable booleans. We will now define an imperative operation on numbers, that takes a given number and produces its square.
; functional square number function
(defn square
  [n]

  (* n n))

; imperative square number function
(defn square!
  [n]

  (.setValue n (square (.getValue n))))
With these out of the way, how would you define an imperative version of the factorial function using Clojure? We can actually achieve this using while loops. Programming this way, you can almost forget you are using Clojure and not Java.
; imperative factorial function
(defn factorial
  [n]

  (let [i (new MutableInt 1)
        rval (new MutableInt 1)]
    (while (<= (.getValue i) n)
      (.setValue rval (* (.getValue rval) i))
      (.increment i))
    rval))
Here is one more simple example that demonstrates the use of mutable integers provided by apache commons lang.
; imperative calculation of square pyramidal numbers
(defn square-pyramidal-number
  [n]

  (let [i (new MutableInt 1)
        rval (new MutableInt 0)]
    (while (<= (.getValue i) n)
      (.add rval (square (.getValue i)))
      (.increment i))
    rval))
Mutable number types like these are the one missing thing in Clojure. Apache commons lang resolves that issue for you. Writing imperative Clojure is a lot like writing Java, so you have to decide for yourself what kind of mix of languages and practices you want to go with.

Strings

Mutable strings:
The java standard library provides two different classes to support mutable string types: the StringBuilder and the StringBuffer. The difference between them is one of synchronization.
  • StringBuffer: a thread-safe mutable string type. String buffers are safe to be used on multiple threads and methods on them are synchronized.
  • StringBuilder: a compatible API with StringBuffer but with no support for synchronization. It is faster when used is single threaded programs.
So you have your choice of how you want to get mutable strings. In this case, these are provided by the Java standard library available with any Clojure distribution so you don't need to separately acquire apache commons lang.
; create a mutable string
(def string-builder (StringBuilder.))

; convert the string builder back to a string
(def string (.toString string-builder))
The major way that you perform side effects on a StringBuilder is by using the append method which is overloaded to handle characters, strings, and primitive data types. Here is an example that creates a String storing the alphabet by using its encoding in ASCII:
(def alphabet
  (let [str (StringBuilder.)]
    (doseq [i (range 97 123)]
      (.append str (char i)))
    (.toString str)))
This implements an imperitive version of the String reversal method using the StringBuilder class. As the underlying String is immutable this doesn't have to use the temporary store and swapping method of reversing a mutable string in place.
(defn build-reverse-string
  [str]

  (let [rval (new StringBuilder "")
        i (new MutableInt (dec (count str)))]
    (while (<= 0 (.getValue i))
      (.append rval (.charAt str i))
      (.decrement i))
    (.toString rval)))
So this is one more example of a mutable data structure that you can master which may be useful in either Java or Clojure. In both languages Strings are immutable by default, but mutable versions are also provided for you.

Mutable collections

Arrays:
Java arrays are inherently mutable, so we can always modify them using Clojure's Java interop functions lke aget and aset. A familiar use of Java arrays is in creating prime number sieves.
(defn sieve
  [n]

  (let [primes (boolean-array (repeat (inc n) true))
        p (new MutableInt 2)]
    (aset primes 0 false)
    (aset primes 1 false)

    (while (<= (square (.getValue p)) n)

      (when (aget primes (.getValue p))
        (let [i (new MutableInt (square (.getValue p)))]
          (while (<= (.getValue i) n)
            (aset primes i false)
            (.setValue i (+ (.getValue i) p)))))

      (.increment p))

    primes))
This prime number sieve lists out all the prime numbers up to a number n in a mutable boolean array. In addition, this uses apache commons language mutable integers to demonstrate the most imperative Clojure.

Mutable sets:
In Clojure an immutable set is created by a collection of elements surrounded by braces like #{1,2,3}. Sets are therefore immutable by default. In order to create an immutable set, you can use HashSet and similar classes of the java.util collections framework.
(defn index-set
   [coll]

  (let [rval (new HashSet)]
    (doseq [i (range (count coll))]
      (when (aget coll i)
        (.add rval i)))
    rval))
The above example simply takes the list of indices in a boolean array such as those produced by a sieve and it iteratively adds elements to a HashSet when it finds indices that have true values determined by aget.

Mutable lists:
Mutable lists and ordered collections are also provided by the java.util collections framework by ArrayLists and Vectors among other classes.
(defn sorted-index-set
  [coll]

  (let [rval (new ArrayList)]
    (doseq [i (range (count coll))]
      (when (aget coll i)
        (.add rval i)))
    rval))
The above example does the same thing as the index-set but it produces an ordered result by keeping track of the order of elements append to the collection. This could also be applied after the sieve method.

Mutable maps:
Clojure supports immutable maps by collections of pairs of elements contained between braces like {:x 1, :y 2}. On the other hand, mutable maps can be created by java.util.HashMap.
(def indices (new java.util.HashMap))
(.put indices "first" 1)
(.put indices "second" 2)
In order to transfer a list, vector, set, etc from its immutable Clojure form into a mutable Java form you can always use the addAll method. This applies to Clojure's immutable collections because they all implement the Collection interface. It isn't too hard, however, to create a method to insert elements of a Clojure map collection into a HashMap.
(defn add-entries!
  [rval coll]

  (doseq [[i v] coll]
    (.put rval i v)
    rval))
These different types of map types allow us to freely choose the kind of programming we want to do. Mutable data structures are more amenable to imperative programming and immutable data structures are more amenable to functional programming. With the right data structures, you can use either approach in Java or Clojure.

References:
Commons lang

Saturday, April 16, 2022

Rendering mathematical expressions

You might want to render mathematical expressions in your JVM based applications. An obvious way to do that is to use an existing library like jlatexmath. The jlatexmath library can be integrated into your swing programs as demonstrated below.
import javax.swing.*;
import org.scilab.forge.jlatexmath.TeXConstants;
import org.scilab.forge.jlatexmath.TeXFormula;
import org.scilab.forge.jlatexmath.TeXIcon;

public class FormulaViewer {

    public static void main(String[] args) {

        var frame = new JFrame();
        frame.setSize(400, 200);

        String expr = "\\zeta(x) = \\sum_{n=1}^{\\infty} \\frac{1}{n^x}";
        TeXFormula form = new TeXFormula(expr);
        TeXIcon icon = form.createTeXIcon(TeXConstants.STYLE_DISPLAY, 40);

        frame.setTitle("Expression Viewer");
        var panel = new JPanel();
        var label = new JLabel();
        label.setIcon(icon);
        panel.add(label);

        frame.add(panel);
        frame.setVisible(true);

    }

}

Here is the Reimann zeta function displayed in a JFrame:



There is also the JEuclid project for MathML, in case you want to go that route. These established libraries solve all your rendering needs, so the only thing that remains is conversion. We need to be able to take S-expressions and convert them into Latex.

S-expression $\to$ Latex

S-expressions have always been the best way of encoding mathematical expressions for use in computer algebra, going back to Macsyma. Later computer algebra systems made minor variations on the format, but there is still a distinction between how mathematical expressions are stored and how they are rendered. A few simple conversion routines can be made to address that.

External links:
jlatexmath
jeuclid

Friday, April 8, 2022

Everything is a presheaf

You could take the classical point of view that everything is a set, but that isn't very rewarding beyond a few nesting levels. You could go from studying sets to studying sets of sets, but in general there isn't any point in going deeper then that. We need some kind of organizing principle that goes deeper then that.

Is a function now to be represented as a set of set systems of the form {{0},{0,1}}? Perhaps a function is a morphism $f : A \to B$ of sets? In fact neither approach is really satisfying. To cut a long story short, a function $f : A \to B$ should be represented as a presheaf of the topos $Sets^{\to}$. Only then can we start to reason about functions logically.

Taken to its logical conclusion, topos theory will eliminate the unneccessary division between the functional and logic programming paradigms. Functions are just another object of a topos like any other presheaf, and now we can reason about them logically. In particular, the topos $Sets^{\to}$ enables us to construct the dual lattices of subalgebras and congruences of functions. The manner that we do so is no different then for any other presheaf.
  • Sets: objects of the topos $Sets$
  • Functions: objects of the topos $Sets^{\to}$
With the issue of the foundation of functions finally resolved by topos theory, we can now construct a whole wide range of algebraic structures using sets and functions. We have foundations for more then just sets and set systems. Any algebraic structure from a commutative magma to a lie algebra can be constructed from fundamental presheaves like sets and functions.

Then there is the issue of the categories themselves. All the nicest structures that we can reason about logically are presheaves, and it would seem categories are not that. To expose category theory to logical reasoning we can first construct the presheaf topos of quivers $Quiv$ and the functor $f: Cat \to Quiv$ taking any category to its underlying quiver. Then we are part way to reasoning about categories logically.

The only missing ingredients are composition and identities. In fact we can represent these as functions of the topos $Sets^{\to}$. Any functor induces morphisms of its composition and identity functions in $Sets^{\to}$ which describe the preservation of composition and identities. Then we can reason logically about categories using the presheaf topos $Quiv \times Sets^{\to} \times Sets^{\to}$.

All the data of a category is encoded in its corresponding presheaf. All this can be defined abstractly, so it doesn't matter how you encode categories. When you want to pick out a presheaf from them you simply use one of the presheaf valued functors like $f: Cat \to Quiv$. What matters is you have the option of reasoning about them logically using presheaf theory, so they are integrated into the overall topos theory.

So we have a pretty reasonably thorough system of reasoning about algebraic structures using presheaves not to mention objects that are already sheaves. Sheaves appear quite often in applications in algebraic and differential geometry. This same framework can be extended to deal with anything from structure sheaves, to schemes, or algebraic spaces. All is possible if you understand the simple fact that everything is a presheaf.

Sunday, April 3, 2022

What needs to be done

I can't deal with any of the large issues in the world, but I think we can still make computing be the way it is supposed to be. That is the beauty of computers, you can mold them into any form you like. With that in mind, lets discuss what needs to be done to build the new future of computing.

Computation ought to be organized around the presheaf programming paradigm, instead of the functional or logical paradigms. Functions should be treated as much as possible as presheafs over the ordered pair category, while sets are presheafs over a single point. The presheaf programming paradigm will remove the ackwardness of the separation between functions and logic. In particular,
  • We need classes for dealing with the different kinds of presheaves like quivers, higher order quivers, sets, functions, bijections, incidence functors, MSets, etc and a whole database of the most important algorithms on them.
  • We need an extensive ontology of different classes of presheaves. Think something like graphclasses, but instead focusing on presheaves.
  • We need tools like the copresheaf viewer that make it more pleasant to work with presheaves.
  • We need to have a knowledge base of ways of using presheaves to deal with other branches of mathematics like ring theory, such as through the use of presheaf valued functors.
  • We need to further develop the theory of the topos $Sets^{\to}$ and its use in the topos theoretic foundations of computation. In particular, we need research into more advanced mechanisms for modeling data dependencies using congruences in the topos $Sets^{\to}$.
  • Finally, the more advanced applications of sheaves in algebraic geometry and logic should be implemented in the same system.
When you look at algebraic geometry, you see that the fundamental objects are sheaves and not sets. The logic used in algebraic geometry is a categorical logic and not a classical one. Set theory is obsolete.

The amazing thing which I have described in my research is that the fundamental objects of computation are also not sets but rather presheaves as well. Thusly, the same sort of objects are used in both algebraic geometry and in the topos theoretic model of computation. In short, to make computing more pleasant we need new technologies for dealing with presheaves.

Friday, April 1, 2022

Locus 0.81 changes

In order to further develop the new elementary topos theoretic foundations of computation, I have produced a new version of the Locus project. Here are some of the changes.
  • The topos theoretic foundations of computation are defined in terms of $Sets$ and $Sets^{\to}$. An abstraction layer over that is provided by set relations and flow models. This new version contains a new and complete implementation of this fundamental research into the foundations of computation. At the same time you can get the lattice of subobjects of a set relation by calling the $sub$ multimethod.
  • We provide an implementation of relational functors which are functors of the form $F : C \to Rel$ and several techniques for dealing with them. In particular, an algorithm is provided for converting a family of disets into a relational functor over the two arrow category.
  • Support for partial transformation semigroups, such as the action by atomic charts of a preorder is provided. The action of a partial transformation semigroup is defined by a relational functor, with partial transformations described as set relations
  • The conversion of morphisms of functions into copresheaves is defined basically based upon the presence of identities in either the input or output function. As a result, a morphism of functions could be presented as a triangle copresheaf if one of the two functions is an identity. This makes for a more pleasant experience with the copresheaf viewer.
  • I wrote a function for creating module categories, defined as enriched categories with each hom class being an additive group. At the same time, the category of set relations is described as a 2-category with each hom class being a poset.
  • I wrote a new function for converting topological spaces into sites. This will be useful when we further develop our Grothendeick topos theory subsystem.
  • Half the functionality of the Locus project was moved into the elementary folder, dealing strictly with elementary topoi of copresheaves. This will make the project more organized when I add support for some things related to grothendeick toposes and schemes.