{% import 'circuit_css.html' as style %} {# Define macros to help render circuit blocks #} {# ------------------------------------------- #} {# Gap #} {% macro gap(link_vertical=false) -%}
{% if link_vertical %} {% endif %}
{%- endmacro %} {# Plain wire #} {% macro wire(type=1, link_vertical=false) -%}
{% if link_vertical %} {% endif %}
{%- endmacro %} {# Generic single qubit gate #} {% macro gate1(name, wire_type=1, link_vertical=false) -%}
{{ wire(type=wire_type) }}
{% if name == "X" %} {{ wire() }}
{% elif name == "Reset" %}
{% else %}
{{ name }}
{% endif %} {% if link_vertical %} {% endif %}
{{ wire(type=wire_type) }}
{%- endmacro %} {# Generic multi qubit gate #} {% macro gateN(wire_type=1, pos=-1, name='', display_name=false, link=0, link_vertical=false) -%}
{% if link_vertical %} {% endif %}
{%- endmacro %} {# Controlled gate #} {% macro c_gate(params, type, wire_type=1, pos=-1, top=false, bottom=false, args=[], options={}) -%} {# Render the involved registers #} {% if pos > -1 %} {# If this is a gate, render it using the usual macro #} {% if wire_type < 2 and pos > -1 %} {{ render_gate({ "op": { "type": type }, "pos": -1 if top else (0 if bottom else 1), "params": params, "args": [(wire_type, pos)], "t_args": args|length, "n_args": - (args|get_target_args|length) }, link_vertical=not top, options=options) }} {% else %} {# Otherwise, it's a control bit #}
{{ wire(type=wire_type-2) }}
{% if not top %} {% endif %}
{% endif %} {# Registers that aren't involed are just vertical links #} {% else %}
{{ wire(type=wire_type) if pos != 1}}
{% if not top %} {% endif %}
{% endif %} {%- endmacro %} {# SWAP #} {% macro swap_gate(pos=-1, link_vertical=false, is_bottom=False) -%}
{% if not is_bottom %} {% endif %} {% if link_vertical %} {% endif %} {{ wire() }}
{%- endmacro %} {# Measurement #} {% macro measure_gate(pos=0, wire_type=1, link_vertical=false) -%}
{% if pos > -1 %} {% endif %} {% if link_vertical %} {% endif %} {{ wire(type=wire_type) }}
{%- endmacro %} {# List out the qubits #} {% macro register_list(qubits, bits) -%}
{% for qubit in qubits %}
{{ qubit.reg_name ~ qubit.index }}
{% endfor %} {% for bit in bits %}
{{ bit.reg_name ~ bit.index }}
{% endfor %}
{%- endmacro %} {% macro render_circuit(circuit, options={}, nested=false) -%} {% if not nested %}
{% endif %}
{{ register_list(circuit.qubits, circuit.bits) }} {% for layer in circuit.layers %}
{% for gate in layer %} {# Controlled gates get special treatment #} {% if gate.op.type|is_control_gate %} {% for (arg_type, pos) in gate.args %} {{ c_gate(gate.params, gate.op.type|get_op_name(gate.op.raw), wire_type=arg_type, pos=pos, top=loop.first, bottom=loop.last, args=gate.args, options=options) }} {% endfor %} {% else %} {{ render_gate(gate, options=options) }} {% endif %} {% endfor %}
{% endfor %} {{ register_list(circuit.qubits, circuit.bits) }}
{% if not nested %}
{% endif %} {%- endmacro %} {% macro render_gate(gate, options={}, link_vertical=false) %} {# Decide what to render by case, in 2 steps: first, type of operation, second no. of qbits involved #} {% if gate.op.type == 'ID' %} {% for (arg_type, pos) in gate.args %} {{ wire(type=arg_type, link_vertical=link_vertical) }} {% endfor %} {# SWAP #} {% elif gate.op.type == 'SWAP' %} {% for arg_type, pos in gate.args %} {{ swap_gate(pos=pos, link_vertical=link_vertical, is_bottom=loop.index == loop.length) }} {% endfor %} {# Measurements #} {% elif gate.op.type == "Measure" %} {{ measure_gate(pos=1, wire_type=gate.args[0][0], link_vertical=link_vertical) }} {% for arg_type, pos in gate.args[1:-1] %} {{ measure_gate(wire_type=arg_type) }} {% endfor %} {{ measure_gate(pos=-1, wire_type=gate.args[-1][0], link_vertical=link_vertical) }} {# Nested circuit #} {% elif gate.op.type == "CircBox" and options.recursive %}
{% for (arg_type, link) in gate.args %} {% if link > -1 %} {{ wire(type=arg_type) }} {% else %} {{ gap() }} {% endif %} {% endfor %}
{% for (arg_type, link) in gate.args %}
{{ link if link > -1 }}
{% endfor %}
{{ render_circuit(gate.op.raw.box.circuit|parse_circuit, options=options, nested=true) }}
{% for (arg_type, link) in gate.args %}
{{ link if link > -1 }}
{% endfor %}
{% for (arg_type, link) in gate.args %} {% if link > -1 %} {{ wire(type=arg_type) }} {% else %} {{ gap() }} {% endif %} {% endfor %}
{# Generic gate #} {% else %} {% if gate.n_args > 1 %} {{ gateN(wire_type=gate.args[0][0], link=gate.args[0][1], link_vertical=link_vertical) }} {% for (arg_type,link) in gate.args[1:] %} {{ gateN( wire_type=arg_type, pos=gate.n_args - loop.index - 1, name=gate.op.type ~ gate.params, display_name=loop.index * 2 == gate.n_args - 1 or loop.index * 2 == gate.n_args, link=link, link_vertical=link_vertical) }} {% endfor %} {% elif gate.n_args < -1 %} {# We are rendering an n-gate incrementally #} {{ gateN( wire_type=gate.args[0][0], pos=gate.pos, name=gate.op.type ~ gate.params, display_name=gate.args[0][1] == gate.t_args + gate.n_args, link=gate.args[0][1], link_vertical=link_vertical) }} {% else %} {{ gate1(gate.op.type ~ gate.params, wire_type=gate.args[0][0], link_vertical=link_vertical) }} {% endif %} {% endif %} {% endmacro %} {# Render the circuit as a standalone page #} {# ------------------------------------------- #} {{ style.get_css() }}
{{ render_circuit(circuit|parse_circuit, options=display_options) }}