Skip to content

A javascript library for easily writing QASM 2.0 code for quantum computing

License

Notifications You must be signed in to change notification settings

ljcamargo/quantumjs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

QuantumJS

GitHub version

This is an open source library to ease the creation of complex QASM 2.0 quantum circuits (algorithms) with the simplicity of javascript chaining patterns and other high-level language features.

QuantumJS generates compliant Quantum Assembly Language 2.0 capable of being executed on a real five qubits quantum processor from IBM Quantum Experience or simulate the execution of circuits other topologies on this platform.

The aim of this library is to provide a framework to bind current classical computing with quantum computing beyond experimental levels.

To know more and get access to the quantum processor and platform visit IBM Quantum Experience.

Usage

Setup

Include quantum.js on your project.

Initialize an IDEAL quantum processor with unlimited qubits and unlimited interactions.

var Q = new QuantumJS();

Or initialize with the 5-qubit IBMQX2.

var Q = new QuantumJS('ibmqx2');

You may initialize with a custom topology:

var Q = new QuantumJS({
  'name': 'ibmqx3',
  'registries': [
    {
      'kind':'quantum',
      'name':'q',
      'length': 5,
      'coupling_map': [[0,1],[0,2],[1,2],[3,2],[3,4],[4,2]],
      'topology': [[1,2],[2],[],[2,4],[2]]
    },
    {
      'kind':'classical',
      'name':'c',
      'length': 5
    }
  ]
});

Qubits

Select a qubit by its index number

Q.bit(0);

You can also specify a q-register name for the qubit array.

Q.bit(0, 'a');

The default qubit register name is ‘q’

If no index is specified, the entire 'q' register array is returned

Q.bit();

When using an IDEAL processor (no topology) qubits and q-registers are created on demand if they do not exist.

When a topology is specified, qubits and q-registers must be within the predefined configuration or an error is thrown.

Quantum Gates

After selecting a qubit, you can apply a quantum gate (or transformation);

Gates

Pauli X (bit-flip, not)

Q.bit(0).x();

Pauli Y

Q.bit(0).y();

Pauli Z

Q.bit(0).z();

Idle Gate (Identity)

Q.bit(0).id();

Hadamard Gate

Q.bit(0).h();

Square Root Gate (S) and conjugate (S†, SDG)

Q.bit(0).s(); //S
Q.bit(0).s_(); //S conjugate

Non-Clifford T and conjugate (T†, TDG)

Q.bit(0).t(); //T
Q.bit(0).t_(); //T conjugate

Rotation Gates (U) You must provide rotation angles in an array (lambda, phi, theta)

// lambda
Q.bit(0).u( [Q.π.div(2)] );     // u1(pi/2) q[0]; 
// lambda, phi
Q.bit(0).u( [Q.π.div(2), Q.π.div(4)] ); // u2(pi/2, pi/4) q[0]; 
// lambda, phi, theta
Q.bit(0).u( [0.3, 0.2, 0.1] );    // u3(0.3, 0.2, 0.1) q[0]; 

Controlled Gates

CNOT or CX

Q.bit(0).cnot(1); // apply x gate to q(1) when q(0) is |1> 
Q.bit(0).cx(1); // another name for the same function

CY, CZ

Q.bit(1).cy(2); // apply y gate to q(2) when q(1) is |1> 
Q.bit(3).cz(2); // apply z gate to q(2) when q(3) is |1> 

Controlled gates are limited on real devices. When using real or non-ideal topology a compile error is thrown if the interaction is not allowed.

Measuring

Measuring qubits to specific classical registers.

Q.bit(2).measureTo(2); // measure q[2] to c[2], the default register is ‘c’
Q.bit(2).measure(); // measure q[2] to c[2], index of classical bit will be inferred from qubit
Q.bit(2).measureTo(0,’c2’); // measure q[2] to c2[0]

Measuring the entire array. Qubits and Classical array must be of the same size or error is thrown

