Java units of measurement libraries other than JSR-275 and Units of Measure API - units-of-measurement

Are there any Java libraries dealing with units of measurement except for JSR 275 (rejected and abandoned) and Units of Measure API (which doesn't seem to have any production-quality implementations)?

I have written a units library that does not use static typesetting (as in many practical applications I encountered this would have been more cumbersome that I would like such a library to be).
It is designed to handle string based units as well as sharper defined units.
Some of the supported features include:
conversions of values, e.g.:
Units.convert(3, "m", "mm");
Units.convert(3, SiBaseUnit.METER, "mm");
would both return 3000.
simplification of string based units, e.g.:
Units.simplify("kg^3 m^4 s^-6 A^-1");
would return "J^2 T".
finding the names of a unit in a specific context, e.g.:
Units.inContext("lx s", UnitContextMatch.COMPATIBLE, PhysicsContext.PHOTOMETRY)
would return a navigable set containing ("luminous exposure").
supports SI units, binary units, imperial units, US customary units, atomic units, planck units and many more. The user can also easily define own units.
fully supports arbitrary logarithmic units, e.g.
LevelUnit.BEL.inReferenceTo(1, Unit.of("mV")); // automatically determines ref type -> root power
LevelUnit.BEL.inReferenceTo(1, Unit.of("W"), LevelUnitReferenceType.POWER); // specify type explicitly
Unit.of("ln(re 1 nA)") == LevelUnit.NEPER.inReferenceTo(1, Unit.of("nA")); // true
supports SI prefixes, binary prefixes and allows the user to easily implement own prefixes
Can handle unknown units if not relevant, e.g.:
Units.convert(3, "m^2 this_is_not_a_unit", "mm^2 this_is_not_a_unit");
would return 3e6, as the unknown unit this_is_not_a_unit is the same on both sides of the conversion.
for performance critical parts of the code one can obtain the conversion factor (if the conversion is purely multiplicative), e.g.:
Units.factor("kg", "t");
will return 1e-3.
Allows to check for equivalence, e.g.
Units.equivalent(1, "s", "min");
will return false, as 1min is not the same as 1s. On the other hand, checking for convertibility
Units.convertible("s", "min");
will return true.
tightly integrated in the coordinates library (as of Java 16 this library still requires preview-features, but as of Java 17 it will production ready)
The constants are implemented via a Constant interface that supports e.g.:
definition of own constants, e.g.
// (3 ± 0.2) mole
Constant.of(3, 0.2, "mole");
chaining commands, e.g.
// constant with the distance travelled by light in vacuum in (2 ± 0) seconds as value
PhysicsConstant.SPEED_OF_LIGHT_IN_VACUUM.mul(2, 0, SiBaseUnit.SECOND);
// constant of the elementary charge per (electron) mass
PhysicsConstant.ELEMENTARY_CHARGE.div(PhysicsConstant.ELECTRON_MASS);
Constant c = Constant.of(3, 0.2, "mole");
PhysicsConstant.SHIELDING_DIFFERENCE_OF_T_AND_P_IN_HT.mul(c);
(simple) uncertainty propagation
the Constant interface provides default implementations for the Texable interface from the jatex module, such that a constant can easily return proper LaTeX code.
properly documented implementations for most of the physics constants as defined by NIST, as well as some mathematical constants.

https://github.com/unitsofmeasurement/uom-se from JSR 363
https://mvnrepository.com/artifact/org.unitsofmeasurement/unit-api/0.6.2-RC1
Hopefully your problem got solved approx. 4 yrs ago!

Related

Are there more complex functions to call from within Solidity (Smart Contracts/Ethereum)?

I am wondering besides these below mathematical expressions are there any other functions available to call inside a smart contract? Like math functions, like pi, sin, cosine, random() etc?
I am wondering if one can write smart contracts that require a little more than just basic arithmetic.
Below Image is taken from this page:
https://docs.soliditylang.org/en/develop/cheatsheet.html#function-visibility-specifiers
Solidity doesn't natively support storing floating point numbers both in storage and memory, probably because the EVM (Ethereum Virtual Machine; underlying layer) doesn't support it.
It allows working with them to some extent such as uint two = 3 / 1.5;.
So most floating point operations are usually done by defining a uint256 (256bit unsigned integer) number and another number defining the decimal length.
For example token contracts generally use 18 decimal places:
uint8 decimals = 18;
uint256 one = 1000000000000000000;
uint256 half = 500000000000000000;
There are some third-party libraries for calculating trigonometric functions (link), working with date time (link) and other use cases, but the native language currently doesn't support many of these features.
As for generating random numbers: No native function, but you can calculate a modulo of some pseudo-random variables such as block.hash and block.timestamp. Mind that these values can be (to some extent) manipulated by a miner publishing the currently mined block.
It's not recommended to use them in apps that work with money (pretty much most of smart contracts), because if the incentive is big enough, there can be a dishonest miner who can use the advantage of knowing the values before rest of the network and being able to modify them to some extent to their own benefit.
Example:
// a dishonest miner can publish a block with such params,
// that will result in the condition being true
// and their own tx to be the first one in the block that executes this function
function win10ETH() external {
if (uint256(blockhash(block.number)) % 12345 == 0) {
payable(msg.sender).transfer(10 ether);
}
}
If you need a random number that is not determinable by a miner, you can use the oracle approach, where an external app (called oracle) listens to transactions in a predefined format (generally also from&to specific addresses), performs an off-chain action (such as generating a random number, retrieving a google search result, or basically anything) and afterwards sends another transaction to your contract, containing the result of the off-chain action.

Can OpenMDAO unit conversion handle nonstandard-power scalings?

In tokamak plasma physics, scaling laws are often used to estimate plasma performance. These often require non-standard units, in particular, plasma density n in units of 10^19 or 10^20 particles per cubic meter, often called n19 and n20, respectively. (Nobody calls these 10 or 100 exa-particles-per-cubic-meter.) At the same time, many physics formulae call for these values in the "standard" m^-3.
I can imagine an OpenMDAO ScalingLaw component taking in an input with units=m**-3 (and probably ref=1e19 for numerical ease), and then manually dividing by 1e19 to get an n19.
Is there a 'better' way to handle this scale conversion automatically?
It sounds like the appropriate approach here might just be to add new units to OpenMDAO's unit library. This would make the conversion automatic as the data is passed around.
For instance, in astrodynamics we sometimes invent "canonical" units in which the distance unit is set to some specified value (like the Earth's radius), the gravitational parameter GM is assumed to be 1, and time units fall out of this. In OpenMDAO, the Distance Units (DU) can be set using the following code somewhere in your script before you start defining inputs and outputs:
import openmdao.utils.units as units
# Add canonical units to OpenMDAO
MU_earth = 3.986592936294783e14
R_earth = 6378137.0
period = 2 * np.pi * np.sqrt(R_earth**3 / MU_earth)
units.add_unit('TU', f'{period}*s')
units.add_unit('DU', f'{R_earth}*m')
You can verify the functionality by adding the units and then using the OpenMDAO convert_units function to test them:
import openmdao.utils.units as units
from openmdao.api import convert_units
units.add_unit('n19', '10**19/m**3')
units.add_unit('n20', '10**20/m**3')
print(convert_units(1, 'n19', 'm**-3'))
which outputs
1e+19
Once those units are added to the system, you can specify units='n19' or units='n20' when you add inputs or outputs.

Flexible programing for inverse function or root finding in Freepascal

I have a huge lib of math functions, like pdf or cdf of statistical distributions. But often e.g. the inverse cdf can be only calculated numerically, e.g. using Newton-Raphson or bisection, in the latter we would need to check if cdf(x) is > or < then the target y0.
However, many functions have further parameters like a Gaussian distribution having certain mean and sigma, so cdf is cdf(x,mean,sigma). Whereas other functions, such as standard normal cdf, have no further parameters, or some have even 3 or 4 further parameters.
A similar problem would happen if you want to apply bisection for either linear functions (2 parameters) or parabolas (3 parameters). Or if you want not the inverse function, but e.g. the integral of f.
The easiest implementation would be to define cdf as global function f(x); and to check for >y0 or global variables.
However, this is a very old-fashioned way, and Freepascal also supports procedural parameters, for calls like x=icdf(0.9987,#cdfStdNorm)
Even overloading is supported to allow calls like x2=icdf(0.9987,0,2,#cdfNorm) to pass also mean and sigma.
But this ends up still in two separate code blocks (even whole functions), because in one case we need to call cdf only with x, and in 2nd example also with mean and sigma.
Is there an elegant solution for this problem in Freepascal? Maybe using variant records? Or an object-oriented approach? I have no glue about OO, but I know the variant object style would require to change at least the headers of many functions because I want to apply the technique not only for inverse cdf calculation, but also to numerical integration, root finding, optimization, etc.
Or is it "best" just to define a real function type with e.g. x + 5 parameters (maybe as array), and to ignore the unused parameters? But for me it looks that then I would need many "wrapper" functions or to re-code all the existing functions (to use the arrays, even if they are sometimes not needed!).
Maybe macros can help as well? Any Freepascal hints are very welcome!
If you make it a (function .. of object), mean and sigma could be part of the class, and the function could internally just access it. Only the really changing parameters during the iteration would be parameters. (read: x)
Anonymous methods as talked about by David and Rudy is a further step to avoid having to declare a class for each such invocation, but that is convenience thing and IMHO not the core of the question. At the expense of declaring the class, your core code is free of global variable use and anonymous methods might also come with a performance cost, depending on usage.
Free Pascal also supports nested functions (function... is nested), which is the original Pascal closure-like way which was never adopted by Pascal compilers from Borland. A nested procedure passed as callback can access local variables in the procedure where it was declared. The Free Pascal numlib numeric math package uses this in some cases for similar cases like yours. For math it is even more natural.
Delphi never implements old constructs because borrowing syntax from other languages looks better on bulletlists and keeps the subscriptions flowing.

Rules to set hyper-parameters alpha and theta in LDA model

I will like to know more about whether or not there are any rule to set the hyper-parameters alpha and theta in the LDA model. I run an LDA model given by the library gensim:
ldamodel = gensim.models.ldamodel.LdaModel(corpus, num_topics=30, id2word = dictionary, passes=50, minimum_probability=0)
But I have my doubts on the specification of the hyper-parameters. From what I red in the library documentation, both hyper-parameters are set to 1/number of topics. Given that my model has 30 topics, both hyper-parameters are set to a common value 1/30. I am running the model in news-articles that describe the economic activity. For this reason, I expect that the document-topic distribution (theta) to be high (similar topics in documents),while the topic-word distribution (alpha) be high as well (topics sharing many words in common, or, words not being so exclusive for each topic). For this reason, and given that my understanding of the hyper-parameters is correct, is 1/30 a correct specification value?
I'll assume you expect theta and phi (document-topic proportion and topic-word proportion) to be closer to equiprobable distributions instead of sparse ones, with exclusive topics/words.
Since alpha and beta are parameters to a symmetric Dirichlet prior, they have a direct influence on what you want. A Dirichlet distribution outputs probability distributions. When the parameter is 1, all possible distributions are equally liked to outcome (for K=2, [0.5,0.5] and [0.99,0.01] have the same chances). When parameter>1, this parameter behaves as a pseudo-counter, as a prior belief. For a high value, equiprobable output is preferred (P([0.5,0.5])>P([0.99,0.01]). Parameter<1 has the opposite behaviour. For big vocabularies you don't expect topics with probability in all words, that's why beta tends to be under 1 (the same for alpha).
However, since you're using Gensim, you can let the model learn alpha and beta values for you, allowing to learn asymmetric vectors (see here), where it stands
alpha can be set to an explicit array = prior of your choice. It also
support special values of ‘asymmetric’ and ‘auto’: the former uses a
fixed normalized asymmetric 1.0/topicno prior, the latter learns an
asymmetric prior directly from your data.
The same for eta (which I call beta).

Term for percent, percentage, fraction, scale factor?

I have functions that conceptually all return the same thing, but the result can take different forms:
function GetThingy()
There are four different functions, each can return different things:
0.071 (a float value representing an increase of 7.1%)
7.1 (a float value representing an increase of 7.1%)
1.071 (a float value representing an increase of 7.1%)
"7.1%" (a string value representing a percentage of 7.1%)
What terms can I use to help document these functions return values?
I've come up with my own terminology:
fraction: A fraction of one; where the value is understood to be between 0..1 (e.g. 0.07 represents 7%)
percent: A per-one-hundred value; where the value is understood to be between 0..100 (e.g. 7 represents 7%) Note: This contrasts with a fraction, with is per-one, rather than per-hundred
factor: A scale factor, that can be used to directly multiply; understood to be equivalent to 1+fraction (e.g. 1.07 implies an increase of 7%)
percentage: A string that contains the actual percent character (i.e. %), suitable for display to the user, or cases that prefer the localized text (e.g. "7%" implies 7%)
So applying my own naming scheme to the functions:
GetThingyFraction() = 0.071
GetThingyPercent() = 7.1
GetThingyFactor() = 1.071
GetThingyPercentage()= "7.1%"
What say you?
Not really sure there is an "answer" to this, but naming the functions as you have demonstrated makes it very easy for the consumer to understand what they are getting back. I like the terms you have chosen as well.
Are you planning on implementing all four (or n) flavors of each function, or is this strictly a naming question for when different operations process the result differently?
I am not so sure about the utility of the "percentage" version. Typically making strings for UI of messages should be handled in the presentation, not in the computation. The presentation would determine how many decimal places, "%" vs. "pct" vs "percent", etc.
I'd say you've just about got it, but I'd add the word "Increase" in some places, and put your examples in the documentation/comments:
GetThingyFractionIncrease() [e.g. 0.071 represents an increase of 7.1%]
GetThingyPercentIncrease() [e.g. 7.1 represents an increase of 7.1%]
GetThingyFactor() [e.g. 1.071 represents an increase of 7.1%]
GetThingyPercentageString() [e.g. "7.1%" represents an increase of 7.1%]
Even though your tag is language-agnostic, I'm assuming that you are writing in a modern Object-Oriented Programming language.
If you had a Thingy class with a thingy object that had a private fraction, then you could allow public access through methods like these:
double thingy.asFractionIncrease
double thingy.asPercentIncrease
double thingy.asFactor
String thingy.asPercentIncreaseString
P.S. I'm going to upvote your EL&U posting. As of this moment, this will get you back to 0 and you'll be net positive on the reputation