Thursday, February 10, 2022

Preservation and reflection of subsemigroups

The functoriality of the Alexandrov topology of a thin category is a good first example of the broad theme of functorially produced set systems of algebraic structures. In order to continue along these lines we need to generalize from the category $Top$ of topological spaces and continuous maps to the categories of hypergraphs and either reflecting or preserving maps respectively. These produce functors that can be defined, for example over the category of semigroups.

Theorem. let $f : S \to T$ be a morphism of semigroups. Then $f$ preserves subsemigroups.

Proof. let $A \subseteq S$ then $\forall a_1,a_2 \in A: a1_a2 \in A$. So consider the image $f(A)$ and let $t_1,t_2 \in f(A)$ then there exists $a, b$ such that $f(a) = t_1$ and $f(b) = t_2$. Now consider the product $f(a)f(b)$ then by the definition of semigroup homomorphisms this is equal to $f(ab)$ but we have that $ab \in A$ so $t_1t_2 = f(ab) \in f(A)$ so that $f(A)$ is composition closed. $\square$

Theorem. let $f: S \to T$ be a morphism of semigroups. Then $f$ reflects subsemigroups.

Proof. let $B \subseteq T$ then $f^{-1}(B)$ is a subset of $S$. Suppose that $x,y \in f^{-1}(B)$ then $f(x) \in B$ and $f(y) \in B$. The product $f(xy)$ is equal to $f(x)f(y)$ by the definition of semigroup homomorphisms. Then since $f(x)$ is in $B$, $f(y)$ is in $B$ and $B$ is composition closed $f(xy) = f(x)f(y)$ is in $B$ which implies that $f^{-1}(B)$ is composition closed. $\square$

Theorem. let $f: M \to N$ be a morphism of monoids. Then $f$ preserves and reflect submonoids.

Proof. (1) let $S \subseteq M$ be a submonoid of $M$ then $1 \in S$ and by the definition of monoid homomorphisms $f(1)$ is the identity of $M$ so $1 \in f(S)$. (2) In the other direction, suppose that $S \subseteq M$ is a submonoid so that $1_N \in S$ then by the definition of monoid homomorphisms $f(1_M) = 1_M$ so that $1_M \in f^{-1}(S)$ so that monoid maps reflect identities. (3) then since $f$ preserves and reflects identities as well as subsemigroups it necessarily must also do so for submonoids as well. $\square$

Theorem. let $f: G \to H$ be a group homomorphism. Then $g$ preserves and reflects subgroups.

Proof. (1) let $S \subseteq G$ be a subgroup. Then for all $s \in S$ we have that $-s \in S$. Then consider $f(S)$ if $h$ is in $f(S)$ then we have that there exists $g$ such that $f(g) = h$. Then consider $-h$ by the definition of group homomorphisms $f(-g) = -h$ but then $-g$ is in $S$ because $S$ is a subgroup and therefore inverse closed. It follows that $f(-g) = -h$ is in $f(S)$ so that the image is a subgroup.

(2) in the other direction suppose that $S \subseteq H$ is a subgroup. Then $\forall s \in S : -s \in S$. Suppose that $g \in G$ and $f(g) \in S$. Then $f(-g) = -f(g)$ by the definition of group homomorphisms. By the fact that $S$ is a subgroup and $f(g)$ is in $S$ we have that $-f(g)$ is in $S$ which implies that $f^{-1}(S)$ is inverse closed for all $g \in f^{-1}(S)$. It follows that it is a subgroup. $\square$

We saw that monotone maps reflect ideals over thin categories. A generalization of this which is applicable to semigroups involves the reflection of semigroup ideals, which can be either left, right, or two sided. This produces a functor from the category of semigroups to the category of topological spaces.

Theorem. let $f : S \to T$ be a morphism of semigroups. Then $f$ reflects left, right, or two sided ideals.

