Path: blob/main/frontend/vue/components/WhatIsQuantumVolume/LayersCircuit.vue
3375 views
<template> <div class="layers-circuit" :style="`--circuit-wrapper-width: ${wrappersDim.x}px; --circuit-wrapper-height: ${wrappersDim.y}px;`" > <svg width="1" height="1" class="layers-circuit__svg-definitions"> <defs> <pattern :id="`graphite-uid${uid}`" patternUnits="userSpaceOnUse" width="512" height="512"> <image href="../../images/PencilTexture.png" x="0" y="0" width="512" height="512" /> </pattern> <linearGradient :id="`layer-gradient-uid${uid}`" gradientUnits="objectBoundingBox" gradientTransform="rotate(90)"> <stop :stop-color="gradientColor[0]" /> <stop offset="1" :stop-color="gradientColor[1]" /> </linearGradient> <mask :id="`marker-uid${uid}`" style="mask-type: luminance"> <image href="../../images/MarkerBg.jpg" x="0" y="0" width="100%" height="100%" preserveAspectRatio="none" /> </mask> </defs> </svg> <div class="layers-circuit__circuit-lines-wrapper"> <KetCircuitLine v-for="m in parseInt(lines)" :key="m" class="layers-circuit__circuit-line" :line-lenght="circuitLineLength" :stroke-style="`url(#graphite-uid${uid})`" /> </div> <div class="layers-circuit__qv-layers-wrapper" :style="`--qv-layers-wrapper-width: ${wrappersDim.x}px; --qv-layers-wrapper-height: ${wrappersDim.y}px;`" > <div v-for="(m, j) in parseInt(layers)" :key="m" class="layers-circuit__qv-layer" :class="{'layers-circuit__qv-layer_inspectable': enableInspection }" > <SketchSquare class="layers-circuit__qv-layer-content-wrapper" :width="inspectionWidth(j)" :height="layersHeight" :style="`--center-distance: ${normalizedCenterDistance(j)}; --inspection-width: ${inspectionWidth(j)}px;`" > <div class="layers-circuit__qv-layer-content"> <MarkerArea class="layers-circuit__qv-layer__layer-square" :marker-mask-id="`marker-uid${uid}`" :fill-id="`layer-gradient-uid${uid}`" :width="inspectionWidth(j)" :height="layersHeight" /> <SU4Gate class="layers-circuit__qv-layer__unitary" :style="`${gatePositionStyle(j, 0)}`" :space-between="gateSpaceBetween(j, 0)" /> <SU4Gate class="layers-circuit__qv-layer__unitary" :style="`${gatePositionStyle(j, 1)}`" :space-between="gateSpaceBetween(j, 1)" /> </div> </SketchSquare> </div> <div class="layers-circuit__veil" /> </div> </div> </template> <script lang="ts"> import { Options, prop, Vue } from 'vue-class-component' import { Point } from '@mathigon/euclid' import SketchSquare from '../Sketch/SketchSquare.vue' import MarkerArea from '../Sketch/MarkerArea.vue' import KetCircuitLine from '../Sketch/KetCircuitLine.vue' import SU4Gate from './SU4Gate.vue' type LayerUnitary = { q1: number; q2: number; }; class Props { lines = prop<Number>({ default: 5 }) layers = prop<Number>({ default: 5 }) gradientColor = prop<Array<string>>({ default: ['#78A9FF', '#8A3FFC'], validator: (val: Array<string>) => val.length === 2 }) enableInspection = prop<boolean>({ default: true }) gatesInspection = prop<Array<Array<LayerUnitary>>>({}) } @Options({ components: { MarkerArea, SketchSquare, KetCircuitLine, SU4Gate }, computed: { wrappersDim (): Point { const dimX = this.layers as number * 85 + 25 const dimY = this.lines as number * 85 + 25 return new Point(dimX, dimY) }, layersHeight (): number { return this.lines as number * 85 - 10 } } }) export default class LayersCircuit extends Vue.with(Props) { uid = Math.random().toString().replace('.', '') circuitLineLength = this.layers as number * 85 - 17 unitaryQubitText (configIdx: number, gateIdx: number, line: number) : string { const config = this.gatesConfig[configIdx % this.gatesConfig.length] const q1 = config[gateIdx].q1 const q2 = config[gateIdx].q2 return q1 < q2 ? `${line}` : `${1 - line}` } normalizedCenterDistance (idx: number) : number { const semiLayersCount = (this.layers as number - 1) / 2 return (-semiLayersCount + idx) / semiLayersCount } gateSpaceBetween (configIdx: number, gateIdx: number) : number { if (!this.gatesConfig) { return 0 } const config = this.gatesConfig[configIdx % this.gatesConfig.length] return config[gateIdx].q2 - config[gateIdx].q1 } gatePositionStyle (configIdx: number, gateIdx: number) : string { if (!this.gatesConfig) { return '' } const config = this.gatesConfig[configIdx % this.gatesConfig.length] let style = `top: ${11 + 85 * Math.min(config[gateIdx].q1, config[gateIdx].q2)}px;` if (this.gatesOverlaping(configIdx)) { style += gateIdx === 0 ? 'transform: translateX(45px);' : 'transform: translateX(-45px);' } return style } inspectionWidth (configIdx: number) : number { return this.gatesOverlaping(configIdx) ? 200 : 100 } gatesOverlaping (configIdx: number) : boolean { if (!this.gatesConfig) { return false } const config = this.gatesConfig[configIdx % this.gatesConfig.length] const u0 = config[0] const u1 = config[1] const between = (a: number, b: number, c: number) => (c < a && a < b) || (b < a && a < c) return between(u0.q2, u1.q1, u1.q2) || between(u0.q1, u1.q1, u1.q2) || between(u1.q1, u0.q1, u0.q2) || u0.q1 === u1.q1 || u0.q1 === u1.q2 || u0.q2 === u1.q1 || u0.q2 === u1.q2 } randomPop (freePositions: number[]) : number { const position = Math.floor(Math.random() * freePositions.length) return freePositions.splice(position, 1)[0] } randomUnitaryPair () { const freePositions = Array.from({ length: (this.layers as number) }, (v, i) => i) return [{ q1: this.randomPop(freePositions), q2: this.randomPop(freePositions) }, { q1: this.randomPop(freePositions), q2: this.randomPop(freePositions) }] } gatesRandomConfig: LayerUnitary[][] = Array.from({ length: Math.floor(this.layers as number) }, (_v, _i) => this.randomUnitaryPair()) get gatesConfig (): LayerUnitary[][] { if (this.gatesInspection !== undefined) { return this.gatesInspection } return this.gatesRandomConfig } } </script> <style scoped lang="scss"> @import '~/../scss/variables/colors.scss'; .layers-circuit { position: relative; margin: 0 auto; width: var(--circuit-wrapper-width, 400px); min-width: var(--circuit-wrapper-width, 400px); &__circuit-lines-wrapper { top: 0; left: 0; width: var(--circuit-wrapper-width, 400px); height: var(--circuit-wrapper-height, 400px); display: flex; flex-direction: column; justify-content: center; } &__circuit-line { width: var(--circuit-wrapper-width, 400px); } &__qv-layers-wrapper { position: absolute; top: 0; left: 0; width: var(--qv-layers-wrapper-width, 400px); height: var(--qv-layers-wrapper-height, 400px); display: flex; flex-direction: row; justify-content: space-between; padding: 15px 20px 20px 40px; } &__qv-layer { flex: 0 0 50px; max-width: 50px; &-content { overflow: hidden; transition: width 0.5s ease-out, left 0.5s ease-out, z-index 0.5s ease-out; width: 50px; position: relative; left: 0px; display: flex; justify-content: center; z-index: 0; } &-content-wrapper { position: relative; transition: left 0.5s ease-out, z-index 0.5s ease-out; width: 50px; left: 0px; display: flex; justify-content: center; z-index: 0; height: 100%; :deep() > .sketch-square__lines { transition: opacity 0s ease-out 0s; opacity: 0; } :deep() > .sketch-square__content { box-shadow: none; width: auto; } } &_inspectable:hover #{&}-content-wrapper, &_inspectable:hover #{&}-content { width: var(--inspection-width, 150px); --semi-extra-width: calc((var(--inspection-width, 150px) - 50px) / 2); } &_inspectable:hover #{&}-content-wrapper { left: calc((var(--semi-extra-width) + var(--center-distance, 0) * (var(--semi-extra-width) - 20px)) * -1 ); z-index: 10; :deep() .sketch-square__lines { transition: opacity 0.2s ease-out 0.5s; opacity: 1; } } &__layer-square { flex: 0 0 auto; @at-root x-step svg#{&} { max-width: none; } } &__unitary { transition: opacity 0.2s ease-out 0s; opacity: 0; } &_inspectable:hover ::v-deep(.marker-area rect) { fill: $blue-40; // mask: none; } &_inspectable:hover #{&}__unitary { transition: opacity 0.3s ease-out 0.2s; opacity: 1; } &_inspectable:hover #{&}__unitary :deep() .sketch-line-path { stroke-dashoffset: 0; transition: stroke-dashoffset 0.7s ease-out 0.3s; } &_inspectable:hover #{&}__unitary :deep() .sketch-square__content { opacity: 1; background-position: 0% 0%; } } &__veil { position: absolute; width: 100%; height: 100%; pointer-events: none; background-color: $background-color-lighter; transition: opacity 0.5s ease-out; opacity: 0; } &__qv-layer_inspectable:hover ~ &__veil { opacity: 0.4; } } </style>