Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
quantum-kittens
GitHub Repository: quantum-kittens/platypus
Path: blob/main/translations/bn/ch-states/representing-qubit-states.ipynb
3855 views
Kernel: Python 3

Qubit স্টেটের প্রতিনিধিত্ব

আপনি এখন বিট সম্পর্কে কিছু জানেন, এবং আমাদের পরিচিত ডিজিটাল কম্পিউটারগুলি কীভাবে কাজ করে সে সম্পর্কে। আধুনিক সফ্টওয়্যারগুলিতে ব্যবহৃত সমস্ত জটিল ভেরিয়েবল, অবজেক্ট এবং ডেটা স্ট্রাকচারগুলি মূলত বিটের বড় স্তূপ। আমরা যারা কোয়ান্টাম কম্পিউটিং নিয়ে কাজ করি তারা এই ক্লাসিক্যাল ভেরিয়েবলকে বলি। যে কম্পিউটারগুলি সেগুলি ব্যবহার করে, যেমন আপনি এই নিবন্ধটি পড়ার জন্য ব্যবহার করছেন, আমরা ক্লাসিক্যাল কম্পিউটার বলি।

কোয়ান্টাম কম্পিউটারে, আমাদের মৌলিক ভেরিয়েবল হল qubit: বিটের একটি কোয়ান্টাম বৈকল্পিক। এগুলোর ঠিক একই রকম বিধিনিষেধ রয়েছে যেমন সাধারণ বিটগুলি করে: তারা শুধুমাত্র একটি একক বাইনারি তথ্য সঞ্চয় করতে পারে এবং শুধুমাত্র আমাদের [[0 বা 1|-1 বা 1|0|1|-1]] এর আউটপুট দিতে পারে। . যাইহোক, এগুলিকে এমনভাবে ম্যানিপুলেট করা যেতে পারে যা শুধুমাত্র কোয়ান্টাম মেকানিক্স দ্বারা বর্ণনা করা যেতে পারে। এটি আমাদের সাথে খেলার জন্য নতুন গেট দেয়, যা আমাদের অ্যালগরিদম ডিজাইন করার নতুন উপায় খুঁজে পেতে দেয়।

এই নতুন গেটগুলি সম্পূর্ণরূপে বোঝার জন্য, আমাদের প্রথমে বুঝতে হবে কিভাবে qubit রাজ্যগুলি লিখতে হয়। এর জন্য আমরা ভেক্টর, ম্যাট্রিস এবং জটিল সংখ্যার গণিত ব্যবহার করব। যদিও আমরা যেতে যেতে এই ধারণাগুলি প্রবর্তন করব, আপনি যদি ইতিমধ্যে তাদের সাথে স্বাচ্ছন্দ্য বোধ করেন তবে এটি সর্বোত্তম হবে। আপনার যদি আরও গভীর ব্যাখ্যা বা রিফ্রেশার প্রয়োজন হয়, আপনি এখানে গাইডটি খুঁজে পেতে পারেন।

1. ক্লাসিক্যাল বনাম কোয়ান্টাম বিট

1.1 স্টেটভেক্টর

কোয়ান্টাম পদার্থবিজ্ঞানে আমরা আমাদের সিস্টেমের অবস্থা বর্ণনা করতে স্টেটভেক্টর ব্যবহার করি। বলুন আমরা একটি ট্র্যাক বরাবর একটি গাড়ির অবস্থান বর্ণনা করতে চেয়েছিলাম, এটি একটি ক্লাসিক্যাল সিস্টেম তাই আমরা একটি সংখ্যা xx ব্যবহার করতে পারি:

স্কেলার দিয়ে একটি গাড়ি ট্র্যাক করা

x=4x=4

বিকল্পভাবে, আমরা পরিবর্তে স্টেটভেক্টর নামে একটি ভেক্টরে সংখ্যার সংগ্রহ ব্যবহার করতে পারি। স্টেটভেক্টরের প্রতিটি উপাদানে একটি নির্দিষ্ট জায়গায় গাড়িটি খুঁজে পাওয়ার সম্ভাবনা রয়েছে:

স্কেলার দিয়ে একটি গাড়ি ট্র্যাক করা

