Skip to content

Instantly share code, notes, and snippets.

@daxfohl
Created May 10, 2025 15:02
Show Gist options
  • Save daxfohl/1de1d9c824a21e816ea62035647ea80a to your computer and use it in GitHub Desktop.
Save daxfohl/1de1d9c824a21e816ea62035647ea80a to your computer and use it in GitHub Desktop.
// QReg interface and implementations
interface QReg<T : QReg<T>> {
fun mapIndices(mapper: (Int) -> Int): T
fun indices(): List<Int>
}
data class Qubit(val index: Int) : QReg<Qubit> {
override fun mapIndices(mapper: (Int) -> Int) = Qubit(mapper(index))
override fun indices() = listOf(index)
}
data class QPair(val i1: Int, val i2: Int) : QReg<QPair> {
override fun mapIndices(mapper: (Int) -> Int) = QPair(mapper(i1), mapper(i2))
override fun indices() = listOf(i1, i2)
}
// Operation
data class Operation<S>(
val opName: String,
val apply: (S) -> String
)
// Channels and state representations
data class DM(val r: Float, val i: Float)
data class SV(val value: Float)
data class Channel(val r: Float, val i: Float)
data class Unitary(val factor: Float)
fun mockApplyChannel(channel: Channel, indices: List<Int>, dm: DM): String =
"channel: $channel dm$dm indices$indices"
fun mockApplyUnitary(unitary: Unitary, indices: List<Int>, sv: SV): String =
"unitary: $unitary sv$sv indices$indices"
fun unitaryToChannel(u: Unitary) = Channel(u.factor, u.factor)
// Interfaces
interface GateReader {
fun name(): String
}
interface Gate<Q : QReg<Q>, S> : GateReader {
fun on(qureg: Q): Operation<S>
}
interface ChannelGateReader : GateReader {
fun getChannel(): Channel
}
interface ChannelGate<Q : QReg<Q>> : ChannelGateReader, Gate<Q, DM> {
fun applyChannel(qureg: Q, dm: DM): String {
return mockApplyChannel(getChannel(), qureg.indices(), dm)
}
override fun on(qureg: Q): Operation<DM> =
Operation(name()) { dm -> applyChannel(qureg, dm) }
}
interface UnitaryGateReader : GateReader {
fun getUnitary(): Unitary
}
interface UnitaryGate<Q : QReg<Q>> : UnitaryGateReader, Gate<Q, SV> {
fun applyUnitary(qureg: Q, sv: SV): String {
return mockApplyUnitary(getUnitary(), qureg.indices(), sv)
}
override fun on(qureg: Q): Operation<SV> =
Operation(name()) { sv -> applyUnitary(qureg, sv) }
}
// Extension to convert UnitaryGate into ChannelGate
fun <Q : QReg<Q>> UnitaryGate<Q>.asChannelGate(): ChannelGate<Q> =
UnitaryChannelGate(this)
// BitFlip gate
data class BitFlip(val p: Float) : ChannelGate<Qubit> {
override fun getChannel() = Channel(p, p)
override fun name() = "BitFlip"
}
// XPowGate
data class XPowGate(val exp: Float) : UnitaryGate<Qubit> {
override fun getUnitary() = Unitary(exp)
override fun name() = "XPowGate"
}
// UnitaryChannelGate: generalized over Q
data class UnitaryChannelGate<Q : QReg<Q>>(
val u: UnitaryGate<Q>
) : ChannelGate<Q> {
override fun getChannel(): Channel = unitaryToChannel(u.getUnitary())
override fun name(): String = u.name()
}
// Simulator
fun <S> sim(state: S, ops: List<Operation<S>>): String =
ops.joinToString("\n") { it.apply(state) }
// Example usage
fun main() {
val dm = DM(0.3f, 0.5f)
val ops = listOf(
BitFlip(0.4f).on(Qubit(4)),
BitFlip(0.4f).on(Qubit(4)),
XPowGate(0.4f).asChannelGate().on(Qubit(4))
)
val result = sim(dm, ops)
println(result)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment