k1lib.eqn module
The idea of this module looks something like this:
from k1lib.imports import *
settings.eqn.eqnPrintExtras = False
s = k1lib.eqn.System("""
# comments like this are okay. This section's for buying things
10 cent -> 1 kWh
1.5 dollar -> 1000 H2O
12 dollar -> O2
1.4 dollar -> CH4
# conversions
100 cent -> 1 dollar
1 MJ -> 0.27 kWh
""");
# parsing extra equations down the line
s.parse("1 H2O + 16 MJ -> 0.11 H2 + 0.88 O2")
Essentially, you can create a system of equations. Here, all the chemicals are in kilograms, so you can buy 1 kg oxygen for 12 dollars. Then, you can get equations relating to a specific term:
s.O2
Output:
Consumers:
Producers:
1. H2O + 16 MJ -> 0.11 H2 + 0.88 O2
2. 12 dollar -> O2
Then, you can pick out a single equation that has another unique term “dollar”:
print(s.O2.dollar) # outputs "O2 -> 12 dollar"
This will return the flipped equation, going from “O2” to “dollar”, because the
expression looks like s.O2.dollar
. You can go in the reverse order if you want
to:
print(s.dollar.O2) # outputs "12 dollar -> O2"
For complex case where s.dollar.O2
can have multiple answers, use
Eqns.pick()
instead. You can also do random math on these equations:
print(s.dollar.O2 * 5 + s.dollar.CH4) # outputs "61.4 dollar -> 5 O2 + CH4"
You can also “combine” multiple equations together like this:
print(s.cent.dollar @ s.dollar.O2) # outputs "100 cent -> 0.083 O2"
This looks for common terms between the 2 equations, in this case “dollar”. It
then tries to add these 2 equations together so that “dollar” cancels out. “0.083”
is a hideous number. To bring it to 1kg, you can multiply the equation by
1/0.083
. This is sort of tedious, depends a lot on the original equation’s
values, so you can just do it like this instead:
# outputs "1200 cent -> O2", rounds the last term to 1
print(round(s.cent.dollar @ s.dollar.O2))
# outputs "1200 cent -> O2", rounds specific term to 1
print(round(s.cent.dollar @ s.dollar.O2, "O2"))
# outputs "3600 cent -> 3 O2", rounds the last term to value
print(round(s.cent.dollar @ s.dollar.O2, 3))
# outputs "12000 cent -> 10 O2", rounds specific term to specific value
print(round(s.cent.dollar @ s.dollar.O2, ["O2", 10]))
So, using this module, you can do quick back-of-the-envelope calculations for anything you want, like comparing between making your own oxygen, or buying oxygen tanks from outside:
# outputs "12 dollar -> O2"
print(s.dollar.O2)
# outputs "0.493 dollar -> 0.125 H2 + O2"
print(round(s.dollar.cent @ s.cent.kWh @ s.kWh.MJ @ (s.dollar.H2O @ s.H2O.O2)))
So yeah, apparently, it’s much, much cheaper to make your own oxygen from electrolysis than buying it from outside. Makes me wonder why hospitals still buy oxygen tanks.
This module can definitely be improved. Right now, chemicals are implicitly in kilograms, but what if you want to convert between mol and kg? This module doesn’t really provide the facilities for that. Main reason is I’m lazy to implement, and it sounds more trouble than its worth. I still use this module for all kinds of chemical flow analysis, and it works out fine for me, so there’re really no incentives to do this.
- class k1lib.eqn.Eqn(system: System)[source]
Bases:
object
- __init__(system: System)[source]
Creates a blank equation. Not expected to be instantiated by the end user.
- save()[source]
Saves this (potentially new) equation to the system, so that it can be used directly later on
- __getattr__(term: str)[source]
Gets the value of the term in this equation. Negative if on consumer side, positive if on producer side
- __getitem__(idx: str)[source]
Same as
__getattr__()
Gets a list of shared terms between this equation and the specified one.
- join(eqn: Eqn, term: str) Eqn [source]
Tries to cancel out this equation with another equation at the specified term. Example:
s = eqn.System("""a + b -> c + d c + 2e -> f""") s.a.c.join(s.c.f, "c") # returns the equation "a + b + 2e -> d + f"
For simpler cases, where the shared term to be joined is obvious, use
__matmul__()
instead
- __matmul__(eqn: Eqn) Eqn [source]
Convenience method that does the same thing as
join()
. Example:s = eqn.System("""a + b -> c + d c + 2e -> f""") s.a.c @ s.c.f # returns the equation "a + b + 2e -> d + f"
Preference order of which term to join:
If term is on producer side of
self
, and consumer side ofeqn
If term is on consumer side of
self
, and producer side ofeqn
Other cases
- class k1lib.eqn.Eqns(system: System, eqns: List[Eqn], focusTerm: Optional[str] = None)[source]
Bases:
object
- __init__(system: System, eqns: List[Eqn], focusTerm: Optional[str] = None)[source]
Creates a new list of equations. Not expected to be instantiated by the end user.
- Parameters
system – injected
System
eqns – list of equations
focusTerm – if the list of equations are from the result of focusing in a single term, then use this parameter to prioritize certain search parameters.
- __getitem__(idx: Union[int, str]) Optional[Eqn] [source]
If int, return the equation with that index. Not really helpful for exploring the system of equations, but good for automated scripts
If string, then effectively the same as
__getattr__()
- __getattr__(term: str) Optional[Eqn] [source]
Picks out a specific
Eqn
that has the specified term. Prefer shorter equations, and the returnedEqn
always have the term on the products side. Meaning:eqns = eqn.System("a + 2b -> c").b # gets an Eqns object with that single equation eqns.a # gets the equation "c -> a + 2b" instead
This is a convenience way to search for equations. If you need more granularity, use
pick()
instead
- pick(*terms: List[str]) Optional[Eqn] [source]
Like the quick method (
__getattr__()
), but here, picks equations more carefully, with selection for multiple terms. Example:s = eqn.System("""a + 2b -> c b + c -> d a -> 3d a + b + c -> 2d""") s.a.pick("b", "d") # returns last equation
As you can see, it’s impossible to pick out the last equation using
__getattr__()
alone, as they will all prefer the shorter equations, so this is wherepick()
can be useful.
- class k1lib.eqn.System(strToParse: Optional[str] = None)[source]
Bases:
object
- __init__(strToParse: Optional[str] = None)[source]
Creates a new system of equations.
- Parameters
strToParse – if specified, then it gets feed into
parse()