Kooperace mezi knihovnami Pint a SymPy při manipulaci s veličinami a jednotkami

18. 4. 2024
Doba čtení: 23 minut

Sdílet

 Autor: Root.cz s využitím DALL-E
Ve druhém článku o manipulacích s hodnotami a jednotkami si ukážeme kooperaci knihovny Pint s knihovnou SymPy. I samotná knihovna SymPy práci s jednotkami a veličinami do určité míry podporuje.

Obsah

1. Kooperace mezi knihovnami Pint a SymPy při manipulaci s veličinami a jednotkami

2. Instalace knihovny Sympy

3. Manipulace se symboly a výrazy

4. Symboly, veličiny a jednotky

5. Základní výpočty se symboly, k nimž jsou připojeny jednotky

6. Výpis hodnoty odděleně od jednotek

7. Automatická konverze jednotek

8. Kontrola, zda jsou jednotky kompatibilní

9. Omezení kooperace mezi knihovnami Pint a SymPy

10. Jednotky, které jsou přímo součástí knihovny SymPy

11. Derivace výrazu s jednotkami

12. Výpočet kořenů kvadratické rovnice s jednotkami

13. Kombinace různých jednotek při výpočtu kořenů kvadratické rovnice

14. Řešení nerovnice v případě, že jsou použity jednotky

15. Řešení soustavy nerovnic s jednotkami

16. Příloha 1: parsing řetězců s hodnotami a jednotkami

17. Příloha 2: seznam všech jednotek podporovaných knihovnou SymPy

18. Repositář s demonstračními příklady

19. Odkazy na Internetu

1. Kooperace mezi knihovnami Pint a SymPy při manipulaci s veličinami a jednotkami

úvodním článku o knihovnách umožňujících manipulaci s jednotkami a veličinami jsme se seznámili se základními vlastnostmi knihovny Pint. Tato knihovna umožňuje provádět běžné výpočty (aritmetické operace a některé další operace typu druhé odmocniny), přičemž vstupem a výstupem není prostá numerická hodnota (tedy číslo 0.5 atd.), ale hodnota, ke které je přiřazena nějaká (fyzikální aj.) jednotka a nepřímo tedy i veličina (0.5 sekundy, 0.5 metru, 0.5 otočky atd.).

V některých případech je ovšem vyžadována i manipulace s celými matematickými výrazy, například se zápisem polynomu atd. Jedná se typicky o symbolické výpočty, kde výsledkem není konkrétní numerická hodnota (či vektor, resp. matice hodnot), ale jiný výraz. Příkladem takových problémů je zjednodušování výrazů, hledání kořenů kvadratických rovnic, faktorizace polynomů, symbolická derivace, symbolická integrace, výpočet limit atd. Jedním z nástrojů, které tyto manipulace se symboly podporují, je knihovna nazvaná SymPy, jež je založená (jak již ostatně její název napovídá) na Pythonu. SymPy jde dokonce tak daleko, že jednotlivé výrazy jsou přímo zapsány jako výrazy programovacího jazyka Python, se všemi výhodami, které toto řešení přináší. Výsledkem činnosti SymPy jsou většinou výrazy, které mohou být vytištěny na terminál či ve formě kvalitního „2D“ výstupu provedeného TeXem.

V mnoha ohledech by tedy bylo zajímavé a užitečné propojit možnosti minule popsané knihovny Pint s knihovnou SymPy. Jak uvidíme v dalších kapitolách, je to skutečně do jisté míry možné, i když výsledky nemusí být vždy dokonalé. Navíc má knihovna SymPy vlastní variantu práce s veličinami a jednotkami, což je oblast, které se taktéž budeme věnovat v navazujícím textu.

2. Instalace knihovny Sympy

Knihovna Sympy je, ostatně stejně jako knihovna Pint a (deseti)tisíce dalších balíčků, nabízena přes PyPi, takže její instalace by měla být jednoduchá a přímočará. Knihovnu nainstalujeme pro aktuálně přihlášeného uživatele následujícím způsobem:

$ pip3 install --user sympy
 
Collecting sympy
  Downloading sympy-1.10.1-py3-none-any.whl (6.4 MB)
     |████████████████████████████████| 6.4 MB 2.0 MB/s
Collecting mpmath>=0.19
  Downloading mpmath-1.2.1-py3-none-any.whl (532 kB)
     |████████████████████████████████| 532 kB 36.8 MB/s
Installing collected packages: mpmath, sympy
Successfully installed mpmath-1.2.1 sympy-1.10.1
Poznámka: povšimněte si, že jedinou závislostí je knihovna mpmath, s níž se ještě na stránkách Roota setkáme (na druhou stranu existuje mnoho balíčků, které naopak závisí na SymPy).

Základní kontrolu instalace provedeme jednoduše – přímo v interpretru programovacího jazyka Python:

$ python
 