ParseError: KaTeX parse error: Undefined control sequence: \cssId at position 1: \̲c̲s̲s̲I̲d̲{x_ket}{|x\rang…

এটি কেবল অবস্থানের মধ্যেই সীমাবদ্ধ নয়, আমরা গাড়ির সম্ভাব্য সব গতির একটি স্টেটভেক্টরও রাখতে পারি এবং গাড়ির সম্ভাব্য সমস্ত রঙ থাকতে পারে। ক্লাসিক্যাল সিস্টেমের সাথে (উপরের গাড়ির উদাহরণের মতো), এটি করা একটি মূর্খ কাজ কারণ এটির জন্য বিশাল ভেক্টর রাখা প্রয়োজন যখন আমাদের শুধুমাত্র একটি সংখ্যার প্রয়োজন হয়। কিন্তু আমরা যেমন এই অধ্যায়ে দেখব, স্টেটভেক্টরগুলি কোয়ান্টাম কম্পিউটার সহ কোয়ান্টাম সিস্টেমের ট্র্যাক রাখার একটি খুব ভাল উপায়।

1.2 কিউবিট স্বরলিপি

একটি গণনার সময় ক্লাসিক্যাল বিট সর্বদা 0 বা 1 প্রতি পয়েন্টে। আমরা এর চেয়ে কিছুটা রাজ্যে যোগ করতে পারি এমন আর কোনও বিশদ নেই। সুতরাং ক্লাসিক্যাল বিটের a এর অবস্থা ( c ) লিখতে আমরা শুধু এই দুটি বাইনারি মান ব্যবহার করতে পারি। উদাহরণ স্বরূপ:

c=0c = 0

কোয়ান্টাম বিটের জন্য এই সীমাবদ্ধতা তুলে নেওয়া হয়েছে। আমরা একটি কিউবিট থেকে একটি 0 বা একটি 1 পাই কিনা তা শুধুমাত্র ভালভাবে সংজ্ঞায়িত করা প্রয়োজন যখন একটি আউটপুট বের করার জন্য একটি পরিমাপ করা হয়। সেই সময়ে, এটি অবশ্যই এই দুটি বিকল্পের একটিতে প্রতিশ্রুতিবদ্ধ। অন্য সব সময়ে, এর অবস্থা একটি সাধারণ বাইনারি মান দ্বারা ক্যাপচার করার চেয়ে আরও জটিল কিছু হবে।

এগুলিকে কীভাবে বর্ণনা করতে হয় তা দেখতে, আমরা প্রথমে দুটি সহজ ক্ষেত্রে ফোকাস করতে পারি। যেমনটি আমরা শেষ বিভাগে দেখেছি, এটি এমন একটি অবস্থায় একটি qubit প্রস্তুত করা সম্ভব যার জন্য এটি পরিমাপ করার সময় ফলাফল 0 দেয়।

আমাদের এই রাজ্যের জন্য একটি নাম দরকার। আসুন কল্পনাবিহীন হই এবং এটিকে 00 বলি। একইভাবে, একটি কিউবিট অবস্থা রয়েছে যা একটি 1 আউটপুট করতে নিশ্চিত। আমরা এই 11 কল করব. এই দুটি রাষ্ট্র সম্পূর্ণরূপে পারস্পরিক [[এক্সক্লুসিভ|ইনক্লুসিভ]]। হয় qubit অবশ্যই একটি 0 আউটপুট করে, অথবা এটি অবশ্যই একটি 1 আউটপুট করে। কোন ওভারল্যাপ আছে. গণিতের সাথে এটি উপস্থাপন করার একটি উপায় হল দুটি অর্থোগোনাল ভেক্টর ব্যবহার করা।

ParseError: KaTeX parse error: Undefined control sequence: \cssId at position 1: \̲c̲s̲s̲I̲d̲{|0\rangle…

এই সব একবারে নিতে স্বরলিপি অনেক. প্রথমে, আসুন অদ্ভুত | এবং \rangle আনপ্যাক করি। তাদের কাজটি মূলত আমাদের মনে করিয়ে দেওয়া যে আমরা ভেক্টর সম্পর্কে কথা বলছি যেগুলি 00 এবং 11 লেবেলযুক্ত qubit রাজ্যগুলিকে প্রতিনিধিত্ব করে। এটি আমাদেরকে বিট মান 0 এবং 1 বা 0 এবং 1 সংখ্যার মতো জিনিসগুলি থেকে আলাদা করতে সাহায্য করে। এটি ডিরাক দ্বারা প্রবর্তিত ব্রা-কেট নোটেশনের অংশ।

আপনি যদি ভেক্টরের সাথে পরিচিত না হন তবে আপনি মূলত সেগুলিকে সংখ্যার তালিকা হিসাবে ভাবতে পারেন যা আমরা নির্দিষ্ট নিয়ম ব্যবহার করে পরিচালনা করি। আপনি যদি আপনার উচ্চ বিদ্যালয়ের পদার্থবিদ্যার ক্লাস থেকে ভেক্টরের সাথে পরিচিত হন তবে আপনি জানবেন যে এই নিয়মগুলি ভেক্টরগুলিকে একটি মাত্রা এবং দিকনির্দেশ সহ পরিমাণ বর্ণনা করার জন্য উপযুক্ত করে তোলে। উদাহরণস্বরূপ, একটি ভেক্টর দিয়ে একটি বস্তুর বেগ নিখুঁতভাবে বর্ণনা করা হয়। যাইহোক, কোয়ান্টাম স্টেটের জন্য আমরা যেভাবে ভেক্টর ব্যবহার করি তা এর থেকে কিছুটা আলাদা, তাই আপনার আগের অন্তর্দৃষ্টিকে খুব বেশি ধরে রাখবেন না। এটা নতুন কিছু করার সময়!

ভেক্টরের সাহায্যে আমরা শুধুমাত্র 0|0\rangle এবং 1|1\rangle এর চেয়ে আরও জটিল অবস্থা বর্ণনা করতে পারি। উদাহরণস্বরূপ, ভেক্টর বিবেচনা করুন

ParseError: KaTeX parse error: Undefined control sequence: \cssId at position 1: \̲c̲s̲s̲I̲d̲{|q_0\rangle…

এই অবস্থার অর্থ কী তা বোঝার জন্য, আমাদের ভেক্টর ম্যানিপুলেট করার জন্য গাণিতিক নিয়মগুলি ব্যবহার করতে হবে। বিশেষ করে, আমাদের বুঝতে হবে কিভাবে ভেক্টর একসাথে যোগ করতে হয় এবং কিভাবে তাদের স্কেলার দ্বারা গুণ করা যায়।

অনুস্মারক

ম্যাট্রিক্স ম্যাথ দুটি ভেক্টর যোগ করতে, আমরা তাদের উপাদানগুলিকে একসাথে যুক্ত করি:
a=[a0 a1  an],b=[b0 b1  bn]|a\rangle = \begin{bmatrix}a_0 \ a_1 \ \vdots \ a_n \end{bmatrix}, \quad |b\rangle = \begin{bmatrix}b_0 \ b_1 \ \vdots \ b_n \end{bmatrix}a+b=[a0+b0 a1+b1  an+bn]|a\rangle + |b\rangle = \begin{bmatrix}a_0 + b_0 \ a_1 + b_1 \ \vdots \ a_n + b_n \end{bmatrix}

এবং একটি ভেক্টরকে স্কেলার দ্বারা গুণ করতে, আমরা প্রতিটি উপাদানকে স্কেলার দ্বারা গুণ করি:

xa=[x×a0 x×a1  x×an]x|a\rangle = \begin{bmatrix}x \times a_0 \ x \times a_1 \ \vdots \ x \times a_n \end{bmatrix}

এই দুটি নিয়ম ভেক্টর q0|q_0\rangle (উপরে দেখানো হয়েছে) পুনরায় লিখতে ব্যবহৃত হয়:

q0amp;=120+i21 amp;=12[1 0]+i2[0 1] amp;=[12 0]+[0 i2] amp;=[12 i2] \begin{aligned} |q_0\rangle &= \tfrac{1}{\sqrt{2}}|0\rangle + \tfrac{i}{\sqrt{2}}|1\rangle \ &= \tfrac{1}{\sqrt{2}}\begin{bmatrix}1 \ 0\end{bmatrix} + \tfrac{i}{\sqrt{2}}\begin{bmatrix}0 \ 1\end{bmatrix} \ &= \begin{bmatrix}\tfrac{1}{\sqrt{2}} \ 0\end{bmatrix} + \begin{bmatrix}0 \ \tfrac{i}{\sqrt{2}}\end{bmatrix} \ &= \begin{bmatrix}\tfrac{1}{\sqrt{2}} \ \tfrac{i}{\sqrt{2}} \end{bmatrix} \ \end{aligned}
অর্থনর্মাল বেস এটি আগে বলা হয়েছিল যে দুটি ভেক্টর 0|0\rangle এবং 1|1\rangle অর্থনর্মাল, এর মানে তারা উভয়ই _অর্থোগোনাল_ এবং _নর্মালাইজড_। অর্থোগোনাল মানে ভেক্টরগুলি সমকোণে রয়েছে:

basis

এবং স্বাভাবিক করা মানে তাদের মাত্রা (তীরের দৈর্ঘ্য) 1 এর সমান। 0|0\rangle এবং 1|1\rangle দুটি ভেক্টর রৈখিকভাবে স্বাধীন , যার মানে আমরা 0|0\rangle এর পরিপ্রেক্ষিতে বর্ণনা করতে পারি না 1|1\rangle, এবং তদ্বিপরীত। যাইহোক, 0|0\rangle এবং 1|1\rangle উভয় ভেক্টর ব্যবহার করে, এবং স্কেলার দ্বারা যোগ ও গুণের আমাদের নিয়ম, আমরা 2D স্থানের সমস্ত সম্ভাব্য ভেক্টর বর্ণনা করতে পারি:

basis

কারণ ভেক্টর 0|0\rangle এবং 1|1\rangle রৈখিকভাবে স্বাধীন, এবং ভেক্টর যোগ এবং স্কেলার গুণ ব্যবহার করে 2D স্থানের যেকোনো ভেক্টরকে বর্ণনা করতে ব্যবহার করা যেতে পারে, আমরা ভেক্টর বলি 0|0\rangle এবং 1 |1\rangle একটি ভিত্তি তৈরি করে। এই ক্ষেত্রে, যেহেতু তারা অর্থোগোনাল এবং নরমালাইজড উভয়ই, আমরা এটিকে একটি অর্থনর্মাল ভিত্তি বলি।

যেহেতু 0|0\rangle এবং 1|1\rangle একটি অর্থনরমাল ভিত্তি তৈরি করে, তাই আমরা এই দুটি অবস্থার সংমিশ্রণে যেকোনো 2D ভেক্টরকে উপস্থাপন করতে পারি। এটি আমাদের বিকল্প আকারে আমাদের qubit এর অবস্থা লিখতে দেয়:

ParseError: KaTeX parse error: Undefined control sequence: \cssId at position 1: \̲c̲s̲s̲I̲d̲{|q_0\rangle…

এই ভেক্টর, q0|q_0\rangle কে কিউবিটের স্টেটভেক্টর বলা হয়, এটি আমাদের এই কিউবিট সম্পর্কে সম্ভবত যা জানতে পারে তা আমাদের বলে। আপাতত, আমরা একটি স্টেটভেক্টরের এই বিশেষ উদাহরণ সম্পর্কে কয়েকটি সহজ সিদ্ধান্তে আঁকতে সক্ষম: এটি সম্পূর্ণরূপে 0|0\rangle এবং সম্পূর্ণরূপে 1|1\rangle নয়। পরিবর্তে, এটি দুটির একটি রৈখিক সমন্বয় দ্বারা বর্ণিত হয়েছে। কোয়ান্টাম মেকানিক্সে, আমরা সাধারণত 'সুপারপজিশন' শব্দটি ব্যবহার করে রৈখিক সংমিশ্রণগুলি বর্ণনা করি।

যদিও আমাদের উদাহরণ স্টেট q0|q_0\rangle কে 0|0\rangle এবং 1|1\rangle এর সুপারপজিশন হিসাবে প্রকাশ করা যেতে পারে, তবে এটি তাদের চেয়ে কম একটি নির্দিষ্ট এবং সু-সংজ্ঞায়িত qubit রাষ্ট্র নয়। এটি দেখতে, আমরা কিভাবে একটি qubit ম্যানিপুলেট করা যেতে পারে অন্বেষণ শুরু করতে পারেন.

1.3 কিস্কিট দিয়ে কিউবিট অন্বেষণ করা

প্রথমত, আমাদের প্রয়োজনীয় সমস্ত সরঞ্জাম আমদানি করতে হবে:

from qiskit import QuantumCircuit, assemble, Aer from qiskit.visualization import plot_histogram, plot_bloch_vector from math import sqrt, pi

QuantumCircuit -এ, আমরা আমাদের সার্কিটগুলি সঞ্চয় করার জন্য কোয়ান্টাম সার্কিট অবজেক্ট ব্যবহার করি, এটি মূলত আমাদের সার্কিটের কোয়ান্টাম ক্রিয়াকলাপগুলির একটি তালিকা এবং সেগুলি প্রয়োগ করা হয়।

qc = QuantumCircuit(1) # Create a quantum circuit with one qubit

আমাদের কোয়ান্টাম সার্কিটে, আমাদের qubits সর্বদা 0|0\rangle রাজ্যে শুরু হয়। এটিকে যেকোনো অবস্থায় রূপান্তর করতে আমরা initialize() পদ্ধতি ব্যবহার করতে পারি। আমরা initialize() ভেক্টরটি একটি তালিকা আকারে দিই, এবং এটিকে বলি যে আমরা এই অবস্থায় কোন qubit(গুলি) আরম্ভ করতে চাই:

qc = QuantumCircuit(1) # Create a quantum circuit with one qubit initial_state = [0,1] # Define initial_state as |1> qc.initialize(initial_state, 0) # Apply initialisation operation to the 0th qubit qc.draw() # Let's view our circuit
Image in a Jupyter notebook

তারপরে আমরা আমাদের কিউবিটের ফলাফলের অবস্থা দেখতে কিস্কিটের একটি সিমুলেটর ব্যবহার করতে পারি।

sim = Aer.get_backend('aer_simulator') # Tell Qiskit how to simulate our circuit

আমাদের সার্কিট থেকে ফলাফল পেতে, আমরা আমাদের সার্কিট run জন্য রান ব্যবহার করি, সার্কিট এবং ব্যাকএন্ডকে আর্গুমেন্ট হিসেবে দিই। আমরা তারপর এটির ফলাফল পেতে .result() ব্যবহার করি:

qc = QuantumCircuit(1) # Create a quantum circuit with one qubit initial_state = [0,1] # Define initial_state as |1> qc.initialize(initial_state, 0) # Apply initialisation operation to the 0th qubit qc.save_statevector() # Tell simulator to save statevector qobj = assemble(qc) # Create a Qobj from the circuit for the simulator to run result = sim.run(qobj).result() # Do the simulation and return the result

from result, we can then get the final state vector using .get statevector():

out_state = result.get_statevector() print(out_state) # Display the output state vector
[0.+0.j 1.+0.j]

দ্রষ্টব্য: পাইথন জটিল সংখ্যায় ii উপস্থাপন করতে j ব্যবহার করে। আমরা দুটি জটিল উপাদান সহ একটি ভেক্টর দেখতে পাই: 0.+0.j = 0, এবং 1.+0.j = 1।

এখন আমাদের qubit পরিমাপ করা যাক যেভাবে আমরা একটি বাস্তব কোয়ান্টাম কম্পিউটারে করব এবং ফলাফলটি দেখব:

qc.measure_all() qc.draw()
Image in a Jupyter notebook

এইবার, স্টেটভেক্টরের পরিবর্তে আমরা .get_counts() ব্যবহার করে 0 এবং 1 ফলাফলের জন্য গণনা পাব :

qobj = assemble(qc) result = sim.run(qobj).result() counts = result.get_counts() plot_histogram(counts)
Image in a Jupyter notebook

আমরা দেখতে পাচ্ছি যে আমাদের (আশ্চর্যজনকভাবে) 1|1\rangle পরিমাপের [[100]]% সম্ভাবনা রয়েছে।

এই সময়, এর পরিবর্তে একটি সুপারপজিশনে আমাদের qubit করা যাক এবং দেখুন কি হয়. আমরা এই বিভাগে আগের থেকে q0|q_0\rangle রাষ্ট্রটি ব্যবহার করব:

ParseError: KaTeX parse error: Undefined control sequence: \cssId at position 53: …angle + \tfrac{\̲c̲s̲s̲I̲d̲{i}{i}}{\sqrt{2…

আমাদের একটি পাইথন তালিকায় এই প্রশস্ততা যোগ করতে হবে। একটি জটিল প্রশস্ততা যোগ করতে, পাইথন কাল্পনিক এককের জন্য j ব্যবহার করে (আমরা সাধারণত এটিকে গাণিতিকভাবে "ii" বলি):

initial_state = [1/sqrt(2), 1j/sqrt(2)] # Define state |q_0>

এবং তারপরে আমরা আগের মতো কিউবিট শুরু করার জন্য পদক্ষেপগুলি পুনরাবৃত্তি করি:

qc = QuantumCircuit(1) # Must redefine qc qc.initialize(initial_state, 0) # Initialize the 0th qubit in the state `initial_state` qc.save_statevector() # Save statevector qobj = assemble(qc) state = sim.run(qobj).result().get_statevector() # Execute the circuit print(state) # Print the result
[0.70710678+0.j 0. +0.70710678j]
qobj = assemble(qc) results = sim.run(qobj).result().get_counts() plot_histogram(results)
Image in a Jupyter notebook

আমরা দেখতে পাচ্ছি যে আমাদের 1|1\rangle এর তুলনায় 0|0\rangle পরিমাপের [[সমান|কম|বৃহত্তর]] সম্ভাবনা রয়েছে। এটি ব্যাখ্যা করার জন্য, আমাদের পরিমাপ সম্পর্কে কথা বলতে হবে।

2. পরিমাপের নিয়ম

2.1 একটি অত্যন্ত গুরুত্বপূর্ণ নিয়ম

পরিমাপের জন্য একটি সহজ নিয়ম আছে। একটি স্টেট ψ|\psi \rangle x|x\rangle এ স্টেট পরিমাপের সম্ভাবনা খুঁজে পেতে আমরা করি:

p(x)=xψ2p(|x\rangle) = | \langle x| \psi \rangle|^2

\langle এবং | চিহ্নগুলি আমাদের জানায় x\langle x | একটি সারি ভেক্টর। কোয়ান্টাম মেকানিক্সে আমরা কলাম ভেক্টরকে কেট এবং সারি ভেক্টরকে ব্রা বলি। তারা একসাথে ব্রা-কেট স্বরলিপি তৈরি করে। যেকোনো কেট a|a\rangle এর একটি অনুরূপ ব্রা a\langle a| থাকে এবং আমরা কনজুগেট ট্রান্সপোজ ব্যবহার করে তাদের মধ্যে রূপান্তর করি।

অনুস্মারক

অভ্যন্তরীণ পণ্য ভেক্টর গুন করার বিভিন্ন উপায় আছে, এখানে আমরা _inner product_ ব্যবহার করি। অভ্যন্তরীণ পণ্য হল _ডট পণ্য_ এর একটি সাধারণীকরণ যা আপনি ইতিমধ্যে পরিচিত হতে পারেন। এই নির্দেশিকায়, আমরা একটি ব্রা (সারি ভেক্টর) এবং একটি কেট (কলাম ভেক্টর) এর মধ্যে অভ্যন্তরীণ পণ্যটি ব্যবহার করি এবং এটি এই নিয়ম অনুসরণ করে:
a=[a0,amp;a1,amp;amp;an]\langle a| = \begin{bmatrix}a_0, & a_1, & \dots & a_n \end{bmatrix}b=[b0 b1  bn]|b\rangle = \begin{bmatrix}b_0 \ b_1 \ \vdots \ b_n \end{bmatrix}ab=a0b0+a1b1anbn\langle a|b\rangle = a_0 b_0 + a_1 b_1 \dots a_n b_n

আমরা দেখতে পাচ্ছি যে দুটি ভেক্টরের অভ্যন্তরীণ গুণফল সবসময় আমাদের একটি স্কেলার দেয়। মনে রাখা একটি দরকারী জিনিস হল যে দুটি অর্থোগোনাল ভেক্টরের অভ্যন্তরীণ গুণফল হল 0, উদাহরণস্বরূপ যদি আমাদের অর্থোগোনাল ভেক্টর 0|0\rangle এবং 1|1\rangle থাকে:

10=[0,amp;1][1 0]=0\langle1|0\rangle = \begin{bmatrix} 0 , & 1\end{bmatrix}\begin{bmatrix}1 \ 0\end{bmatrix} = 0

উপরন্তু, মনে রাখবেন যে ভেক্টর 0|0\rangle এবং 1|1\rangleও স্বাভাবিক করা হয়েছে (ম্যাগনিটিউড 1 এর সমান):

00amp;=[1,amp;0][1 0]=1 11amp;=[0,amp;1][0 1]=1\begin{aligned} \langle0|0\rangle &= \begin{bmatrix} 1 , & 0\end{bmatrix}\begin{bmatrix}1 \ 0\end{bmatrix} = 1 \ \langle1|1\rangle &= \begin{bmatrix} 0 , & 1\end{bmatrix}\begin{bmatrix}0 \ 1\end{bmatrix} = 1 \end{aligned}
কনজুগেট ট্রান্সপোজ কনজুগেট ট্রান্সপোজ পদ্ধতি ব্যবহার করে ব্রা-কেটের মধ্যে রূপান্তর ঘটে। আমরা জানি একটি কেট (কলাম ভেক্টর) নিম্নরূপ উপস্থাপন করা হয়:
a=[a0 a1  an]\quad|a\rangle = \begin{bmatrix}a_0 \ a_1 \ \vdots \ a_n \end{bmatrix}

কনজুগেট ট্রান্সপোজ পেতে, ম্যাট্রিক্সটি স্থানান্তরিত হয় এবং উপাদানগুলি জটিল সংযোজিত ("∗" অপারেশন দ্বারা উপস্থাপিত হয়) যেখানে একটি জটিল সংখ্যার জটিল সংযোজক হল একটি সংখ্যা যার একটি সমান বাস্তব অংশ এবং একটি কাল্পনিক অংশ পরিমাণে সমান কিন্তু বিপরীতে চিহ্ন. এটি নিম্নলিখিত হিসাবে সংশ্লিষ্ট ব্রা (সারি ভেক্টর) দেয়:

a=[a0,amp;a1,amp;amp;an]\langle a| = \begin{bmatrix}a_0^*, & a_1^*, & \dots & a_n^* \end{bmatrix}

উপরের সমীকরণে, x|x\rangle যেকোনো qubit অবস্থা হতে পারে। x|x\rangle পরিমাপের সম্ভাব্যতা খুঁজে বের করতে, আমরা x|x\rangle এর অভ্যন্তরীণ গুণফল এবং আমরা যে অবস্থাটি পরিমাপ করছি (এই ক্ষেত্রে ψ|\psi\rangle) নিই, তারপরে পরিমাপের বর্গাকার করি। এটি কিছুটা জটিল বলে মনে হতে পারে, তবে এটি শীঘ্রই দ্বিতীয় প্রকৃতিতে পরিণত হবে।

আমরা যদি আগে থেকে q0|q_0\rangle এর অবস্থা দেখি, তাহলে আমরা দেখতে পাব 0|0\rangle পরিমাপের সম্ভাবনা প্রকৃতপক্ষে 0.50.5:

q0amp;=120+i21 0q0amp;=1200+i201 amp;=121+i20 amp;=12 0q02amp;=12\begin{aligned} |q_0\rangle & = \tfrac{1}{\sqrt{2}}|0\rangle + \tfrac{i}{\sqrt{2}}|1\rangle \ \langle 0| q_0 \rangle & = \tfrac{1}{\sqrt{2}}\langle 0|0\rangle + \tfrac{i}{\sqrt{2}}\langle 0|1\rangle \ & = \tfrac{1}{\sqrt{2}}\cdot 1 + \tfrac{i}{\sqrt{2}} \cdot 0\ & = \tfrac{1}{\sqrt{2}}\ |\langle 0| q_0 \rangle|^2 & = \tfrac{1}{2} \end{aligned}

আপনি একটি অনুশীলন হিসাবে 1|1\rangle পরিমাপ সম্ভাবনা যাচাই করা উচিত.

এই নিয়মটি নিয়ন্ত্রণ করে কিভাবে আমরা কোয়ান্টাম স্টেট থেকে তথ্য পাই। তাই কোয়ান্টাম কম্পিউটেশনে আমরা যা কিছু করি তার জন্য এটা খুবই গুরুত্বপূর্ণ। এটি অবিলম্বে বেশ কয়েকটি গুরুত্বপূর্ণ তথ্য বোঝায়।

2.2 এই নিয়মের প্রভাব

#1 স্বাভাবিকীকরণ

নিয়মটি আমাদের দেখায় যে প্রশস্ততাগুলি সম্ভাব্যতার সাথে সম্পর্কিত। যদি আমরা সম্ভাব্যতাগুলি 1 পর্যন্ত যোগ করতে চাই (যা তাদের উচিত!), আমাদের নিশ্চিত করতে হবে যে স্টেটভেক্টর সঠিকভাবে স্বাভাবিক করা হয়েছে। বিশেষ করে, আমাদের স্টেট ভেক্টরের মাত্রা 1 হতে হবে।

ψψ=1\langle\psi|\psi\rangle = 1

সুতরাং যদি:

ψ=α0+β1|\psi\rangle = \alpha|0\rangle + \beta|1\rangle

তারপর:

α2+β2=1|\alpha|^2 + |\beta|^2 = 1

এটি 2\sqrt{2} এর কারণগুলি ব্যাখ্যা করে যা আপনি এই অধ্যায় জুড়ে দেখেছেন৷ আসলে, যদি আমরা initialize() এমন একটি ভেক্টর দেওয়ার চেষ্টা করি যা স্বাভাবিক করা হয় না, এটি আমাদের একটি ত্রুটি দেবে:

vector = [1,1] qc.initialize(vector, 0)
--------------------------------------------------------------------------- QiskitError Traceback (most recent call last) <ipython-input-12-ddc73828b990> in <module> 1 vector = [1,1] ----> 2 qc.initialize(vector, 0) /usr/local/anaconda3/lib/python3.7/site-packages/qiskit/extensions/quantum_initializer/initializer.py in initialize(self, params, qubits) 453 454 num_qubits = None if not isinstance(params, int) else len(qubits) --> 455 return self.append(Initialize(params, num_qubits), qubits) 456 457 /usr/local/anaconda3/lib/python3.7/site-packages/qiskit/extensions/quantum_initializer/initializer.py in __init__(self, params, num_qubits) 89 if not math.isclose(sum(np.absolute(params) ** 2), 1.0, 90 abs_tol=_EPS): ---> 91 raise QiskitError("Sum of amplitudes-squared does not equal one.") 92 93 num_qubits = int(num_qubits) QiskitError: 'Sum of amplitudes-squared does not equal one.'

দ্রুত অনুশীলন

  1. একটি স্টেট ভেক্টর তৈরি করুন যা 0|0\rangle পরিমাপের একটি 1/31/3 সম্ভাব্যতা দেবে।

  2. একটি ভিন্ন স্টেট ভেক্টর তৈরি করুন যা একই পরিমাপের সম্ভাব্যতা দেবে।

  3. যাচাই করুন যে এই দুটি অবস্থার জন্য 1|1\rangle পরিমাপের সম্ভাব্যতা হল 2/32/3

আপনি নীচের উইজেটে আপনার উত্তরটি পরীক্ষা করতে পারেন (উত্তরগুলি ±1% নির্ভুলতা গ্রহণ করে, আপনি ভেক্টরে ' pi ' এবং ' sqrt() ' এর মতো numpy ব্যবহার করতে পারেন):

# Run the code in this cell to interact with the widget from qiskit_textbook.widgets import state_vector_exercise state_vector_exercise(target=1/3)

#2 বিকল্প পরিমাপ

পরিমাপের নিয়মটি আমাদের সম্ভাব্যতা দেয় p(x)p(|x\rangle) যে একটি রাষ্ট্র ψ|\psi\rangle x|x\rangle হিসাবে পরিমাপ করা হয়। এটি কোথাও আমাদের বলে না যে x|x\rangle শুধুমাত্র 0|0\rangle বা 1|1\rangle হতে পারে।

আমরা এখন পর্যন্ত যে পরিমাপগুলি বিবেচনা করেছি তা আসলে একটি কিউবিট পরিমাপ করার সম্ভাব্য অসীম সংখ্যক উপায়গুলির মধ্যে একটি মাত্র। যেকোন অর্থোগোনাল জোড় রাজ্যের জন্য, আমরা একটি পরিমাপ সংজ্ঞায়িত করতে পারি যা একটি কিউবিটকে দুটির মধ্যে বেছে নিতে পারে।

এই সম্ভাবনা পরবর্তী বিভাগে আরো অন্বেষণ করা হবে. আপাতত, শুধু মনে রাখবেন যে x|x\rangle শুধুমাত্র 0|0\rangle বা 1|1\rangle হওয়ার মধ্যে সীমাবদ্ধ নয়।

#3 গ্লোবাল ফেজ

আমরা জানি যে 1|1\rangle স্টেট পরিমাপ করলে আমাদের নিশ্চিতভাবে আউটপুট 1 পাওয়া যাবে। কিন্তু আমরা যেমন স্টেট লিখতে সক্ষম

[0 i]=i1.\begin{bmatrix}0 \ i\end{bmatrix} = i|1\rangle.

এটি কীভাবে আচরণ করে তা দেখতে, আমরা পরিমাপের নিয়ম প্রয়োগ করি।

x(i1)2=ix12=x12|\langle x| (i|1\rangle) |^2 = | i \langle x|1\rangle|^2 = |\langle x|1\rangle|^2

এখানে আমরা দেখতে পাই যে ii এর ফ্যাক্টরটি একবার অদৃশ্য হয়ে যায় যখন আমরা জটিল সংখ্যার মাত্রা নিই। এই প্রভাব পরিমাপ করা অবস্থা x|x\rangle থেকে সম্পূর্ণ স্বাধীন। আমরা কোন পরিমাপ বিবেচনা করছি তা বিবেচ্য নয়, i1i|1\rangle রাষ্ট্রের সম্ভাব্যতাগুলি 1|1\rangle এর জন্য অভিন্ন। যেহেতু পরিমাপই একমাত্র উপায় যা আমরা একটি কিউবিট থেকে যেকোনো তথ্য বের করতে পারি, এটি বোঝায় যে এই দুটি অবস্থা শারীরিকভাবে প্রাসঙ্গিক সমস্ত উপায়ে সমান।

আরো সাধারণভাবে, আমরা একটি রাষ্ট্রে γ\gamma যে কোনো সামগ্রিক ফ্যাক্টর উল্লেখ করি যার জন্য γ=1|\gamma|=1 একটি 'গ্লোবাল ফেজ' হিসাবে। যে স্টেটগুলি শুধুমাত্র একটি বৈশ্বিক পর্যায়ের দ্বারা পৃথক হয় তা শারীরিকভাবে আলাদা করা যায় না।

x(γa)2=γxa2=xa2|\langle x| ( \gamma |a\rangle) |^2 = | \gamma \langle x|a\rangle|^2 = |\langle x|a\rangle|^2

মনে রাখবেন যে এটি একটি সুপারপজিশনের পদগুলির মধ্যে ফেজ পার্থক্য থেকে আলাদা, যা 'আপেক্ষিক ফেজ' নামে পরিচিত। আমরা যখন বিভিন্ন ধরনের পরিমাপ এবং একাধিক কিউবিট বিবেচনা করি তখন এটি প্রাসঙ্গিক হয়ে ওঠে।

#4 পর্যবেক্ষক প্রভাব

আমরা জানি যে প্রশস্ততাগুলি একটি নির্দিষ্ট অবস্থায় কিউবিট খুঁজে পাওয়ার সম্ভাবনা সম্পর্কে তথ্য ধারণ করে, কিন্তু একবার আমরা কিউবিট পরিমাপ করলে, আমরা নিশ্চিতভাবে জানি যে কিউবিটের অবস্থা কী। উদাহরণস্বরূপ, যদি আমরা স্টেটে একটি qubit পরিমাপ করি:

q=α0+β1|q\rangle = \alpha|0\rangle + \beta|1\rangle

এবং এটিকে 0|0\rangle রাজ্যে খুঁজুন, যদি আমরা আবার পরিমাপ করি, তাহলে 0|0\rangle রাজ্যে qubit খুঁজে পাওয়ার সম্ভাবনা 100% আছে। এর মানে পরিমাপের কাজটি আমাদের কিউবিটগুলির অবস্থা পরিবর্তন করে।

q=[α β]Measure 0q=0=[1 0]|q\rangle = \begin{bmatrix} \alpha \ \beta \end{bmatrix} \xrightarrow{\text{Measure }|0\rangle} |q\rangle = |0\rangle = \begin{bmatrix} 1 \ 0 \end{bmatrix}

আমরা কখনও কখনও এটিকে কিউবিটের অবস্থার পতন হিসাবে উল্লেখ করি। এটি একটি শক্তিশালী প্রভাব, এবং তাই এটি অবশ্যই বুদ্ধিমানের সাথে ব্যবহার করা উচিত। উদাহরণস্বরূপ, একটি গণনার প্রতিটি পয়েন্টে তাদের মান ট্র্যাক রাখার জন্য আমরা যদি আমাদের প্রতিটি কিউবিটকে ক্রমাগত পরিমাপ করি, তবে তারা সর্বদা 0|0\rangle বা 1এরএকটিসুসংজ্ঞায়িতঅবস্থায়থাকবে।|1\rangle-এর একটি সু-সংজ্ঞায়িত অবস্থায় থাকবে। যেমন, তারা ক্লাসিক্যাল বিট থেকে আলাদা হবে না এবং আমাদের গণনা সহজে একটি ক্লাসিক্যাল গণনা দ্বারা প্রতিস্থাপিত হতে পারে। সত্যিকারের কোয়ান্টাম গণনা অর্জনের জন্য আমাদের অবশ্যই কিউবিটগুলিকে আরও জটিল অবস্থা অন্বেষণ করার অনুমতি দিতে হবে। তাই পরিমাপ শুধুমাত্র তখনই ব্যবহার করা হয় যখন আমাদের একটি আউটপুট বের করতে হবে। এর মানে হল যে আমরা প্রায়শই আমাদের কোয়ান্টাম সার্কিটের শেষে সমস্ত পরিমাপ রাখি।

আমরা কিস্কিটের স্টেটভেক্টর সিমুলেটর ব্যবহার করে এটি প্রদর্শন করতে পারি। সুপারপজিশনে একটি কিউবিট শুরু করা যাক:

qc = QuantumCircuit(1) # We are redefining qc initial_state = [0.+1.j/sqrt(2),1/sqrt(2)+0.j] qc.initialize(initial_state, 0) qc.draw()
Image in a Jupyter notebook

এটি স্টেটে আমাদের qubit শুরু করা উচিত:

q=i20+121|q\rangle = \tfrac{i}{\sqrt{2}}|0\rangle + \tfrac{1}{\sqrt{2}}|1\rangle

আমরা সিমুলেটর ব্যবহার করে এটি যাচাই করতে পারি:

qc.save_statevector() result = sim.run(assemble(qc)).result() state = result.get_statevector() print("Qubit State = " + str(state))
Qubit State = [0. +0.70710678j 0.70710678+0.j ]

আমরা এখানে দেখতে পাচ্ছি যে কিউবিটটি স্টেটে শুরু করা হয়েছে [0.+0.70710678j 0.70710678+0.j] , যেটি আমরা আশা করেছিলাম।

এখন একটি সার্কিট তৈরি করা যাক যেখানে আমরা এই qubit পরিমাপ করব:

qc = QuantumCircuit(1) # We are redefining qc initial_state = [0.+1.j/sqrt(2),1/sqrt(2)+0.j] qc.initialize(initial_state, 0) qc.measure_all() qc.save_statevector() qc.draw()
Image in a Jupyter notebook

যখন আমরা এই সম্পূর্ণ সার্কিটটি অনুকরণ করি, তখন আমরা দেখতে পাব যে একটি প্রশস্ততা সর্বদা 0:

qobj = assemble(qc) state = sim.run(qobj).result().get_statevector() print("State of Measured Qubit = " + str(state))
State of Measured Qubit = [0.+1.j 0.+0.j]

আপনি qubit পুনরায় চালু করতে এবং আবার পরিমাপ করতে এই ঘরটি কয়েকবার পুনরায় চালাতে পারেন। আপনি লক্ষ্য করবেন যে উভয় ফলাফলই সমানভাবে সম্ভাব্য, কিন্তু কিউবিটের অবস্থা কখনোই 0|0\rangle এবং 1|1\rangle-এর একটি সুপারপজিশন নয়। কিছুটা মজার বিষয় হল, রাষ্ট্রে বিশ্বব্যাপী পর্যায় 0|0\rangle টিকে আছে, কিন্তু যেহেতু এটি বৈশ্বিক পর্যায়, তাই আমরা কখনই এটি একটি বাস্তব কোয়ান্টাম কম্পিউটারে পরিমাপ করতে পারি না।

কোয়ান্টাম সিমুলেটর সম্পর্কে একটি নোট

আমরা দেখতে পাচ্ছি যে একটি কিউবিটের অবস্থা লেখার জন্য দুটি জটিল সংখ্যার ট্র্যাক রাখা প্রয়োজন, কিন্তু একটি বাস্তব কোয়ান্টাম কম্পিউটার ব্যবহার করার সময় আমরা প্রতিটি কিউবিটের জন্য শুধুমাত্র একটি হ্যাঁ-বা-না ( 0 বা 1 ) উত্তর পাব। একটি 10-কুবিট কোয়ান্টাম কম্পিউটারের আউটপুট এইরকম দেখাবে:

0110111110

মাত্র 10 বিট, কোন সুপারপজিশন বা জটিল প্রশস্ততা নেই। একটি বাস্তব কোয়ান্টাম কম্পিউটার ব্যবহার করার সময়, আমরা আমাদের কিউবিটগুলির মধ্য গণনার অবস্থা দেখতে পারি না, কারণ এটি তাদের ধ্বংস করবে! এই আচরণটি শেখার জন্য আদর্শ নয়, তাই কিস্কিট বিভিন্ন কোয়ান্টাম সিমুলেটর সরবরাহ করে: ডিফল্টরূপে, aer_simulator একটি বাস্তব কোয়ান্টাম কম্পিউটারের সঞ্চালনের অনুকরণ করে, তবে যদি আমরা আমাদের সার্কিটে নির্দিষ্ট নির্দেশাবলী অন্তর্ভুক্ত করি তবে পরিমাপের আগে আপনাকে কোয়ান্টাম অবস্থার দিকে উঁকি দেওয়ার অনুমতি দেবে। উদাহরণস্বরূপ, এখানে আমরা .save_statevector() নির্দেশনা অন্তর্ভুক্ত করেছি, যার অর্থ আমরা সিমুলেশনের ফলাফলে .get_statevector() ব্যবহার করতে পারি।

3. ব্লচ গোলক

3.1 সীমাবদ্ধ কুবিট রাজ্যের বর্ণনা

আমরা এই অধ্যায়ে আগে দেখেছি যে একটি কিউবিটের সাধারণ অবস্থা (q|q\rangle) হল:

q=α0+β1|q\rangle = \alpha|0\rangle + \beta|1\rangleα,βC\alpha, \beta \in \mathbb{C}

(দ্বিতীয় লাইন আমাদের বলে যে α\alpha এবং β\beta হল জটিল সংখ্যা)। বিভাগ 2-এর প্রথম দুটি প্রভাব আমাদের বলে যে আমরা এই রাজ্যগুলির মধ্যে কিছু পার্থক্য করতে পারি না। এর মানে আমরা আমাদের কিউবিটের বর্ণনায় আরও সুনির্দিষ্ট হতে পারি।

প্রথমত, যেহেতু আমরা গ্লোবাল ফেজ পরিমাপ করতে পারি না, তাই আমরা শুধুমাত্র স্টেট 0|0\rangle এবং 1|1\rangle এর মধ্যে ফেজের পার্থক্য পরিমাপ করতে পারি। α\alpha এবং β\beta জটিল হওয়ার পরিবর্তে, আমরা তাদের প্রকৃত সংখ্যার মধ্যে সীমাবদ্ধ করতে পারি এবং তাদের মধ্যে আপেক্ষিক পর্যায় বলতে একটি শব্দ যোগ করতে পারি:

q=α0+eiϕβ1|q\rangle = \alpha|0\rangle + e^{i\phi}\beta|1\rangleα,β,ϕR\alpha, \beta, \phi \in \mathbb{R}

অবশেষে, যেহেতু qubit অবস্থা স্বাভাবিক করা আবশ্যক, অর্থাৎ

α2+β2=1\sqrt{\alpha^2 + \beta^2} = 1

আমরা ত্রিকোণমিতিক পরিচয় ব্যবহার করতে পারি:

sin2x+cos2x=1\sqrt{\sin^2{x} + \cos^2{x}} = 1

প্রকৃত α\alpha এবং β\beta একটি ভেরিয়েবলের পরিপ্রেক্ষিতে বর্ণনা করতে, θ\theta:

α=cosθ2,β=sinθ2\alpha = \cos{\tfrac{\theta}{2}}, \quad \beta=\sin{\tfrac{\theta}{2}}

এটি থেকে আমরা ϕ\phi এবং θ\theta দুটি ভেরিয়েবল ব্যবহার করে যেকোনো কিউবিটের অবস্থা বর্ণনা করতে পারি:

q=cosθ20+eiϕsinθ21|q\rangle = \cos{\tfrac{\theta}{2}}|0\rangle + e^{i\phi}\sin{\tfrac{\theta}{2}}|1\rangleθ,ϕR\theta, \phi \in \mathbb{R}

3.2 একটি Qubit স্টেট দৃশ্যত প্রতিনিধিত্ব করা

আমরা আমাদের সাধারণ Qubit অবস্থা প্লট করতে চাই:

q=cosθ20+eiϕsinθ21|q\rangle = \cos{\tfrac{\theta}{2}}|0\rangle + e^{i\phi}\sin{\tfrac{\theta}{2}}|1\rangle

যদি আমরা θ\theta এবং ϕ\phi কে গোলাকার কো-অর্ডিনেট হিসাবে ব্যাখ্যা করি (r=1r = 1, যেহেতু qubit অবস্থার মাত্রা হল 11), আমরা একটি গোলকের পৃষ্ঠে যেকোনো একক qubit অবস্থাকে প্লট করতে পারি, ব্লোচ গোলক নামে পরিচিত।

নীচে আমরা +|{+}\rangle স্টেটে একটি কিউবিট প্লট করেছি। এই ক্ষেত্রে, θ=π/2\theta = \pi/2 এবং ϕ=0\phi = 0

(কিস্কিট-এ একটি ব্লচ গোলক প্লট করার জন্য একটি ফাংশন রয়েছে, plot_bloch_vector() , কিন্তু লেখার সময় এটি শুধুমাত্র কার্টেসিয়ান স্থানাঙ্ক নেয়। আমরা একটি ফাংশন অন্তর্ভুক্ত করেছি যা স্বয়ংক্রিয়ভাবে রূপান্তর করে)।

আপনি এই ইন্টারেক্টিভ Bloch গোলক ডেমোও চেষ্টা করে দেখতে পারেন।

from qiskit_textbook.widgets import plot_bloch_vector_spherical coords = [pi/2,0,1] # [Theta, Phi, Radius] plot_bloch_vector_spherical(coords) # Bloch Vector with spherical coordinates
Image in a Jupyter notebook

সতর্কতা !

কিউবিট স্টেটস সম্বন্ধে প্রথম শেখার সময়, কিউবিট স্টেটভেক্টরকে এর ব্লচ ভেক্টরের সাথে বিভ্রান্ত করা সহজ। মনে রাখবেন স্টেটভেক্টর হল 1.1 এ আলোচিত ভেক্টর, যা আমাদের কিউবিট যে দুটি অবস্থায় থাকতে পারে তার প্রশস্ততা ধারণ করে। ব্লচ ভেক্টর হল একটি ভিজ্যুয়ালাইজেশন টুল যা 2D, জটিল স্টেটভেক্টরকে বাস্তব, 3D স্পেসে ম্যাপ করে।

দ্রুত অনুশীলন

রাজ্যে একটি কিউবিট প্লট করতে plot_bloch_vector plot_bloch_vector() বা plot_bloch_sphere_spherical() ব্যবহার করুন:

  1. 0 |0\rangle

  2. 1 |1\rangle

  3. 12(0+1)\tfrac{1}{\sqrt{2}}(|0\rangle + |1\rangle)

  4. 12(0i1)\tfrac{1}{\sqrt{2}}(|0\rangle - i|1\rangle)

  5. ParseError: KaTeX parse error: Undefined control sequence: \1 at position 36: …begin{bmatrix}i\̲1̲\end{bmatrix}

আমরা নীচে একটি উইজেট অন্তর্ভুক্ত করেছি যা plot_bloch_vector() সাথে ব্যবহারের জন্য গোলাকার কো-অর্ডিনেট থেকে কার্টেসিয়ানে রূপান্তরিত হয়:

from qiskit_textbook.widgets import bloch_calc bloch_calc()
import qiskit.tools.jupyter %qiskit_version_table