Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

CLP(*) Puzzle: Units

170 views
Skip to first unread message

Jan Burse

unread,
Nov 5, 2013, 5:15:31 PM11/5/13
to
Dear All,

Question 1: I just wondered a little bit
about the following. Can I use some CLP(*)
for unit calculations?

Here is an example expectation:

?- X ~ 5*M, Y ~ 10*S, Z ~ X/Y
Z ~ 1/2*M/S.

The (~)/2 would be the equality of the
corresponding CLP(*).

Question 2: What CHR framework would
one use to implement such a CLP(*), and
how complex would it be.

Bye

P.S.: I know a couple of reasons why
CLP(FD) cannot do it:

Hurdle 1: 1/2 is not an integer.

Hurdle 2: CLP(FD) usually cannot deal
with X1^A1*...*Xn^An, although it can
often represent A*X1+..+An*Xn.

Hurdle 3: CLP(FD) usually does not
substitute expression, it just keeps
them in the constraint store.

P.P.S.: Puzzle inspired by:
http://perso.ens-lyon.fr/guillaume.allais/?en/main/blog/read/dimension-aware-computations

Julio Di Egidio

unread,
Nov 5, 2013, 5:37:23 PM11/5/13
to
"Jan Burse" <janb...@fastmail.fm> wrote in message
news:l5bqm2$d61$1...@news.albasani.net...
> Dear All,
>
> Question 1: I just wondered a little bit
> about the following. Can I use some CLP(*)
> for unit calculations?
>
> Here is an example expectation:
>
> ?- X ~ 5*M, Y ~ 10*S, Z ~ X/Y
> Z ~ 1/2*M/S.

