Example #1
0
File: Gate.js Project: perak/Quirk
 /**
  * @param {T} gatesObj
  * @returns {T}
  * @template T
  */
 static makeFamily(gatesObj) {
     let oldGates = Util.decomposeObjectValues(gatesObj);
     let newGates = oldGates.map(e => e._copy());
     for (let g of newGates) {
         g.gateFamily = newGates;
     }
     return Util.recomposedObjectValues(gatesObj, newGates);
 }
Example #2
0
File: Hand.js Project: perak/Quirk
 /**
  * @param {!Hand|*} other
  * @returns {!boolean}
  */
 isEqualTo(other) {
     if (this === other) {
         return true;
     }
     return other instanceof Hand &&
         Util.CUSTOM_IS_EQUAL_TO_EQUALITY(this.pos, other.pos) &&
         Util.CUSTOM_IS_EQUAL_TO_EQUALITY(this.holdOffset, other.holdOffset) &&
         Util.CUSTOM_IS_EQUAL_TO_EQUALITY(this.heldGate, other.heldGate) &&
         Util.CUSTOM_IS_EQUAL_TO_EQUALITY(this.resizingGateSlot, other.resizingGateSlot);
 }
Example #3
0
suite.test("decomposeObjectValues", () => {
    assertThat(Util.decomposeObjectValues({})).isEqualTo([]);
    assertThat(Util.decomposeObjectValues({a: "x"})).isEqualTo(["x"]);
    assertThat(Util.decomposeObjectValues({a: {b: "y"}})).isEqualTo([{b: "y"}]);
    assertThat(Util.decomposeObjectValues({a: "x", b: "y"})).isEqualTo(["x", "y"]);
    assertThat(Util.decomposeObjectValues({b: "y", a: "x"})).isEqualTo(["x", "y"]);
    assertThat(Util.decomposeObjectValues({a: []})).isEqualTo([]);
    assertThat(Util.decomposeObjectValues({a: [1, 2, 3]})).isEqualTo([1, 2, 3]);
    assertThat(Util.decomposeObjectValues({a: [1, 2, 3], b: "x", c: [4, 5]})).isEqualTo([1, 2, 3, "x", 4, 5]);
    assertThat(Util.decomposeObjectValues({a: [1, [2, 4], 3]})).isEqualTo([1, 2, 4, 3]);
    assertThat(Util.decomposeObjectValues({a: [1, [], 3]})).isEqualTo([1, 3]);
});
Example #4
0
 /**
  *
  * @param {undefined|!Point} pt
  *
  * @returns {?{groupIndex: !int, gateIndex: !int, gate: !Gate}}
  */
 findGateAt(pt) {
     if (pt === undefined) {
         return null;
     }
     for (let groupIndex = 0; groupIndex < Gates.Sets.length; groupIndex++) {
         let group = Gates.Sets[groupIndex];
         for (let gateIndex = 0; gateIndex < group.gates.length; gateIndex++) {
             let gate = group.gates[gateIndex];
             if (gate !== null && this.gateDrawRect(groupIndex, gateIndex).containsPoint(Util.notNull(pt))) {
                 return {groupIndex: groupIndex, gateIndex: gateIndex, gate: Util.notNull(gate)};
             }
         }
     }
     return null;
 }