Proof. let $I$ be a left ideal of $T$ then we have that for all $i \in I$ and $t \in T$ it holds that $it \in T$. So consider $f^{-1}(I)$ then if we have $x \in f^{-1}(I)$ it follows that $f(x) \in I$. Let $s \ in S$ then $f(sx) = f(s)f(x)$ and since $f(x)$ is in $I$ and $I$ is a left ideal $f(s)f(x)$ is in $I$. So $f$ reflects left ideals and by dualizing it reflects right ideals. By combining this $f$ reflects two sided ideals. $\square$

It is not enough for us to show that semigroup homomorphisms reflect subsemigroups. We would also like to know that they reflect prime ideals. This will then allow us to reproduce the familiar theorems of ring theory dealing with prime ideals.

Theorem. let $f : A \to B$ be a morphism of semigroups then $f$ reflects prime subsemigroups.

Proof. let $P \subseteq B$ be a prime subsemigroup then we have that $Q = B-P$ is a subsemigroup and in total we have $P,Q$ are subsemigroups with $P \cup Q = B$ and $P \cap Q = \emptyset$. Every element of $A$ produces some image, so by the fact that inverse images are lattice homomorphisms we have $f^{-1}(P) \cup f^{-1}(Q) = A$ and $f^{-1}(P) \cap f^{-1}(Q) = \emptyset$. So by the fact that $f$ reflects subsemigroups it follows that $f^{-1}(P)$ is a subsemigroup with complement subsemigroup $f^{-1}(Q)$. $\square$

Corollary. let $f : S \to T$ be a morphism of semigroups. Then $f$ reflects prime ideals.

The one other class of ideals we are really interested in are the radical ideals, especially in commutative algebra because of theri relationship to algebraic varieties under Hilbert'z nullstellensatz. There is a corresponding notion for semigroups, and so by considering that we will get closer to solving some problems related to radical subsemigroups and ideals.

Theorem. let $f : S \to T$ be a morphism of semigroups. Then $f$ reflects radical subsemigroups.

Proof. let $B \subseteq T$ be a radical subsemigroup. Then $f^{-1}(B)$ is a subsemigroup of $S$ because $f$ reflects subsemigroups, so it remains to show that $f^{-1}(B)$ is a radical subsemigroup. Let $x \in f^{-1}(B)$ and suppose that $y^n = x$ Then we can apply $f$ to both sides to get $f(y^n) = f(x)$ and expanding this $f(y)^n = f(x)$. Now since, $f(x)$ is in $B$ and $B$ is radical this implies that $f(y) \in B$. So to sum up this means that $f^{-1}(B)$ is a radical subsemigroup. $\square$

Corollary. let $f : S \to T$ be a morphism of semigroups. Then $f$ reflects semigroup radical ideals.

We can apply these semigroup theorems to our favourite algebraic structures, all of which are constructed out of semigroups. Like lattices (thin categories with all products and coproducts), semirings, and rings. In particular, this is enough to recover that the pre image of a prime ideal of a ring is a prime ideal.

Corollaries.
  • Lattice homomorphisms preserve and reflect sublattices
  • Semigroup homomorphisms preserve and reflect subsemirings
  • Ring homomorphisms preserve and reflect subrings
  • Ring homomorphisms reflect left, right, and two sided ideals, prime ideals, and radical ideals
It is always nice to apply our theorems to semigroups so that they have the widest degree of applicability to other common algebraic structures like lattices and semirings, but in the process we also recovered theorems applicable to rings. Each of these different notions of preservation and reflection naturally produce functors over appropriate categories.

Wednesday, February 9, 2022

Functorality of the Alexandrov topology

A number of set systems associated to structured sets either preserve or reflect substructures and they therefore form functors to categories of hypergraphs or topologies. The Alexandrov topology consisting of all lower sets (respectively upper sets) of a poset is a basic example.

Lemma 1. Let $f: A \to B$ be a monotone map of posets. Let $L$ be a lower set of $B$, then $f^{-1}(L)$ is a lower set of $A$.

