From b074da8fde38913cce8fa708c245a5d1a10f7e38 Mon Sep 17 00:00:00 2001 From: fmhaus Date: Sun, 2 Jun 2024 23:49:39 +0200 Subject: [PATCH] Added basic custom matrix input --- index.html | 53 +++++++++++++++-------- quantum.js | 12 ++++++ ui.js | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 164 insertions(+), 24 deletions(-) diff --git a/index.html b/index.html index dc45855..79f9d55 100644 --- a/index.html +++ b/index.html @@ -1,4 +1,4 @@ - + Bloch sphere visualizer @@ -13,12 +13,12 @@ - + - - + + @@ -30,7 +30,7 @@ $('.collapsible').collapsible(); }); - +
Init @@ -53,8 +53,8 @@
Download - - + +
@@ -105,7 +105,7 @@ + - +
  • @@ -158,6 +158,24 @@
  • +
  • +
    clearCustom Quantum gate
    +
    + + + + + + + + + + + + +
    Apply
    +
    +
  • rss_feedPulses
    @@ -208,9 +226,9 @@
  • - - - + + + @@ -220,14 +238,14 @@ - + - - - + + + @@ -235,7 +253,6 @@ - + - diff --git a/quantum.js b/quantum.js index 13c95e2..95def2f 100644 --- a/quantum.js +++ b/quantum.js @@ -101,6 +101,18 @@ function rot_phosphor(axis_op, angle, state, divider=10) { PHOSPHOR.push(hist); } +function apply_custom_op(custom_op, state) { + let transformed = math.multiply(custom_op, state); + // We have no guarantee the custom_op is unitary; make sure the state stays unit length + let length_sum = 0.0; + for (var i = 0; i < transformed.size()[0]; i++) { + let abs = transformed.get([i]).abs(); + length_sum += abs * abs; + } + + return math.multiply(1.0 / math.sqrt(length_sum), transformed); +} + function rabi_plot(data=null) { time = document.getElementById('pulselength').value; if (data === null) { diff --git a/ui.js b/ui.js index d7991b2..1ac4f1d 100644 --- a/ui.js +++ b/ui.js @@ -24,7 +24,6 @@ function pulse_apply(axis){ } - function export_png() { var currentdate = new Date(); var datetime = currentdate.getFullYear() + "-" + (currentdate.getMonth()+1) + "-" + currentdate.getDate() + "_" + currentdate.getHours() + '- ' + currentdate.getMinutes() + '-' + currentdate.getSeconds(); @@ -40,7 +39,6 @@ function hadamard(){ rotate_state(rot_op,math.PI); } - function custom_rotate_state(){ opX = math.matrix([[0,math.complex(0.5,0)],[math.complex(0.5,0),0]]); opY = math.matrix([[0,math.complex(0,-0.5)],[math.complex(0,0.5),0]]); @@ -53,13 +51,126 @@ function custom_rotate_state(){ rotate_state(rot_op,document.getElementById('custom_axis_rot_angle').value/180*math.PI); } +function apply_custom_matrix() { + let op = math.matrix([[parse_complex_field('custom_m00'), parse_complex_field('custom_m01')], [parse_complex_field('custom_m10'), parse_complex_field('custom_m11')]]); + + QMSTATEVECTOR.push(apply_custom_op(op, QMSTATEVECTOR[QMSTATEVECTOR.length-1])); + update_state_plot(); +} + +function on_update_complex(event) { + let parsed = parse_complex(event.target.value); + event.target.value = parsed.format(4); +} + +function parse_complex_field(field_id) { + return parse_complex(document.getElementById(field_id).value); +} + +function parse_complex(string) { + string = string.trim(); + if (string.startsWith('e^')) { + // parse e^complex + string = string.slice(2); + if (string.startsWith('(')) { + string = string.slice(1); + } + if (string.endsWith(')')) { + string = string.slice(0, -1); + } + let c = parse_complex(string); + return math.Complex.fromPolar(Math.exp(c.re), c.im); + } else { + // Remove the first sign and store its value + let beginSign = '+'; + if (string.startsWith('-')) { + beginSign = '-'; + string = string.slice(1).trim(); + } else if (string.startsWith('+')) { + string = string.slice(1).trim(); + } + + // split by + or - sign to seperate real and imaginary number + let split = string.split(/[\+\-]/); + if (split.length == 1) { + // we only have a real or imaginary part + let trimmed_value = split[0].trim(); + if (trimmed_value.endsWith('i')) { + // only imaginary + if (trimmed_value.length == 1) { + // catch i (without any number) + return math.complex(0, parseFloat(beginSign + '1')); + } + let parsed = parseFloat(beginSign + trimmed_value.slice(0, -1)); + if (isNaN(parsed)) { + return math.complex(0, 0); + } + return math.complex(0, parsed); + } else { + // only real + let parsed = parseFloat(beginSign + trimmed_value); + if (isNaN(parsed)) { + return math.complex(0, 0); + } + return math.complex(parsed, 0); + } + + } else if (split.length == 2) { + + let trimmed1 = split[0].trim(); + let trimmed2 = split[1].trim(); + let re, im; + + // reappend signedness + trimmed1 = beginSign + trimmed1; + + if (string.includes('-')) { + trimmed2 = '-' + trimmed2; + } + + // find which part is real and which imaginary + if (trimmed2.endsWith('i') && !trimmed1.endsWith('i')) { + re = trimmed1; + im = trimmed2; + } else if (!trimmed2.endsWith('i') && trimmed1.endsWith('i')) { + re = trimmed2; + im = trimmed1; + } else { + return math.complex(0, 0); + } + + let re_parsed = parseFloat(re); + let im_parsed; + + // catch +i or -i + if (im.length == 1 || (im.length == 2 && im[0] == '+')) { + im_parsed = 1; + } else if (im.length == 2 && im[0] == '-') { + im_parsed = -1; + } else { + im_parsed = parseFloat(im.slice(0, -1)); + } + + if (isNaN(re_parsed)) { + re_parsed = 0.0; + } + if (isNaN(im_parsed)) { + im_parsed = 0.0; + } + + return math.complex(re_parsed, im_parsed); + } else { + return math.complex(0, 0); + } + } +} function undo() { if (QMSTATEVECTOR.length> 1){ - QMSTATEVECTOR.pop(); - PHOSPHOR.pop(); - update_state_plot(); -} + QMSTATEVECTOR.pop(); + PHOSPHOR.pop(); + update_state_plot(); + } }