Example #5
0
CircuitTextures.superpositionToQubitPairDensities = (stateTex, controls, keptBitMask) => {
    if (keptBitMask === 0) {
        return new WglTexture(0, 0);
    }
    let hasControls = !controls.isEqualTo(Controls.NONE);
    let reducedTex = stateTex;
    if (hasControls) {
        reducedTex = allocQubitTexture(CircuitTextures.qubitCount(stateTex) - controls.includedBitCount());
        CircuitShaders.controlSelect(controls, stateTex).renderTo(reducedTex);
    }
    let p = 1;
    for (let i = 1; i <= controls.inclusionMask; i <<= 1) {
        if ((controls.inclusionMask & i) === 0) {
            p <<= 1;
        } else {
            keptBitMask = (keptBitMask & (p - 1)) | ((keptBitMask & ~(p-1)) >> 1)
        }
    }
    let unsummedTex = CircuitTextures._superpositionTexToUnsummedQubitPairDensitiesTex(reducedTex, keptBitMask);
    if (hasControls) {
        CircuitTextures.doneWithTexture(reducedTex, "reducedTex in superpositionToQubitDensities");
    }
    let keptQubitCount = Util.numberOfSetBits(keptBitMask);
    let result = CircuitTextures._sumDown(unsummedTex, keptQubitCount * 4);
    CircuitTextures.doneWithTexture(unsummedTex, "unsummedTex in superpositionToQubitDensities");
    return result;
};
Example #6
0
GatePainting.makeCycleDrawer = (xScale=1, yScale=1, tScale=1) => args => {
    GatePainting.DEFAULT_DRAWER(args);

    if (args.isInToolbox && !args.isHighlighted) {
        return;
    }
    let τ = 2 * Math.PI;
    let t = Util.properMod(-args.stats.time * τ * tScale, τ);
    let c = args.rect.center();
    let r = 0.4 * args.rect.w;

    args.painter.ctx.save();

    args.painter.ctx.translate(c.x, c.y);
    args.painter.ctx.scale(xScale, yScale);
    args.painter.ctx.strokeStyle = 'black';
    args.painter.ctx.fillStyle = 'yellow';
    args.painter.ctx.globalAlpha = 0.4;

    args.painter.ctx.beginPath();
    args.painter.ctx.moveTo(0, 0);
    args.painter.ctx.lineTo(0, r);
    args.painter.ctx.arc(0, 0, r, τ/4, τ/4 + t, true);
    args.painter.ctx.lineTo(0, 0);
    args.painter.ctx.closePath();
    args.painter.ctx.stroke();
    args.painter.ctx.fill();

    args.painter.ctx.restore();
};
Example #7
0
 /**
  * @param {!number} t
  * @returns {!CircuitStats}
  */
 statsAtApproximateTime(t) {
     let i = Util.properMod(Math.round(t * this._divisions - 0.5), this._divisions);
     if (this._cachedCircuitStatsByTime[i] === undefined) {
         this._cachedCircuitStatsByTime[i] = this._computeStateForBucket(i);
     }
     return this._cachedCircuitStatsByTime[i].withTime(t);
 }
Example #8
0
GatePainting.makeCycleDrawer = factor => args => {
    GatePainting.DEFAULT_DRAWER(args);

    if (args.isInToolbox && !args.isHighlighted) {
        return;
    }
    let τ = 2 * Math.PI;
    let t = Util.properMod(-args.stats.time * τ * factor, τ);
    let c = args.rect.center();
    let r = 0.4 * args.rect.w;

    args.painter.ctx.beginPath();
    args.painter.ctx.moveTo(c.x, c.y);
    args.painter.ctx.lineTo(c.x, c.y + r);
    args.painter.ctx.arc(c.x, c.y, r, τ/4, τ/4 + t, factor > 0);
    args.painter.ctx.lineTo(c.x, c.y);
    args.painter.ctx.closePath();

    args.painter.ctx.strokeStyle = 'black';
    args.painter.ctx.fillStyle = 'yellow';
    args.painter.ctx.globalAlpha = 0.3;
    args.painter.ctx.stroke();
    args.painter.ctx.fill();
    args.painter.ctx.globalAlpha = 1.0;
};
Example #9
0
 return new WglConfiguredShader(destinationTexture => {
     CYCLE_ALL_SHADER.withArgs(
         WglArg.texture("inputTexture", inputTexture, 0),
         WglArg.float("outputWidth", destinationTexture.width),
         WglArg.vec2("inputSize", inputTexture.width, inputTexture.height),
         WglArg.float("shiftAmount", 1 << Util.properMod(-shiftAmount, size))
     ).renderTo(destinationTexture);
 });