Proof. suppose that $a \in f^{-1}(L)$ then $f(a) \in L$ and further suppose that $b \subseteq a$. By the fact that $f$ is monotone we have $f(a) \subseteq f(b)$ and now by the fact that $f(b) \in L$ and $L$ is a lower set, we have that $f(a) \in L$. Which implies that $a \in f^{-1}$ so in short $b \subseteq a \text{ and } a \in f^{-1}(L)$. Therefore, $f^{-1}(L)$ is a lower set.

The dual proposition that monotone maps preserve lower sets is trivially false, consider $F : 1 \to 3$ that maps the singleton poset to the middle element of an ordered triple. Then this map preserves neither upper sets or lower sets. So the Alexandrov topology is not functorial to the category of topologies and open maps, but it is for the more relevent category $Top$ of topologies and continuous maps.

Theorem 1. $F: Ord \to Top$ is a covariant functor from the category of thin categories to the category of topological spaces and continuous maps.

Proof. (1) let $P$ be a thin category then $F(P)$ is the topology generated by the map of singletons that produces all predecessor elements and this is trivially an Alexandrov topology (2) and by lemma 1 for any functor $f : A \to B$ we have that $F(f) : F(A) \to F(B)$ is a continuous map. Finally (3) $F$ preserves composition by preserving underlying functions so $F$ is functorial. $\square$

The fact that monotone maps reflect lower sets (respectively upper sets) is simply a long line of a group of theorems dealing with the preservation and reflection of open sets. For example, the fact that the pre image of a prime ideal is a prime ideal is used in commutative algebra to describe the functoriality of the topology $Spec(R)$. We see that order ideals are not that different from ring ideals.

Sunday, February 6, 2022

Composition homomorphisms and partial algebras

The basic universal algebraic framework for dealing with total algebras, consisting of a set of elements $S$ and a set of n-ary operator functions on it $f: S^n \to S$ needs to be extended to deal with partial algebras, such as the partial composition semigroup of a category. The key to this construction it turns out is simply the construction of a relation homomorphism of the domains of the two partial algebras.

Definition. let $A$ be a set and $R \subseteq A^n$ an n-ary relation on $A$. Then there exists an inclusion function $i_R : R \hookrightarrow A^n$ associated with $R$. A partial algebra on $R$ is then simply a function $f: R \to A$.

We can freely define any kind of function we want, but in order to get a valid category we also need to define morphisms. The first component to that will be the definition of composition relation homomorphisms.

Definition. let $(A,f: R \to A)$ and $(B,g : S \to B)$ be n-ary partial algebras. Then $m : A \to B$ is a composition relation homomorphism provided that $m : (A,R) \to (B,S)$ is a homomorphism of relations meanining that $(a_1,a_2,...) \in R$ implies that $(f(a_1),f(a_2),...) \in S$.

In the case of total algebras, we don't need a relation homomorphism. On the other hand, since partial algebras are defined over arbitrary n-ary relations we need the composition relation homomorphism to ensure the validity of the partial algebra homomorphism construction.

Definition. let $(A,f: R \to A)$ and $(B,g : S \to B)$ be n-ary partial algebras. Then $m : A \to B$ is a partial algebra homomorphism provided that (1) it is a composition relation homomorphism and (2) $f(a_1,a_2,...) = g(m(a_1),m(a_2),...)$ for any $(a_1,a_2,...) \in R$. The first condition ensures that $(m(a_1),m(a_2),...)$ actually exists and is in the domain of $g$. The second condition ensures that they are also equal.

A category is simply a special combination of objects and morphisms so now that we have the preliminary definitions out of the way we can define the category of partial nary algebras.

Definition. let $n \in \mathbb{N}$ then $PA_n$ is the category of $n-ary$ partial algebras with homomorphisms previously defined. The composition domain is a forgetful functor $D : PA_n \to Rel_n$ from this categroy to the category of nary relations.

In order to continue, we now need to prove a basic lemma about relation homomorphisms. This will allow us to construct the input function component of the morphism of functions in the topos $Sets^{\to}$ that emerges from partial algebra homomorphisms.

Lemma 1. let $f : (A,R) \to (B,S)$ be a homomorphism of n-ary relations then consider the product function $f^n : A^n \to B^n$ of the underlying function $f$. Then $(R,S)$ defines a subfunction of $f^n$ in the topos of functions.

