# An outer-product in Yao?

**URL:** <https://discourse.julialang.org/t/an-outer-product-in-yao/89543>\
**Category:** Quantum\
**Created:** [October 31, 2022, 6:27am UTC](https://discourse.julialang.org/t/an-outer-product-in-yao/89543 "2022-10-31T06:27:33Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![BoltzmannEntropy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/boltzmannentropy/32/43605_2.png) [@BoltzmannEntropy](https://discourse.julialang.org/u/BoltzmannEntropy)\
**Post date:** [October 31, 2022, 6:27am UTC](https://discourse.julialang.org/t/an-outer-product-in-yao/89543/1 "2022-10-31T06:27:33Z")

</div>

Hello,  
I am trying to evaluate the following expression:  
`I3 + ψ*ψ'`

First, is there a way in Yao to create an arbitrary sized Identity matrix like I3?

```julia
using Yao, YaoPlots
using YaoBlocks: eigenbasis

ψ=ArrayReg(bit"111") |> normalize!
ψ = rand_state(3);
I3 = [
  1 0 0 0 0 0 0 0
  0 1 0 0 0 0 0 0
  0 0 1 0 0 0 0 0
  0 0 0 1 0 0 0 0
  0 0 0 0 1 0 0 0
  0 0 0 0 0 1 0 0
  0 0 0 0 0 0 1 0
  0 0 0 0 0 0 0 1
]

ψ' * ψ

```

This fails to run, I must be missing something.

> print(ψ\*adjoint(ψ))

Thanks,

---

<div class="post-metadata">

**Author:** ![1115](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/1115/32/4465_2.png) [@1115](https://discourse.julialang.org/u/1115)\
**Post date:** [October 31, 2022, 8:22am UTC](https://discourse.julialang.org/t/an-outer-product-in-yao/89543/2 "2022-10-31T08:22:30Z")

</div>

We already have similar feature in Yao master branch, which is called `projector`:  
[Yao.jl/reflect.jl at master · QuantumBFS/Yao.jl · GitHub](https://github.com/QuantumBFS/Yao.jl/blob/master/lib/YaoBlocks/src/primitive/reflect.jl). You can try this feature in develop mode already:

```julia
(@v1.8) pkg> dev YaoAPI YaoArrayRegister YaoBlocks YaoSym Yao

```

```julia
julia> using Yao

julia> igate(3) + projector(rand_state(3))
nqubits: 3
+
├─ igate(3)
└─ |s⟩⟨s|, nqudits = 3

```

To stick to the released version, I think we have to use the following implementation should be good enough.

```julia
julia> igate(nqubits(ψ)) + matblock(OuterProduct(statevec(ψ), conj.(statevec(ψ))); tag="|ψ⟩⟨ψ|")
nqubits: 12
+
├─ igate(12)
└─ |ψ⟩⟨ψ|

```

If you want to apply this operator to a register. The block implementation is much faster than computing the matrix explicitly,

```julia
julia> ψ = rand_state(12);

julia> @benchmark apply($ψ, igate(nqubits($ψ)) + matblock(OuterProduct(statevec($ψ), conj.(statevec($ψ)))))
BenchmarkTools.Trial: 10000 samples with 1 evaluation.
 Range (min … max): 25.104 μs … 998.618 μs ┊ GC (min … max): 0.00% … 93.86%
 Time (median): 28.515 μs ┊ GC (median): 0.00%
 Time (mean ± σ): 33.041 μs ± 55.170 μs ┊ GC (mean ± σ): 10.66% ± 6.16%

    ▃▄▆▇████▇▇▆▆▅▄▃▂▁▁ ▁ ▁ ▃
  ▆█████████████████████▇█▆▅▅▅▅▅▆▅▆▇████▇█▆▇▄▆▅▄▆▇▇████▇█▆▆▆▅▄ █
  25.1 μs Histogram: log(frequency) by time 47.8 μs <

 Memory estimate: 192.95 KiB, allocs estimate: 27.

julia> @benchmark mat(igate(12)) + statevec($ψ) * statevec($ψ')
BenchmarkTools.Trial: 26 samples with 1 evaluation.
 Range (min … max): 158.426 ms … 331.332 ms ┊ GC (min … max): 17.13% … 52.31%
 Time (median): 189.718 ms ┊ GC (median): 14.30%
 Time (mean ± σ): 192.315 ms ± 40.352 ms ┊ GC (mean ± σ): 18.93% ± 10.08%

  ▂ ▂█                                                   
  █▁▁▃▁▁▁▁▁▁██▃▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▃▁▁▁▁▁▁▃ ▁
  158 ms Histogram: frequency by time 331 ms <

 Memory estimate: 512.00 MiB, allocs estimate: 9.

```

---

<div class="post-metadata">

**Author:** ![BoltzmannEntropy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/boltzmannentropy/32/43605_2.png) [@BoltzmannEntropy](https://discourse.julialang.org/u/BoltzmannEntropy)\
**Post date:** [October 31, 2022, 10:05am UTC](https://discourse.julialang.org/t/an-outer-product-in-yao/89543/3 "2022-10-31T10:05:43Z")

</div>

Thank you so much for your prompt reply.  
Let me understand whats going on since I have only now started using Julia. Here, in the expression:

```julia
ψ=ArrayReg(bit"011") |> normalize!
I3 =igate(3)
ψ1= I3 - 2*projector(ψ)
@show(ψ1)
ψ1 = nqubits: 3
+
├─ igate(3)
└─ [scale: -2] |s⟩⟨s|, nqudits = 3

```

`ψ1` should have resulted in an evaluated numerical value, not an operator right? How do I see that value?

Here:  
`ψ1=igate(nqubits(ψ)) + matblock(OuterProduct(statevec(ψ), conj.(statevec(ψ))); tag="|ψ⟩⟨ψ|")`  
The result of the outer product should have been compatible, what does it have to be coerced into a matblock?

I am trying to do something very simple `I3 - 2*|ψ⟩⟨ψ|` to yield a numerical value.

Thanks,

---

<div class="post-metadata">

**Author:** ![BoltzmannEntropy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/boltzmannentropy/32/43605_2.png) [@BoltzmannEntropy](https://discourse.julialang.org/u/BoltzmannEntropy)\
**Post date:** [October 31, 2022, 10:11am UTC](https://discourse.julialang.org/t/an-outer-product-in-yao/89543/4 "2022-10-31T10:11:15Z")

</div>

OK I see what I did wrong, I have a state `ψ2 = rand_state(3)` which I want the operator to act on.

```julia
using Yao, YaoPlots
using YaoBlocks: eigenbasis
# state preparation 
cr=(    
    kron(H, H, H))
plot(cr)
ψ0=ArrayReg(bit"000") |> normalize!
ψ0 = (ψ0 |> cr) 
@show (state(ψ0))

#Operator
ψ011=ArrayReg(bit"011") |> normalize!
I3 =igate(3)
ψ_op= I3 - 2*projector(ψ011)

#Apply the operator on the state
print(apply(ψ0,ψ_op))

```

How do I access the unitary of the operator?  
How do I access the resulting value of applying the op to the state?

Thanks,

---

<div class="post-metadata">

**Author:** ![1115](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/1115/32/4465_2.png) [@1115](https://discourse.julialang.org/u/1115)\
**Post date:** [October 31, 2022, 12:51pm UTC](https://discourse.julialang.org/t/an-outer-product-in-yao/89543/5 "2022-10-31T12:51:06Z")

</div>

> `ψ1` should have resulted in an evaluated numerical value, not an operator right? How do I see that value?

It is an operator. If you want to get its matrix representation, you can use

```julia
mat(ψ1)

```

Maybe you will find this notebook helpful: [https://giggleliu.github.io/notebooks/notebooks/yaoblocks.html](https://giggleliu.github.io/notebooks/notebooks/yaoblocks.html)

To obtain the resulting value of applying the op to the state `reg`, please just use

```julia
julia> reg = apply(state, op);

julia> reg.state

```

---

<div class="post-metadata">

**Author:** ![BoltzmannEntropy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/boltzmannentropy/32/43605_2.png) [@BoltzmannEntropy](https://discourse.julialang.org/u/BoltzmannEntropy)\
**Post date:** [October 31, 2022, 12:52pm UTC](https://discourse.julialang.org/t/an-outer-product-in-yao/89543/6 "2022-10-31T12:52:17Z")

</div>

Perfect thanks.