Example #10
0
const CYCLE_BITS_MATRIX_MAKER = (shift, span) => Matrix.generate(1<<span, 1<<span, (r, c) => {
    shift = Util.properMod(shift, span);
    let expected = r;
    let input = c;
    let actual = input << shift;
    actual = (actual & ((1 << span) - 1)) | (actual >> span);
    return expected === actual ? 1 : 0;
});
Example #11
0
suite.test("recomposedObjectValues", () => {
    assertThrows(() => Util.recomposedObjectValues({}, [1]));
    assertThrows(() => Util.recomposedObjectValues({a: []}, [1]));
    assertThrows(() => Util.recomposedObjectValues({a: ""}, []));

    assertThat(Util.recomposedObjectValues({}, [])).isEqualTo({});
    assertThat(Util.recomposedObjectValues({a: "x"}, ["r"])).isEqualTo({a: "r"});
    assertThat(Util.recomposedObjectValues({a: {b: "y"}}, ["r"])).isEqualTo({a: "r"});
    assertThat(Util.recomposedObjectValues({a: "x", b: "y"}, [2, 3])).isEqualTo({a:2, b:3});
    assertThat(Util.recomposedObjectValues({b: "y", a: "x"}, [2, 3])).isEqualTo({a:2, b:3});
    assertThat(Util.recomposedObjectValues({a: []}, [])).isEqualTo({a:[]});
    assertThat(Util.recomposedObjectValues({a: [2, 3]}, [4, 5])).isEqualTo({a: [4, 5]});
    assertThat(Util.recomposedObjectValues({a: [1, 2, 3], b: "x", c: [4, 5]}, ["a", "b", "c", "d", "e", "f"])).
        isEqualTo({a: ["a", "b", "c"], b: "d", c: ["e", "f"]});
    assertThat(Util.recomposedObjectValues({a: [1, [2, 4], 3]}, ["a", "b", "c", "d"])).
        isEqualTo({a: ["a", ["b", "c"], "d"]});
    assertThat(Util.recomposedObjectValues({a: [1, [], 3]}, ["a", "b"])).isEqualTo({a: ["a", [], "b"]});
});
Example #12
0
CircuitTextures._superpositionTexToUnsummedQubitPairDensitiesTex = (superpositionTex, keptBitMask) => {
    if (keptBitMask === 0) {
        throw new DetailedError("keptBitMask === 0", {superpositionTex, keptBitMask});
    }
    let startingQubitCount = CircuitTextures.qubitCount(superpositionTex);
    let remainingQubitCount = Util.numberOfSetBits(keptBitMask);
    let inter = allocQubitTexture(startingQubitCount + Math.ceil(Math.log2(remainingQubitCount)));
    CircuitShaders.qubitPairDensities(superpositionTex, keptBitMask).renderTo(inter);
    return inter;
};
Example #13
0
suite.test("isPowerOf2", () => {
    assertFalse(Util.isPowerOf2(-1));
    assertFalse(Util.isPowerOf2(0));
    assertTrue(Util.isPowerOf2(1));
    assertTrue(Util.isPowerOf2(2));
    assertFalse(Util.isPowerOf2(3));
    assertTrue(Util.isPowerOf2(4));
    assertFalse(Util.isPowerOf2(5));
});
Example #14
0
 new WglConfiguredShader(destinationTexture => {
     CYCLE_SHADER.withArgs(
         WglArg.texture("inputTexture", inputTexture, 0),
         WglArg.texture("controlTexture", controlTexture, 1),
         WglArg.float("outputWidth", destinationTexture.width),
         WglArg.vec2("inputSize", inputTexture.width, inputTexture.height),
         WglArg.float("qubitIndex", 1 << qubitIndex),
         WglArg.float("qubitSpan", 1 << qubitSpan),
         WglArg.float("shiftAmount", 1 << Util.properMod(-shiftAmount, qubitSpan))
     ).renderTo(destinationTexture);
 });
Example #15
0
 new WglConfiguredShader(destinationTexture => {
     Util.need(operation.width() === 2 && operation.height() === 2);
     let [ar, ai, br, bi, cr, ci, dr, di] = operation.rawBuffer();
     CUSTOM_SINGLE_QUBIT_OPERATION_SHADER.withArgs(
         WglArg.vec2("inputSize", destinationTexture.width, destinationTexture.height),
         WglArg.texture("inputTexture", inputTexture, 0),
         WglArg.float("qubitIndexMask", 1 << qubitIndex),
         WglArg.texture("controlTexture", controlTexture, 1),
         WglArg.vec2("matrix_a", ar, ai),
         WglArg.vec2("matrix_b", br, bi),
         WglArg.vec2("matrix_c", cr, ci),
         WglArg.vec2("matrix_d", dr, di)
     ).renderTo(destinationTexture);
 });