Proof. in order for $(R,S)$ to be a subfunction of $f^n$ then it must be that for all $(a_1,a_2,...) \in R$ we have that $(f(a_1),f(a_2),...)$ but this is precisely the definition of a relation homomorphism. $\square$

Then we can restrict $f^n$ to $f^n_{R,S}$ to a get a monomorphism in the topos of functions as depicted in the commutative diagram below. The point of this construction is to enable us to prove our main theorem which is that homomorphisms of partial nary functional algebras as we have defined them induce morphisms in the topos of functions $Sets^{\to}$.

Theorem 1. let $m : (A, \circ_A : R \to A) \to (B, \circ_B : S \to B)$ be a homomorphism of partial n-ary functional algebras. Then $(m^n_{(R,s) : R \to S},m: A \to B)$ is a morphism of functions from $\circ_A$ to $\circ_B$.

Proof. by lemma 1 we have that $f^n_{R,S}$ is a well defined function. By the definition of partial algebra homomorphisms we have that for each $(a_1,a_2,...) \in R$ that $f(\circ_A(a_1,a_2,..)) = \circ_B(f(a_1),f(a_2),...)$. It follows that $f \circ \circ_A = \circ_B \circ f^{n_{(R,S)}}$ as depited in the following commutative diagram. It follows that $(m^n_{(R,s) : R \to S},m: A \to B)$ is a morphism in the topos of functions $Sets^{\to}$. It follows that $F : PA_n \to Sets^{\to}$ is a monomorphism from the category of partial algebras to the topos of functions. $\square$

This allows us to create a topos theoretic model for theory of partial algebras. We can now apply this to categories by definining the composition function of a category as a partial algebra.

Definition. let $(Ob(C),Arrows(C),source,target,id,\circ)$ be a category then $(Arrows(C), \circ : Arrows(C)^2_* \to Arrows(C))$ is a partial binary algebra defined over the morphism set of $C$.

Firstly, we can naturally relate functors to homomorphisms of composition relations. This produces a natural forgetful functor from the category of categories $Cat$ to the category of binary relations $Rel$ and relation homomorphisms.

Lemma 2. let $F: C \to D$ then $F$ induces a homomorphism of binary relations from $Arrows(C)^2_*$ to $Arrows(D)^2_*$.

Proof. let $m_1 : A \to B$ and $m_2 : C \to D$ be morphisms of $C$ then in order for them to be composable we humst have $B=C$. Then by the definition of functors, we have that $f(m_1) : f(A) \to f(B)$ and $f(m_2) : f(C) \to f(D)$ are the object signatures of $f(m_1)$ and $f(m_2)$. The fact that $B=C$ implies that $f(B) = f(C)$. It follows that $f(m_1)$ and $f(m_2)$ are composable, so that if $m_1$ and $m_2$ are composable then their outputs by $f$ are. It follows that the morphic component of $F$ is a homomorphism of composition relations. $\square$.

Lemma 3. let $F : C \to D$ be a functor then $F$ induces a homomorphism of partial algebras $PA_F : (Arrows(C)^2_*, \circ) \to (Arrows(D)^2_*, \circ)$.

Proof. in order for a function to be a partial algebra homomorphism it must satisfy two conditions. Condition (1) is satisfied by lemma 2. Condition (2) follows immediately from the definition of functors which ensures that $f(m_1 \circ m_2) = f(m_1) \circ f(m_2)$ whenever the two exist.

We started this discussion by relating the category $PA_n$ to the topos of functions $Sets^{\to}$. With this preliminary out of the way, we can now relate the category of categories $Cat$ itself to the topos of functions $Sets^{\to}$ by defining a forgetful functor from any category to its composition function.

Theorem 2. let $\circ : Cat \to Sets^{\to}$ be the function that maps any category to its underlying composition function, and any functor to its morphism of composition functions. Then $\circ$ is a forgetful functor from the category of categories to the topos of functions.