Python 3.11.8 (main, Feb  7 2024, 00:00:00) [GCC 13.2.1 20231011 (Red Hat 13.2.1-4)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

Provedeme jednoduchý test, jestli je možné naimportovat balíček sympy a zobrazit k němu nápovědu:

>>> import sympy
>>> help(sympy)
 
Help on package sympy:
 
NAME
    sympy
 
DESCRIPTION
    SymPy is a Python library for symbolic mathematics. It aims to become a
    full-featured computer algebra system (CAS) while keeping the code as simple
    as possible in order to be comprehensible and easily extensible.  SymPy is
    written entirely in Python. It depends on mpmath, and other external libraries
    may be optionally for things like plotting support.
 
    See the webpage for more information and documentation:
 
        https://sympy.org
 
PACKAGE CONTENTS
    abc
    algebras (package)
    assumptions (package)
    benchmarks (package)
    calculus (package)
    categories (package)
    ...
    ...
    ...

3. Manipulace se symboly a výrazy

Velká síla knihovny Sympy spočívá v její schopnosti manipulace s výrazy, v nichž jsou použity pojmenované proměnné, pojmenované konstanty a další symboly. Tyto výrazy se přitom mohou zapsat přímo v Pythonu – není nutné je tedy zapisovat do řetězců či použít nějaký specializovaný DSL (doménově specifický jazyk). Je zde pouze jediný (a to zcela pochopitelný) háček: nejdříve je totiž nutné každou proměnnou zkonstruovat jako objekt typu „symbol“ (nejedná se tedy o proměnnou chápanou kontextu interpretru Pythonu). Provádí se to následujícím způsobem:

import sympy as sp
 
x = sp.symbols("x")
expression = 2 * x
print(expression)

Výsledek by přitom měl vypadat následovně:

2*x

Povšimněte si, že v proměnné (v tomto případě v běžné Pythonovské proměnné) je uložen objekt typu „výraz“, který obsahuje celý zapsaný výraz, nikoli pouze jeho výsledek (ten ostatně není možné vyhodnotit bez znalosti hodnoty x).

4. Symboly, veličiny a jednotky

Pokusme se nyní zkombinovat možnosti knihovny Pint (přiřazení veličiny a jednotky k hodnotě) a knihovny SymPy (práce se symboly). Vytvoříme symbol nazvaný x, kterému ovšem vynásobením s jednotkou, zde konkrétně s metrem, tuto jednotku přiřadíme. Výsledkem je hodnota nesoucí informace jak o symbolu, tak i o jeho jednotce, takže je možné do určité míry pokračovat v symbolických výpočtech:

from pint import UnitRegistry
import sympy as sp
 
ureg = UnitRegistry()
 
x = sp.symbols("x") * ureg.meter
print(x)
 
expression = 2 * x
print(expression)

Tento skript nejdříve vypíše symbol s jeho jednotkou a potom výsledek výrazu 2*x, což je výraz s přiřazenou délkovou jednotkou:

x meter
2*x meter

Nyní zkusme nepatrně sofistikovanější příklad. Opět symbolu se jménem x přiřadíme délkovou jednotku, nyní ovšem použijeme výraz x*x. Výsledek tedy bude mít odlišnou jednotku, neboť se již nebude jednat o délku, ale o plochu:

from pint import UnitRegistry
import sympy as sp
 
ureg = UnitRegistry()
 
x = sp.symbols("x") * ureg.meter
print(x)
 
expression = x * x
print(expression)

Skript opět nejdříve vypíše symbol s jeho jednotkou a posléze výsledek výrazu x*x:

x meter
x**2 meter ** 2

5. Základní výpočty se symboly, k nimž jsou připojeny jednotky

Se symboly je možné provádět (symbolické) výpočty a totéž do jisté míry platí i pro symboly, ke kterým je přiřazena jednotka. Interně se ovšem jedná o situaci, kterou musí zpracovat knihovna Pint a nikoli SymPy, k čemuž se ostatně ještě vrátíme. Ovšem nyní se podívejme na chování obou knihoven při některých výpočtech. Příkladem je výpočet rychlosti se symboly s a t, ke kterým jsou přiřazeny jednotky metr a sekunda (tedy nic překvapivého, základní fyzika pana Newtona):

from pint import UnitRegistry
import sympy as sp
 
ureg = UnitRegistry()
 
s = sp.Symbol("s") * ureg.meter
t = sp.Symbol("t") * ureg.second
 
print(s/t)

Výsledkem bude výraz s/t, jehož jednotkou bude meter / second:

s/t meter / second

Podobně můžeme provést i nepatrně složitější výpočet, tentokrát výpočet síly na základě hmotnosti a zrychlení; vše opět podle fyziky pana Newtona:

from pint import UnitRegistry
import sympy as sp
 
ureg = UnitRegistry()
 
m = sp.Symbol("m") * ureg.kilogram
t = sp.Symbol("t") * ureg.second
s = sp.Symbol("s") * ureg.meter
v = s/t
a = v/t
f = m*a
 
print(m)
print(t)
print(v)
print(a)
print(f)

Výsledkem jsou výrazy se symboly, které mají korektní jednotky:

m kilogram
t second
s/t meter / second
s/t**2 meter / second ** 2
m*s/t**2 kilogram * meter / second ** 2
Poznámka: naformátování výsledků není příliš dobré, protože ve výchozím nastavení jsou jednotky od výrazu odděleny jen jedinou mezerou, což není příliš čitelné.

6. Výpis hodnoty odděleně od jednotek

V předchozí kapitole jsme si ukázali, že naformátování výsledků (výrazu+jednotky) není příliš čitelné. Ovšem stále můžeme využít triku, s nímž jsme se seznámili minule, tedy získání samotné hodnoty (což je ovšem v tomto případě výraz a nikoli číslo) a jednotky odděleně. Tyto dvě informace jsou přístupné přes atributy magnitude a units, takže toho můžeme snadno dosáhnout:

from pint import UnitRegistry
import sympy as sp
 
ureg = UnitRegistry()
 
m = sp.Symbol("m") * ureg.kilogram
t = sp.Symbol("t") * ureg.second
s = sp.Symbol("s") * ureg.meter
v = s/t
a = v/t
f = m*a
 
print(f"{m.magnitude} \t [{m.units}]")
print(f"{t.magnitude} \t [{t.units}]")
print(f"{v.magnitude} \t [{v.units}]")
print(f"{a.magnitude} \t [{a.units}]")
print(f"{f.magnitude} \t [{f.units}]")

Po spuštění tohoto skriptu se v prvním sloupci zobrazí hodnota (výraz, nikoli číslo) a ve druhém sloupci jednotka umístěná do hranatých závorek, jak bývá zvykem:

m           [kilogram]
t           [second]
s/t         [meter / second]
s/t**2      [meter / second ** 2]
m*s/t**2    [kilogram * meter / second ** 2]

7. Automatická konverze jednotek

V dalším kroku si vyzkoušíme, jaká situace nastane v případě, že nejdříve vypočteme sílu (z jiných jednotek) a sečteme ji s hodnotou vyjádřenou přímo v Newtonech. Výsledkem bude podle očekávání výraz (se symboly), ovšem nás bude zajímat především výsledná jednotka vypočtená, resp. odvozená knihovnou Pint:

from pint import UnitRegistry
import sympy as sp
 
ureg = UnitRegistry()
 
m = sp.Symbol("m") * ureg.kilogram
t = sp.Symbol("t") * ureg.second
s = sp.Symbol("s") * ureg.meter
v = s/t
a = v/t
f = m*a
 
g = sp.Symbol("g") * ureg.newton
 
fx = f + g
 
print(fx.magnitude, "\t", fx.units)

Z výsledků, zejména ze druhého sloupce, je patrné, že se jednotky odvodily správně a tudíž nedošlo k vyhození výjimky:

1.0*g + m*s/t**2         kilogram * meter / second ** 2

8. Kontrola, zda jsou jednotky kompatibilní

V případě, že ve výrazu použijeme jednotky, které nejsou kompatibilní, dojde k běhové výjimce. To si můžeme snadno ukázat po modifikaci předchozího příkladu tak, že budeme sčítat sílu s časem (jednotky u symbolu g se změnily):

from pint import UnitRegistry
import sympy as sp
 
ureg = UnitRegistry()
 
m = sp.Symbol("m") * ureg.kilogram
t = sp.Symbol("t") * ureg.second
s = sp.Symbol("s") * ureg.meter
v = s/t
a = v/t
f = m*a
 
g = sp.Symbol("g") * ureg.second
 
fx = f + g

Povšimněte si zejména důvodu, proč výjimka vznikla (poslední řádek):

  File "/home/ptisnovs/src/most-popular-python-libs/sympy-pint/16_wrong_units.py", line 15, in <module>
    fx = f + g
         ~~^~~
  File "/home/ptisnovs/.local/lib/python3.11/site-packages/pint/facets/plain/quantity.py", line 841, in __add__
    return self._add_sub(other, operator.add)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ptisnovs/.local/lib/python3.11/site-packages/pint/facets/plain/quantity.py", line 103, in wrapped
    return f(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/ptisnovs/.local/lib/python3.11/site-packages/pint/facets/plain/quantity.py", line 743, in _add_sub
    raise DimensionalityError(
pint.errors.DimensionalityError: Cannot convert from 'kilogram * meter / second ** 2' ([length] * [mass] / [time] ** 2) to 'second' ([time])

9. Omezení kooperace mezi knihovnami Pint a SymPy

Při pročtení předchozích kapitol by se mohlo zdát, že kooperace mezi knihovnami Pint a SymPy je naprosto bezproblémová, ovšem ve skutečnosti tomu tak není, protože při některých manipulacích se symbolicky zapsanými výrazy se informace o jednotkách ztratí. Příkladem může být symbolická derivace. Pokusme se například derivovat výraz f=m*a (kde a je výsledkem jiných výrazů) podle t:

from pint import UnitRegistry
import sympy as sp
 
ureg = UnitRegistry()
 
m = sp.Symbol("m") * ureg.kilogram
t = sp.Symbol("t") * ureg.second
s = sp.Symbol("s") * ureg.meter
v = s/t
a = v/t
f = m*a
 
print(f.magnitude, "\t", f.units)
 
df = sp.diff(f, "t")
print(df)

Povšimněte si, že výsledkem je sice skutečně zderivovaný výraz, ovšem již bez jednotek:

m*s/t**2         kilogram * meter / second ** 2
-2*m*s/t**3

Informace o jednotkách se taktéž ztratí například při hledání kořenů kvadratické rovnice (přičemž koeficienty a, b a c mají přiřazenu jednotku):

from pint import UnitRegistry
from sympy import pprint, solve, Symbol
 
ureg = UnitRegistry()
 
a = Symbol("a") * ureg.meter
b = Symbol("b") * ureg.meter
c = Symbol("c") * ureg.meter
 
x = Symbol("x")
 
f = a * x ** 2 + b * x + c
 
print(f)
print()
 
solution = solve(f, x)
pprint(solution)

Opět platí, že výsledkem jsou nalezené kořeny, ale bez jednotky:

a*x**2 + b*x + c meter
 
⎡        _____________          _____________⎤
⎢       ╱           2          ╱           2 ⎥
⎢-b - ╲╱  -4⋅a⋅c + b    -b + ╲╱  -4⋅a⋅c + b  ⎥
⎢─────────────────────, ─────────────────────⎥
⎣         2⋅a                    2⋅a         ⎦

10. Jednotky, které jsou přímo součástí knihovny SymPy

Ve skutečnosti určitou podporu pro práci s veličinami a jednotkami nalezneme přímo v knihovně SymPy, i když její možnosti v tomto ohledu nejsou tak velké, jako v případě knihovny Pint. Symboly představující jednotky nalezneme v modulu sympy.physics.units a jednotky se přiřazují hodnotám či symbolům tak, jak to známe – operací součinu. Pouze si v praxi musíme nepatrně pomoci při tisku jednotek. Pro tento účel je použita pomocná funkce unit, která je součástí dalšího demonstračního skriptu:

from sympy.physics.units import meter, second
from sympy.physics.units import Quantity
import sympy as sp
 
 
def unit(expr):
    return expr.subs({x: 1 for x in expr.args if not x.has(Quantity)})
 
 
s = sp.Symbol("m") * meter
t = sp.Symbol("t") * second
v = s/t
a = v/t
a2 = 100*a
 
print(v)
print(a)
print(a2)
 
print()
 
print(unit(v))
print(unit(a))
print(unit(a2))

Tento skript po spuštění nejdříve vypíše symboly i s jednotkami a posléze pouze jednotky (již bez symbolů či výrazů):

meter*m/(second*t)
meter*m/(second**2*t**2)
100*meter*m/(second**2*t**2)
 
meter/second
meter/second**2
meter/second**2

11. Derivace výrazu s jednotkami

Zkusme si tedy ověřit, zda jednotky přiřazené k symbolům nebo k výrazům „přežijí“ operaci derivace:

from sympy.physics.units import meter, second
from sympy.physics.units import Quantity
import sympy as sp
 
 
def unit(expr):
    return expr.subs({x: 1 for x in expr.args if not x.has(Quantity)})
 
 
s = sp.Symbol("m") * meter
t = sp.Symbol("t") * second
v = s/t
a = sp.diff(v, "t")
 
print(v)
print(a)

Z výsledků je patrné, že tomu tak skutečně je – nejprve se vypíše výraz představující rychlost (i s jednotkou) a posléze výraz představující zrychlení (změnu rychlosti), a to opět s jednotkou:

meter*m/(second*t)
-meter*m/(second*t**2)
Poznámka: tuto derivaci si můžete ověřit například na stránce https://www.derivative-calculator.net/.

12. Výpočet kořenů kvadratické rovnice s jednotkami

Naprosto stejným způsobem si můžeme vyzkoušet, zda jednotky přiřazené ke koeficientům a, b a c „přežijí“ algoritmus pro nalezení kořenů kvadratické rovnice (což v knihovně SymPy můžeme realizovat funkcí solve):

from sympy import pprint, solve, Symbol
from sympy.physics.units import meter, second
 
a = Symbol("a") * meter
b = Symbol("b") * meter
c = Symbol("c") * meter
 
x = Symbol("x")
 
f = a * x ** 2 + b * x + c
 
pprint(f)
print()
 
solution = solve(f, x)
pprint(solution)

V tomto případě se informace o jednotkách nezobrazí, takže by se mohlo zdát, že problém přetrvává:

   2
a⋅x ⋅meter + b⋅x⋅meter + c⋅meter
 
⎡        _____________          _____________⎤
⎢       ╱           2          ╱           2 ⎥
⎢-b - ╲╱  -4⋅a⋅c + b    -b + ╲╱  -4⋅a⋅c + b  ⎥
⎢─────────────────────, ─────────────────────⎥
⎣         2⋅a                    2⋅a         ⎦

13. Kombinace různých jednotek při výpočtu kořenů kvadratické rovnice

Pokusme se nyní příklad z předchozí kapitoly upravit takovým způsobem, aby ke každému koeficientu a, b a c byla přiřazena odlišná jednotka (i když to fyzikálně nedává význam). Nicméně symbolicky je možné tento zápis použít a pokusit se vypočítat kořeny této podivné kvadratické rovnice:

from sympy import pprint, solve, Symbol
from sympy.physics.units import meter, second, kelvin
 
a = Symbol("a") * meter
b = Symbol("b") * second
c = Symbol("c") * kelvin
 
x = Symbol("x")
 
f = a * x ** 2 + b * x + c
 
pprint(f)
print()
 
solution = solve(f, x)
pprint(solution)

Nyní se jednotky objevují i ve vypočtených kořenech (opět – fyzikálně to nemá žádný význam, resp. o něm nevím):

              2
c⋅kelvin + a⋅x ⋅meter + b⋅x⋅second
 
⎡               __________________________________                 __________________________________⎤
⎢              ╱                        2       2                 ╱                        2       2 ⎥
⎢-b⋅second - ╲╱  -4⋅a⋅c⋅kelvin⋅meter + b ⋅second    -b⋅second + ╲╱  -4⋅a⋅c⋅kelvin⋅meter + b ⋅second  ⎥
⎢─────────────────────────────────────────────────, ─────────────────────────────────────────────────⎥
⎣                    2⋅a⋅meter                                          2⋅a⋅meter                    ⎦

14. Řešení nerovnice v případě, že jsou použity jednotky

Funkce solvesolveset můžeme použít i pro vyřešení jednoduché nerovnice, konkrétně pro zjištění, pro jaké hodnoty x je nerovnost platná. Začněme velmi jednoduchým příkladem s nerovnicí x > 10 metrů (tedy i s jednotkami), kterou je pochopitelně snadné vyřešit i ručně:

from sympy import init_printing, pprint, solve, solveset, symbols
from pint import UnitRegistry
from sympy.physics.units import meter
 
ureg = UnitRegistry()
 
 
init_printing(use_unicode=True)
 
x = symbols("x")
 
f = x > 10 * meter
 
pprint(f)
 
print()
 
solution = solve(f, x)
pprint(solution)
 
print()
 
solution = solveset(f, x)
pprint(solution)

Tento skript po svém spuštění nejdříve vypíše původní nerovnici a posléze i výsledky získané funkcemi solve a solveset:

x > 10⋅meter
 
x > 10⋅meter
 
{x │ x ∊ ℂ ∧ (x > 10⋅meter)}

Vidíme, že v tomto případě jsou jednotky zachovány.

15. Řešení soustavy nerovnic s jednotkami

Funkci solve můžeme využít i k vyřešení soustavy několika nerovnic. Opět se podívejme na velmi jednoduchý příklad se dvěma nerovnicemi, každá se stejnou proměnnou x, ke které je přiřazena jednotka. Při volání funkce solve se obě nerovnice (nebo i větší počet nerovnic) předává v n-tici nebo v seznamu jako první parametr (druhý parametr totiž obsahuje symbol, pro který je řešení vypočteno):

from sympy import init_printing, pprint, solve, symbols
from sympy.physics.units import second
 
init_printing(use_unicode=True)
 
t = symbols("t")
 
f1 = t > 10 * second
f2 = t < 20 * second
 
pprint(f1)
pprint(f2)
 
print()
 
solution = solve((f1, f2), t)
pprint(solution)

Tato jednoduchá soustava nerovnic má jednoznačné řešení, v tomto případě včetně jednotek:

t > 10⋅second
t < 20⋅second
 
t > 10⋅second ∧ t < 20⋅second

16. Příloha: parsing řetězců s hodnotami a jednotkami

Vraťme se ještě na chvíli ke knihovně Pint. Mezi její přednosti patří relativně vyspělý parsing řetězců, které mohou obsahovat jak hodnotu, tak i její jednotku. Ovšem řetězce mohou obsahovat i kombinace jednotek atd. Vyzkoušejme si nejdříve parsing řetězce „10 kilometers“:

from pint import UnitRegistry
 
ureg = UnitRegistry()
value = ureg("10 kilometers")
 
print(value)
print(value.to_base_units())

Výsledkem parsingu je skutečně hodnota délky interně uložená jako 10 kilometrů, se kterou se dají provádět další operace:

10 kilometer
10000.0 meter

Využít lze jakékoli hodnoty a jednotky, včetně jednotek, které nejsou základní. Příkladem může být načtení síly 10N:

from pint import UnitRegistry
 
ureg = UnitRegistry()
value = ureg("10 newtons")
 
print(value)
print(value.to_base_units())

Výsledky by v tomto případě neměly být příliš překvapující:

10 newton
10.0 kilogram * meter / second ** 2

Ovšem při parsingu řetězců narazíme i na určité pasti. Asi největší z nich spočívá v tom, jak má vlastně vypadat řetězec obsahující nějakou hodnotu rozdělenou do více jednotek. Zkusme tedy naparsovat řetězec se specifikací jednoho metru, 23 centimetrů a čtyř milimetrů:

from pint import UnitRegistry
 
ureg = UnitRegistry()
value = ureg("1 meter 23 centimeters 4 millimeters")
 
print(value)
print(value.to_base_units())

Výsledkem v tomto případě nebude délka 1234 milimetrů, ale objem získaný vynásobením všech tří délek!

92 centimeter * meter * millimeter
0.00092 meter ** 3

Pokud budeme chtít, aby se všechny délky sečetly, musí řetězec vypadat odlišně:

from pint import UnitRegistry
 
ureg = UnitRegistry()
value = ureg("1 meter + 23 centimeters + 4 millimeters")
 
print(value)
print(value.to_base_units())

Nyní již výsledek odpovídá očekávání:

1.234 meter
1.234 meter

Pravděpodobně nejčastěji na tento problém narazíme u časových jednotek:

from pint import UnitRegistry
 
ureg = UnitRegistry()
value = ureg("1 hour 30 minutes")
 
print(value)
print(value.to_base_units())

S výsledkem:

30 hour * minute
6480000 second ** 2

Korektní řešení:

from pint import UnitRegistry
 
ureg = UnitRegistry()
value = ureg("1 hour + 30 minutes")
 
print(value)
print(value.to_base_units())

S výsledkem:

ict ve školství 24

1.5 hour
5400.0 second

17. Příloha 2: seznam všech jednotek podporovaných knihovnou SymPy

Všechny jednotky, které jsou knihovnou SymPy podporovány, jsou vypsány pod tímto odstavcem. Připomeňme si, že tyto jednotky lze naimportovat z modulu sympy.physics.units:

percent
permille
rad             radian          radians
deg             degree          degrees
sr              steradian       steradians
mil             angular_mil     angular_mils
m               meter           meters
g               gram            grams
kg              kilogram        kilograms
s               second          seconds
A               ampere          amperes
K               kelvin          kelvins
mol             mole            moles
cd              candela         candelas
newton          newtons         N
kilonewton      kilonewtons     kN
meganewton      meganewtons     MN
joule           joules          J
watt            watts           W
pascal          pascals         Pa              pa
hertz           hz              Hz
dyne
erg
coulomb         coulombs        C
volt            volts           v               V
ohm             ohms
siemens         S               mho             mhos
farad           farads          F
henry           henrys          H
tesla           teslas          T
weber           webers          Wb              wb
statampere
statcoulomb     statC           franklin
statvolt
gauss
maxwell
debye
oersted
optical_power   dioptre         diopter         D
lux             lx
katal           kat
gray            Gy
becquerel       Bq
mg              milligram       milligrams
ug              microgram       micrograms
t               metric_ton      tonne
me              electron_rest_mass
km              kilometer       kilometers
dm              decimeter       decimeters
cm              centimeter      centimeters
mm              millimeter      millimeters
um              micrometer      micrometers     micron          microns
nm              nanometer       nanometers
pm              picometer       picometers
ft              foot            feet
inch            inches
yd              yard            yards
mi              mile            miles
nmi             nautical_mile   nautical_miles
angstrom        angstroms
ha              hectare
l               L               liter           liters
dl              dL              deciliter       deciliters
cl              cL              centiliter      centiliters
ml              mL              milliliter      milliliters
ms              millisecond     milliseconds
us              microsecond     microseconds
ns              nanosecond      nanoseconds
ps              picosecond      picoseconds
minute          minutes
h               hour            hours
day             days
anomalistic_year                anomalistic_years
sidereal_year   sidereal_years
tropical_year   tropical_years
common_year     common_years
julian_year     julian_years
draconic_year   draconic_years
gaussian_year   gaussian_years
full_moon_cycle full_moon_cycles
year            years           tropical_year

18. Repositář s demonstračními příklady

Zdrojové kódy všech prozatím popsaných demonstračních příkladů určených pro programovací jazyk Python 3 byly uloženy do Git repositáře dostupného na adrese https://github.com/tisnik/most-popular-python-libs. Prvních 25 příkladů je založeno pouze na knihovně Pint, další příklady pak vyžadují i knihovnu Sympy:

# Demonstrační příklad Stručný popis příkladu Cesta
1 01_time.py základní použití časových jednotek https://github.com/tisnik/most-popular-python-libs/blob/master/pint/01_time.py
2 02_dimensionality.py získání veličiny https://github.com/tisnik/most-popular-python-libs/blob/master/pint/02_di­mensionality.py
3 03_time.py operace s časovými jednotkami https://github.com/tisnik/most-popular-python-libs/blob/master/pint/03_time.py
4 04_time_dimensionality.py získání veličiny https://github.com/tisnik/most-popular-python-libs/blob/master/pint/04_ti­me_dimensionality.py
       
5 05_velocity.py rychlostní jednotky https://github.com/tisnik/most-popular-python-libs/blob/master/pint/05_velocity.py
6 06_velocity_dimensionality.py získání veličiny (nebo jejího přiblížení) https://github.com/tisnik/most-popular-python-libs/blob/master/pint/06_ve­locity_dimensionality.py
7 07_wrong_op.py detekce nekorektních operací https://github.com/tisnik/most-popular-python-libs/blob/master/pint/07_wrong_op.py
8 08_conversion.py konverze jednotek, první příklad https://github.com/tisnik/most-popular-python-libs/blob/master/pint/08_conversion.py
9 09_conversion.py konverze jednotek, druhý příklad https://github.com/tisnik/most-popular-python-libs/blob/master/pint/09_conversion.py
10 10_area.py výpočet plochy https://github.com/tisnik/most-popular-python-libs/blob/master/pint/10_area.py
11 11_velocity.py výpočet rychlosti https://github.com/tisnik/most-popular-python-libs/blob/master/pint/11_velocity.py
12 12_acceleration.py výpočet zrychlení https://github.com/tisnik/most-popular-python-libs/blob/master/pint/12_ac­celeration.py
13 13_force.py výpočet síly https://github.com/tisnik/most-popular-python-libs/blob/master/pint/13_force.py
14 14_units_and_dimensionality.py veličiny a jednotky https://github.com/tisnik/most-popular-python-libs/blob/master/pint/14_u­nits_and_dimensionality.py
15 15_prefixes.py použití prefixů u jednotek, první příklad https://github.com/tisnik/most-popular-python-libs/blob/master/pint/15_prefixes.py
16 16_prefixes.py použití prefixů u jednotek, druhý příklad https://github.com/tisnik/most-popular-python-libs/blob/master/pint/16_prefixes.py
17 17_prefixes.py použití prefixů u jednotek, třetí příklad https://github.com/tisnik/most-popular-python-libs/blob/master/pint/17_prefixes.py
18 18_binary_prefixes.py binární prefixy https://github.com/tisnik/most-popular-python-libs/blob/master/pint/18_bi­nary_prefixes.py
19 19_byte_to_bites.py binární prefixy a převod bajtů na bity https://github.com/tisnik/most-popular-python-libs/blob/master/pint/19_by­te_to_bites.py
20 20_angle.py úhlové jednotky https://github.com/tisnik/most-popular-python-libs/blob/master/pint/20_angle.py
       
21 21_list_units.py výpis všech dostupných jednotek https://github.com/tisnik/most-popular-python-libs/blob/master/pint/21_list_units.py
       
22 22_reduced_units.py redukce dimensionality https://github.com/tisnik/most-popular-python-libs/blob/master/pint/22_re­duced_units.py
23 23_to_base_units.py redukce na základní jednotky https://github.com/tisnik/most-popular-python-libs/blob/master/pint/23_to_ba­se_units.py
24 24_to_base_units.py redukce na základní jednotky https://github.com/tisnik/most-popular-python-libs/blob/master/pint/24_to_ba­se_units.py
25 25_formatting.py formátovaný výstup https://github.com/tisnik/most-popular-python-libs/blob/master/pint/25_formatting.py
       
26 01_symbol.py použití symbolů v knihovně Sympy https://github.com/tisnik/most-popular-python-libs/blob/master/sympy-pint/01_symbol.py
27 02_symbol_and_unit.py kombinace symbolů a jednotek, první příklad https://github.com/tisnik/most-popular-python-libs/blob/master/sympy-pint/02_symbol_and_unit.py
28 03_symbol_and_unit.py kombinace symbolů a jednotek, druhý příklad https://github.com/tisnik/most-popular-python-libs/blob/master/sympy-pint/03_symbol_and_unit.py
29 04_velocity.py výpočet rychlosti s využitím jednotek https://github.com/tisnik/most-popular-python-libs/blob/master/sympy-pint/04_velocity.py
30 05_force.py výpočet síly s využitím jednotek https://github.com/tisnik/most-popular-python-libs/blob/master/sympy-pint/05_force.py
31 06_better_output.py tisk hodnoty i jednotek https://github.com/tisnik/most-popular-python-libs/blob/master/sympy-pint/06_better_output.py
       
32 07_symbolic_computation.py symbolické výpočty v knihovně Sympy, první příklad https://github.com/tisnik/most-popular-python-libs/blob/master/sympy-pint/07_symbolic_computation.py
33 08_symbolic_computation.py symbolické výpočty v knihovně Sympy, první příklad https://github.com/tisnik/most-popular-python-libs/blob/master/sympy-pint/08_symbolic_computation.py
34 09_solve.py symbolické řešení rovnice https://github.com/tisnik/most-popular-python-libs/blob/master/sympy-pint/09_solve.py
       
35 10_sympy_units.py jednotky přímo z knihovny Sympy https://github.com/tisnik/most-popular-python-libs/blob/master/sympy-pint/10_sympy_units.py
36 11_diff.py symbolický výpočet derivace s využitím jednotek https://github.com/tisnik/most-popular-python-libs/blob/master/sympy-pint/11_diff.py
37 12_solve.py symbolické řešení rovnice s využitím jednotek, první příklad https://github.com/tisnik/most-popular-python-libs/blob/master/sympy-pint/12_solve.py
38 13_solve.py symbolické řešení rovnice s využitím jednotek, druhý příklad https://github.com/tisnik/most-popular-python-libs/blob/master/sympy-pint/13_solve.py
39 14_solve.py symbolické řešení nerovnice s využitím jednotek, první příklad https://github.com/tisnik/most-popular-python-libs/blob/master/sympy-pint/14_solve.py
40 15_solve.py symbolické řešení nerovnice s využitím jednotek, druhý příklad https://github.com/tisnik/most-popular-python-libs/blob/master/sympy-pint/15_solve.py
41 16_wrong_units.py použití nekompatibilních jednotek https://github.com/tisnik/most-popular-python-libs/blob/master/sympy-pint/16_wrong_units.py
       
42 28_parsing.py parsing vstupních řetězců v knihovně Piny, příklad číslo 1 (vzdálenost) https://github.com/tisnik/most-popular-python-libs/blob/master/pint/28_parsing.py
43 29_parsing.py parsing vstupních řetězců v knihovně Piny, příklad číslo 2 (síla) https://github.com/tisnik/most-popular-python-libs/blob/master/pint/29_parsing.py
44 30_parsing.py parsing vstupních řetězců v knihovně Piny, příklad číslo 3 (údaje o délkách) https://github.com/tisnik/most-popular-python-libs/blob/master/pint/30_parsing.py
45 31_parsing.py parsing vstupních řetězců v knihovně Piny, příklad číslo 4 (údaje o délkách) https://github.com/tisnik/most-popular-python-libs/blob/master/pint/31_parsing.py
46 32_parsing.py parsing vstupních řetězců v knihovně Piny, příklad číslo 5 (časové údaje) https://github.com/tisnik/most-popular-python-libs/blob/master/pint/32_parsing.py
47 33_parsing.py parsing vstupních řetězců v knihovně Piny, příklad číslo 6 (časové údaje) https://github.com/tisnik/most-popular-python-libs/blob/master/pint/33_parsing.py

19. Odkazy na Internetu

  1. Units and Quantities
    https://uomresearchit.git­hub.io/programming_with_pyt­hon/06-units_and_quantities/index.html
  2. Derivative Calculator
    https://www.derivative-calculator.net/
  3. Fyzikální veličina (Wikipedia)
    https://cs.wikipedia.org/wi­ki/Fyzik%C3%A1ln%C3%AD_ve­li%C4%8Dina
  4. Fyzikální jednotka (Wikipedia)
    https://cs.wikipedia.org/wi­ki/Fyzik%C3%A1ln%C3%AD_jed­notka
  5. Soustava SI (Wikipedia)
    https://cs.wikipedia.org/wi­ki/Soustava_SI
  6. Dokumentace ke knihovně Pint
    https://pint.readthedocs.i­o/en/stable/index.html
  7. Knihovna astropy na PyPi
    https://pypi.org/project/astropy/
  8. Knihovna Pint na PyPi
    https://pypi.org/project/Pint/
  9. Repositář knihovny Pint
    https://github.com/hgrecco/pint
  10. Knihovna units na PyPi (nevyvíjený projekt)
    https://pypi.org/project/units/
  11. Knihovna quantity na PyPi
    https://pypi.org/project/quantity/
  12. Repositář s knihovnou quantity
    https://github.com/mamrhein/quantity
  13. SymPy
    https://www.sympy.org/en/index.html
  14. SymPy na PyPi
    https://pypi.org/project/sympy/
  15. mpmath
    https://mpmath.org/
  16. mpmath na PyPi
    https://pypi.org/project/mpmath/
  17. Symbolic Maths in Python
    https://alexandrugris.git­hub.io/maths/2017/04/30/sym­bolic-maths-python.html
  18. SymPy shell
    https://live.sympy.org/
  19. Symbolic programming
    https://en.wikipedia.org/wi­ki/Symbolic_programming
  20. Symbolic language (programming)
    https://en.wikipedia.org/wi­ki/Symbolic_language_(pro­gramming)
  21. Computer algebra
    https://en.wikipedia.org/wi­ki/Computer_algebra
  22. Knihovna xarray-units na PyPi
    https://pypi.org/project/xarray-units/
  23. Kawa: překvapivě silný a výkonný dialekt Scheme pro JVM
    https://www.root.cz/clanky/kawa-prekvapive-silny-a-vykonny-dialekt-scheme-pro-jvm/
  24. Jazyk Kawa v ekosystému virtuálního stroje Javy
    https://www.root.cz/clanky/jazyk-kawa-v-ekosystemu-virtualniho-stroje-javy/
  25. Zpracování vektorů, matic a N-rozměrných polí v programovacím jazyku Kawa
    https://www.root.cz/clanky/zpracovani-vektoru-matic-a-n-rozmernych-poli-v-programovacim-jazyku-kawa/
  26. Kawa: Compiling Scheme to Java
    https://www.mit.edu/afs.new/sip­b/project/kawa/doc/kawa-tour.html
  27. Kawa in Languages shootout
    http://per.bothner.com/blog/2010/Kawa-in-shootout/
  28. Kawa 2.0 Supports Scheme R7RS
    https://developers.slashdot­.org/story/14/12/13/2259225/ka­wa-20-supports-scheme-r7rs/
  29. Kawa — fast scripting on the Java platform
    https://lwn.net/Articles/623349/
ikonka

Zajímá vás toto téma? Chcete se o něm dozvědět víc?

Objednejte si upozornění na nově vydané články do vašeho mailu. Žádný článek vám tak neuteče.

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.