Contents
- Setting up
- Scala REPL with UACalc objects
- The LUAU Library
- Constructing general algebras with Scala
- EXAMPLE: a unary operation defined from a (Scala) function.
- Computing Congruences for Quantumn Physicists
- More Learning Resources
- Contributions Welcome
Setting up
Scala is a (non-pure) functional language that supports object oriented programming. It runs on the Java virtual machine (jvm), and because of this it is possible to import UACalc Java packages into Scala programs (just like we do in Jython.
-
Install Java if you don't already have it.
Ubuntu users can follow these instructions for installing (even multiple versions of) Java. -
Download and Install Scala following the instructions given on the download page.
Ubuntu users can download the file scala-2.13.3.tgz, unpack it and put a link to the
scala-2.13.3/bin
directory in yourPATH
, OR put a symbolic link to thescala-2.13.3/bin/scala
file your$HOME/bin
directory (assuming the latter is in your path). For example, I did the following:cd ~/opt/SCALA # (where I downloaded scala-2.13.3.tgz) tar xvzf scala-2.13.3.tgz ln $HOME/opt/SCALA/scala-2.13.3/bin/scala $HOME/bin/scala source ~/.bash_profile
-
Download the uacalc.jar file from uacalc.org/lib/uacalc.jar
Scala REPL with UACalc objects
-
Start the Scala REPL with UACalc dependencies.
In a terminal window, change to the directory containing the jar files you downloaded above and doscala -classpath uacalc.jar
You should see something like the following
Welcome to Scala 2.13.3 (Java HotSpot(TM) 64-Bit Server VM, Java 15). Type in expressions for evaluation. Or try :help. scala>
-
Import UACalc classes and make some objects.
scala> import org.uacalc.alg.conlat.BasicPartition scala> val a = new BasicPartition("|0,1|2,3|") a: org.uacalc.alg.conlat.BasicPartition = |0,1|2,3| scala> val b = new BasicPartition("|0|1,2|3|") b: org.uacalc.alg.conlat.BasicPartition = |0|1,2|3| scala> a.compose(b) blocks: [[0,1],[2,3]] val res1: org.uacalc.alg.conlat.BinaryRelation = [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 1], [2, 2], [2, 3], [3, 1], [3, 2], [3, 3]]
The LUAU Library
This section gives an example use of the Lazy Universe Algebra Utilities (aka Lūʻau) Scala library.
ScalaLūʻau is a Scala library providing some tools that facilitate computational algebra research and, in particular, importing and using Java packages from the Universal Algebra Calculator in Scala programs.
Constructing general algebras with Scala
We first describe how to construct an algebra that we can compute with.
The file UACalcAlgebraFactory.scala in the basic_algebra package of ScalaLūʻau makes it easy to build operation tables from Scala functions, lists, or arrays.
Some examples are given in the Scala worksheet called AlgebraFactory.sc, which is well documented with comments and self-explanatory. Nonetheless, we describe the first of those examples here.
EXAMPLE: a unary operation defined from a (Scala) function.
In this example, we define a typical function in Scala, then we use that function to construct some UACalc operations and, finally, we construct a UACalc BasicAlgebra
with these operations.
The required imports for this example are
import org.uacalc.alg.BasicAlgebra import basic_algebra.UACalcAlgebraFactory._ import scala.jdk.javaapi.CollectionConverters.asJava
First, we define a Scala function by specifying what the function does at each point.
val plusMod5: List[Int] => Int = l.sum % 5
It should be clear that this function takes a list of Ints and outputs their sum modulo 5. The type signature of this function, List[Int] => Int
, is optional in this context since it can be inferred by the Scala type checker; nonetheless, we make the types explicit for clarity.
Next we use the plusMod5
function to construct a couple of UACalc operations using the method UACalcOpFromFun
(defined in the basic_algebra package).
val op1: UACalcOperation = UACalcOpFromFun(plusMod5, "binaryMod5", 2, 5) val op2: UACalcOperation = UACalcOpFromFun(plusMod5, "ternaryMod5", 3, 5)
In order to use these operations as input to UACalc's BasicAlgebra
constructor, we need to put them into a Java list.
val my_ops = asJava(List(op1, op2))
Finally, we are ready to build our algebra using the BasicAlgebra
constructor (imported above).
val myAlg: BasicAlgebra = new BasicAlgebra("My 1st Alg", 5, my_ops)
We can now apply any of the UACalc methods available for BasicAlgebra instances, e.g.,
myAlg.getName() myAlg.universe() myAlg.con().getUniverseList
These method calls produce the following output:
res10: String = My 1st Alg res11: java.util.Set[_] = [0, 1, 2, 3, 4] res12: java.util.List[org.uacalc.alg.conlat.Partition] = [|0|1|2|3|4|, |0,1,2,3,4|]
revealing that the algebra we constructed is called "My 1st Alg", has universe {0, 1, ..., 4}, and is simple.
Finally, we can write the algebra to a UACalc .ua (xml) file by invoking
AlgebraIO.writeAlgebraFile(myAlg, "~/UACalcAlgebraFromScalaFunctions.ua")
The resulting file could then be opened in the UACalc GUI.
Computing Congruences for Quantumn Physicists
Here are some highlights from the file TumaExample.scala, which we used to find congruences of cellular automata for quantum physics. This was for joint work with Jiri Tu̇ma.
First we created a class called Tuma and defined (in the file Tuma.scala) as follows.
package basic_algebra import algebra_util._ class Tuma (n: Int, m: Int) { private val N = Math.pow(2, m).toInt def cardinality: Int = N /** Process state * @param inputstate * @param t a String representing an Int in base 2 * @param iters an Int number of iterations */ def processState(inputstate: String, t: String, iters: Int): String = { @scala.annotation.tailrec def proc_state_aux(state: String, indx: Int): String = { if (indx == 0) state else { def newstate(k: Int): Int = strAt(t,Integer.parseInt(strAt(state,k-1)+strAt(state, k)+strAt(state,k+1),2)).toInt val newstatestr: String = fun2str(newstate, 1 until (state.length-1)) proc_state_aux(newstatestr, indx - 1) } } proc_state_aux(inputstate, iters) } def state_list(x: Int, y: Int, z: Int): String = int2bin((N * (N * x + y)) + z, 3 * m) val t : String = int2bin(n, 8).reverse def op: (Int, Int, Int) => Int = (x, y, z) => Integer.parseInt(processState(state_list(x, y, z), t, m), 2) }
Next we construct an instance of the Tuma class for parameters n = 110
and m = 7
.
val n = 110; val m = 7 val tuma = new Tuma(n, m) val N = tuma.cardinality def t_def(args: List[Int]): Int = tuma.op(args(0), args(1), args(2))
Notice that in the last line above we converted the type of tuma.op
from Int × Int × Int => Int
to List[Int] => Int
. This is so we can pass the resulting function, t_def
, into UACalcOpFromFun
and construct UACalc operation.
val t_op: UACalcOperation = UACalcOpFromFun(t_def, "t", 3, N) // make a singleton Java list containing the operation val t_uacalc_op = asJava(List(t_op)) // construct the basic algebra val t_Alg: BasicAlgebra = new BasicAlgebra("Jiri's Alg" + "(" + n + "," + m + ")", N, t_uacalc_op)
Next we write the algebraic structure to a UACalc algebra file so we can inspect the algebra in the UACalc GUI if desired.
val A = AlgebraIO.writeAlgebraFile(t_Alg, algebra_dir + "/Tuma-" + n + "-" + m + ".ua")
Most of the congruences of the algebra will have the same block structure and will be "obvious" or uninteresting. These tend to have small blocks and, after some experimentation, we realized that they are generated by values in the following list.
val smblocks = List(10,18,20,21,34,36,37,40,41,42,43,74,82,84,85,106)
Finally, for each a
and b
not in the smblocks
list, we compute and print out the congruence generated by (a, b)
as follows.
for (a <- (0 until N-1).filterNot(smblocks.contains)) for (b <- (a+1 until N).filterNot(smblocks.contains)) { val cab = t_Alg.con().Cg(a,b, null) if (cab.numberOfBlocks() > 17) println("Cg(" + a + "," + b + ") = " + cab + " NUM BLOCKS = " + cab.numberOfBlocks())
(The if
conditional limits the printed output to only interesting congruences.)
More Learning Resources
The Best Scala Books
(Please support this site by using the links above to order the books.)
The Best Scala Courses
Martin Odersky, creator of Scala, (along with some colleagues) offers an excellent sequence of online courses on the Coursera platform. They are listed below.
- Functional Programming Principles in Scala
- Functional Program Design in Scala
- Parallel Programming in Scala
- Big Data Analysis with Scala and Spark
Contributions Welcome
This page was created by volunteers. Help grow it into a more useful resource. If you have any comments, suggestions, or other contributions, please create a new gitlab issue or email williamdemeo at gmail.