google / mangle

Apache License 2.0
1.07k stars 38 forks source link

Any plans for float constants #15

Closed maxott closed 1 year ago

maxott commented 1 year ago

Hi,

I just realised that mangle only supports integers as numbers. Most of the data I want to operate on contain float values.

Is there are reason on why only int? Are floats on the roadmap? Or would I need to add that myself. To far down the rabbit hole now :)

burakemir commented 1 year ago

Yes, Mangle should have float64 data type. No reason, other than taking things step by step. It is probably a good time to add this now.

This is what one would need to do:

I'd appreciate help, but I can also do it one of these days.

kamahen commented 1 year ago

You might consider using a multi-precision integer and rational package. There seem to be two: GMP and libBF. GMP has some licensing issues but apparently is faster. There is some discussion here about the two and some performance improvements, also some discussions about rationals vs floats [spoiler alert: floats are a pain]: https://swi-prolog.discourse.group/t/libbf-binding/5892 https://swi-prolog.discourse.group/t/correct-floating-point-arithmetic/5857 (and probably in a few other threads)

maxott commented 1 year ago

Thanks for the clarification.

Would there be any major performance concern if Constant would be turned into an interface? This would not only reduce the size of the Constant structure (any type can reduce it to what it really needs), but may also allow for lazy loading of large "fact sets" and even some extended type checking (think references to other predicates).

That would also make it easier to address @kamahen suggestions as that would just be another implementation (ignoring 'generic' builtins for the moment).

I would like to take a stab at this over the next few days as mangle just ticks too many boxes right now for a use case I'm working on, but I don't want to end up with a complete orphan :)

maxott commented 1 year ago

Oh, just realised that you have been working on this already - 4b0ef3a. I guess I better sit back and watch this space:) Let me know if there is anything I can help with.

kamahen commented 1 year ago

Floating point in general has some unpleasant properties for logic programming, including multiple interpretations (is it a rational number or does it represent an interval, for example; or what exactly does "equal" mean?). Rational numbers can be used instead of floating point, except they're slower. So, you might want to implement rational (and bignum) first, using one of the packages I mentioned.

Here's some more discussion of the problems of floating point, from a number of points of view, including constraint programming: https://swi-prolog.discourse.group/t/arithmetic-functions-rational-1-and-rationalize-1/6010 ... a number of people in the discussion have considerable experience with implementing logic programming languages.

burakemir commented 1 year ago

I added some easy parts, will eventually get to the basic operations and check that serializating works.

Peter, thanks for the words of caution. I do not think the datalog++ part of Mangle will be the kind of programming language used for sophisticated numeric code (except if such tasks are handled by extension functions), and for the functional part people should be aware of what they are doing when they are using floats.

The rules for equality are clear: there is only one equality which is "the diagonal": every constant is equal only to itself (similar to the "unique name assumption"). So even if we added a base type of rationals or bignums (no plan to do so right now, but hypothetically), they it will never be equal to an element of /float64 or /number. and there will also not be any other equality operators.

I am not yet sure about implicit conversion as function arguments. I prefer to not have to deal with overloading, subtyping, type inference and implicit conversions at the same time. It would be nice if fn:plus just accepted a mix of /number and /float64 but if the arguments are all /number then the result should be /number - so fn:plus really has two possible function types at the same time. Or we go for something much simpler (but verbose) and instead require an entirely separate fn:float:plus and if you want to use an int64 number as argument you have to be convert it explicitly with fn:float(n)

burakemir commented 1 year ago

The /float64 part has been added a while ago and there are some simple operations. There are of course a lot of questions, around overloading type inference, but leaving all that for when the type system gets written up.