Proof. by lemma 3 we have a functor $Cat \to PA_2$ from $Cat$ to partial binary algebras. By theorem 1, we can then compose this with the functor from $PA_2$ to $Sets^{\to}$ to get a functor from $Cat$ to $Sets^{\to}$. $\square$

There are two main functors from $Cat$ to topoi the underlying quiver $q : Cat \to Quiv$ and the underlying composition functor $\circ : Cat \to Sets^{\to}$. The other topos valued functors from $Cat$ can be defined by composition with these functors, like the functor to $Sets^2$ or the different functors to $Sets$ defined by taking the object set or the morphism set of the category.

Sunday, January 30, 2022

Displaying Hiccup generated HTML with Swing

HTML is a very common data format, so we can make use of it with both ClojureScript as well as Clojure. In the later case, we can use HTML generated by Clojure in Java Swing applications. A number of Java Swing classes optionally use HTML in order to enrich the content of their interfaces. We can provide that HTML using Hiccup like so.
(ns swing-hiccup.basic
  (:require [hiccup.core :refer :all]
            [garden.core :refer [css]))
  (:import (javax.swing JFrame JLabel)))

(def introduction-to-category-theory
  [:html
   [:h1 "Introduction to category theory"]
   "The elements of a category are"
   [:ol
    [:li "Objects"]
    [:li "Morphisms"]]
   "associated to these elements of a category are functions"
   [:ol
    [:li "A source function f : Morphisms -> Objects"]
    [:li "A target function f : Morphisms -> Objects"]
    [:li "A composition function f : Morphisms2* -> Morphisms"]
    [:li "An identity function f : Objects -> Morphisms"]]
   "that satisfy axioms of associativity and identity."])

(defn view-html
  [arg]

  (let [^JFrame f (JFrame.)
        ^JLabel p (JLabel.
                    ^String
                    (html arg))]
    (.add f p)
    (.setTitle f "Abstract Algebra")
    (.setVisible f true)
    (.setSize f 450 300)))
This produces a Java Swing JFrame as depicted below, and so with Hicccup you can freely integrate HTML generated by Clojure into your Java swing applications. The Java standard library is much more sophisticated then just this, however. Java also comes with standard support for stylesheets provided by the java.swing.text.html package in the java.desktop module. In order to make things a little more interesting, here we not only use HTML and CSS in a Java Swing application, we programatically generate the HTML using Clojure.

This demonstrates how easy it is to generate HTML using Clojure because thanks to Hiccup it allows you to represent HTM as the same sort of S-expression the rest of the language deals with. It is for this resaon that I have always felt that Clojure is the best language for generating HTML (such as in Java Swing applications that make use of HTML or on the web).

In order to also programatically generate CSS as well we can simply make use of the Garden library. Garden is for CSS what Hiccup is for HTML, as it allows us to generated CSS from Clojure's EDN expressions. With this HTML, CSS, etc can all be represented as no different then any other data structure in Clojure. This gets to one of the advantages of the language which is that it is a common format for all kinds of data, as well as a common language for both the server side and the client side with Clojure Common.

In order to then display the generated HTML and CSS we just have to create a JEditorPane containing a HTMLEditorKit and then put it in a standard Java Swing JFrame. The CSS is added automatically by add rule on the Swing StyleSheet, and the HTML is provided as the text of the JEditorPane. Type hinting is used throughout to improve performance.
(ns swing-hiccup.styled
  (:require [hiccup.core :refer :all]
            [garden.core :refer [css]]
            [swing-hiccup.basic :refer :all])
  (:import (javax.swing JFrame JEditorPane)
           (javax.swing.text.html HTMLEditorKit StyleSheet)))

(defn join-table
  [n]

  (letfn [(cell-value [x y]
            (bit-or x y))]
    (map
      (fn [i]
        (map
          (fn [j]
            (cell-value i j))
          (range n)))
      (range n))))

(defn wrap-table
  [coll]

  (vec
    (conj
      (map
        (fn [row]
          (vec
            (conj
              (map
                (fn [i]
                  [:td (.toString i)])
                row)
              :tr)))
        coll)
      :table)))

