Created
May 10, 2025 15:02
-
-
Save daxfohl/1de1d9c824a21e816ea62035647ea80a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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