Skip to content

Commit

Permalink
refactor project structure for types
Browse files Browse the repository at this point in the history
  • Loading branch information
dakk committed Oct 13, 2023
1 parent bf3c163 commit f1961e4
Show file tree
Hide file tree
Showing 16 changed files with 258 additions and 180 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ This tool will be useful for any algorithm that relies on a 'blackbox' function

```python
@qlassf
def f(n: Int4) -> bool:
def f(n: Qint4) -> bool:
if n == 3:
return True
else:
Expand All @@ -30,7 +30,7 @@ qc.append(f.gate(), f.qubits_list(0))
Or, you can define a function with parameters:
```python
@qlassf
def f(n: Int4, n_it: Param[int]) -> Int8:
def f(n: Qint4, n_it: Param[int]) -> Qint8:
v = 0
for x in range(n_it):
v += n
Expand All @@ -49,13 +49,13 @@ Qlasskit (will) supports complex data types, like tuples and fixed size lists:

```python
@qlassf
def f(a: Tuple[Int8, Int8]) -> Tuple[bool, bool]:
def f(a: Tuple[Qint8, Qint8]) -> Tuple[bool, bool]:
return a[0] == 42, a[1] == 0
```

```python
@qlassf
def search(alist: List4[Int2], to_search: Int2):
def search(alist: List4[Qint2], to_search: Qint2):
for x in alist:
if x == to_search:
return True
Expand Down
5 changes: 3 additions & 2 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,19 @@
- [x] Doc: emphatize the compiler flow
- [x] Doc: properly render documentation
- [x] Builtin debug functions: print()
- [x] Fix code structure and typing location

### Week 4: (16 Oct 23)
- [ ] Publish doc
- [ ] Fix structure and typing location
- [ ] Int arithmetic expressions (+, -, *, /)
- [ ] Int arithmetic: +
- [ ] Function call
- [ ] Builtin functions: sum(), max(), min(), len()

## Month 2:

### Week 1: (23 Oct 23)
- [ ] Inner function
- [ ] Int arithmetic expressions (-, *, /)
- [ ] Parametrized qlassf

### Week 2: (30 Oct 23)
Expand Down
4 changes: 2 additions & 2 deletions examples/ex2.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from qiskit import QuantumCircuit

from qlasskit import Int8, Param, qlassf
from qlasskit import Param, Qint8, qlassf


@qlassf
def f(n: Int4, n_it: Param[int]) -> Int8:
def f(n: Qint4, n_it: Param[int]) -> Qint8:
v = 0
for x in range(n_it):
v += n
Expand Down
11 changes: 10 additions & 1 deletion qlasskit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,13 @@
from .qcircuit import QCircuit # noqa: F401
from .qlassf import QlassF, qlassf # noqa: F401
from .ast2logic import exceptions # noqa: F401
from .ast2logic.typing import * # noqa: F401, F403
from .types import ( # noqa: F401, F403
Qtype,
Qbool,
Qint,
Qint2,
Qint4,
Qint8,
Qint12,
Qint16,
)
2 changes: 1 addition & 1 deletion qlasskit/ast2logic/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@

from .env import Env, Binding # noqa: F401, E402
from .utils import flatten # noqa: F401, E402
from .typing import Args, BoolExpList # noqa: F401, E402
from .t_arguments import translate_argument, translate_arguments # noqa: F401, E402
from .t_expression import translate_expression, type_of_exp # noqa: F401, E402
from .t_statement import translate_statement # noqa: F401, E402
from .t_ast import translate_ast # noqa: F401, E402
from .typing import Qint, Qint2, Qint4, Qint8, Qint12, Qint16, Qtype # noqa: F401
from . import exceptions # noqa: F401, E402
3 changes: 2 additions & 1 deletion qlasskit/ast2logic/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@

from typing_extensions import TypeAlias

from ..types import Qint # noqa: F401, E402
from . import exceptions
from .typing import Arg, Qint # noqa: F401, E402
from .typing import Arg

Binding: TypeAlias = Arg

Expand Down
5 changes: 3 additions & 2 deletions qlasskit/ast2logic/t_arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
import ast
from typing import List, Tuple

from ..types import * # noqa: F401, F403
from ..types import TType
from . import exceptions
from .typing import * # noqa: F401, F403
from .typing import Arg, Args, TType
from .typing import Arg, Args


def translate_argument(ann, base="") -> Arg:
Expand Down
8 changes: 4 additions & 4 deletions qlasskit/ast2logic/t_expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
from sympy import Symbol
from sympy.logic import ITE, And, Not, Or, false, true

from ..types import Qbool, Qint, Qint2, Qint4, Qint8, Qint12, Qint16, TExp
from . import Env, exceptions
from .typing import Qint, Qint2, Qint4, Qint8, Qint12, Qint16, TExp, bool_eq, bool_neq


def type_of_exp(vlist, base, res=[]) -> List[Symbol]:
Expand Down Expand Up @@ -173,7 +173,7 @@ def unfold(v_exps, op):
# Eq
if isinstance(expr.ops[0], ast.Eq):
if tleft[0] == bool and tcomp[0] == bool:
return (bool, bool_eq(tleft[1], tcomp[1]))
return (bool, Qbool.eq(tleft[1], tcomp[1]))
elif issubclass(tleft[0], Qint) and issubclass(tcomp[0], Qint): # type: ignore
return Qint.eq(tleft, tcomp)

Expand All @@ -182,9 +182,9 @@ def unfold(v_exps, op):
# NotEq
elif isinstance(expr.ops[0], ast.NotEq):
if tleft[0] == bool and tcomp[0] == bool:
return (bool, bool_neq(tleft[1], tcomp[1]))
return (bool, Qbool.neq(tleft[1], tcomp[1]))
elif issubclass(tleft[0], Qint) and issubclass(tcomp[0], Qint): # type: ignore
return Qint.not_eq(tleft, tcomp)
return Qint.neq(tleft, tcomp)

raise exceptions.TypeErrorException(tcomp[0], tleft[0])

Expand Down
158 changes: 0 additions & 158 deletions qlasskit/ast2logic/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,7 @@
from typing import List, Tuple

from sympy import Symbol
from sympy.logic import And, Not, Or, Xor, false, true
from sympy.logic.boolalg import Boolean
from typing_extensions import TypeAlias

# from .ast2logic.t_expression import TType

TType: TypeAlias = object
TExp: TypeAlias = Tuple[TType, Boolean]


# XOR
def bool_neq(a, b):
return Xor(a, b)


# !XOR
def bool_eq(a, b):
return Not(bool_neq(a, b))


class Arg:
Expand All @@ -56,144 +39,3 @@ def to_exp(self) -> List[Symbol]:
Args = List[Arg]
BoolExpList = List[Tuple[Symbol, Boolean]]
LogicFun = Tuple[str, Args, int, BoolExpList]


class Qtype:
BIT_SIZE = 0


class Qint(int, Qtype):
BIT_SIZE = 8

def __init__(self, value):
super().__init__()
self.value = value

def __getitem__(self, i):
if i > self.BIT_SIZE:
raise Exception("Unbound")

return self.to_bool_str()[i] == "1"

@classmethod
def from_bool(cls, v: List[bool]):
return cls(int("".join(map(lambda x: "1" if x else "0", v[::-1])), 2))

def to_bool_str(self) -> str:
s = bin(self.value)[2:][0 : self.BIT_SIZE]
return ("0" * (self.BIT_SIZE - len(s)) + s)[::-1]

@staticmethod
def const(v: int) -> List[bool]:
"""Return the list of bool representing an int"""
return list(map(lambda c: True if c == "1" else False, bin(v)[2:]))[::-1]

@staticmethod
def fill(v: Tuple[TType, List[bool]]) -> Tuple[TType, List[bool]]:
"""Fill a Qint to reach its bit_size"""
if len(v[1]) < v[0].BIT_SIZE: # type: ignore
v = (
v[0],
(v[0].BIT_SIZE - len(v[1])) * v[1] + [False], # type: ignore
)
return v

@staticmethod
def eq(tleft: TExp, tcomp: TExp) -> TExp:
"""Compare two Qint for equality"""
ex = true
for x in zip(tleft[1], tcomp[1]):
ex = And(ex, bool_eq(x[0], x[1]))

if len(tleft[1]) > len(tcomp[1]):
for x in tleft[1][len(tcomp[1]) :]:
ex = And(ex, Not(x))

if len(tleft[1]) < len(tcomp[1]):
for x in tcomp[1][len(tleft[1]) :]:
ex = And(ex, Not(x))

return (bool, ex)

@staticmethod
def not_eq(tleft: TExp, tcomp: TExp) -> TExp:
"""Compare two Qint for inequality"""
ex = false
for x in zip(tleft[1], tcomp[1]):
ex = Or(ex, bool_neq(x[0], x[1]))

if len(tleft[1]) > len(tcomp[1]):
for x in tleft[1][len(tcomp[1]) :]:
ex = Or(ex, x)

if len(tleft[1]) < len(tcomp[1]):
for x in tcomp[1][len(tleft[1]) :]:
ex = Or(ex, x)

return (bool, ex)

@staticmethod
def gt(tleft: TExp, tcomp: TExp) -> TExp:
"""Compare two Qint for greater than"""
prev: List[Symbol] = []

for a, b in list(zip(tleft[1], tcomp[1]))[::-1]:
if len(prev) == 0:
ex = And(a, Not(b))
else:
ex = Or(ex, And(*(prev + [a, Not(b)])))

prev.append(bool_eq(a, b))

if len(tleft[1]) > len(tcomp[1]):
for x in tleft[1][len(tcomp[1]) :]:
ex = Or(ex, x)

if len(tleft[1]) < len(tcomp[1]):
for x in tcomp[1][len(tleft[1]) :]:
ex = Or(ex, x)

return (bool, ex)

@staticmethod
def lt(tleft: TExp, tcomp: TExp) -> TExp:
"""Compare two Qint for lower than"""
return (bool, And(Not(Qint.gt(tleft, tcomp)[1]), Not(Qint.eq(tleft, tcomp)[1])))

@staticmethod
def lte(tleft: TExp, tcomp: TExp) -> TExp:
"""Compare two Qint for lower than - equal"""
return (bool, Not(Qint.gt(tleft, tcomp)[1]))

@staticmethod
def gte(tleft: TExp, tcomp: TExp) -> TExp:
"""Compare two Qint for greater than - equal"""
return (bool, Not(Qint.lt(tleft, tcomp)[1]))

# @staticmethod
# def add(tleft: TExp, tright: TExp) -> TExp:
# """Add two Qint"""


class Qint2(Qint):
BIT_SIZE = 2


class Qint4(Qint):
BIT_SIZE = 4


class Qint8(Qint):
BIT_SIZE = 8


class Qint12(Qint):
BIT_SIZE = 12


class Qint16(Qint):
BIT_SIZE = 16


# class Qlist
# class Qfixed
5 changes: 2 additions & 3 deletions qlasskit/qlassf.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@
from typing import Callable, List, Tuple, Union # noqa: F401

from . import compiler
from .ast2logic import flatten, translate_ast
from .ast2logic.typing import * # noqa: F403, F401
from .ast2logic.typing import Args, BoolExpList
from .ast2logic import Args, BoolExpList, flatten, translate_ast
from .types import * # noqa: F403, F401

MAX_TRUTH_TABLE_SIZE = 20

Expand Down
17 changes: 17 additions & 0 deletions qlasskit/types/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Copyright 2023 Davide Gessa

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

# http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from .qbool import Qbool # noqa: F401
from .qint import Qint, Qint2, Qint4, Qint8, Qint12, Qint16 # noqa: F401
from .qtype import Qtype, TExp, TType # noqa: F401
25 changes: 25 additions & 0 deletions qlasskit/types/qbool.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright 2023 Davide Gessa

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

# http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from sympy.logic import Not, Xor


class Qbool:
@staticmethod
def neq(a, b):
return Xor(a, b)

@staticmethod
def eq(a, b):
return Not(Qbool.neq(a, b))
Loading

0 comments on commit f1961e4

Please sign in to comment.