Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/qar.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
require_relative "qar/version"
require "qbit"
require "entanglement"
require "qgates"
require_relative "quantum_exception"

module Qar
Expand Down
7 changes: 0 additions & 7 deletions lib/qar/extensions/extensions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,6 @@ def round(digits)
end
end

# Integer class round extension
class Integer
def round(num)
num
end
end

# Matrix class product and print extensions
class Matrix
class << self
Expand Down
4 changes: 4 additions & 0 deletions lib/qbit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ def vector=(vector)
raise NormalizationException unless normalized?
end

def nil_entanglement()
@entanglement = nil
end

# Measurement give information about current qubit that is
# use probabilities of one and zero to give the answer what
# qubit contains now
Expand Down
106 changes: 106 additions & 0 deletions lib/qgates.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
require "matrix"
require_relative "qar/extensions/extensions"

# This class represents quantum logic gates as matrices.
# List of implemented quantum gates:
# X_GATE
# Y_GATE
# Z_GATE
# H_GATE
# T_GATE
# C_NOT_GATE
# SWAP_GATE
# TOFFOLI_GATE
class Gate < Matrix
# Operation,that applies the effect on both qubits and states containing an array of qubits
def *(*args)
case args[0]
when Qubit
qubits = []
args = args.map do |i|
qubits << i
i.vector
end.inject{|p,a| Matrix.kronecker(p,a)}
qubits=measure(qubits, super(args))
State.new(*qubits)


when State
qubits = []
temp=[]
args.map do |i|
i.qubits.map do |j|
qubits << j
temp << j.vector
end
end
args=temp.inject{|p,a| Matrix.kronecker(p,a)}
qubits=measure(qubits, super(args))
State.new(*qubits)
else
super(*args)
end
end

private
# Function that takes array of qubits and their Kronecker product and calculates new state.
# Works properly only for single qubits. For multiple qubits, Kronecker product of qubits become entangled
def measure(qubits, vector)
cnt=qubits.count()
case cnt
when 1
vector=vector.to_a.flatten
return [Qubit.new(vector[0],vector[1])]
when 2
vector=vector.to_a.flatten
return [Qubit.new(vector[0],vector[1]),Qubit.new(vector[2],vector[3])]
when 3
vector=vector.to_a.flatten
return [Qubit.new(vector[0],vector[1]),Qubit.new(vector[2],vector[3]),Qubit.new(vector[4],vector[5])]
else
return raise GateArgumentException
end
end
end

X_GATE = Gate[
[0, 1],
[1, 0]]

Y_GATE = Gate[
[0, -1i],
[1i, 0]]

Z_GATE = Gate[
[1, 0],
[0, -1]]

H_GATE = 1 / Math.sqrt(2) * Gate[
[1, 1],
[1, -1]]

T_GATE = Gate[
[1,0],
[0, Math::E**((1i * Math::PI) / 4)]]

CNOT_GATE = Gate[
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 0, 1],
[0, 0, 1, 0]]

SWAP_GATE = Gate[
[1, 0, 0, 0],
[0, 0, 1, 0],
[0, 1, 0, 0],
[0, 0, 0, 1]]

TOFFOLI_GATE = Gate[
[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, 0, 1],
[0, 0, 0, 0, 0, 0, 1, 0]]
6 changes: 6 additions & 0 deletions lib/quantum_exception.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,10 @@ def initialize(msg = "An entanglement cannot be empty")
super(msg)
end
end

class GateArgumentException < StandardError
def initialize(msg = "Quantum gates arguments are incorrect")
super(msg)
end
end
end
1 change: 1 addition & 0 deletions test/qar_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
require_relative "test_helper"
require_relative "qbit_test"
require_relative "entanglement_test"
require_relative "qgates_test"

class QarTest < Minitest::Test

Expand Down
100 changes: 100 additions & 0 deletions test/qgates_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
require_relative "test_helper"

class QgatesTest < Minitest::Test

def test_it_does_something_useful
# test that we are not a teapot... just 4 fun
assert self != :i_am_a_teapot

# test that no errors occur when importing the module
assert_nothing_raised do
require "qar"
end
end

#test section for single-qubit quantum gates

# x_gate = [[0, 1],
# [1, 0]]
def test_X_GATE

q1=Qubit.new(1,0)
s1=X_GATE * q1
assert_equal s1.qubits.map!{ |i| i.vector },[ Qubit.new(0,1).vector]
end

# y_gate = [[0, -1i],
# [1i, 0]]
def test_Y_GATE
q1=Qubit.new(1,0)
s1=Y_GATE * q1
assert_equal s1.qubits.map!{ |i| i.vector },[ Qubit.new(0+0i,0+1i).vector]
end

# z_gate = [[1, 0],
# [0, -1]]
def test_Z_GATE
q1=Qubit.new(1,0)
s1=Z_GATE*q1
assert_equal s1.qubits.map!{ |i| i.vector },[Qubit.new(1,0).vector]
end

# h_gate = 1/sqrt(2)[[1, 1],
# [1, -1]]
def test_H_GATE
q1=Qubit.new(1,0)
s1=H_GATE * q1
assert_equal s1.qubits.map!{ |i| i.vector },[Qubit.new(1/Math.sqrt(2),1/Math.sqrt(2)).vector]
end

# t_gate = [[1, 0],
# [0, e^(i*pi/4)]]
def test_T_GATE
q1=Qubit.new(1,0)
s1=T_GATE * q1
assert_equal s1.qubits.map!{ |i| i.vector },[Qubit.new(1,0).vector]
end

#test section for states with single qubit in it

def test_X_GATE_State

q1=Qubit.new(1,0)
s1=X_GATE*X_GATE * q1
assert_equal s1.qubits.map!{ |i| i.vector },[q1.vector]
end

def test_Y_GATE_State

q1=Qubit.new(1,0)
s1=Y_GATE*Y_GATE * q1
assert_equal s1.qubits.map!{ |i| i.vector },[q1.vector]
end

def test_Z_GATE_State

q1=Qubit.new(1,0)
s1=Z_GATE*Z_GATE * q1
assert s1.qubits.map!{ |i| i.vector },[q1.vector]
end

#test need more accuracy due to accumulated error
def test_H_GATE_State
q1=Qubit.new(1,0)
s1=H_GATE*H_GATE * q1
assert_equal s1.qubits.map!{ |i| i.vector }, [Qubit.new(0.9999999999999998,0).vector]
end

def test_T_GATE_State

q1=Qubit.new(1,0)
s1=T_GATE*T_GATE * q1
assert_equal s1.qubits.map!{ |i| i.vector },[q1.vector]
end

def test_Muptiple_Gates_Combination
q1=Qubit.new(1,0)
s1=Z_GATE*X_GATE*T_GATE*X_GATE*Y_GATE * q1
assert_equal s1.qubits.map!{ |i| i.vector },[Qubit.new(0+0i,0-1i).vector]
end
end
2 changes: 1 addition & 1 deletion test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
SimpleCov.start

$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
require_relative "qar"
require "qar"
require 'simplecov'

require "minitest/autorun"
Expand Down