Skip to content

Commit

Permalink
v1.4.4
Browse files Browse the repository at this point in the history
- major code refactor, merging ejml and jblas project
- AllInit granularity improve
  • Loading branch information
dedztbh committed Oct 11, 2020
1 parent 8f267f6 commit eef49de
Show file tree
Hide file tree
Showing 23 changed files with 943 additions and 167 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Another 15-459 Assignment(-ish).

There are 2 versions with identical usage implemented with different libraries:
- EJML version: No native dependencies, super lightweight, good for small input
- JBLAS version: Accelerated with BLAS, good for big input (see [jblas_dev](https://github.com/DEDZTBH/KuantumCircuitSim/tree/jblas_dev) branch)
- JBLAS version: Accelerated with BLAS, good for big input
- JBLAS comes with default BLAS library for major OS's so it works right out of the box. For extreme performance, you can build JBLAS with custom BLAS library (like OpenBlas, ATLAS, cuBLAS) and put the library file(s) under library load path (for example, current working directory). See [JBLAS github page](https://github.com/jblas-project/jblas) for more detail.

### Table of Contents
Expand Down Expand Up @@ -57,7 +57,7 @@ Options:
--no_t, -q [false] -> Do not print circuit matrix in commandline after simulation if present
--sequential, -s [false] -> Use sequential instead of concurrent implementation if present
--init_state, -i [] -> Read custom initial joint state from csv if specified { String }
--binary_matrix, -b [false] -> Use binary format instead of csv for read/save circuit matrix if present
--binary_matrix, -b [false] -> Use binary format instead of csv for read/save circuit matrix if present (EJML version only)
--help, -h -> Usage info
```

Expand Down Expand Up @@ -136,4 +136,4 @@ is stored in CSV file like
1,0,0,1
0,-1,1,0
```
Alternatively, circuit matrix can be saved/loaded in Java binary format (with -b option). It might be faster to save/load but it is not human readable. In case you want to read it, it is a `org.ejml.data.ZMatrixRMaj` (`org.jblas.ComplexDoubleMatrix` for JBLAS version).
(EJML version only) Alternatively, circuit matrix can be saved/loaded in Java binary format (with -b option). It might be faster to save/load but it is not human readable. In case you want to read it, it is a `org.ejml.data.ZMatrixRMaj`.
43 changes: 35 additions & 8 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@ plugins {
id("com.github.johnrengelman.shadow") version "6.0.0"
}
group = "com.dedztbh"
version = "1.4.3-ejml"
version = "1.4.4"

val projectRoot = "${group}.kuantum"
val projectRootExclude = "/${projectRoot.replace('.', '/')}"

val ejmlVersion = "0.39"
val jblasVersion = "1.2.5"

repositories {
mavenCentral()
Expand All @@ -27,6 +31,7 @@ kotlin {
dependencies {
implementation("org.ejml:ejml-core:${ejmlVersion}")
implementation("org.ejml:ejml-zdense:${ejmlVersion}")
implementation("org.jblas:jblas:${jblasVersion}")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9")
implementation("com.github.cvb941:kotlin-parallel-operations:1.3")
implementation("com.github.doyaaaaaken:kotlin-csv-jvm:0.11.1")
Expand All @@ -44,18 +49,40 @@ tasks.withType<KotlinCompile> {
}

tasks {
named<ShadowJar>("shadowJar") {
archiveBaseName.set("Kuantum")
register("shadowJarEjml", ShadowJar::class) {
archiveBaseName.set("Kuantum-ejml")
from(sourceSets.main.get().output)
configurations.add(project.configurations.runtime.get())
configurations.add(project.configurations.implementation.get().apply {
isCanBeResolved = true
})
mergeServiceFiles()
manifest {
attributes(mapOf("Main-Class" to "MainKt"))
attributes(mapOf("Main-Class" to "${projectRoot}.ejml.MainKt"))
}
dependencies {
exclude(dependency("org.jblas:jblas:${jblasVersion}"))
}
exclude("${projectRootExclude}/jblas")
minimize()
}
}

tasks {
build {
dependsOn(shadowJar)
register("shadowJarJBLAS", ShadowJar::class) {
archiveBaseName.set("Kuantum-jblas")
from(sourceSets.main.get().output)
configurations.add(project.configurations.runtime.get())
configurations.add(project.configurations.implementation.get().apply {
isCanBeResolved = true
})
mergeServiceFiles()
manifest {
attributes(mapOf("Main-Class" to "${projectRoot}.jblas.MainKt"))
}
dependencies {
exclude(dependency("org.ejml:ejml-core:${ejmlVersion}"))
exclude(dependency("org.ejml:ejml-zdense:${ejmlVersion}"))
}
exclude("${projectRootExclude}/ejml")
minimize()
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
package com.dedztbh.kuantum.common

import kotlinx.cli.ArgParser
import kotlinx.cli.ArgType
import kotlinx.cli.default
import kotlinx.cli.optional


/**
* Created by DEDZTBH on 2020/09/27.
* Project KuantumCircuitSim
*/

const val DEFAULT_N = 5

const val CMD = "java -jar Kuantum.jar"

class Config(parser: ArgParser) {
val input by parser.argument(ArgType.String, description = "Input file")
val operator by parser.argument(ArgType.String, description = "Operator name")
Expand Down Expand Up @@ -44,6 +47,6 @@ class Config(parser: ArgParser) {
val binary_matrix by parser.option(
ArgType.Boolean,
shortName = "b",
description = "Use binary format instead of csv for read/save circuit matrix if present"
description = "Use binary format instead of csv for read/save circuit matrix if present (EJML version only)"
).default(false)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package operator
package com.dedztbh.kuantum.common

import Config
import kotlinx.coroutines.CoroutineScope

/**
Expand All @@ -9,7 +8,7 @@ import kotlinx.coroutines.CoroutineScope
*/

/**
* Children class must have a constructor that takes an Config object and a coroutine scope
* Children class must have a constructor that takes an common.Config object and a coroutine scope
*/
interface Operator {
suspend fun runCmd(cmd: String): Int
Expand All @@ -18,8 +17,8 @@ interface Operator {

companion object {
@JvmStatic
fun get(config: Config, scope: CoroutineScope) =
Class.forName("operator.${if (config.sequential) "" else "P"}${config.operator}")
fun get(config: Config, scope: CoroutineScope, lib: String) =
Class.forName("com.dedztbh.kuantum.${lib}.operator.${if (config.sequential) "" else "P"}${config.operator}")
.getDeclaredConstructor(Config::class.java, CoroutineScope::class.java)
.newInstance(config, scope) as Operator
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
package com.dedztbh.kuantum.common

import kotlinx.cli.ArgParser
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import operator.Operator
import java.io.File

/**
* Created by DEDZTBH on 2020/09/22.
* Project KuantumCircuitSim
*/

fun main(args: Array<String>) {
val parser = ArgParser("java -jar Kuantum.jar")
fun main(args: Array<String>, lib: String) {
val parser = ArgParser(CMD)
val config = Config(parser)
parser.parse(args)

reader = File(config.input).bufferedReader()

runBlocking(Dispatchers.Default) {
val operator = Operator.get(config, this)
val operator = Operator.get(config, this, lib)

var cmd = read()
while (true) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package com.dedztbh.kuantum.common

import java.io.BufferedReader
import java.util.*
import kotlin.math.pow
Expand Down
10 changes: 10 additions & 0 deletions src/main/kotlin/com/dedztbh/kuantum/ejml/main.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.dedztbh.kuantum.ejml

import com.dedztbh.kuantum.common.main

/**
* Created by DEDZTBH on 2020/10/11.
* Project KuantumCircuitSim
*/

fun main(args: Array<String>) = main(args, "ejml")
112 changes: 112 additions & 0 deletions src/main/kotlin/com/dedztbh/kuantum/ejml/matrix/CMatrixIO.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package com.dedztbh.kuantum.ejml.matrix

import com.github.doyaaaaaken.kotlincsv.client.CsvReader
import com.github.doyaaaaaken.kotlincsv.client.CsvWriter
import org.ejml.UtilEjml
import org.ejml.data.MatrixSparse
import org.ejml.data.MatrixType
import org.ejml.ops.MatrixIO
import java.io.*
import java.text.DecimalFormat

/**
* Created by DEDZTBH on 2020/09/27.
* Project KuantumCircuitSim
*/

fun getMatrixType(mat: CMatrix): String {
return if (mat.type == MatrixType.UNSPECIFIED) {
mat.javaClass.simpleName
} else {
mat.type.name
}
}

fun printTypeSize(out: PrintStream, mat: CMatrix) {
if (mat is MatrixSparse) {
val m = mat as MatrixSparse
out.println(
"Type = " + getMatrixType(mat) + " , rows = " + mat.getNumRows() +
" , cols = " + mat.getNumCols() + " , nz_length = " + m.nonZeroLength
)
} else {
out.println("Type = " + getMatrixType(mat) + " , rows = " + mat.getNumRows() + " , cols = " + mat.getNumCols())
}
}

fun padSpace(builder: java.lang.StringBuilder, length: Int): String {
builder.delete(0, builder.length)
for (i in 0 until length) {
builder.append(' ')
}
return builder.toString()
}

fun saveCsv(A: CMatrix, fileName: String) =
CsvWriter().writeAll(A.data.asList().windowed(A.rowStride, A.rowStride), fileName)


fun loadCsv(fileName: String): CMatrix =
CMatrix(CsvReader().open(fileName) {
readAllAsSequence().map {
DoubleArray(it.size) { i -> it[i].toDouble() }
}.toMutableList().toTypedArray()
})

fun <T> saveBin(A: T, fileName: String) {
val fileStream = FileOutputStream(fileName)
val stream = ObjectOutputStream(fileStream)
try {
stream.writeObject(A)
stream.flush()
} finally {
// clean up
fileStream.use {
stream.close()
}
}
}

@Suppress("UNCHECKED_CAST")
fun <T> loadBin(fileName: String): T {
val fileStream = FileInputStream(fileName)
val stream = ObjectInputStream(fileStream)
val ret: T
try {
ret = stream.readObject() as T
if (stream.available() != 0) {
throw RuntimeException("File not completely read?")
}
} catch (e: ClassNotFoundException) {
throw RuntimeException(e)
}
stream.close()
return ret
}

fun CMatrix.printFancy2(
allssket: List<String>,
out: PrintStream = System.out,
length: Int = MatrixIO.DEFAULT_LENGTH,
) {
// printTypeSize(out, this)
val format = DecimalFormat("#")
val builder = StringBuilder(length)
val cols = numCols
val c = CNum()
var i = 0
for (y in 0 until numRows) {
for (x in 0 until cols) {
get(y, x, c)
var real = UtilEjml.fancyString(c.real, format, length, 4)
var img = UtilEjml.fancyString(c.imaginary, format, length, 4)
real += padSpace(builder, length - real.length)
img = img + "i" + padSpace(builder, length - img.length)
out.print("${allssket[i++]}: $real + $img")
if (x < numCols - 1) {
out.print(" , ")
}
}
out.println()
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package matrix
package com.dedztbh.kuantum.ejml.matrix

/**
* Created by DEDZTBH on 2020/09/25.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
package matrix

package com.dedztbh.kuantum.ejml.matrix

/**
* Created by DEDZTBH on 2020/09/22.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package matrix
package com.dedztbh.kuantum.ejml.matrix

import org.ejml.data.Complex_F64
import org.ejml.data.ZMatrixRMaj
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package operator
package com.dedztbh.kuantum.ejml.operator

import Config
import com.dedztbh.kuantum.common.Config
import com.dedztbh.kuantum.ejml.matrix.*
import com.lukaskusik.coroutines.transformations.map.mapParallel
import com.lukaskusik.coroutines.transformations.reduce.reduceParallel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.async
import matrix.*
import matrix.CMatrixIO.printFancy2

/**
* Created by DEDZTBH on 2020/09/22.
Expand All @@ -19,8 +17,9 @@ class AllInit(config: Config, scope: CoroutineScope) : TFinder(config, scope) {
println("\nFinal states: ")
alls.forEachIndexed { idx, arr ->
println("Init ${allssket[idx]}")
var jointState = I1
arr.forEach { i ->
val it = arr.iterator()
var jointState = if (it.next() == 0) KET0 else KET1
it.forEachRemaining { i ->
jointState = jointState kron (if (i == 0) KET0 else KET1)
}
(opMatrix * jointState).printFancy2(allssket = allssket)
Expand All @@ -35,9 +34,12 @@ class PAllInit(config: Config, scope: CoroutineScope) : PTFinder(config, scope)
println("\nFinal states: ")
alls.mapParallel { arr ->
scope.async {
opMatrix *
arr.mapParallel { if (it == 0) KET0 else KET1 }
.reduceParallel { a, b -> a kron b }
val it = arr.iterator()
var jointState = if (it.next() == 0) KET0 else KET1
it.forEachRemaining { i ->
jointState = jointState kron (if (i == 0) KET0 else KET1)
}
opMatrix * jointState
}
}.forEachIndexed { i, mat ->
println("Init ${allssket[i]}")
Expand Down
Loading

0 comments on commit eef49de

Please sign in to comment.