Path: blob/main/frontend/vue/components/WhatIsQuantumVolume/LayersCircuit.vue
4051 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>