Q.bit().measure(); // measure all qubits from q to c
// this is equal to..
Q.bit(0).measureTo(0);
Q.bit(1).measureTo(1);
Q.bit(2).measureTo(2);
// and so on...

Rotate to V, W, X, Y or Z and measure (to simplify bloch tomography)

Q.bit(2).measureX(2); 
// equal to: Q.bit(2).h().measureTo(2);

Q.bit(2).measureY(2); 
// equal to: Q.bit(2).s_().h().measureTo(2);

Q.bit(2).measureW(2); 
// equal to: Q.bit(2).s().h().t().h().measureTo(2);

Compile

Get the QASM2.0 code for on IBM Quantum Experience on a variable.

var qasm = Q.compile(); 

You may also use a callback pattern for compiling

Q.compile(function(str) {
  $('div').text(str); // In this examples we use jQuery to write the qasm code to a div
  hljs.initHighlightingOnLoad(); //and highlight.js to highlight the code
});

Custom Functions

You may create and import custom routines and use it in the same chaining pattern.

Quantum Fourier Transform (n-bits)

function qft(bits, values) {
  //Q variable will be prepended to the function after adding it
  if (bits && bits instanceof Object) {
    values = bits; bits = values.length;
  }
  Q.comment(bits + "-bit Quantum Fourier Transform");
  if (values) Q.init(values);
  Q.barrier().brk();
  for (var i = 0; i < bits; i++) {
    for (var j = 0; j < i; j++) {
      Q.bit(i).cu1(Q.π.div(Math.pow(2, i-j)), j);
    }
    Q.bit(i).h().brk();
  }
  //The appended function will return Q variable
};

var values = [1,0,1,0,1,0,1,0];
var Q = new QuantumJS();
Q.addFunction('qft', qft); //add the function to Q
Q.fnc.qft(values); //and call it, the function will return Q.
Q.bit().h();
Q.bit().measure();
Q.compile(function(compiled) {
  console.log(compiled);
});

###Other Custom Functions Examples

Inverse Quantum Fourier Transform (n-bits)

function iqft(bits, values) {
  if (bits && bits instanceof Object) {
    values = bits; bits = values.length;
  }
  Q.comment(bits + "-bit Inverse Quantum Fourier Transform");
  if (values) Q.init(values);
  Q.barrier().brk();
  for (var i = 0; i < bits; i++) {
    for (var j = 0; j < i; j++) {
      Q.bit(i).u([Q.π.div(Math.pow(2, i-j))])._if(Q.cbit('c'+(i-1)));
    }
    Q.bit(i).h().brk();
    Q.bit(i).measureTo(0,'c'+i);
  }
};

//IQFT FROM A UNIFORM SUPERPOSITION OF 8-qubits
var values = ['+','+','+','+','+','+','+','+'];
var Q = new QuantumJS();
Q.addFunction('iqft', iqft);
Q.fnc.iqft(values);
var qasm = Q.compile();
console.log(qasm);

N-bit Control X

function getNCXSpannedArray(arr) {
  var span = [];
  span.push(arr[0]); span.push(arr[1]); span.push('');
  for (var i = 2; i < arr.length; i++) { span.push(arr[i]); span.push(''); }
  return span;
}

var values = [1,1,1,1];
var Q = new QuantumJS();
var span = getNCXSpannedArray(values);

Q.addFunction('ncx', n => {
  for (var i = 0; i <= n; i+=2) Q.bit(i).ccx(i+1, i+2);
  var l = (n % 2 == 0) ? 0 : 1;
  for (var i = (n-l); i >= 2; i-=2) Q.bit(i-2).ccx(i-1, i);
});
Q.comment("Set Initial State");
Q.init(span);
Q.barrier().brk();
Q.fnc.ncx(values.length);
Q.bit().measure();

var qasm = Q.compile();
console.log(qasm);

About

A javascript library for easily writing QASM 2.0 code for quantum computing

Resources

License

Stars

Watchers

Forks

Packages

No packages published