Symbolic Paradigm#

Initial Set-Up#

import sympy as sp

x, y = sp.symbols("x, y")

Predecessor and Successor#

def predecessor(a: sp.Symbol) -> sp.Expr:
    return a - 1


assert predecessor(x).subs(x, 1) == 0
assert predecessor(x).subs(x, 10) == 9
def successor(a: sp.Symbol) -> sp.Expr:
    return a + 1


assert successor(x).subs(x, 0) == 1
assert successor(x).subs(x, 10) == 11

Addition#

def addition(addend_1: sp.Symbol, addend_2: sp.Symbol) -> sp.Expr:
    return addend_1 + addend_2


assert addition(x, y).subs({x: 0, y: 0}) == 0
assert addition(x, y).subs({x: 1, y: 0}) == 1
assert addition(x, y).subs({x: 0, y: 1}) == 1
assert addition(x, y).subs({x: 10, y: 10}) == 20

Multiplication#

def multiplication(multiplicand: sp.Symbol, multiplier: sp.Symbol) -> sp.Expr:
    return multiplicand * multiplier


assert multiplication(x, y).subs({x: 0, y: 0}) == 0
assert multiplication(x, y).subs({x: 2, y: 0}) == 0
assert multiplication(x, y).subs({x: 0, y: 2}) == 0
assert multiplication(x, y).subs({x: 10, y: 10}) == 100

Exponentiation#

def exponentiation(base: sp.Symbol, exponent: sp.Symbol) -> sp.Expr:
    return base**exponent


assert exponentiation(x, y).subs({x: 1, y: 0}) == 1
assert exponentiation(x, y).subs({x: 0, y: 1}) == 0
assert exponentiation(x, y).subs({x: 3, y: 3}) == 27

What is the particularity of the Symbolic Paradigm?#

z, w, b = sp.symbols("z, w, b")
%%timeit
exponentiation(2, 10) / exponentiation(2, 9)
751 ns ± 4.97 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
%%timeit
(exponentiation(z, w) / exponentiation(z, b)).simplify().subs({z: 2, w: 10, b: 9})
7.13 ms ± 455 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
%%timeit
exponentiation(2, 10000000) / exponentiation(2, 9999999)
78.5 ms ± 570 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%%timeit
(exponentiation(z, w) / exponentiation(z, b)).simplify().subs({z: 2, w: 10000000, b: 9999999})
6.8 ms ± 60.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%%timeit
exponentiation(2, 1000000000) / exponentiation(2, 999999999)
---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
Cell In[12], line 1
----> 1 get_ipython().run_cell_magic('timeit', '', 'exponentiation(2, 1000000000) / exponentiation(2, 999999999)\n')

File ~/.local/share/virtualenvs/understanding-programming-paradigms-RqbJTeHH/lib/python3.10/site-packages/IPython/core/interactiveshell.py:2430, in InteractiveShell.run_cell_magic(self, magic_name, line, cell)
   2428 with self.builtin_trap:
   2429     args = (magic_arg_s, cell)
-> 2430     result = fn(*args, **kwargs)
   2432 # The code below prevents the output from being displayed
   2433 # when using magics with decodator @output_can_be_silenced
   2434 # when the last Python token in the expression is a ';'.
   2435 if getattr(fn, magic.MAGIC_OUTPUT_CAN_BE_SILENCED, False):

File ~/.local/share/virtualenvs/understanding-programming-paradigms-RqbJTeHH/lib/python3.10/site-packages/IPython/core/magics/execution.py:1168, in ExecutionMagics.timeit(self, line, cell, local_ns)
   1165         if time_number >= 0.2:
   1166             break
-> 1168 all_runs = timer.repeat(repeat, number)
   1169 best = min(all_runs) / number
   1170 worst = max(all_runs) / number

File /usr/lib/python3.10/timeit.py:206, in Timer.repeat(self, repeat, number)
    204 r = []
    205 for i in range(repeat):
--> 206     t = self.timeit(number)
    207     r.append(t)
    208 return r

File ~/.local/share/virtualenvs/understanding-programming-paradigms-RqbJTeHH/lib/python3.10/site-packages/IPython/core/magics/execution.py:158, in Timer.timeit(self, number)
    156 gc.disable()
    157 try:
--> 158     timing = self.inner(it, self.timer)
    159 finally:
    160     if gcold:

File <magic-timeit>:1, in inner(_it, _timer)

Cell In[6], line 2, in exponentiation(base, exponent)
      1 def exponentiation(base: sp.Symbol, exponent: sp.Symbol) -> sp.Expr:
----> 2     return base**exponent

KeyboardInterrupt: 
%%timeit
(exponentiation(z, w) / exponentiation(z, b)).simplify().subs({z: 2, w: 1000000000, b: 999999999})
13.8 ms ± 1.27 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)