(def css-data
  [[:body {:color "white"}]
   [:td {:border "1px solid black"
         :color "black"
         :font-size "16px"}]])

(def html-data
  [:html
   [:body
    (wrap-table (join-table 8))]])

(defn view-styled-html
  [html-data css-data]

  (let [^JEditorPane pane (JEditorPane.)
        ^HTMLEditorKit kit (HTMLEditorKit.)
        ^StyleSheet style-sheet (.getStyleSheet kit)
        ^JFrame frame (JFrame. )]
    (.setEditable pane false)
    (.setEditorKit pane kit)
    (.addRule style-sheet (css css-data))
    (.setDocument pane (.createDefaultDocument kit))
    (.setText pane (html html-data))
    (.add frame pane)
    (.setSize frame 350 350)
    (.setVisible frame true)
    (.setTitle frame "Multiplication Table")))
This Clojure based Java Swing application then produces an output JFrame that looks as displayed in the image below. The table displayed is a join semilattice of a boolean algebra, which can simply be described by bitwise operations. Hopefully this demonstrates the utility of HTML and CSS both in Clojure and in ClojureScript because even when are building our graphical interfaces with Java and Swing there are a number of cases in which we can make use of HTML and CSS. Its typically easier to use Clojure to generate HTML then Java, but it is easy enough to switch between the two of them.

Saturday, January 29, 2022

Drawing Young diagrams with HTML5 Canvas

The previous Java Swing program to visualize members of Young's lattice $\mathbb{Y}$ can fairly easily be ported to ClojureScript to make an HTML based application.
; this is a clojure common method
(defn determine-coordinates
  "Get the coordinates of a young diagram."
  [coll]

  (let [sorted-seq (sort > (seq coll))]
    (apply
     concat
     (map-indexed
      (fn [x v]
        (map
         (fn [y]
           [x y])
         (range 0 v)))
      sorted-seq))))
      
; this is specific to clojurescript
(defn display-young-diagram
  "Display a young diagram onto an html canvas"
  [ctx data start end block-width block-height]
  
  (let [coords (determine-coordinates data)] 
    (set! (.-strokeStyle ctx) "black")
    (doseq [[x y] coords] 
      (.strokeRect 
        ctx 
        (+ start (* x block-width)) 
        (+ end (* y block-height)) 
        block-width 
        block-height))))