Example #16
0
suite.test("reverseGroupMap", () => {
    assertThat(Util.reverseGroupMap(new Map())).isEqualTo(new Map());
    assertThat(Util.reverseGroupMap(new Map([["a", ["b"]]]))).isEqualTo(new Map([["b", ["a"]]]));
    assertThat(Util.reverseGroupMap(new Map([
        ["a", ["b", "c"]]
    ]))).isEqualTo(new Map([
        ["b", ["a"]],
        ["c", ["a"]]
    ]));
    assertThat(Util.reverseGroupMap(new Map([
        ["a", ["b"]],
        ["c", ["b"]]
    ]))).isEqualTo(new Map([
        ["b", ["a", "c"]]
    ]));
    assertThat(Util.reverseGroupMap(new Map([
        ["a", [1, 2, 3]],
        ["b", [2, 3, 4]],
        ["c", [3, 4, 5]]
    ]))).isEqualTo(new Map([
        [1, ["a"]],
        [2, ["a", "b"]],
        [3, ["a", "b", "c"]],
        [4, ["b", "c"]],
        [5, ["c"]]
    ]));

    assertThat(Util.reverseGroupMap(new Map([
        ["a", [1, 2, 3]],
        ["b", [2, 3, 4]],
        ["c", [3, 4, 5]]
    ]), true)).isEqualTo(new Map([
        [1, ["a"]],
        [2, ["a", "b"]],
        [3, ["a", "b", "c"]],
        [4, ["b", "c"]],
        [5, ["c"]],
        ["a", []],
        ["b", []],
        ["c", []]
    ]));
    assertThat(Util.reverseGroupMap(new Map([
        [3, [1, 2]],
        [2, [1]]
    ]), true)).isEqualTo(new Map([
        [1, [3, 2]],
        [2, [3]],
        [3, []]
    ]));
});
Example #17
0
CircuitTextures._sumDown = (summandsTex, outCount) => {
    let outSize = Util.ceilingPowerOf2(outCount);
    let outWidth = Math.min(summandsTex.width, outSize);

    return CircuitTextures.aggregateReusingIntermediates(
        summandsTex,
        Seq.range(Math.round(Math.log2(summandsTex.width * summandsTex.height / outSize))),
        accTex => {
            let [w, h] = accTex.width > Math.max(outWidth, accTex.height) ?
                [accTex.width / 2, 0] :
                [0, accTex.height / 2];
            let halfTex = allocSizedTexture(accTex.width - w, accTex.height - h);
            Shaders.sumFold(accTex, w, h).renderTo(halfTex);
            return halfTex;
        });
};
Example #18
0
    /**
     * @param {!Painter} painter
     * @param {!CircuitStats} stats
     * @param {!Hand} hand
     */
    paint(painter, stats, hand) {
        painter.fillRect(this.area, Config.BACKGROUND_COLOR_TOOLBOX);

        for (let groupIndex = 0; groupIndex < Gates.Sets.length; groupIndex++) {
            let group = Gates.Sets[groupIndex];
            painter.printLine(group.hint, this.groupLabelRect(groupIndex), 0.5, 'black', 16);

            for (let gateIndex = 0; gateIndex < group.gates.length; gateIndex++) {
                let gate = group.gates[gateIndex];
                if (gate !== null) {
                    let rect = this.gateDrawRect(groupIndex, gateIndex);
                    let isHighlighted = seq(hand.hoverPoints()).any(pt => rect.containsPoint(pt));
                    let drawer = gate.customDrawer || GatePainting.DEFAULT_DRAWER;
                    painter.noteTouchBlocker({rect, cursor: 'pointer'});
                    drawer(new GateDrawParams(
                        painter,
                        true,
                        isHighlighted,
                        false,
                        false,
                        rect,
                        Util.notNull(gate),
                        stats,
                        null,
                        [],
                        undefined));
                }
            }
        }

        // Draw tooltip when hovering, but also when dragging a gate over its own toolbox spot.
        let f = this.findGateAt(hand.pos);
        if (f !== null && (hand.heldGate === undefined || f.gate.symbol === hand.heldGate.symbol)) {
            let gateRect = this.gateDrawRect(f.groupIndex, f.gateIndex);
            let hintRect = new Rect(gateRect.right() + 1, gateRect.center().y, 500, 200).
                snapInside(painter.paintableArea().skipTop(gateRect.y));
            painter.defer(() => WidgetPainter.paintGateTooltip(painter, hintRect, f.gate, stats.time));
        }

        let r = new Rect(0, 0, Config.TOOLBOX_MARGIN_X, this.area.h);
        let {x, y} = r.center();
        painter.ctx.save();
        painter.ctx.translate(x, y);
        painter.ctx.rotate(-Math.PI/2);
        painter.printLine("Toolbox", new Rect(-r.h / 2, -r.w / 2, r.h, r.w), 0.5, 'black', 24);
        painter.ctx.restore();
    }
