Coder Social home page Coder Social logo

dakk / qlasskit Goto Github PK

View Code? Open in Web Editor NEW
55.0 3.0 10.0 8.04 MB

A python-to-quantum compiler

Home Page: https://dakk.github.io/qlasskit/

License: Apache License 2.0

Python 100.00%
quantum quantum-algorithms quantum-computing quantum-programming-language quantum-annealing

qlasskit's Introduction

Qlasskit

Logo

Unitary Fund CI Status PyPI - Version License: Apache 2.0 Discord Codacy Badge Downloads

Qlasskit is a Python library that allows quantum developers to write classical algorithms in pure Python and translate them into unitary operators (gates) for use in quantum circuits, using boolean expressions as intermediate form.

This tool will be useful for any algorithm that relies on a 'blackbox' function and for describing the classical components of a quantum algorithm.

Qlasskit implements circuit / gate exporters for Qiskit, Cirq, Qasm, Sympy and Pennylane.

Qlasskit also support exporting to Binary Quadratic Models (bqm, ising and qubo) ready to be used in quantum annealers, ising machines, simulators, etc.

Transformations

pip install qlasskit

For a quickstart, read the quickstart and examples notebooks from the documentation: https://dakk.github.io/qlasskit.

from qlasskit import qlassf, Qint 

@qlassf
def h(k: Qint[4]) -> bool:
    h = True
    for i in range(4):
        h = h and k[i]
    return h

Qlasskit will take care of translating the function to boolean expressions, simplify them and translate to a quantum circuit.

Grover

Then, we can use grover to find which h(k) returns True:

from qlasskit.algorithms import Grover

algo = Grover(h, True)
qc = algo.circuit().export("circuit", "qiskit")

And that's the result:

Grover

Qlasskit also offers type abstraction for encoding inputs and decoding results:

counts_readable = algo.decode_counts(counts)
plot_histogram(counts_readable)

Decoded counts

You can also use other functions inside a qlassf:

@qlassf
def equal_8(n: Qint[4]) -> bool:
  return equal_8 == 8

@qlassfa(defs=[equal_8])
def f(n: Qint[4]) -> bool:
  n = n+1 if equal_8(n) else n
  return n

Qlasskit supports complex data types, like tuples and fixed size lists:

@qlassf
def f(a: Tuple[Qint[8], Qint[8]]) -> Tuple[bool, bool]:
  return a[0] == 42, a[1] == 0
@qlassf
def search(alist: Qlist[Qint[2], 4], to_search: Qint[2]):
  for x in alist:
    if x == to_search:
      return True
  return False

Qlasskit function can be parameterized, and the parameter can be bind before compilation:

@qlassf
def test(a: Parameter[bool], b: bool) -> bool:
    return a and b

qf = test.bind(a=True)

Contributing

Read CONTRIBUTING for details.

License

This software is licensed with Apache License 2.0.

Cite