; clojurescript is the best way to develop web applications
(defn init []
  (let [ctx (.getContext (.getElementById js/document "canvas") "2d")]
    (display-young-diagram ctx data '(1 2 3 4) 50 30 30)))
The real hero of this port is Clojure Common, which allows us to share code between the backend and the frontend, so that we can more easily port JVM based applications to the web. The determine coordinates function as you can see can be shifted over to ClojureScript without a single change to our code base.

Its not a perfect solution, as there are obviously things you can do on the JVM (like make use of Java libraries such as apache commons and the standard library) that cannot readily be ported to the browser setting but it is better then nothing which is quite often is what we were left with doing web development in the old days.

So write as much code as possible in Clojure Commons so that porting JVM based applications to the web will be easier. Generally, these will be pure functions that express business logic, and since they don't need side effects they won't have to depend so much on the platform they are running on.

Sunday, January 23, 2022

Mutable multisets

The implementation of mutable multisets in Clojure deosn't contradict the currently existing multiset implementations in the Java platform, in particular the one provided by apache commons, because Java collections tend to be mutable. So in general we have different JVM datatypes for mutable and immutable collections. To use the mutable one just call up the apache commons collection library and import the multiset data type.
import java.util.ArrayList;
import java.util.Arrays;
import org.apache.commons.collections4.multiset.HashMultiSet;
In order to create a multiset, it is good to first have a java.util.Collection created first. So to create one I simply using I simply use the asList method of the java.util.Arrays class.
// create a mutable multiset
var ms = new HashMultiSet < Integer > (Arrays.asList(1,2,2,2,3));

// print its curent contents
System.out.println(ms);

// add elements to the multiset to change it
ms.add(4);
ms.add(5);

// now the multiset is actually different
System.out.println(ms);

// remove the elements we added to change it back
ms.remove(4);
ms.remove(5);

// the multiset is back to its original state
System.out.println(ms);
There are slight differences in the API from the more familiar multiset implementation, like we use uniqueSet for what is commonly called the support in multiset theory and we use getCount to get the multiplicity of them element. But aside from a few terminology differences the apache commons provides everything you need to deal with multisets. It also provides a ton of other nice things like the best math library programmed in Java.

See also:
Immutable multisets in Clojure

Friday, January 14, 2022

Sieve of Eratosthenes in Jasmin

I have hand written a number of programs in pure Java bytecode. So for example, the sieve which I implemented before in Java is something I have written out in bytecode before by hand. In particular, what you will notice about this code is the high amount of documentation and structure for JVM bytecode.
; Compute the sieve of an integer
; @param(0) the integer argument
; @local(1) the boolean array
; @local(2) the current index
; @local(3) the limit
; @local(4) the other index
.method public static sieve(I)[Z
    .limit stack 8
    .limit locals 8

    iload_0
    iconst_1
    iadd
    newarray boolean    
    astore_1

    iload_0
    i2d
    invokestatic java/lang/Math.sqrt(D)D
    d2i
    iconst_1
    iadd
    istore_3
        
    iconst_2    
    istore 4

    aload_1
    iconst_0    
    iconst_1    
    bastore

    aload_1
    iconst_1
    iconst_1
    bastore
    
    aload_1
    iconst_2
    iconst_0
    bastore

    bipush 4
    istore_2
initialization_loop:
    iload_2 
    iload_0
    if_icmpgt initialization_loop_breakpoint

    aload_1
    iload_2
    iconst_0
    bastore

    iinc 2 1
    goto initialization_loop
initialization_loop_breakpoint:
    iconst_2
    istore_2

loop:
    iload_2
    iload_3
    if_icmpge loop_breakpoint
    
    aload_1
    iload_2
    baload
    ifne inner_loop_breakpoint

    iload_2
    iload_2
    imul
    istore 4

inner_loop:
    iload 4
    iload_0
    if_icmpgt inner_loop_breakpoint

    aload_1
    iload 4
    iconst_1
    bastore    

    iload 4
    iload_2
    iadd
    istore 4
    goto inner_loop
inner_loop_breakpoint:

    iinc 2 1
    goto loop
loop_breakpoint:
    
    aload_1
    areturn
.end method

; @locals
; @param(0) the array argument
; @local(1) the count
; @local(2) the current index
; @local(3) the array argument length
.method public static falseCount([Z)I
    .limit stack 4
    .limit locals 4  

    iconst_0
    istore_1
    
    iconst_0
    istore_2
    
    aload_0
    arraylength
    istore_3
loop:
    iload_2
    iload_3
    if_icmpge loop_breakpoint

    aload_0
    iload_2
    baload
    ifeq is_false
    goto is_false_breakpoint

is_false:
    iinc 1 1
is_false_breakpoint:

    iinc 2 1
    goto loop
loop_breakpoint:
    iload_1
    ireturn
.end method

; Get the true indices of a boolean array
; @param(0) the argument array
; @local(1) the return array
; @local(2) the current index
; @local(3) the argument array length
; @local(4) the return array index
.method public static falseIndices([Z)[I
    .limit stack 4
    .limit locals 5

    aload_0
    invokestatic Sieve/falseCount([Z)I
    newarray int
    astore_1
    
    iconst_0
    istore_2
    
    aload_0
    arraylength
    istore_3
    
    iconst_0
    istore 4
loop:
    iload_2
    iload_3
    if_icmpge loop_breakpoint

    aload_0
    iload_2
    baload
    ifeq is_false
    goto is_false_breakpoint

is_false:
    aload_1
    iload 4
    iload_2
    iastore
    iinc 4 1
is_false_breakpoint:    

    iinc 2 1
    goto loop
loop_breakpoint:
    aload_1
    areturn
.end method