Example #19
0
suite.test("binarySearchForTransitionFromTrueToFalse", () => {
    let r = ["axe", "cat", "def", "g"];
    assertThat(Util.binarySearchForTransitionFromTrueToFalse(r.length, i => r[i] < "a")).isEqualTo(0);
    assertThat(Util.binarySearchForTransitionFromTrueToFalse(r.length, i => r[i] < "b")).isEqualTo(1);
    assertThat(Util.binarySearchForTransitionFromTrueToFalse(r.length, i => r[i] < "d")).isEqualTo(2);
    assertThat(Util.binarySearchForTransitionFromTrueToFalse(r.length, i => r[i] < "e")).isEqualTo(3);

    for (let n = 0; n < 10; n++) {
        for (let t = 0; t <= n; t++) {
            assertThat(Util.binarySearchForTransitionFromTrueToFalse(n, i => i < t)).isEqualTo(t);
            assertThat(Util.binarySearchForTransitionFromTrueToFalse(n, i => i <= t)).isEqualTo(Math.min(n, t + 1));
        }
    }
});
Example #20
0
/**
 * @param {!GateDrawParams} args
 */
function _paintSampleDisplay_result(args) {
    let {painter, rect: {x, y, w, h}} = args;
    let d = Config.WIRE_SPACING;
    let startY = y + h/2 - d*args.gate.height/2;

    let {i: sample, p} = sampleFromDistribution(args);
    for (let i = 0; i < args.gate.height; i++) {
        let bit = ((sample >> i) & 1) !== 0;
        if (bit) {
            painter.fillRect(
                new Rect(x, startY+d*i+5, w, d-10),
                Config.OPERATION_FORE_COLOR);
        }
        painter.print(
            bit ? 'on' : 'off',
            x+w/2,
            startY+d*(i+0.5),
            'center',
            'middle',
            'black',
            '16px Helvetica',
            w,
            d);
    }

    for (let pt of args.focusPoints) {
        let k = Math.floor((pt.y - y) * 2 / d) /2;
        if (args.rect.containsPoint(pt)) {
            MathPainter.paintDeferredValueTooltip(
                painter,
                x + w,
                y + k * d,
                `Chance of |${Util.bin(sample, args.gate.height)}⟩`,
                (p * 100).toFixed(4) + "%",
                undefined,
                Config.OPERATION_BACK_COLOR);
        }
    }
}
Example #21
0
CircuitTextures.mergedReadFloats = textures => {
    let pixelCounts = textures.map(e => e.width * e.height);
    let pixelOffsets = seq(pixelCounts).scan(0, (a, e) => a + e).toArray();
    let lgTotal = Math.round(Math.log2(Util.ceilingPowerOf2(pixelOffsets[pixelOffsets.length - 1])));
    let combinedTex = allocQubitTexture(lgTotal);
    Shaders.color(0, 0, 0, 0).renderTo(combinedTex);
    combinedTex = CircuitTextures.aggregateWithReuse(
        combinedTex,
        Seq.range(textures.length).filter(i => textures[i].width > 0),
        (accTex, i) => {
            let inputTex = textures[i];
            let nextTex = allocQubitTexture(lgTotal);
            CircuitShaders.linearOverlay(pixelOffsets[i], inputTex, accTex).renderTo(nextTex);
            CircuitTextures.doneWithTexture(inputTex, "inputTex in mergedReadFloats");
            return nextTex;
        });

    let combinedPixels;
    if (Config.ENCODE_FLOATS_AS_BYTES_WHEN_READING_PIXELS) {
        let combinedTexBytes = allocSizedTexture(combinedTex.width*2, combinedTex.height*2,
            WebGLRenderingContext.UNSIGNED_BYTE);
        Shaders.encodeFloatsIntoBytes(combinedTex).renderTo(combinedTexBytes);

        let combinedBytePixels = combinedTexBytes.readPixels();
        combinedPixels = Shaders.decodeByteBufferToFloatBuffer(combinedBytePixels);
        CircuitTextures.doneWithTexture(combinedTexBytes, "combinedTexBytes in mergedReadFloats");
    } else {
        combinedPixels = combinedTex.readPixels();
    }
    CircuitTextures.doneWithTexture(combinedTex, "combinedTex in mergedReadFloats");


    return Seq.range(textures.length).map(i => {
        let offset = pixelOffsets[i] * 4;
        let length = pixelCounts[i] * 4;
        return combinedPixels.subarray(offset, offset + length);
    }).toArray();
};
Example #22
0
suite.test("ceilingPowerOf2", () => {
    assertThat(Util.ceilingPowerOf2(-1)).isEqualTo(1);
    assertThat(Util.ceilingPowerOf2(0)).isEqualTo(1);
    assertThat(Util.ceilingPowerOf2(1)).isEqualTo(1);
    assertThat(Util.ceilingPowerOf2(2)).isEqualTo(2);
    assertThat(Util.ceilingPowerOf2(3)).isEqualTo(4);
    assertThat(Util.ceilingPowerOf2(4)).isEqualTo(4);
    assertThat(Util.ceilingPowerOf2(5)).isEqualTo(8);
    assertThat(Util.ceilingPowerOf2(6)).isEqualTo(8);
    assertThat(Util.ceilingPowerOf2(7)).isEqualTo(8);
    assertThat(Util.ceilingPowerOf2(8)).isEqualTo(8);
    assertThat(Util.ceilingPowerOf2(9)).isEqualTo(16);
    assertThat(Util.ceilingPowerOf2((1 << 20) - 1)).isEqualTo(1 << 20);
    assertThat(Util.ceilingPowerOf2(1 << 20)).isEqualTo(1 << 20);
    assertThat(Util.ceilingPowerOf2((1 << 20) + 1)).isEqualTo(1 << 21);
});
Example #23
0
    /**
     * Draws a peek gate on each wire at the right-hand side of the circuit.
     *
     * @param {!Painter} painter
     * @param {!CircuitStats} stats
     * @param {!int} col
     * @param {!Hand} hand
     * @private
     */
    _drawOutputSuperpositionDisplay(painter, stats, col, hand) {
        let numWire = this.importantWireCount();
        if (numWire >= Config.NO_SUPERPOSITION_DRAWING_WIRE_THRESHOLD) {
            return;
        }

        let [colWires, rowWires] = [Math.floor(numWire/2), Math.ceil(numWire/2)];
        let [colCount, rowCount] = [1 << colWires, 1 << rowWires];
        let outputStateBuffer = stats.finalState.rawBuffer();
        if (stats.circuitDefinition.numWires !== this.importantWireCount()) {
            outputStateBuffer = outputStateBuffer.slice(0, outputStateBuffer.length/2);
        }
        let amplitudeGrid = new Matrix(colCount, rowCount, outputStateBuffer);

        let topRect = this.gateRect(0, col);
        let bottomRect = this.gateRect(numWire-1, col);
        let gridRect = new Rect(topRect.x, topRect.y, 0, bottomRect.bottom() - topRect.y);
        gridRect = gridRect.withW(gridRect.h * (colCount/rowCount));
        MathPainter.paintMatrix(
            painter,
            amplitudeGrid,
            gridRect,
            numWire < Config.SIMPLE_SUPERPOSITION_DRAWING_WIRE_THRESHOLD ? Config.SUPERPOSITION_MID_COLOR : undefined,
            'black',
            numWire < Config.SIMPLE_SUPERPOSITION_DRAWING_WIRE_THRESHOLD ? Config.SUPERPOSITION_FORE_COLOR : undefined,
            Config.SUPERPOSITION_BACK_COLOR,
            hand.hoverPoints());

        let expandedRect = gridRect.withW(gridRect.w + 50).withH(gridRect.h + 50);
        let [dw, dh] = [gridRect.w / colCount, gridRect.h / rowCount];

        // Row labels.
        for (let i = 0; i < rowCount; i++) {
            let label = "_".repeat(colWires) + Util.bin(i, rowWires);
            let x = gridRect.right();
            let y = expandedRect.y + dh*(i+0.5);
            painter.print(label, x + 2, y, 'left', 'middle', 'black', '12px monospace', 50, dh, (w, h) => {
                painter.fillRect(new Rect(x, y-h/2, w + 4, h), 'lightgray');
            });
        }

        // Column labels.
        painter.ctx.save();
        painter.ctx.rotate(Math.PI/2);
        let maxY = 0;
        for (let i = 0; i < colCount; i++) {
            let labelRect = expandedRect.skipTop(gridRect.h + 2).skipLeft(dw*i).skipBottom(2).withW(dw);
            labelRect = new Rect(labelRect.y, -labelRect.x-labelRect.w, labelRect.h, labelRect.w);

            let label = Util.bin(i, colWires) + "_".repeat(rowWires);
            let x = expandedRect.x + dw*(i+0.5);
            let y = gridRect.bottom();
            painter.print(label, y + 2, -x, 'left', 'middle', 'black', '12px monospace', 50, dw, (w, h) => {
                painter.fillRect(new Rect(y, -x-h/2, w + 4, h), 'lightgray');
                maxY = Math.max(maxY, w + 8);
            });
        }
        painter.ctx.restore();

        // Hint text.
        painter.printParagraph(
            "Final amplitudes\n(deferring measurement)",
            expandedRect.withY(gridRect.bottom() + maxY).withH(40).withW(200),
            new Point(0, 0),
            'gray');
    }
Example #24
0
 assertThrows(() => Util.need(false));
Example #25
0
suite.test("need", () => {
    assertThrows(() => Util.need(false));
    Util.need(true);
});
Example #26
0
suite.test("properMod", () => {
    assertThrows(() => Util.properMod(0, 0));
    assertThrows(() => Util.properMod(1, 0));
    assertThrows(() => Util.properMod(1, -1));

    assertThat(Util.properMod(502, 501)).isEqualTo(1);
    assertThat(Util.properMod(-502, 501)).isEqualTo(500);

    assertThat(Util.properMod(-2, 1.5)).isEqualTo(1);
    assertThat(Util.properMod(-1.5, 1.5)).isEqualTo(0);
    assertThat(Util.properMod(-1, 1.5)).isEqualTo(0.5);
    assertThat(Util.properMod(-0.5, 1.5)).isEqualTo(1);
    assertThat(Util.properMod(0, 1.5)).isEqualTo(0);
    assertThat(Util.properMod(0.5, 1.5)).isEqualTo(0.5);
    assertThat(Util.properMod(1, 1.5)).isEqualTo(1);
    assertThat(Util.properMod(1.5, 1.5)).isEqualTo(0);
    assertThat(Util.properMod(2, 1.5)).isEqualTo(0.5);
});
Example #27
0
 assertThrows(() => Util.properMod(1, -1));
