Skip to content

Commit

Permalink
Merge pull request #12 from itsubaki/ctrlx
Browse files Browse the repository at this point in the history
Add ctrl @ x
  • Loading branch information
itsubaki committed May 26, 2022
2 parents 567142e + 60fd805 commit 11481be
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 74 deletions.
10 changes: 7 additions & 3 deletions pkg/ast/stmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ func (s *BlockStmt) Pow(y int) *BlockStmt {
return &out
}

func (s *BlockStmt) Add(m Modifier) *BlockStmt {
func (s *BlockStmt) Add(m Modifier, qargs ...Expr) *BlockStmt {
var out BlockStmt
for _, b := range s.List {
switch s := b.(type) {
Expand All @@ -279,7 +279,9 @@ func (s *BlockStmt) Add(m Modifier) *BlockStmt {
Modifier: append(s.Modifier, m),
Name: s.Name,
Params: s.Params,
QArgs: s.QArgs,
QArgs: ExprList{
List: append(qargs, s.QArgs.List...),
},
})
case *ExprStmt:
switch X := s.X.(type) {
Expand All @@ -289,7 +291,9 @@ func (s *BlockStmt) Add(m Modifier) *BlockStmt {
Name: X.Name,
Modifier: append(X.Modifier, m),
Params: X.Params,
QArgs: X.QArgs,
QArgs: ExprList{
List: append(qargs, X.QArgs.List...),
},
},
})
default:
Expand Down
32 changes: 17 additions & 15 deletions pkg/evaluator/env/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,26 @@ type Func map[string]ast.Decl
type Const map[string]object.Object

type Environ struct {
Const Const
Func Func
Bit *Bit
Qubit *Qubit
Decl []ast.Decl
Modifier []ast.Modifier
Outer *Environ
Const Const
Func Func
Bit *Bit
Qubit *Qubit
Modifier []ast.Modifier
Decl []ast.Decl
CtrlQArgs []ast.Expr
Outer *Environ
}

func New() *Environ {
return &Environ{
Func: make(map[string]ast.Decl),
Const: make(map[string]object.Object),
Bit: NewBit(),
Qubit: NewQubit(),
Decl: make([]ast.Decl, 0),
Modifier: make([]ast.Modifier, 0),
Outer: nil,
Func: make(map[string]ast.Decl),
Const: make(map[string]object.Object),
Bit: NewBit(),
Qubit: NewQubit(),
Modifier: make([]ast.Modifier, 0),
Decl: make([]ast.Decl, 0),
CtrlQArgs: nil,
Outer: nil,
}
}

Expand All @@ -39,8 +41,8 @@ func (e *Environ) NewEnclosed(decl ast.Decl, mod []ast.Modifier) *Environ {
Const: e.Const,
Bit: NewBit(),
Qubit: NewQubit(),
Decl: append(e.Decl, decl),
Modifier: append(e.Modifier, mod...),
Decl: append(e.Decl, decl),
Outer: e,
}
}
Expand Down
75 changes: 44 additions & 31 deletions pkg/evaluator/evaluator.go
Original file line number Diff line number Diff line change
Expand Up @@ -413,11 +413,6 @@ func (e *Evaluator) Apply(s *ast.ApplyStmt, env *env.Environ) error {
return fmt.Errorf("gate=%v not found", lexer.Tokens[s.Kind])
}

// fmt.Printf("mod: %v\n", s.Modifier)
// fmt.Printf("env.mod: %v\n", env.Modifier)
// fmt.Printf("env.decl: %v\n", env.Decl)
// fmt.Printf("qargs: %v\n", qargs)

if len(env.Decl) > 0 && len(qargs) > 1 {
// for j ← 0, 1 do
// g qr0[0],qr1[j],qr2[0],qr3[j];
Expand Down Expand Up @@ -621,38 +616,38 @@ func (e *Evaluator) SetConst(env, outer *env.Environ, decl, args []ast.Expr) {
}

func (e *Evaluator) SetQArgs(env, outer *env.Environ, decl, args []ast.Expr) {
for i := range decl {
if qb, ok := outer.Qubit.Get(args[i]); ok {
env.Qubit.Add(decl[i], qb)
if len(ast.ModCtrl(env.Modifier)) == 0 {
for i := range decl {
if qb, ok := outer.Qubit.Get(args[i]); ok {
env.Qubit.Add(decl[i], qb)
}
}

return
}

// fmt.Printf("args: %v\n", args)
// fmt.Printf("env.Modifier: %v\n", env.Modifier)
// fmt.Printf("env.Decl: %v\n", env.Decl)
// fmt.Printf("out.Qubit: %v\n", outer.Qubit)
// fmt.Printf("env.Qubit: %v\n", env.Qubit)
ctrl := make([]ast.Expr, 0)
for i := range ast.ModCtrl(env.Modifier) {
switch x := args[i].(type) {
case *ast.IdentExpr:
ctrl = append(ctrl, &ast.IdentExpr{Name: fmt.Sprintf("_v%d", i)})
case *ast.IndexExpr:
ctrl = append(ctrl, &ast.IndexExpr{Name: fmt.Sprintf("_v%d", i), Value: x.Value})
}
}
env.CtrlQArgs = ctrl

// args: [c t]
// env.Modifier: [{51 {{[]}}}]
// env.Decl: [gate x q { U(pi, 0, pi) q; }]
// out.Qubit: [c t], map[c:[0] t:[1]]
// env.Qubit: [q], map[q:[0]]
}
cdecl := append(make([]ast.Expr, 0), ctrl...)
for i := range decl {
cdecl = append(cdecl, decl[i])
}

// ModifyU returns modified(inv, pow) U
func (e *Evaluator) ModifyU(mod []ast.Modifier, u matrix.Matrix, env *env.Environ) matrix.Matrix {
// NOTE: pow(2) @ inv @ u is not equal to inv @ pow(2) @ u
for _, m := range mod {
switch m.Kind {
case lexer.INV:
u = u.Dagger()
case lexer.POW:
u = matrix.ApplyN(u, int(ast.Must(e.eval(m.Index.List.List[0], env)).(*object.Int).Value))
for i := range cdecl {
if qb, ok := outer.Qubit.Get(args[i]); ok {
env.Qubit.Add(cdecl[i], qb)
continue
}
}

return u
}

// ModifyStmt returns modified BlockStmt
Expand Down Expand Up @@ -685,10 +680,13 @@ func (e *Evaluator) ModifyStmt(s *ast.BlockStmt, env *env.Environ) *ast.BlockStm
// is not
// inv @ pow(2) @ U(a, b, c) q;
// inv @ pow(3) @ U(c, b, a) q;

var i int
for _, m := range env.Modifier {
switch m.Kind {
case lexer.CTRL, lexer.NEGCTRL:
s = s.Add(m)
s = s.Add(m, []ast.Expr{env.CtrlQArgs[i]}...)
i++
case lexer.INV:
s = s.Inv()
case lexer.POW:
Expand All @@ -698,3 +696,18 @@ func (e *Evaluator) ModifyStmt(s *ast.BlockStmt, env *env.Environ) *ast.BlockStm

return s
}

// ModifyU returns modified(inv, pow) U
func (e *Evaluator) ModifyU(mod []ast.Modifier, u matrix.Matrix, env *env.Environ) matrix.Matrix {
// NOTE: pow(2) @ inv @ u is not equal to inv @ pow(2) @ u
for _, m := range mod {
switch m.Kind {
case lexer.INV:
u = u.Dagger()
case lexer.POW:
u = matrix.ApplyN(u, int(ast.Must(e.eval(m.Index.List.List[0], env)).(*object.Int).Value))
}
}

return u
}
121 changes: 96 additions & 25 deletions pkg/evaluator/evaluator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,49 @@ print;
// [0][ 0]( 1.0000 0.0000i): 1.0000
}

func Example_pow_gate() {
qasm := `
OPENQASM 3.0;
gate u(a, b, c) q {
U(pi, 0, pi) q;
U(a, b, c) q;
}
qubit q;
print;
U(pi, 0, pi) q;
U(pi/2.0, pi, pi) q;
U(pi, 0, pi) q;
U(pi/2.0, pi, pi) q;
U(pi, 0, pi) q;
U(pi/2.0, pi, pi) q;
print;
reset q;
print;
pow(3) @ u(pi/2.0, pi, pi) q;
print;
`

if err := eval(qasm); err != nil {
fmt.Printf("eval: %v\n", err)
return
}

// Output:
// [0][ 0]( 1.0000 0.0000i): 1.0000
// [0][ 0]( 0.7071 0.0000i): 0.5000
// [1][ 1]( 0.7071 0.0000i): 0.5000
// [0][ 0]( 1.0000 0.0000i): 1.0000
// [0][ 0]( 0.7071 0.0000i): 0.5000
// [1][ 1]( 0.7071 0.0000i): 0.5000
}

func Example_inv_gate_ctrl() {
qasm := `
OPENQASM 3.0;
Expand Down Expand Up @@ -918,32 +961,31 @@ print;
// [1 0][ 1 0]( 1.0000 0.0000i): 1.0000
}

func Example_pow_gate() {
func Example_pow_gate_ctrl() {
qasm := `
OPENQASM 3.0;
gate u(a, b, c) q {
U(pi, 0, pi) q;
U(a, b, c) q;
}
gate cu(x, y, z) c, t { ctrl @ U(x, y, z) c, t; }
qubit q;
qubit p;
print;
U(pi, 0, pi) q;
U(pi/2.0, pi, pi) q;
print;
U(pi, 0, pi) q;
U(pi/2.0, pi, pi) q;
cu(pi/2.0, 0, pi) q, p;
cu(pi/2.0, 0, pi) q, p;
cu(pi/2.0, 0, pi) q, p;
print;
U(pi, 0, pi) q;
U(pi/2.0, pi, pi) q;
reset q, p;
print;
reset q;
U(pi, 0, pi) q;
print;
pow(3) @ u(pi/2.0, pi, pi) q;
pow(3) @ cu(pi/2.0, 0, pi) q, p;
print;
`

Expand All @@ -953,28 +995,27 @@ print;
}

// Output:
// [0][ 0]( 1.0000 0.0000i): 1.0000
// [0][ 0]( 0.7071 0.0000i): 0.5000
// [1][ 1]( 0.7071 0.0000i): 0.5000
// [0][ 0]( 1.0000 0.0000i): 1.0000
// [0][ 0]( 0.7071 0.0000i): 0.5000
// [1][ 1]( 0.7071 0.0000i): 0.5000
}

func Example_pow_gate_ctrl() {

// [0 0][ 0 0]( 1.0000 0.0000i): 1.0000
// [1 0][ 1 0]( 1.0000 0.0000i): 1.0000
// [1 0][ 1 0]( 0.7071 0.0000i): 0.5000
// [1 1][ 1 1]( 0.7071 0.0000i): 0.5000
// [0 0][ 0 0]( 1.0000 0.0000i): 1.0000
// [1 0][ 1 0]( 1.0000 0.0000i): 1.0000
// [1 0][ 1 0]( 0.7071 0.0000i): 0.5000
// [1 1][ 1 1]( 0.7071 0.0000i): 0.5000
}

func Example_ctrl_x() {
qasm := `
OPENQASM 3.0;
gate h q { U(pi/2.0, 0, pi) q; }
gate x q { U(pi, 0, pi) q; }
qubit c;
qubit t;
x c;
ctrl @ x c, t;
h c;
print;
ctrl @ x c, t;
Expand All @@ -986,7 +1027,37 @@ print;
return
}

// Not Implemented.
// Output:
// [0 0][ 0 0]( 0.7071 0.0000i): 0.5000
// [1 0][ 1 0]( 0.7071 0.0000i): 0.5000
// [0 0][ 0 0]( 0.7071 0.0000i): 0.5000
// [1 1][ 1 1]( 0.7071 0.0000i): 0.5000
}

func Example_ctrl_x_index() {
qasm := `
OPENQASM 3.0;
gate h q { U(pi/2.0, 0, pi) q; }
gate x q { U(pi, 0, pi) q; }
qubit[2] q;
h q[0];
print;
ctrl @ x q[0], q[1];
print;
`

if err := eval(qasm); err != nil {
fmt.Printf("eval: %v\n", err)
return
}

// Output:
// [00][ 0]( 0.7071 0.0000i): 0.5000
// [10][ 2]( 0.7071 0.0000i): 0.5000
// [00][ 0]( 0.7071 0.0000i): 0.5000
// [11][ 3]( 0.7071 0.0000i): 0.5000
}

0 comments on commit 11481be

Please sign in to comment.