Path: blob/main/frontend/vue/components/MiniComposer/gateUtils.ts
3375 views
// eslint-disable-next-line import/named1import { multiply, subtract, add, gcd, round } from 'mathjs'23export enum GateName {4UNKNOWN = 'UNKNOWN',5ID = 'ID',6H = 'H',7Z = 'Z',8X = 'X',9Y = 'Y',10T = 'T',11S = 'S',12RX = 'RX',13RZ = 'RZ',14RY = 'RY',15MEASURE_Z = 'Measure'16}1718function neg (m: number[][]) {19return multiply(m, -1)20}21export interface StateMatrix {22A: number[][]23B: number[][]24C: number[][]25D: number[][]26m: number27}2829function reduceSingleElement (numerator: number, denominator: number) {30const d = gcd(numerator, denominator)3132return {33numerator: round(numerator / d),34denominator: round(denominator / d)35}36}3738export function IdentityState (): StateMatrix {39return {40A: [[1, 0], [0, 1]],41B: [[0, 0], [0, 0]],42C: [[0, 0], [0, 0]],43D: [[0, 0], [0, 0]],44m: 045}46}4748export interface QuantumGate {49apply (state: StateMatrix): StateMatrix50}5152export const Identity: QuantumGate = {53apply (state: StateMatrix) {54return state55}56}5758export const XGate: QuantumGate = {59apply (state: StateMatrix) {60// Integer part61const K = [[0, 1], [1, 0]]62return {63A: multiply(K, state.A),64B: multiply(K, state.B),65C: multiply(K, state.C),66D: multiply(K, state.D),67m: state.m68}69}70}7172export const YGate: QuantumGate = {73apply (state: StateMatrix) {74// Integer part75const K = [[0, -1], [1, 0]]7677return {78A: neg(multiply(K, state.B)),79B: multiply(K, state.A),80C: neg(multiply(K, state.D)),81D: multiply(K, state.C),82m: state.m83}84}85}8687export const ZGate: QuantumGate = {88apply (state: StateMatrix) {89// Integer part90const K = [[1, 0], [0, -1]]9192return {93A: multiply(K, state.A),94B: multiply(K, state.B),95C: multiply(K, state.C),96D: multiply(K, state.D),97m: state.m98}99}100}101102export const HGate: QuantumGate = {103apply (state: StateMatrix) {104// Integer part105const K = [[1, 1], [1, -1]]106107return {108A: multiply(multiply(K, state.C), 2),109B: multiply(multiply(K, state.D), 2),110C: multiply(K, state.A),111D: multiply(K, state.B),112m: state.m + 1113}114}115}116117export const SGate: QuantumGate = {118apply (state: StateMatrix) {119// Integer part120const K1 = [[1, 0], [0, 0]]121const K2 = [[0, 0], [0, 1]]122123return {124A: subtract(multiply(K1, state.A), multiply(K2, state.B)),125B: add(multiply(K2, state.A), multiply(K1, state.B)),126C: subtract(multiply(K1, state.C), multiply(K2, state.D)),127D: add(multiply(K2, state.C), multiply(K1, state.D)),128m: state.m129}130}131}132133export const TGate: QuantumGate = {134apply (state: StateMatrix) {135// Integer part136const K1 = [[2, 0], [0, 0]]137const K2 = [[0, 0], [0, 1]]138139const K1_A = multiply(K1, state.A)140const K1_B = multiply(K1, state.B)141const K1_C = multiply(K1, state.C)142const K1_D = multiply(K1, state.D)143144const K2_A = multiply(K2, state.A)145const K2_B = multiply(K2, state.B)146const K2_C = multiply(K2, state.C)147const K2_D = multiply(K2, state.D)148149const K2_C_2 = multiply(K2_C, 2)150const K2_D_2 = multiply(K2_D, 2)151152return {153A: subtract(add(K1_A, K2_C_2), K2_D_2),154B: add(add(K1_B, K2_C_2), K2_D_2),155C: add(subtract(K2_A, K2_B), K1_C),156D: add(add(K2_A, K2_B), K1_D),157m: state.m + 1158}159}160}161162export const gateMap = {163[GateName.UNKNOWN]: Identity,164[GateName.ID]: Identity,165[GateName.MEASURE_Z]: Identity,166[GateName.H]: HGate,167[GateName.X]: XGate,168[GateName.Y]: YGate,169[GateName.Z]: ZGate,170[GateName.T]: TGate,171[GateName.S]: SGate,172[GateName.RX]: Identity,173[GateName.RY]: Identity,174[GateName.RZ]: Identity175}176177function signedString (n: number, m: number, symbol: string = '') {178if (n === 0) {179return ''180}181const { numerator, denominator } = reduceSingleElement(n, Math.pow(2, m))182183const absNumerator = Math.abs(numerator)184const sign = numerator > 0 ? '+' : '-'185let numeratorTex = ''186187if (symbol) {188numeratorTex = `${absNumerator > 1 ? absNumerator : ''}${symbol}`189} else {190numeratorTex = `${absNumerator}`191}192193if (denominator !== 1 && m > 0) {194return `${sign}\\frac{${numeratorTex}}{${denominator}}`195} else {196return `${sign}${numeratorTex}`197}198}199200function StateMatrixElementToTex (state: StateMatrix, coords: { x: number, y: number }) {201const { x, y } = coords202const [a, b, c, d] = [state.A[x][y], state.B[x][y], state.C[x][y], state.D[x][y]]203const isZero = (a * a + b * b + c * c + d * d) === 0204205if (isZero) {206return '0'207}208209const aTex = signedString(a, state.m)210const bTex = signedString(b, state.m, 'i')211const cTex = signedString(c, state.m, '\\sqrt{2}')212const dTex = signedString(d, state.m, 'i\\sqrt{2}')213214let tex = `${aTex}${bTex}${cTex}${dTex}`215216if (tex.startsWith('+')) {217tex = tex.substring(1)218}219220return tex221}222223export function StateMatrixToTexMatrix (state: StateMatrix) {224return `225\\begin{pmatrix}226${StateMatrixElementToTex(state, { x: 0, y: 0 })} & ${StateMatrixElementToTex(state, { x: 0, y: 1 })}\\\\227${StateMatrixElementToTex(state, { x: 1, y: 0 })} & ${StateMatrixElementToTex(state, { x: 1, y: 1 })}228\\end{pmatrix}229`230}231232function parenthesis (text: string) {233return `\\left(${text}\\right)`234}235236function valueKetTex (value: string, ket: 0 | 1) {237if (value === '0') {238return ''239}240241const ketTex = `|${ket}\\rangle`242if (value === '1') {243return ketTex244}245246const isMultiElement = value.includes('+') || value.lastIndexOf('-') > 1247const valueTex = isMultiElement ? parenthesis(value) : value248249return `${valueTex}${ketTex}`250}251252export function StateMatrixToTexKetNotation (state: StateMatrix) {253const zeroKetValue = StateMatrixElementToTex(state, { x: 0, y: 0 })254const oneKetValue = StateMatrixElementToTex(state, { x: 1, y: 0 })255256const bothKets = zeroKetValue !== '0' && oneKetValue !== '0'257258const zeroKetTex = valueKetTex(zeroKetValue, 0)259const oneKetTex = valueKetTex(oneKetValue, 1)260261let joinTex = ''262if (bothKets && !oneKetTex.startsWith('-')) {263joinTex = '+'264}265266return `267${zeroKetTex}${joinTex}${oneKetTex}268`269}270271272