Example #28
0
 assertThrows(() => Util.properMod(0, 0));
Example #29
0
    /**
     * @param {!CircuitDefinition} circuitDefinition
     * @param {!number} time
     * @returns {!CircuitStats}
     */
    static _fromCircuitAtTime_noFallback(circuitDefinition, time) {
        const numWires = circuitDefinition.numWires;
        const numCols = circuitDefinition.columns.length;
        const allWiresMask = (1 << numWires) - 1;

        // -- DEFINE TEXTURES TO BE COMPUTED --

        let qubitDensityTexes = [];
        let qubitPairDensityTexes = [];
        let outputTex = CircuitTextures.aggregateWithReuse(
            CircuitTextures.zero(numWires),
            Seq.range(numCols),
            (stateTex, col) => {
                let gateCol = circuitDefinition.columns[col];
                let controls = gateCol.controls();
                let controlTex = CircuitTextures.control(numWires, controls);
                stateTex = CircuitTextures.aggregateReusingIntermediates(
                    stateTex,
                    circuitDefinition.operationShadersInColAt(col, time),
                    (accTex, shaderFunc) => CircuitTextures.applyCustomShader(shaderFunc, accTex, controlTex, time));

                // Stats for inline displays.
                qubitDensityTexes.push(CircuitTextures.superpositionToQubitDensities(
                    stateTex,
                    controls,
                    gateCol.wiresWithSingleQubitDisplaysMask()));
                qubitPairDensityTexes.push(CircuitTextures.superpositionToQubitPairDensities(
                    stateTex,
                    controls,
                    gateCol.wiresWithTwoQubitDisplaysMask()));

                CircuitTextures.doneWithTexture(controlTex, "controlTex in fromCircuitAtTime");
                return stateTex;
            });
        qubitDensityTexes.push(CircuitTextures.superpositionToQubitDensities(outputTex, Controls.NONE, allWiresMask));

        // -- READ ALL TEXTURES --

        let pixelData = Util.objectifyArrayFunc(CircuitTextures.mergedReadFloats)({
            outputTex,
            qubitDensityTexes,
            qubitPairDensityTexes});

        // -- INTERPRET --

        let final = pixelData.qubitDensityTexes[pixelData.qubitDensityTexes.length - 1];
        let unity = final[0] + final[3];
        //noinspection JSCheckFunctionSignatures
        let outputSuperposition = CircuitTextures.pixelsToAmplitudes(pixelData.outputTex, unity);

        let qubitDensities = seq(pixelData.qubitDensityTexes).mapWithIndex((pixels, col) =>
            CircuitStats.scatterAndDecohereDensities(
                CircuitTextures.pixelsToQubitDensityMatrices(pixels),
                numWires,
                1,
                circuitDefinition.colIsMeasuredMask(col),
                // All wires have an output display in the after-last column.
                col === numCols ? -1 : circuitDefinition.colHasSingleQubitDisplayMask(col))
        ).toArray();
        let qubitPairDensities = seq(pixelData.qubitPairDensityTexes).mapWithIndex((pixels, col) =>
            CircuitStats.scatterAndDecohereDensities(
                CircuitTextures.pixelsToQubitPairDensityMatrices(pixels),
                numWires,
                2,
                circuitDefinition.colIsMeasuredMask(col),
                circuitDefinition.colHasDoubleQubitDisplayMask(col))
        ).toArray();

        return new CircuitStats(
            circuitDefinition,
            time,
            qubitDensities,
            qubitPairDensities,
            outputSuperposition);
    }