Why/how CLP? That rather makes me think of an ad-hoc compound structure {
value, unit of measure }, i.e. a data type with its own operations. E.g.
(a; A)/''(b; B) := (a/b; A/'B).

Julio


Jan Burse

unread,
Nov 5, 2013, 5:41:32 PM11/5/13
to
Julio Di Egidio schrieb:
> Why/how CLP? That rather makes me think of an ad-hoc compound structure
> { value, unit of measure }, i.e. a data type with its own operations.
> E.g. (a; A)/''(b; B) := (a/b; A/'B).
>
> Julio

The unit itself would be also structured, respectively
expressions that undergo some simplification, and we would
like to have results such as:

?- X ~ 5*KG, Y ~ 10*G, Z ~ X/Y
Z ~ 500.

You get the pair (a;A) for free in CLP(*) if you don't
think in units, just assume the M, S, etc.. are some
variables.

Maybe we need some predefinitions, such as KG ~ 1000*G.

Right?

Julio Di Egidio

unread,
Nov 5, 2013, 5:59:27 PM11/5/13
to
"Jan Burse" <janb...@fastmail.fm> wrote in message
news:l5bs6r$g88$1...@news.albasani.net...
> Julio Di Egidio schrieb:
>> Why/how CLP? That rather makes me think of an ad-hoc compound structure
>> { value, unit of measure }, i.e. a data type with its own operations.
>> E.g. (a; A)/''(b; B) := (a/b; A/'B).
>
> The unit itself would be also structured, respectively
> expressions that undergo some simplification, and we would
> like to have results such as:
>
> ?- X ~ 5*KG, Y ~ 10*G, Z ~ X/Y
> Z ~ 500.
>
> You get the pair (a;A) for free in CLP(*) if you don't
> think in units, just assume the M, S, etc.. are some
> variables.

But that would not be satisfactory: 5 Kg / 10 g ==> 0.5 Kg/g.

> Maybe we need some predefinitions, such as KG ~ 1000*G.
>
> Right?

Yes, I think so, and still just as a little brainstorming (you know that my
CS competencies are limited anyway), I'd have only "normalised" units in the
core, and maybe do some normalisation-denormalisation before and after the
actual calculations. E.g. 5 Kg / 10 g ==>(normalised) 5000 g / 10 g ==> 500
g/g
==> 500 ==> (denormalised, if we like) 0.5 K.

Julio


Jan Burse

unread,
Nov 6, 2013, 2:52:50 AM11/6/13
to
Julio Di Egidio schrieb:
>> You get the pair (a;A) for free in CLP(*) if you don't
>> think in units, just assume the M, S, etc.. are some
>> variables.
>
> But that would not be satisfactory: 5 Kg / 10 g ==> 0.5 Kg/g.

Yeah, probably there are more problems lurking.
For example we are expecting units to be independent.
So that the following query should not succeed:

?- M ~ S.

But what should it do? Fail? Throw an error? And
how to I teach the CLP(*) that they are independent.
Should I give some predefined inequality:

M \~ S

Or rather something like:

forall A, B in Number (A*M + B*S \~ 0)

Then there is another issue. Units are not only
independent, but I guess they are also incompatible.
Namely one wants the following not to succeed:

?- Z ~ KG + M.

Now assume we use some type inference to handle
the above cases. Thus adding a different layer
to our CLP(*). What would be the type inference
of the following:

?- A*M ~ B*S

I can immagine as a solution A ~ S and B ~ M,
but the following works also A ~ M^-1 and B ~ S^-1.
So the type of A and B can be anything along
X*S and X*M, where X can be any Unit.

Bye

Julio Di Egidio

unread,
Nov 8, 2013, 8:20:52 PM11/8/13
to
"Jan Burse" <janb...@fastmail.fm> wrote in message
news:l5csgj$1ht$1...@news.albasani.net...
> Julio Di Egidio schrieb:
>>
>>> You get the pair (a;A) for free in CLP(*) if you don't
>>> think in units, just assume the M, S, etc.. are some
>>> variables.
>>
>> But that would not be satisfactory: 5 Kg / 10 g ==> 0.5 Kg/g.
>
> Yeah, probably there are more problems lurking.
> For example we are expecting units to be independent.
> So that the following query should not succeed:
>
> ?- M ~ S.
>
> But what should it do? Fail? Throw an error? And
> how to I teach the CLP(*) that they are independent.

I would expect it to fail, 2 = 1 fails.

Anyway, units of measure never come alone, so I'd rather think about:

(V1, U1) ~ (V2, U2)

where, say, Vs are real numbers.

Or even:

(V1, M1, U1) ~ (V2, M2, U2)

to consider the multipliers.

Then I'd imagine an arithmetic on these be developed, finally a CLP that
leverages that arithmetic.

Julio


Jan Burse

unread,
Nov 16, 2013, 7:34:55 PM11/16/13
to
Who needs Go, Dart, etc.. if you have Frink! Disclaimer:
I didn't use it much yet, only tried the Android app once.
But somehow feel sympathetic for a language far away from the
JavaScript, WebGL, Concurrency, etc.. frenzy.

Frink for Android
https://play.google.com/store/apps/developer?id=Alan+Eliasen

Frink Samples
http://futureboy.us/frinkdocs/#SampleCalculations

The bet is still open. Any small Frink kernel in Prolog?


Jan Burse schrieb:

Joachim Schimpf

unread,
Nov 20, 2013, 3:33:46 PM11/20/13
to
For what it's worth, I've written an evaluator for expressions with units,
though not a proper constraint solver. Nevertheless, it solves the sample
problems you posed, and can also do some of the Frink stuff as well.

The main predicate is isu/2 (corresponding to is/2):

% Jan's original example
?- X isu 5m, Y isu 10s, Z isu X/Y.
X = 5 m
Y = 10 s
Z = 0.5 m/(s)

% mixing units (result is always in SI units)
?- X isu 3m + 4ft.
X = 4.2192 m

% units with higher exponents (Note: multiply sign in 4*m^2 is required!)
?- X isu 3m * 4*m^2.
X = 12 * (m)^3

% How much energy is left after you eat a bar of chocolate,
% then spend 1 hour on the treadmill?
?- Y isu 600kcal - 1h*200'W'.
Y = 1790400.0 'J'

% Ohm's law
?- X isu 230'V' / 882'Ohm'.
X = 0.26077097505668934 'A'

% Frink example (http://futureboy.us/frinkdocs/#SampleCalculations)
?- Water isu 1kg/l, X isu 10ft*12ft*8ft * Water / lb.
Water = 1000.0 kg / (m)^3
X = 59930.842153098834


The code is a bit long for posting, but you can download it from
http://eclipseclp.org/wiki/Examples/ComputationWithNumbersAndUnits
It's written for ECLiPSe, for other systems you may have to replace
the do-loops with recursions.

Enjoy,
Joachim

Jan Burse

unread,
Nov 20, 2013, 6:40:39 PM11/20/13
to
Joachim Schimpf schrieb:
> For what it's worth, I've written an evaluator for expressions with units,

Thats gr8. Thank you for sharing.


Jan Burse

unread,
Nov 20, 2013, 6:51:03 PM11/20/13
to
And for those puzzlers that want to compare
notes of their solution or another solution
with what CAS, computer algebra systems, have
in store, two links:

51. ezunits
http://maxima.sourceforge.net/docs/manual/en/maxima_51.html#SEC257

79. unit
http://maxima.sourceforge.net/docs/manual/en/maxima_79.html#SEC369

By way of hardmath / scicomp.stackexchange.com.

Can we push toward CLP(*)?

Jan Burse

unread,
Nov 24, 2013, 10:13:02 AM11/24/13
to
Hi,

I just read:
> % units with higher exponents (Note: multiply sign in
> 4*m^2 is required!)
> ?- X isu 3m * 4*m^2.
> X = 12 * (m)^3

Yes, I get an error on my side:

?- op(300,yf,m).
Yes
?- X = 3m.
X = 3 m
?- X = 3m^4.
Error: Parenthesis ("(") before operator missing.
X = 3m^4.
^
But I guess the dark forces are also strong with
these Prolog systems that are more tolerant. For
example SWI-Prolog since version 7 cannot handle
unquoted operators by default anymore:

> % How much energy is left after you eat a bar of chocolate,
> % then spend 1 hour on the treadmill?
> ?- Y isu 600kcal - 1h*200'W'.
> Y = 1790400.0 'J'

?- op(300,yf,'W').
ERROR: op/3: Domain error: `unquoted_atom' expected, found `W'

To solve the exponentiation problem, I got the idea
that for example the following operators could
be used:

m2 for m^2
m3 for m^3

I see this even sometimes in real world text, so it
would come quite natural.

Bye




Joachim Schimpf

unread,
Nov 24, 2013, 12:59:22 PM11/24/13
to
On 24/11/2013 15:13, Jan Burse wrote:> Hi,
>
> I just read:
>> % units with higher exponents (Note: multiply sign in
>> 4*m^2 is required!)
>> ?- X isu 3m * 4*m^2.
>> X = 12 * (m)^3
>
> Yes, I get an error on my side:
>
> ?- op(300,yf,m).
> Yes
> ?- X = 3m.
> X = 3 m
> ?- X = 3m^4.
> Error: Parenthesis ("(") before operator missing.
> X = 3m^4.
> ^
> But I guess the dark forces are also strong with
> these Prolog systems that are more tolerant.

Nothing to do with tolerance. You want 3m^4 to be equivalent
to 3*(m^4) and you can't have that with Prolog syntax.


> For example SWI-Prolog since version 7 cannot handle
> unquoted operators by default anymore:
>
>> % How much energy is left after you eat a bar of chocolate,
>> % then spend 1 hour on the treadmill?
>> ?- Y isu 600kcal - 1h*200'W'.
>> Y = 1790400.0 'J'
>
> ?- op(300,yf,'W').
> ERROR: op/3: Domain error: `unquoted_atom' expected, found `W'

A new SWI feature, incompatible with all other Prologs and the Standard.


-- Joachim

Jan Burse

unread,
Nov 24, 2013, 2:03:42 PM11/24/13
to
Joachim Schimpf schrieb:
>> ?- X = 3m^4.
>> >Error: Parenthesis ("(") before operator missing.
>> >X = 3m^4.
>> > ^
>> >But I guess the dark forces are also strong with
>> >these Prolog systems that are more tolerant.
> Nothing to do with tolerance. You want 3m^4 to be equivalent
> to 3*(m^4) and you can't have that with Prolog syntax.

Oh, now I see, I was adopting your operator level.
If I use a different operator level, I don't
get an error anymore on my side, but its still
not usable, since m refers to 3 and is not captured
by the (^)/2:

Jekejeke Prolog, Development Environment 0.9.12
(c) 1985-2013, XLOG Technologies GmbH, Switzerland
?- op(100,yf,m).
Yes

?- X = 3m.
X = 3 m

?- X = 3m^7.
X = 3 m^7

?- X = 3m^7, write_canonical(X).
^(m(3),7)X = 3 m^7

Now I understand why you did use the operator level
300. Oki Doki.

If I try a Prolog system that I dub tolerant,
I get some strange result:

Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.1.0)
Copyright (c) 1990-2013 University of Amsterdam, VU Amsterdam
?- op(300,yf,m).
true.

?- X = 3m^4.
X = 3^4 m.

?- X = 3m^4, write_canonical(X).
m(^(3,4))
X = 3^4 m.

My expectation would be that m is postfix of 3,
in case the prolog system is tolerant. What
is going on here?

Bye





Jan Burse

unread,
Nov 24, 2013, 2:12:49 PM11/24/13
to
Jan Burse schrieb:
> Joachim Schimpf schrieb:
>>> ?- X = 3m^4.
>>> >Error: Parenthesis ("(") before operator missing.
>>> >X = 3m^4.
>>> > ^
>>> >But I guess the dark forces are also strong with
>>> >these Prolog systems that are more tolerant.
>> Nothing to do with tolerance. You want 3m^4 to be equivalent
>> to 3*(m^4) and you can't have that with Prolog syntax.
>
> Oh, now I see, I was adopting your operator level.
> If I use a different operator level, I don't

More Testresults. ECLiPSe, same result
as on my side:

ECLiPSe Constraint Logic Programming System [kernel]
Version 6.1 #163 (x86_64_nt), Tue Jul 9 22:11 2013
?- op(100,yf,m).
?- X = 3m^7, write_canonical(X).
^(m(3), 7)
X = 3 m ^ 7

And another check:

Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.1.0)
Copyright (c) 1990-2013 University of Amsterdam, VU Amsterdam
?- op(100,yf,m).
?- X = 3m^7, write_canonical(X).
^(m(3),7)
X = 3 m^7.

So SWI-Prolog only produces something strange, in
my opinion, for a case that I dub tolerant. i.e. when
it accepts the op(300,yf,m). See my previous post.

Interesting
0 new messages