@software{qlasskit2023,
  author = {Davide Gessa},
  title = {qlasskit: a python-to-quantum circuit compiler},
  url = {https://github.com/dakk/qlasskit},
  year = {2023},
}

About the author

Davide Gessa (dakk)

qlasskit's People

Contributors

dakk avatar divshacker avatar tomv42 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

qlasskit's Issues

Fix Qmatrix/TupleOfTuple var access error

This raises Not a tuple in ast2ast visit subscript with not constant _sval: Subscript (value=Name(id='a', ctx=Load()), slice=Name(id='i', ctx=Load()), ctx=Load())

@qlassf
def test(a: Qmatrix[Qint[2], 2, 2]) -> Qint[2]:
   i = 1
   j = i + 1
   return a[i][i]

Parameter on python file does not work

It works only on notebooks.

from qlasskit import Parameter, qlassf

@qlassf
def test(c: Parameter[bool], a: bool) -> bool: 
        return a and c

test.bind(c=True)

Raises

Traceback (most recent call last):
  File "/home/dakk/Repositories/MyRepos/qlasskit/t.py", line 7, in <module>
    test.bind(c=True)
  File "/home/dakk/Repositories/MyRepos/qlasskit/qlasskit/qlassfun.py", line 96, in bind
    exec(c)
  File "<string>", line 2, in <module>
  File "/home/dakk/Repositories/MyRepos/qlasskit/qlasskit/qlassfun.py", line 344, in qlassf
    return QlassF.from_function(
  File "/home/dakk/Repositories/MyRepos/qlasskit/qlasskit/qlassfun.py", line 282, in from_function
    fun_ast = ast.parse(f if isinstance(f, str) else inspect.getsource(f))
  File "/home/dakk/.pyenv/versions/3.10.13/lib/python3.10/inspect.py", line 1139, in getsource
    lines, lnum = getsourcelines(object)
  File "/home/dakk/.pyenv/versions/3.10.13/lib/python3.10/inspect.py", line 1121, in getsourcelines
    lines, lnum = findsource(object)
  File "/home/dakk/.pyenv/versions/3.10.13/lib/python3.10/inspect.py", line 958, in findsource
    raise OSError('could not get source code')
OSError: could not get source code

Single statement compilation mode

Add a compilation method that allows to compile in single statement mode.

We first need to investigate if this could be useful (maybe for big circuits).

Shift and Add multiplication for constants

When we have bin operations with a constant operator, it is sometime possible to do some optimization.

For instance if we want to multiply and diving two numbers, and one operand is a constant, we can achieve it using shift and add multiplication algorithm (https://youtu.be/acUH4lWe2NQ?si=H7GAS241CZuyBe3C&t=880)

We need to refactor the type abastraction in order to have mul (a times b) and mul_c (a times Const), etc; or we can extend mul() to handle different case; or we can call simplify logic directly in operations.

We need a Qtype.is_const #37 to check if a Qtype is constant (only contains False/True).

Qfixed type

Add support for Qfixed, a binary representation for rational numbers, with a fixed point.

Supported operations:

  • add
  • sub
  • eq
  • neq
  • gt
  • lt
  • gte
  • lte
  • Mul by const

Other:

  • Testing
  • Documentation
  • Find a good example for a python notebook

py2qasm cli tool

Create a cli tool in the qlasskit/tools package called py2qasm that receives a python script (file or stdin) in input and outputs qasm code. The python script should contain at least one qlassf function.

  • If not specified by --input-file/-i, read from stdin (-).
  • If not specified by --entrypoint/-e, func_name is the last qlassf defined.
  • If not specified by --output/-o, output to stdout
  • If not specified by --compiler/-c use internal compiler (or tweedledum)
  • If not specified by --qasm-version/-q use v3 qasm version

py2qasm -i pyfile [-e func_name] [-c internal] -o qasm_file

Provide also:

  • -h\--help for usage
  • -v\--version for qlasskit version

Requirements:

Please read CONTRIBUTING.md before contributing.

py2fpga tool

Create a tool able to translate python functions to FPGA synthesis file.

Assertion on List of Tuple of Tuple access

@qlassf
def oracle(io_list: Parameter[List[Tuple[Tuple[bool, bool], bool]]], f: bool) -> bool:
    v = True
    for io in io_list:
        v = v and (io[0][0] and io[0][1]) == io[1]
        
    return v

ttable = [(False, False), (True, False), (False, True), (True, True)]
tt = list(map(lambda e: (e, e[0] or e[1]), ttable))
oracle.bind(io_list=ttable)

Raises:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[74], [line 1](vscode-notebook-cell:?execution_count=74&line=1)
----> [1](vscode-notebook-cell:?execution_count=74&line=1) q_algo = Grover(oracle.bind(io_list=ttable))

File [~/.pyenv/versions/3.10.13/envs/qlasskit_310-env/lib/python3.10/site-packages/qlasskit-0.1.20-py3.10.egg/qlasskit/qlassfun.py:110](https://file+.vscode-resource.vscode-cdn.net/home/dakk/~/.pyenv/versions/3.10.13/envs/qlasskit_310-env/lib/python3.10/site-packages/qlasskit-0.1.20-py3.10.egg/qlasskit/qlassfun.py:110), in UnboundQlassf.bind(self, **kwargs)
    [106](https://file+.vscode-resource.vscode-cdn.net/home/dakk/~/.pyenv/versions/3.10.13/envs/qlasskit_310-env/lib/python3.10/site-packages/qlasskit-0.1.20-py3.10.egg/qlasskit/qlassfun.py:106)         raise Exception("original_f is not available in python notebooks!")
    [108](https://file+.vscode-resource.vscode-cdn.net/home/dakk/~/.pyenv/versions/3.10.13/envs/qlasskit_310-env/lib/python3.10/site-packages/qlasskit-0.1.20-py3.10.egg/qlasskit/qlassfun.py:108)     original_f = orig
--> [110](https://file+.vscode-resource.vscode-cdn.net/home/dakk/~/.pyenv/versions/3.10.13/envs/qlasskit_310-env/lib/python3.10/site-packages/qlasskit-0.1.20-py3.10.egg/qlasskit/qlassfun.py:110) return self._do_translate(fun_ast, original_f)

File [~/.pyenv/versions/3.10.13/envs/qlasskit_310-env/lib/python3.10/site-packages/qlasskit-0.1.20-py3.10.egg/qlasskit/qlassfun.py:295](https://file+.vscode-resource.vscode-cdn.net/home/dakk/~/.pyenv/versions/3.10.13/envs/qlasskit_310-env/lib/python3.10/site-packages/qlasskit-0.1.20-py3.10.egg/qlasskit/qlassfun.py:295), in QlassF.from_function.<locals>._do_translate(fun_ast, original_f)
    [293](https://file+.vscode-resource.vscode-cdn.net/home/dakk/~/.pyenv/versions/3.10.13/envs/qlasskit_310-env/lib/python3.10/site-packages/qlasskit-0.1.20-py3.10.egg/qlasskit/qlassfun.py:293) def _do_translate(fun_ast, original_f):
    [294](https://file+.vscode-resource.vscode-cdn.net/home/dakk/~/.pyenv/versions/3.10.13/envs/qlasskit_310-env/lib/python3.10/site-packages/qlasskit-0.1.20-py3.10.egg/qlasskit/qlassfun.py:294)     fun = ast2ast(fun_ast.body[0])
--> [295](https://file+.vscode-resource.vscode-cdn.net/home/dakk/~/.pyenv/versions/3.10.13/envs/qlasskit_310-env/lib/python3.10/site-packages/qlasskit-0.1.20-py3.10.egg/qlasskit/qlassfun.py:295)     fun_name, args, fun_ret, exps = translate_ast(fun, types, defs)
    [297](https://file+.vscode-resource.vscode-cdn.net/home/dakk/~/.pyenv/versions/3.10.13/envs/qlasskit_310-env/lib/python3.10/site-packages/qlasskit-0.1.20-py3.10.egg/qlasskit/qlassfun.py:297)     exps = bool_optimizer.apply(exps)
    [299](https://file+.vscode-resource.vscode-cdn.net/home/dakk/~/.pyenv/versions/3.10.13/envs/qlasskit_310-env/lib/python3.10/site-packages/qlasskit-0.1.20-py3.10.egg/qlasskit/qlassfun.py:299)     # Return the qlassf object

File [~/.pyenv/versions/3.10.13/envs/qlasskit_310-env/lib/python3.10/site-packages/qlasskit-0.1.20-py3.10.egg/qlasskit/ast2logic/t_ast.py:49](https://file+.vscode-resource.vscode-cdn.net/home/dakk/~/.pyenv/versions/3.10.13/envs/qlasskit_310-env/lib/python3.10/site-packages/qlasskit-0.1.20-py3.10.egg/qlasskit/ast2logic/t_ast.py:49), in translate_ast(fun, types, defs)
     [47](https://file+.vscode-resource.vscode-cdn.net/home/dakk/~/.pyenv/versions/3.10.13/envs/qlasskit_310-env/lib/python3.10/site-packages/qlasskit-0.1.20-py3.10.egg/qlasskit/ast2logic/t_ast.py:47) exps = []
     [48](https://file+.vscode-resource.vscode-cdn.net/home/dakk/~/.pyenv/versions/3.10.13/envs/qlasskit_310-env/lib/python3.10/site-packages/qlasskit-0.1.20-py3.10.egg/qlasskit/ast2logic/t_ast.py:48) for stmt in fun.body:
---> [49](https://file+.vscode-resource.vscode-cdn.net/home/dakk/~/.pyenv/versions/3.10.13/envs/qlasskit_310-env/lib/python3.10/site-packages/qlasskit-0.1.20-py3.10.egg/qlasskit/ast2logic/t_ast.py:49)     s_exps, env = translate_statement(stmt, env, ret_.ttype)
     [50](https://file+.vscode-resource.vscode-cdn.net/home/dakk/~/.pyenv/versions/3.10.13/envs/qlasskit_310-env/lib/python3.10/site-packages/qlasskit-0.1.20-py3.10.egg/qlasskit/ast2logic/t_ast.py:50)     exps.append(s_exps)
     [52](https://file+.vscode-resource.vscode-cdn.net/home/dakk/~/.pyenv/versions/3.10.13/envs/qlasskit_310-env/lib/python3.10/site-packages/qlasskit-0.1.20-py3.10.egg/qlasskit/ast2logic/t_ast.py:52) exps_flat = flatten(exps)

File [~/.pyenv/versions/3.10.13/envs/qlasskit_310-env/lib/python3.10/site-packages/qlasskit-0.1.20-py3.10.egg/qlasskit/ast2logic/t_statement.py:58](https://file+.vscode-resource.vscode-cdn.net/home/dakk/~/.pyenv/versions/3.10.13/envs/qlasskit_310-env/lib/python3.10/site-packages/qlasskit-0.1.20-py3.10.egg/qlasskit/ast2logic/t_statement.py:58), in translate_statement(stmt, env, ret_type)
...
---> [73](https://file+.vscode-resource.vscode-cdn.net/home/dakk/~/.pyenv/versions/3.10.13/envs/qlasskit_310-env/lib/python3.10/site-packages/qlasskit-0.1.20-py3.10.egg/qlasskit/ast2logic/t_expression.py:73) if sn.split(".")[0] not in env:
     [74](https://file+.vscode-resource.vscode-cdn.net/home/dakk/~/.pyenv/versions/3.10.13/envs/qlasskit_310-env/lib/python3.10/site-packages/qlasskit-0.1.20-py3.10.egg/qlasskit/ast2logic/t_expression.py:74)     raise exceptions.UnboundException(sn, env)
     [76](https://file+.vscode-resource.vscode-cdn.net/home/dakk/~/.pyenv/versions/3.10.13/envs/qlasskit_310-env/lib/python3.10/site-packages/qlasskit-0.1.20-py3.10.egg/qlasskit/ast2logic/t_expression.py:76) # Get the inner type

AttributeError: 'NoneType' object has no attribute 'split'

Missing python ast

This is a placeholder issue for keeping track of missing python support; if we choose to implement one of these, open a separate issue.

Builtin functions

  • map

Language support

  • While loop
  • Recursion

Types

  • Lambda
  • Class support
  • Dict
  • Enum

py2bexp bool expressions exporter

Create a cli tool in the qlasskit/tools package called py2bexp that receives a python script (file or stdin) in input and outputs bool expressions. The python script should contain at least one qlassf function.

  • If not specified by --input-file/-i, read from stdin (-).
  • If not specified by --entrypoint/-e, func_name is the last qlassf defined.
  • If not specified by --output/-o, output to stdout
  • Add a parameter [-f/--form] for specifying the expression form (support all sympy: anf, cnf, dnf, nnf
  • Add a parameter [-t/--format] for specifying the output format (default is sympy to_string, supports also dimacs format for cnf https://jix.github.io/varisat/manual/0.2.0/formats/dimacs.html)

py2bexp -i pyfile [-e func_name] -o file

Provide also:

  • -h\--help for usage
  • -v\--version for qlasskit version

Requirements:- Code should be placed on qlasskit/tools

Please read CONTRIBUTING.md before contributing.

QSignedInt

Maybe is better to have Qint to be signed, and QUint to be unsigned?

Exporter for Binary Quadratic Models

Thanks to the fact that qlasskit uses boolean expression as intermediate representation, we can easily write an exporter able to translate a qlassf to a binary quadratic model, exporting a QUBO or an Ising model.

This integration will enable qlasskit to be used on quantum annealers like the DWave, or similar types of machine (like the Fujitsu Digital Annealer).

We can use the pyqubo library for this process, as an optional dependency.

Fix decopt random test

TestCircuitBooleanOptimizer.test_circuit_boolean_optimizer_random_x_cx randomly fails. Remove the "randomness" and use fixed test cases.

____ TestCircuitBooleanOptimizer.test_circuit_boolean_optimizer_random_x_cx ____

self = <test.test_decopt.TestCircuitBooleanOptimizer testMethod=test_circuit_boolean_optimizer_random_x_cx>

    def test_circuit_boolean_optimizer_random_x_cx(self):
        g_total = 0
        g_simp = 0
    
        for i in range(12):
            qc = QCircuit.random(3, 8, [gates.X, gates.CX])
            g_total += 8
    
            qc_n = circuit_boolean_optimizer(qc)
            g_simp += qc_n.num_gates
    
            qc_un = qiskit_unitary(qc.export())
    
            qc_n_un = qiskit_unitary(qc_n.export())
>           self.assertEqual(qc_un, qc_n_un)
E           AssertionError: Opera[85 chars]0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j, 0[521 chars], 2)) != Opera[85 chars]0.j, 1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0[521 chars], 2))

Sum and sub example not working

This test case fails both on tweedledum and internalcompiler with the same result:

AssertionError: '10' != '11'

    def test_sum_and_sub(self):
        f = (
            "def test(a: Qint[2]) -> Qint[2]:\n"
            "\treturn (a + 3) - 3"
        )
        qf = qlassf(f, to_compile=True, compiler=self.compiler, uncompute=True)
        # print(qf.expressions)
        # qf.circuit().draw()
        compute_and_compare_results(self, qf)

The test is situated in test_compiler but it's commented.

Parameterizable qlassf

@qlassf
def test(a: Parameter[Qint2], b: Qint2) -> Qint2
    return a + b

will produce an object QlassF (or UnboundQlassF) that has unbound parameter a. You can get a normal Qlassf by running:

test.bind(a=2)

And a will be set as a constant during compilation.

Use case: sudoku checker

@qlassf
def sudoku_check(const_i: Parameter[Tuple[Qint2, Qint2]], m: Qmatrix[bool, 2, 2]) -> bool:
    constr = m[const_i[0]][const_i[1]]
    sub0 = m[0][0] ^ m[0][1]
    sub1 = m[1][0] ^ m[1][1]
    sub2 = m[0][0] ^ m[1][0]
    sub3 = m[0][1] ^ m[1][1]
    return sub0 and sub1 and sub2 and sub3 and constr

Refactor InternalCompiler

At the moment, the compilation process is splitten between the .compile() and the .compile_expr(); would be better to remove .compile_expr, create a method for compiling every type of expr (compile_symbol, compile_not, compile_xor, compile_and).

Request for algorithms!

  • Propose and implement an algorithm in the qlasskit.algorithms package.
  • Create a notebook in docs, showcasing the algorithm
  • The algorithm have to use one or more qlassf functions.
  • The algorithm have to preferably come from a peer-reviewed paper.
  • The proposed algorithm have to be approved by the maintainer.
  • Take a look at the documentation for hints.

The code of the pull request should include:

  • the QAlgorithm implemented in the algorithm module
  • the test suite with a complete coverage
  • one or more notebook in the docs, showing a cool use case

Please read CONTRIBUTING.md before contributing.

Unable to install in edit mode

        File "/home/xxx/Documents/qlasskit/qlasskit/qcircuit/qcircuit.py", line 20, in <module>
          from sympy import Symbol
      ModuleNotFoundError: No module named 'sympy'
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
error: subprocess-exited-with-error

× Getting requirements to build editable did not run successfully.
│ exit code: 1
╰─> See above for output.

note: This error originates from a subprocess, and is likely not a problem with pip.

Duplicate qubit in gate append for fastOptimized qlassf

from qlasskit import Qint8, Qint16, Qlist, boolopt, qlassfa

@qlassfa(bool_optimizer=boolopt.fastOptimizer)
def test(a_list: Qlist[Qint8, 8]) -> Qint16:
    h_val = Qint16(0)
    for c in a_list:
        h_val = h_val + c
    return h_val

Raises:

Exception: duplicate qubit in gate append: [64, 64, 75, 83]

Qint integer division

Implement integer division // (known as floor_div) for Qint type using the following algorithm: Integer_division_(unsigned)_with_remainder

Handle division by constant using the same optimization method used for multiplying with constant implemented in #36

Tasks:

  • Define a floor_div abstract method for Qtype
  • Implement floor_div on Qint
  • Make ast2logic handle ast.FloorDiv
  • Write test cases in test_int.py
  • Implement div by constant optimization (follow what I do in #36)

Please read CONTRIBUTING.md before contributing.

Evaluate constant expressions on compilation step

When qlasskit parses expressions containing constants, the boolean form containing the constant is created and then optimized (if possible). A smarter approach would be to evaluate constant expression during ast2logic parsing.

This could be performed by calling eval if tleft and tright are ast.Constant in a binop. But we also need to evalute op(const).

Test case:

  • a + (13 - 12 + 1) => a + 2
  • a + len([12]) => a + 1
  • if True then b else c => b

Since ast2ast is getting bigger, we can separate it to different rewriters, so we can simplify the file, and have a prioritization of certain optimizations.

Pow operator

Implement the ast.Pow operator (**) between a variable and an integer constant.
Since a ** n == a * a * ... * a, we implement this operator with a rewriting rule in ast2ast.

The rewriting rule should be placed in the class AstRewriter (https://github.com/dakk/qlasskit/blob/master/qlasskit/ast2ast.py#L137), overriding the method visit_Pow, and rewriting the pow as multiplications.

  • Check that n is an ast.Constant, positive integer
  • If overriding visit_Pow won't work, override visit_BinOp instead and check if the expression is a ast.Pow

Please read CONTRIBUTING.md before contributing.

Qtype.is_const

Add a new static method to qtype, returning True if the given TExp is a constant.

Remove type inconsistency

In some places of the code we are using type: ignore for disabling mypy checks. We need to remove all ignores, enforcing type consistency.

$ grep -R "type: ignore" * | wc -l
87

Qint generics

Make Qint generic like Qfixed, so it's possible to use Qint[4] for a 4 bit Qint. This should be backward compatible.

  • Qint becomes QintImp
  • Qint as generic type
  • Update all tests
  • Update all examples
  • Update documentation

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.