Example #30
0
suite.test("powerOfTwoness", () => {
    assertThat(Util.powerOfTwoness(-2)).isEqualTo(1);
    assertThat(Util.powerOfTwoness(-1)).isEqualTo(0);
    assertThat(Util.powerOfTwoness(0)).isEqualTo(Math.POSITIVE_INFINITY);
    assertThat(Util.powerOfTwoness(1)).isEqualTo(0);
    assertThat(Util.powerOfTwoness(2)).isEqualTo(1);
    assertThat(Util.powerOfTwoness(3)).isEqualTo(0);
    assertThat(Util.powerOfTwoness(4)).isEqualTo(2);
    assertThat(Util.powerOfTwoness(5)).isEqualTo(0);
    assertThat(Util.powerOfTwoness(6)).isEqualTo(1);
    assertThat(Util.powerOfTwoness(7)).isEqualTo(0);
    assertThat(Util.powerOfTwoness(8)).isEqualTo(3);
    assertThat(Util.powerOfTwoness(9)).isEqualTo(0);

    assertThat(Util.powerOfTwoness(1 << 20)).isEqualTo(20);
    assertThat(Util.powerOfTwoness(1 + (1 << 20))).isEqualTo(0);
    assertThat(Util.powerOfTwoness(2 + (1 << 20))).isEqualTo(1);
});