Quantum Bits (Qubit) Bilginin temel kavramı bit’tir. Bu bölüm kapsamında Tek Qubit ve Çoklu Qubit’ler özellikleri itibariyle karşılaştırılacaktır. Peki Qubit nedir ? Qubit kimine göre matematiksel bir nesne kimine göre ise fiziksel bir nesne olarak tanımlanabilmektedir. Bu tanımlamalar doğrudur çünkü fiziksel sistemlerin gerçekleştirilmesini sağlar. Bunu sağlarken soyut matematiksel noktalar ile gerçek sistemler arasında bağlantı kurulur. Genel olarak Qubit’ler soyut matematiksel nesneler olarak düşünülebilir. Bit’ler 0-1 ile temsil edilirken Qubit’ler Bit’lerin bir duruma sahip halidir. Qubit’ler için iki mümkün durum vardır : |0> ve |1> . Bu durumlar sırasıyla Bit’teki 0 ve 1 durumuna karşılık gelmektedir. Bu tür gösterime “Dirac Notasyonu” denilmekte ve bu tür gösterime Quantum Mekaniğinde sıklıkla rastlanır. Bit ve Qubit arasındaki fark Qubit’in Bit’ten farklı olarak |0> ve |1> durumları dışındaki durumları da barındırmasıdır. Bu durumlar lineer kombinasyon durumlarıdır ve buna superposition (üst üste koyma) denilmektedir ve ifade edilme şekli a ve β sayıları kompleks sayılardır. Qubit’in durumu 2 boyutlu vektör uzayında bir vektör ile ifade edilebilir. Ayrıca bir Qubit ölçüldüğünde |a|2 olasılıkla 0, β2 olasılıkla 1 değeri elde edilir. Böylece olasılıkların toplamı da 1 olmalıdır. Geometrik açıdan düşünüldüğünde iki boyutlu kompleks bir vektör uzayında Qubit bir birimlik bir vektör olarak düşünülebilir. Qubitler |0> ve |1> arasında değer almaktadır. Şekil 1. Bir Atomda İki Elektronik Seviye Tarafından Qubit’in Temsili Şekil 1 için matematiksel gösterim : Buradaki g,f ve θ gerçek sayılardır. f ve θ kullanılarak üç boyutlu bir kürede bir nokta tanımlanabilmektedir(Şekil 2). Bloch küresi olarak adlandırılan bu küre bir Single Qubit’i görselleştirmek konusunda oldukça faydalıdır. Şekil 2. Bir Qubit’in Bloch Sphere ile Temsili Teorik açıdan düşünüldüğünde bir Qubit tarafından sonsuz sayıda bilgi temsil edilebilir. Çünkü küre üzerinde sonsuz sayıda nokta bulunmaktadır. Ancak yine de Qubit değeri |0> ve |1> arasında olacaktır. 1.2.1 Multiple Qubits İki Qubit’e sahip olduğumuzu varsayalım. Eğer bunlar iki tane klasik bit ise dört durum söz konusudur : 00, 01, 10, 11. Aynı şekilde bunların durumsal gösterimi ise şeklindedir. Bu dört durumun superposition gösteriminde karmaşık bir sayı olan genişlik (amplitude) kullanılmaktadır. Burada örneğin ilk Qubit ile olasılığı ile 0 değeri alabilir. O zaman ; 1.3.1 Single Qubit Gates Bilgisayar devreleri tellerden ve mantık kapılarından oluşmaktadır. Teller gelen bilgiyi olduğu gibi aktarırken mantık kapıları gelen bilgiler üzerinde oynamalar yapmaktadır. Şekil 3. Single Bit (Sol) ve Single Qubit (Sağ) Mantık Kapıları Burada X tipi kapılar “Değil” şeklinde çalışmakta olup değerleri tersine çevirmektedir. Z tipi kapılar aradaki işareti değiştirir. H tipi yani Hadamard kapıları ise değerleri küresel yapıyı göz önüne alarak (1/√2) ile çarpmaktadır. 1.3.2 Multiple Qubit Gates Çoklu bit’lerle ilgili beş farklı kapı bulunmaktadır : AND, OR, XOR, NAND, NOR. Genel olarak mantık kapıları : Şekil 4. Mantık Kapılarına Genel Bakış 4.1 Quantum Algorithms Zaman zaman klasik bilgisayarlarla çözülemeyen problemlerle karşılaşılmaktadır. Pratikte bu tür problemlerin çözümü için astronomik kaynaklara ihtiyaç duyulduğundan çözümlerinin imkansız olduğu konuşulmaktadır. Bu noktada kuantum bilgisayarları devreye girerek yeni algoritmalar geliştirir ve çözülmesi zor problemleri klasik bilgisayarlar için çözülebilir hale getirir. Bunu gerçekleştiren Quantum Algoritmaları temelde ikiye ayrılmaktadır: ilki Quantum Fourier Transform olarak adlandırılan ve en iyi çözümü veren klasik algoritmalardan kat be kat daha hızlı çalışan algoritmalardır, ikincisi ise Quantum aramasını gerçekleştiren Grover’ın Algoritmasıdır. Şekil 4.1. Quantum Algoritmaları ve Aralarındaki İlişki Her iki algoritmanın kombinasyonu olarak görülen Quantum Counting klasik bilgisayarlara oranla çok daha hızlı bir şekilde problemin çözümlerinin sayısını ortaya koyar. MAKALEDEN Son yıllarda araştırmacılar kuantum bilgisayarları üzerinde çalışarak yapmış oldukları çalışmaların performansını geliştirmeyi hedeflemiştir. Kuantum bilgisayarları üst üste bindirme (superposition) ve dolaşıklık (entanglement) özellikleri sayesinde klasik bilgisayarlara oranla problemleri daha hızlı çözebilmektedir. Kuantum bilgisayarları halihazırda IBM tarafından geliştiriliyor olmasına rağmen quantum algoritmaları özellikle son 20 yıldır geliştirilmektedir. Quantum algoritmaları problemleri çarpanlarına ayırır (faktörizasyon işlemi) ve optimizasyon işlemini gerçekleştirir. Eğer Quantum algoritmalarıyla ilgilenecek kişi bu algoritmaları detaylı olarak anlamak istiyorsa zihinsel anlamdaki bariyerlerin ötesine geçilmelidir. Quantum Durumları {x1,x2,…xn} bir parçacığın pozisyonlarının kümesi olsun Şekil 1. Pozisyonların ayrık kümesi X1 konumuna karşılık gelen sütun vektörü X2 konumuna karşılık gelen sütun vektörü Bir Kuantum alanı kuantum durumları tarafından tanımlanır. Kuantum durumları ise Dirac notasyonu kullanılarak ifade edilir. = karmaşık sayılarla ifade edilen n boyutlu bir vektörü ifade etmektedir. Rassal bir durum ise ile ifade edilirken şu ifadeye eşittir. Kuantum durumunun dönüşümünde ağırlık değerleri (c1, c2,… cn) tarafından kontrol edilen çok sayıda olası superposition vardır. Ağırlık olarak adlandırdığımız karmaşık sayıların karesi bize olasılık değerini vermektedir. . Doğal olarak olasılık değerlerinin toplamı 1 olmalıdır : Bir örnekten elde edilen rassal durum : Kuantumun Gözlenebilirliği Mesela bir sitemde ortaya çıkan gazın sıcaklığında ne kadar enerji çıkışı olduğunu saptamak için F(T)=E şeklinde bir denklem kurulurken kuantum fiziğinde görülebilme durumu burdakinin aksine gerçek olmayan değer içeren fonksiyondan oluşmaktadır ve bu değerler O matrisi tarafından temsil edilmektedir. Tıpkı F fonksiyonunun sitemden veri çekmesi gibi O matrisi de sistemden varlık çekmektedir. değeri durumu , superposition durumunu temsil etmektedir. Quantum Gates Klasik kapılar kullanılarak Bit’ler değiştirilebilir. Mesela DEĞİL kapısı kullanılarak bu işlem gerçekleştirilebilir. ve Yandaki matriste ilk sütun 1’den 0’a dönüşümü ikinci sütun ise 0’dan 1’e dönüşümü temsil etmektedir. Birim Matris: En önemli ve en çok kullanılan kapılardan biri Hadamard Kapısı’dır : Hadamard Kapısı |0> durumundaki bir Qubit’e uygulandığında : |1> durumundaki bir Qubit’e uygulandığında ise : Bir diğer çok kullanılan kapı ise SWAP kapısıdır. Swap’la birlikte iki Qubit ele alınır. durumunun durumuna dönüşümü : Tensor kullanılarak birden fazla Qubit’in Kuantum kapılarında kullanımı Hadamard kapısıyla durumundan durumuna geçiş şu şekilde elde edilir : Artık bir kuantum devresinde Hadamard kapısı kullanılarak bunun gösterimi durumu elde edilir ve şeklindedir. 1 numaralı durumdan 2 numaralı durumu elde ederken de SWAP kapısını kullanacak olursak Artık bir kuantum devresinde hem Hadamard hem de SWAP kapısı kullanılarak elde edilir ve bunun gösterimi durumu şeklindedir. Grover Arama Algoritması Grover’ın algoritması bir kuantum arama algoritmasıdır ve bu algoritma klasik algoritmalardan çok daha hızlı çalışmaktadır. Grover algoritmasının amacı bir elementi (bilgi) veri tabanından bulmak değil fonksiyonun döndürdüğü değerin doğru olup olmadığını fonksiyon girdileri sayesinde aramaktır. Çok karmaşık fonksiyonlar olduğu durumlarda dahi etkin şekilde çalışan bir algoritmadır. Burada bahsedilen fonksiyon bir kuantum oracle olarak temsil edilebilir ve çok sayıda kuantum kapısı tarafından oluşturulabilir. Bize fonksiyonunun verildiğini varsayalım. Bu fonksiyonun kodlanması nispeten kolaydır ancak fonksiyonun true değerini döndüreceği 0’lar ve 1’lerin kombinasyonu önemlidir. Bu durumda klasik makineler için 2n adet senaryo ortaya çıkmaktadır. Kuantum bilgisayarlarda ise fonksiyon kuantum kapılarının geçerli bir kümesi haline dönüştürülürken Grover’ın arama algoritması doğru girdiyi sadece bulabilmektedir. iterasyonda TSP problemi kombinatoryel optimizasyon problemi ailesindeki problemlerden biridir. Bu nedenle bu tip problemlerde çok kısa süre içerisinde çok sayıda mümkün çözüm üretilmelidir. Bu tip problemlerin çözümünde kullanılan algoritmalar temelde ikiye ayrılabilir : kesin metotlar ve yaklaşık metotlar. Kesin metotlar problem için kesin sonuç getirerek şehirler arasındaki en kısa rotayı bulabilmektedir. Ancak problem boyutu büyüdüğünde bunu gerçekleştirmesi oldukça zordur. 33000 şehrin olduğu bir problemi 15 yılda, 85000 şehrin olduğu bir problemi ise 136 yılda çözebilmektedir. Bu yüzden daha çok yaklaşık metotlar tercih edilir. Yaklaşık metotlar optimali vermez ancak %2-%3 oranında yaklaşık bir sonuç elde edilir. BU metotlar daha büyük ölçekli problemlerde daha kullanışlıdır(milyon tane şehrin bulunduğu problemler gibi). QAOA - Quantum Approximate Optimization Algorithm QAOA, kuantum araçlarını kullanarak geniş kapsamlı optimizasyon problemlerinin çözümünü sağlayan bir algoritmadır. MaxCut kullanılarak TSP problemi çözülebilir. MaxCut nedir ? MaxCut problemi eldeki grafı iki alt grafa ayırmakla başlar. Sonrasında alt grafları düğümlerle temsil ederiz. Düğümlerden biri kırmızı diğeri ise mavi olarak kabul edilir. Mavi olan 0 ve kırmızı olan 1 ile temsil edilir. 00 : maliyet = 0 10 : maliyet = 1 01 : maliyet = 1 11 : maliyet = 0 Bu problemi biraz daha geliştirecek olursak 000 : maliyet = 0 001 : maliyet = 1 010 : maliyet = 2 10 : maliyet = 1 011 : maliyet = 1 110 : maliyet = 1 100 : maliyet = 1 101 : maliyet = 2 111 : maliyet = 0 Şimdi 4 düğümlü bir graf üzerinde problemi inceleyelim. Tanımlama gruplarının(tuple) listesi kodlanır ve bu tuple’lar verilen düğümler arasındaki kenarları temsil etmektedir. first_graph = [(0, 1), (0, 2), (0, 3)] Burada optimal çözüm ya 1000 ya da 0111’dir. : Şimdi bu problemi Grove kütüphanesindeki maxcut_solver kullanarak MaxCut problemi olarak çözelim. Şu unutulmamalıdır ki bu algoritmanın çalışma süresi deterministik değildir, bir dakikadan kısa da sürebilir çok uzun da sürebilir. import numpy as np from grove.pyqaoa.maxcut_qaoa import maxcut_qaoa import pyquil.api as api qvm_connection = api.QVMConnection() %%capture #%%capture supresses printing. #get_angles() prints out a lot of stuff that we don't care about right now. maxcut_solver = maxcut_qaoa(graph=first_graph) betas, gammas = maxcut_solver.get_angles() Şimdi beta ve gama değerleri elde edildi. angles = np.hstack((betas, gammas)) param_prog = maxcut_solver.get_parameterized_program() prog = param_prog(angles) qubits = [0, 1, 2, 3] measurements = qvm_connection.run_and_measure(prog, qubits, trials=1000 ) Ve sonuçlar şu şekildedir : from collections import Counter measurements = [tuple(measurement) for measurement in measurements] measurements_counter = Counter(measurements) measurements_counter.most_common() Sonuçlar : [((1, ((0, ((1, ((1, ((0, ((1, ((0, ((0, ((0, ((1, ((0, ((0, ((0, ((1, ((1, ((1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0), 1), 0), 1), 1), 0), 0), 1), 0), 1), 0), 0), 1), 1), 1), 0), 231), 220), 84), 84), 81), 75), 68), 66), 19), 17), 14), 11), 10), 7), 7), 6)] Şimdi kodu adım adım ilerletelim. Doğru açı değerlerinin bulunması: # We initialize the maxcut_qaoa object with our graph maxcut_solver = maxcut_qaoa(graph=first_graph) # The QAOA algorithm tries to find the optimal values of betas and gamm as. # This line is where all the optimization takes place. betas, gammas = maxcut_solver.get_angles() print("Values of betas:", betas) print("Values of gammas:", gammas) Parameters: [1.54679531 6.139004 ] E => -1.4940854241926789 Parameters: [1.54679531 6.139004 ] E => -1.497553504498376 Parameters: [1.54679531 6.139004 ] E => -1.5152091246046904 Parameters: [1.48395675 5.93756793] E => -1.6630606037921771 Parameters: [1.48395675 5.93756793] E => -1.6335549243815815 Parameters: [1.40178325 5.39081289] E => -2.0092685257645435 Parameters: [1.30269167 5.30927924] E => -2.216995479920419 Parameters: [1.08879888 4.17500233] E => -2.261790080569641 Parameters: [1.08879888 4.17500233] E => -2.233258800349405 Parameters: [1.08879888 4.17500233] E => -2.2509385947021006 Parameters: [1.08879888 4.17500233] E => -2.2570753231984773 Parameters: [1.08879888 4.17500233] E => -2.255386716253838 Parameters: [1.11283539 4.14986029] E => -2.242086582256904 Parameters: [1.11283539 4.14986029] E => -2.281399329541506 Parameters: [1.17084493 4.33609311] E => -2.2712914971049964 Parameters: [1.13687189 4.12471825] E => -2.297163937095549 Parameters: [1.13687189 4.12471825] E => -2.293988488017738 Parameters: [1.1609084 4.09957621] E => -2.3040751738756113 Parameters: [1.1609084 4.09957621] E => -2.3093140630074114 Parameters: [1.1609084 4.09957621] E => -2.310056495263365 Parameters: [1.1849449 4.07443417] E => -2.3097331072788796 Parameters: [1.1849449 4.07443417] E => -2.3153114845422595 Parameters: [1.17279654 4.10257319] E => -2.316293546851724 Parameters: [1.17279654 4.10257319] E => -2.3162662044047053 Parameters: [1.18108349 4.09101161] E => -2.316416885858272 Parameters: [1.17929381 4.10469866] E => -2.316450415597711 Parameters: [1.17649259 4.10021416] E => -2.3164730994694076 Values of betas: [1.17649259] Values of gammas: [4.10021416] Burada parametre değerleri ve maliyetler bulunmuştur. Şimdi de açıların düzgün bir dizisi oluşturulur : # We create an array of angles with correct format angles = np.hstack((betas, gammas)) print(angles) [1.17649259 4.10021416] # We take a template for quil program from the maxcut_solver. param_prog = maxcut_solver.get_parameterized_program() # We initialize this program with the angles we have found prog = param_prog(angles) # Now we can print the program. # Some of the values you see here are the angles we calculated earlier. print(prog) print("Number of gates:", len(prog)) H 0 H 1 H 2 H 3 CNOT 0 1 RZ(4.100214159979846) 1 CNOT 0 1 X 0 PHASE(2.050107079989923) 0 X 0 PHASE(2.050107079989923) 0 CNOT 0 2 RZ(4.100214159979846) 2 CNOT 0 2 X 0 PHASE(2.050107079989923) 0 X 0 PHASE(2.050107079989923) 0 CNOT 0 3 RZ(4.100214159979846) 3 CNOT 0 3 X 0 PHASE(2.050107079989923) 0 X 0 PHASE(2.050107079989923) 0 H 0 RZ(-2.3529851869388656) 0 H 0 H 1 RZ(-2.3529851869388656) 1 H 1 H 2 RZ(-2.3529851869388656) 2 H 2 H 3 RZ(-2.3529851869388656) 3 H 3 Number of gates: 37 Kuantum programının çalıştırılması : # These are just the ids of qubits we want to use. # It's not very important if you don't use the real QPU. qubits = [0, 1, 2, 3] # Here we connect to the Forest API and run our program there. # We do that 1000 times and after each one we measure the output. measurements = qvm_connection.run_and_measure(prog, qubits, trials=1000 ) sonuçların analizi : # Since list of 1000 elements is hard to analyze, we use Counter from collections import Counter # This is just a hack - we can't use Counter on a list of lists but we can on a list of tuples. measurements = [tuple(measurement) for measurement in measurements] measurements_counter = Counter(measurements) # This line gives us the results in the diminishing order measurements_counter.most_common() [((1, 0, 0, 0), 232), ((0, ((0, ((0, ((0, ((1, ((1, ((1, ((1, ((0, ((1, ((0, ((0, ((1, ((0, ((1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1), 1), 1), 0), 1), 0), 0), 1), 0), 1), 0), 1), 0), 0), 1), 223), 86), 83), 78), 74), 63), 62), 34), 27), 9), 8), 7), 7), 4), 3)] Algortimamız bazı durumları üretiyor olsa da (yukarıdaki gibi) doğrudan hesaplama yapamıyoruz. Yeniden bazı heasplama işlemleri yapmamız gerekmektedir. Bir simülatör kullanılır : wf = qvm_connection.wavefunction(prog) print(wf) sonuçlar : (0.0813147891-0.1300523955j)|0000> + (0.4653262596+0.1064676374j)|0001> + (0.0804387018-0.0324794329j)|0010> + (-0.2535746518+0.1050939054j)|00 11> + (0.0804387018-0.0324794329j)|0100> + (-0.2535746518+0.1050939054j )|0101> + (-0.2535746518+0.1050939054j)|0110> + (0.0804387018-0.0324794 329j)|0111> + (0.0804387018-0.0324794329j)|1000> + (-0.2535746518+0.105 0939054j)|1001> + (-0.2535746518+0.1050939054j)|1010> + (0.0804387018-0 .0324794329j)|1011> + (-0.2535746518+0.1050939054j)|1100> + (0.08043870 18-0.0324794329j)|1101> + (0.4653262596+0.1064676374j)|1110> + (0.08131 47891-0.1300523955j)|1111> Bu şekilde okuması zor olduğundan başka bir formda yazmak gerekirse : print("Probability amplitudes for all the possible states:") for state_index in range(maxcut_solver.nstates): print(maxcut_solver.states[state_index], wf[state_index]) Tüm mümkün durumlar için olasılık büyüklükleri bu şekilde oluşturulur : 0000 (0.08131478909571628-0.13005239547041625j) 0001 (0.4653262595505163+0.10646763736089705j) 0010 (0.08043870178752226-0.03247943285344676j) 0011 (-0.253574651788108+0.10509390542847408j) 0100 (0.08043870178752226-0.032479432853446726j) 0101 (-0.253574651788108+0.10509390542847413j) 0110 (-0.253574651788108+0.10509390542847415j) 0111 (0.08043870178752228-0.03247943285344669j) 1000 (0.08043870178752228-0.03247943285344669j) 1001 (-0.253574651788108+0.10509390542847415j) 1010 (-0.253574651788108+0.10509390542847413j) 1011 (0.08043870178752226-0.032479432853446726j) 1100 (-0.253574651788108+0.10509390542847408j) 1101 (0.08043870178752226-0.03247943285344676j) 1110 (0.4653262595505163+0.10646763736089705j) 1111 (0.08131478909571628-0.13005239547041625j) bu şekilde yorumlanması oldukça zor ve bu yüzden gerçek olasılık değerlerine dönüştürmek için : print("Probabilities of measuring given states:") states_with_probs = [] for state_index in range(maxcut_solver.nstates): states_with_probs.append([maxcut_solver.states[state_index], np.rea l(np.conj(wf[state_index])*wf[state_index])]) print(states_with_probs[-1][0], states_with_probs[-1][1]) verilen durumların gerçek olasılık değerleri : 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 0.023525720493274362 0.22786388563248594 0.007525298303743494 0.07534483298766928 0.007525298303743491 0.07534483298766928 0.0753448329876693 0.007525298303743493 0.007525298303743493 0.0753448329876693 0.07534483298766928 0.007525298303743491 0.07534483298766928 0.007525298303743494 0.22786388563248594 0.023525720493274362 Kompleks problemlerin çözümünde daha fazla kapıya ve çalışan algoritmaya ihtiyaç duyulur. Bu da optimizasyon için daha fazla beta ve gama değerlerine ihtiyaç olduğunu göstermektedir. Bu metafordan yola çıkılarak beta ve gama değerleri bize yol göstermektedir.