Different representation of units #3

Merged
merged 21 commits into from Aug 15, 2016

Conversation

Projects
None yet
3 participants
@mailund
Contributor

mailund commented Aug 13, 2016

I have implemented a different representation of units. Instead of having units represented as strings there is an explicit representation that I can manipulate, a representation where I keep track of the nominator and denominator.

To avoid introducing new units through spelling-mistakes, now that arbitrary units can be used, I require that all units are defined before they are used. This means that they must be created using the make_unit function. After that, the simplest way to create a units vector is to just multiply a numerics vector with a unit.

m <- make_unit(“m”)
s <- make_unit(“s”)
x <- 1:4 * m
y <- 1:4 * s
z <- x / y

and so on.

I have pulled out all the units in the udunits2 data base and made them into such units and they can be accessed through the ud_units list, so the expressions above can also be done like this:

x <- with(ud_units, 1:4 * m)
y <- with(ud_units, 1:4 * s)
z <- x / y

It is of course also possible to attach the list, but it really pollutes the name-space, so it is better not to.

With the representation of units I have implemented I cannot easily represent log-transformed units. Right now they just become strings like before, and it means you cannot compute on the once you have taken log — but that wasn’t really possible before either because udunits2 wouldn’t know how to converge such units.

I can converge between all the units in udunits2 but haven’t implemented a way of converting between user-defined units yet. I have some ideas but need to think a little more about it.

I have implemented a very basic simplification of units that just removes from the nominator and denominator units that appear both places (the number of times they appear both places, of course).

It should also be possible to converge units and then reduce the units-fraction so more can be simplified, but it requires a little more work. It shouldn’t be hard, but I won’t be able to just run through each list in the fraction once — I would need to check for each part of the nominator if there is a unit in the denominator I can convert to and so on, so it would require a double loop. I will think about how to make a pleasant implementation but I am not quite there yet.

Anyway, except for a slightly different notation for creating units vectors, all the previous functionality should be there.

mailund added some commits Aug 13, 2016

Merge commit '34c4bc7666768f99e4f451aab24578da15d43a6f' into pull_req…
…uest_branch

* commit '34c4bc7666768f99e4f451aab24578da15d43a6f':
  add Thomas as contributor; update help files
Merge commit '901ce8b2846530fdb6f11f28b85df8c82e2fbabb' into pull_req…
…uest_branch

* commit '901ce8b2846530fdb6f11f28b85df8c82e2fbabb':
  add codecov badge

# Conflicts:
#	README.md
Merge branch 'master' into pull_request_branch
* master:
  Fixed issues with loading ud_units inside the package and implemented simple unit-simplification.
  Lots of refactoring to work with the symbolic units
  Representing units as something I can work on symbolically instead of representing them as strings.
  Rolled back an attempted change...
  minor reformatting
@codecov-io

This comment has been minimized.

Show comment
Hide comment
@codecov-io

codecov-io Aug 13, 2016

Current coverage is 100% (diff: 100%)

Merging #3 into master will not change coverage

@@           master    #3   diff @@
===================================
  Files           5     6     +1   
  Lines         137   233    +96   
  Methods         0     0          
  Messages        0     0          
  Branches        0     0          
===================================
+ Hits          137   233    +96   
  Misses          0     0          
  Partials        0     0          

Powered by Codecov. Last update 901ce8b...c659cf6

codecov-io commented Aug 13, 2016

Current coverage is 100% (diff: 100%)

Merging #3 into master will not change coverage

@@           master    #3   diff @@
===================================
  Files           5     6     +1   
  Lines         137   233    +96   
  Methods         0     0          
  Messages        0     0          
  Branches        0     0          
===================================
+ Hits          137   233    +96   
  Misses          0     0          
  Partials        0     0          

Powered by Codecov. Last update 901ce8b...c659cf6

@mailund

This comment has been minimized.

Show comment
Hide comment
@mailund

mailund Aug 14, 2016

Contributor

The powers of units worked like logarithms; they replaced the representation of the underlying units with a string. I handle it better now so I can compute on the result but I only support integer powers. This limits the use of powers, of course, and I don't know by how much -- I don't know how often powers of non-integers are used -- but the way I represent units right now cannot deal with non-integer numbers of each unit. So it is the same problem as with logs.

I think both problems can be solved by representing units as actual expressions. It would complicate the simplification algorithm a lot, but it shouldn't be impossible to do. I will aim at getting simplification and conversion up and running with the current implementation before I look into that, though.

Contributor

mailund commented Aug 14, 2016

The powers of units worked like logarithms; they replaced the representation of the underlying units with a string. I handle it better now so I can compute on the result but I only support integer powers. This limits the use of powers, of course, and I don't know by how much -- I don't know how often powers of non-integers are used -- but the way I represent units right now cannot deal with non-integer numbers of each unit. So it is the same problem as with logs.

I think both problems can be solved by representing units as actual expressions. It would complicate the simplification algorithm a lot, but it shouldn't be impossible to do. I will aim at getting simplification and conversion up and running with the current implementation before I look into that, though.

mailund added some commits Aug 14, 2016

Working version where as far as I can see it all seems to work except…
… simplification on the same sign of / in units...
I think I have the conversion down now, except expressions such as km…
… * m keep having the units km * m and are not uniformed to m * m. I could do that, but I am not sure that is the desired result and it can easily be achieved by changing the units afterward, so the functionality is there, it is just not automatic.
@mailund

This comment has been minimized.

Show comment
Hide comment
@mailund

mailund Aug 14, 2016

Contributor

With the latest push I also simplify unit expressions so km * s / m will have unit s.

with(ud_units, {
  x <- 1:4 * m
  y <- 1:4 * s
  z <- 1:4 * km

  x / y / x  # unit 1/s
  x / y / z  # unit 1/s, with z scaled to make it m before reduction
})

I don't simplify units like km * m, I am not sure that would be the desired result and it can be done explicitly anyway like this:

with(ud_units, {
  x <- 1:4 * m
  y <- 1:4 * km
  z <- x * y  # has units km*m
  units(z) <- km*km # now z has units km*km
})

The conversions for unit simplification are done dimension-wise, and so far I just get the conversion constants from udunit2. Explicit units assignment with units<- is still done by translating the units into strings. I will change that to also work dimension-wise and after that, user defined types can be added with conversions in a table so they can be converted as well.

Contributor

mailund commented Aug 14, 2016

With the latest push I also simplify unit expressions so km * s / m will have unit s.

with(ud_units, {
  x <- 1:4 * m
  y <- 1:4 * s
  z <- 1:4 * km

  x / y / x  # unit 1/s
  x / y / z  # unit 1/s, with z scaled to make it m before reduction
})

I don't simplify units like km * m, I am not sure that would be the desired result and it can be done explicitly anyway like this:

with(ud_units, {
  x <- 1:4 * m
  y <- 1:4 * km
  z <- x * y  # has units km*m
  units(z) <- km*km # now z has units km*km
})

The conversions for unit simplification are done dimension-wise, and so far I just get the conversion constants from udunit2. Explicit units assignment with units<- is still done by translating the units into strings. I will change that to also work dimension-wise and after that, user defined types can be added with conversions in a table so they can be converted as well.

@edzer edzer merged commit 4bdef74 into r-quantities:master Aug 15, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment