Advertisement
Roman_Dushkin

Quantum Technologies. Lecture 03 Task

Aug 9th, 2018
126
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Haskell 16.81 KB | None | 0 0
  1. {-# OPTIONS_HADDOCK prune, ignore-exports #-}
  2.  
  3. {------------------------------------------------------------------------------}
  4. {- | Фреймворк для представления примитивов для реализации квантовых алгоритмов.
  5.  
  6.    Автор:     Душкин Р. В.
  7.    Проект:    Курс «Квантовые технологии» в Телешколе teleschool.me
  8.                                                                               -}
  9. {------------------------------------------------------------------------------}
  10.  
  11. module QuantumFramework
  12. (
  13.   -- * Типы
  14.   QuantumState(..),
  15.   Qubit(..),
  16.   Vector,
  17.   Matrix,
  18.  
  19.   -- * Функции
  20.   -- ** Общие сервисные функции
  21.   groups,
  22.   changeElement,
  23.  
  24.   -- ** Создание квантового состояния
  25.   toPair,
  26.   fromPair,
  27.  
  28.   -- ** Применение функций к квантовому состоянию
  29.   applyQS,
  30.   predicateQS,
  31.   conjugateQS,
  32.  
  33.   -- ** Создание кубита
  34.   toList,
  35.   fromLists,
  36.   toPairList,
  37.   fromPairList,
  38.   toVector,
  39.   fromVector,
  40.  
  41.   -- ** Обработка кубита
  42.   liftQubit,
  43.   entangle,
  44.   conjugateQubit,
  45.   scalarProduct,
  46.   norm,
  47.   normalize,
  48.   measure,
  49.   measureP,
  50.  
  51.   -- ** Обработка гейтов
  52.   apply
  53. --  ylppa,
  54. --  (|>),
  55. --  (>>>)
  56. )
  57. where
  58.  
  59. {-[ СЕКЦИЯ ИМПОРТА ]-----------------------------------------------------------}
  60.  
  61. import Control.Arrow ((&&&))
  62. import Control.Monad (replicateM)
  63. import Data.Complex
  64. import Data.Function (on)
  65. import Data.List (inits, sortBy, transpose)
  66. import Data.Maybe (fromMaybe)
  67. import Data.Ord (comparing)
  68. import Data.Tuple (swap)
  69. import System.Random (Random, randomRIO)
  70.  
  71. {-[ СИНОНИМЫ ТИПОВ ]-----------------------------------------------------------}
  72.  
  73. -- | Вектор как наименование для списка.
  74. type Vector a = [a]
  75.  
  76. -- | Матрица как наименование для списка списков.
  77. type Matrix a = [Vector a]
  78.  
  79. {-[ АЛГЕБРАИЧЕСКИЕ ТИПЫ ДАННЫХ ]-----------------------------------------------}
  80.  
  81. -- | Тип, представляющий одно квантовое состояние.
  82. data QuantumState a = QS
  83.                       {
  84.                         amplitude :: Complex a,  -- ^ Амплитуда квантового состояния.
  85.                         label     :: String      -- ^ Метка квантового состояния.
  86.                       }
  87.  
  88. {-[ ИЗОМОРФНЫЕ ТИПЫ ]----------------------------------------------------------}
  89.  
  90. -- | Тип, представляющий кубит. Это просто список квантовых состояний.
  91. newtype Qubit a = Qubit [QuantumState a]
  92.  
  93. {-[ ЭКЗЕМПЛЯРЫ КЛАССОВ ]-------------------------------------------------------}
  94.  
  95. instance (Eq a, Ord a, Num a, RealFloat a, Show a) => Show (QuantumState a) where
  96.   show (QS a l) = brackets ++ "|" ++ l ++ ">"
  97.     where
  98.       brackets = if realPart a /= 0 && imagPart a /= 0
  99.                    then "(" ++ prettyShowComplex a ++ ")"
  100.                    else prettyShowComplex a
  101.  
  102. instance (RealFloat a, Show a) => Show (Qubit a) where
  103.   show (Qubit       []) = ""
  104.   show (Qubit     [qs]) = show qs
  105.   show (Qubit (qs:qss)) = show qs ++ " + " ++ show (Qubit qss)
  106.  
  107. {-[ ОПРЕДЕЛЕНИЕ ПРИОРИТЕТА ]---------------------------------------------------}
  108.  
  109. -- infixl 6 |>
  110.  
  111. -- infix 5 >>>
  112.  
  113. {-[ ФУНКЦИИ ]------------------------------------------------------------------}
  114.  
  115. -- | Сервисная функция для разбиения заданного списка на подсписки заданной
  116. --   длины.
  117. groups :: Int -> [a] -> [[a]]
  118. groups i s | null s = []
  119.            | otherwise  = let (h, t) = splitAt i s
  120.                           in   h : groups i t
  121.  
  122. -- | Служебная функция для замены элемента в заданном списке на заданной позиции
  123. --   (счёт начинается с 1) на заданное значение.
  124. changeElement :: [a] -> Int -> a -> [a]
  125. changeElement xs i x = take (i - 1) xs ++
  126.                        [x] ++
  127.                        drop i xs
  128.  
  129. -- | Служебная функция для преобразования комплексного числа в «приятную»
  130. --   строку.
  131. prettyShowComplex :: (Eq a, Ord a, Num a, RealFrac a, Show a) => Complex a -> String
  132. prettyShowComplex (r :+ 0) = prettyShowNumber r
  133. prettyShowComplex (0 :+ i) | i == 1    = "i"
  134.                            | i == -1   = "-i"
  135.                            | otherwise = prettyShowNumber i ++ "i"
  136. prettyShowComplex (r :+ i) | i == 1    = prettyShowNumber r ++ " + i"
  137.                            | i == -1   = prettyShowNumber r ++ " - i"
  138.                            | i >= 0    = prettyShowNumber r ++ " + " ++ prettyShowNumber i ++ "i"
  139.                            | otherwise = prettyShowNumber r ++ " - " ++ prettyShowNumber (abs i) ++ "i"
  140.  
  141. -- | Служебная функция, которая преобразует в строку числа (целые и
  142. --   действительные) так, что если у числа нет дробной части, то в строку не
  143. --   выносится никакой дробной части: 2.5 -> "2.5", 2.0 -> "2".
  144. prettyShowNumber :: (RealFrac a, Show a) => a -> String
  145. prettyShowNumber f = if d == 0.0
  146.                        then show n
  147.                        else show f
  148.   where
  149.     (n, d) = properFraction f
  150.  
  151. -- | Функция для преобразования квантового состояния в пару величин.
  152. toPair :: QuantumState a -> (Complex a, String)
  153. toPair (QS a l) = (a, l)
  154.  
  155. -- | Функция для создания квантового состояния из пары вида (Амплитуда, Метка).
  156. fromPair :: (Complex a, String) -> QuantumState a
  157. fromPair (a, l) = QS a l
  158.  
  159. -- | Функция высшего порядка для применения заданной функции к амплитуде
  160. --   заданного квантового состояния.
  161. applyQS :: (Complex a -> Complex a) -> QuantumState a -> QuantumState a
  162. applyQS f (QS a l) = QS (f a) l
  163.  
  164. -- | Ещё одна функция высшего порядка для применения заданного предиката к
  165. --   амплитуде заданного квантового состояния.
  166. predicateQS :: (Complex a -> Bool) -> QuantumState a -> Bool
  167. predicateQS p (QS a _) = p a
  168.  
  169. -- | Специализированная функция, которая возвращает комплексно-сопряжённое
  170. --   квантовое состояние для заданного. Является обёрткой над функцией
  171. --   \conjugate\ из модуля \Data.Complex\ и предназначена для упрощения работы с
  172. --   квантовыми состояниями.
  173. conjugateQS :: RealFloat a => QuantumState a -> QuantumState a
  174. conjugateQS = applyQS conjugate
  175.  
  176. -- | Служебная функция для получения из кубита списка его квантовых состояний
  177. --   (разворачиватель). Хотя, конечно, это можно было сделать при помощи
  178. --   именованного поля.
  179. quantumStates :: Qubit a -> [QuantumState a]
  180. quantumStates (Qubit qs) = qs
  181.  
  182. -- | Функция для преобразования кубита в вектор (список). На выходе получается
  183. --   просто список амплитуд.
  184. toList :: Qubit a -> [Complex a]
  185. toList = map amplitude . quantumStates
  186.  
  187. -- | Функция для преобразования кубита в список меток его квантовых состояний.
  188. toLabelList :: Qubit a -> [String]
  189. toLabelList = map label . quantumStates
  190.  
  191. -- | Функция для создания кубита из двух списков — списка комплексных амплитуд и
  192. --   списка меток. Разработчик сам должен следить за тем, что семантика кубита
  193. --   должна выполняться (например, при полном задействовании всех базисных
  194. --   состояний их количество должно составлять степень двойки).
  195. fromLists :: [Complex a] -> [String] -> Qubit a
  196. fromLists a l = Qubit $ zipWith QS a l
  197.  
  198. -- | Функция для преобразования кубит в список пар.
  199. toPairList :: Qubit a -> [(Complex a, String)]
  200. toPairList = map toPair . quantumStates
  201.  
  202. -- | Функция для создания кубита из списка пар — пар комплексных амплитуд и
  203. --   меток. Разработчик сам должен следить за тем, что семантика кубита должна
  204. --   выполняться (например, при полном задействовании всех базисных состояний их
  205. --   количество должно составлять степень двойки).
  206. fromPairList :: [(Complex a, String)] -> Qubit a
  207. fromPairList = Qubit . map fromPair
  208.  
  209. -- | Функция для преобразования кубита к векторному представлению в стандартном
  210. --   базисе.
  211. toVector :: Num a => Qubit a -> [Complex a]
  212. toVector q = if all (`elem` "01") labels
  213.                then map (fromMaybe (0 :+ 0) . flip lookup qsPairs) basis
  214.                else error "Некорректные метки кубита."
  215.   where
  216.     n       = length $ label $ head $ quantumStates q
  217.     labels  = concatMap label $ quantumStates q
  218.     qsPairs = map (swap . toPair) $ sortBy (comparing label) $ quantumStates q
  219.     basis   = replicateM n "01"
  220.  
  221. -- | Функция для создания кубита из векторного представления в стандартном
  222. --   базисе.
  223. fromVector :: Int -> [Complex a] -> Qubit a
  224. fromVector n q = fromLists q $ replicateM n "01"
  225.  
  226. -- | Сервисная функция для «втягивания» заданной функции в кубит и применения её
  227. --   к списку квантовых состояний.
  228. liftQubit :: ([QuantumState a] -> [QuantumState b]) -> Qubit a -> Qubit b
  229. liftQubit f (Qubit qs) = Qubit $ f qs
  230.  
  231. -- | Функция для связывания двух кубитов в одну систему из нескольких кубитов.
  232. --   По сути, производит тензорное умножение кубитов друг на друга.
  233. entangle :: RealFloat a => Qubit a -> Qubit a -> Qubit a
  234. entangle (Qubit qss1) (Qubit qss2)
  235.   = Qubit $ filter (predicateQS (/= 0)) [QS (((*)  `on` amplitude) qs1 qs2)
  236.                                             (((++) `on` label) qs1 qs2) | qs1 <- qss1,
  237.                                                                           qs2 <- qss2]
  238.  
  239. -- | Функция для получения комплексно-сопряжённого кубита для заданного.
  240. conjugateQubit :: RealFloat a => Qubit a -> Qubit a
  241. conjugateQubit = liftQubit (map conjugateQS)
  242.  
  243. -- | Функция для вычисления скалярного (внутреннего) произведения двух заданных
  244. --   кубитов.
  245. scalarProduct :: RealFloat a => Qubit a -> Qubit a -> a
  246. scalarProduct q1 q2 = realPart $
  247.                         sum $
  248.                         ((zipWith (*)) `on` toVector) q1 q2
  249.  
  250. -- | Функция для получения нормы вектора, представляющего собой кубит (то есть
  251. --   его длину).
  252. norm :: RealFloat a => Qubit a -> a
  253. norm q = sqrt $ scalarProduct q (conjugateQubit q)
  254.  
  255. -- | Функция для нормализации заданного кубита, то есть для получения из кубита
  256. --   нового, норма (длина) которого равна в точности 1. Это значит, что у
  257. --   результирующего кубита сумма квадратов модулей амплитуд равна 1, и
  258. --   выполняется условие нормированности.
  259. normalize :: RealFloat a => Qubit a -> Qubit a
  260. normalize q = liftQubit (map (applyQS (/ (norm q :+ 0)))) q
  261.  
  262. -- | Функция для осуществления процесса измерения заданного кубита. В
  263. --   зависимости от распределения амплитуд вероятности выбирает одно из
  264. --   квантовых состояний кубита и возвращает его метку.
  265. measure :: (RealFloat a, Random a) => Qubit a -> IO String
  266. measure q = getRandomElementWithProbabilities $
  267.               sortBy (compare `on` snd) $
  268.               map ((swap . \(a, l) -> (realPart (a * conjugate a), l)) . toPair) $
  269.               quantumStates q
  270.  
  271. -- | Функция для осуществления процесса частичного измерения заданного кубита. В
  272. --   зависимости от распределения амплитуд вероятности выбирает одно из
  273. --   частичных квантовых состояний, определяемых набором индексов (второй
  274. --   аргумент). Возвращает пару (измеренная метка, оставшиеся квантовые
  275. --   состояния)
  276. measureP :: (RealFloat a, Random a) => Qubit a -> [Int] -> IO (String, Qubit a)
  277. measureP q xs = undefined
  278.  
  279. -- | Служебная функция для получения случайного элемента из заданного списка с
  280. --   учётом распределения вероятностей. Список должен содержать пары, первым
  281. --   элементом которых являются возвращаемые элементы, а вторым — вероятность.
  282. --   Значения вероятности не обязательно должны быть нормированы.
  283. getRandomElementWithProbabilities :: (Ord b, Num b, Random b) => [(a, b)] -> IO a
  284. getRandomElementWithProbabilities l = (head . goodList) `fmap` randomRIO (0, sumProbs l)
  285.   where
  286.     goodList p = map fst $
  287.                    dropWhile (\(_, p') -> p' < p) $
  288.                    map ((fst . last) &&& sumProbs) $
  289.                    tail $
  290.                    inits l
  291.     sumProbs = sum . map snd
  292.  
  293. -- | Функция, вычисляющая произведение матрицы на вектор. В итоге получается
  294. --   вектор. Разработчик должен сам следить за корректностью размерностей
  295. --   матрицы и вектора, подаваемых на вход этой фунции.
  296. apply :: Num a => Matrix a -> Vector a -> Vector a
  297. apply m v = map (sum . zipWith (*) v) m
  298.  
  299. {-[ ЗАДАЧА ]-------------------------------------------------------------------}
  300. {- *****************************************************************************
  301.  
  302.    Вашей задачей является реализация операторов |> и >>>. Первый применяется для
  303. отправки кубита в гейт, а второй — для отправки кубита в операцию измерения.
  304.  
  305.    Если что-то не будет получаться, можете подсмотреть внизу, как это  сделано у
  306. меня. Дерзайте.
  307.  
  308. ***************************************************************************** -}
  309.  
  310. {-
  311.  
  312. -- | Специальный синоним для функции `apply` из модуля `Gate`, которая меняет
  313. --   порядок аргументов. Эта функция предназначена для прямой записи
  314. --   последовательности применения гейтов к кубитам.
  315. ylppa :: Num a => Vector a -> Matrix a -> Vector a
  316. ylppa = flip apply
  317.  
  318. -- | Синоним для неудобочитаемой функции `ylppa`.
  319. (|>) :: Num a => Vector a -> Matrix a -> Vector a
  320. (|>) = ylppa
  321.  
  322. -- | Синоним оператора (\$\) для передачи потока управления в функцию измерения.
  323. (>>>) :: a -> (a -> b) -> b
  324. (>>>) = flip ($)
  325.  
  326. -}
  327.  
  328. {-[ КОНЕЦ МОДУЛЯ ]-------------------------------------------------------------}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement