-
Request for comments, Novacore the sequel to ISO modules
From
Mostowski Collapse@21:1/5 to
All on Wed Aug 17 05:18:24 2022
Now I have an idea for a novell Prolog core, called Novacore.
What should it be able to do? A few features from JavaScript:
a) Renaming Module Import
The have even renaming module import. For example one
can do in JavaScript:
const emitter = require('events');
But is there a Prolog system that has a renaming module import?
Like for example this here:
:- use_module(events as emitter).
b) Polyfills
In JavaScript new functionality can be added to old versions
via so called polyfills. On the module/class level, this requires
that you can do code injections, later mixins.
Although Prolog would be in a good position here, since for
example it has multifile predicates. But does this work for a
module system of a Prolog system? And how would a polyfill
exactly be done?
I tried this in Ciao Prolog playground, but there seems a couple
of other problems:
:- use_module(library(lists)).
lists:subtract([], _, R) :- !,
R = [].
lists:subtract([E|T], D, R) :- !,
( memberchk(E, D)
-> lists:subtract(T, D, R)
; R = [E|R1],
lists:subtract(T, D, R1)
).
I get quite a funny bouquet of errors:
ERROR: (lns 6-11) Predicate memberchk/2 undefined in source
ERROR: (lns 6-11) Bad module qualification of subtract/3,
predicate not imported from module lists
ERROR: (lns 6-11) Bad module qualification of subtract/3,
predicate not imported from module lists
ERROR: Aborted module compilation
If I am not totally mistaken the subtract/3 mixing works in SWI-Prolog
and in Jekejeke Prolog. Have to try again. But there could be issues
with reconsult, in general it makes a few things more complicated
concerning the Prolog system tooling. But frankly I didn’t use it so
often, there were a few use cases though.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Wed Aug 17 07:00:40 2022
In as far the pure modules by Ciao Prolog are a good exercise.
Now imagine a pure+common module, which uses totally different
library than Ciao does currently have as a status quo. No changes
needed to the libraries that Ciao Prolog has, only a common context,
where the name space looks different and some common libraries
are provided. So the Ciao Prolog system would see the current
status quo of Ciao, and the user would see the common. Would this
be possible, such a Chimera Prolog? Or can Ciao Prolog remove
built-ins (for pure) but not add built-ins (for pure+common)?
Mostowski Collapse schrieb am Mittwoch, 17. August 2022 um 15:37:18 UTC+2:
So what would be the benefit of Novacore? It would solve
some of the bottlenecks in Prolog systems. Somebody wrote:
"Surely if SWI-Prolog is the outlier I’m happy to change that,
considering that the impact is most likely low."
How can you do **widescale change** and semantic confluence
without waiting for every Prolog system, even without waiting
for SWI-Prolog? Thats what Polyfills do in JavaScript. But I don’t
know how popular they are right now. In the past there
was Babel, and it is still there:
Babel is a JavaScript compiler
Use next generation JavaScript, today.
https://babeljs.io/
Logtalk is kind of the Prolog Babel, with the difference that
Logtalk doesn’t do existing Prolog system module system
injection. But the Bable toolchain consists of more than only
Polyfills, some are similar to Logtalk again (codemods):
- Transform syntax
- Polyfill features that are missing in your target environment
(through a third-party polyfill such as core-js)
^- Source code transformations (codemods)
- And more!
To some extend there is also a third option besides the alternative
of if-then-else conditional Prolog compilation. You could also
use goal_expansion/2 to do some things.
Mostowski Collapse schrieb am Mittwoch, 17. August 2022 um 14:18:25 UTC+2:
Now I have an idea for a novell Prolog core, called Novacore.
What should it be able to do? A few features from JavaScript:
a) Renaming Module Import
The have even renaming module import. For example one
can do in JavaScript:
const emitter = require('events');
But is there a Prolog system that has a renaming module import?
Like for example this here:
:- use_module(events as emitter).
b) Polyfills
In JavaScript new functionality can be added to old versions
via so called polyfills. On the module/class level, this requires
that you can do code injections, later mixins.
Although Prolog would be in a good position here, since for
example it has multifile predicates. But does this work for a
module system of a Prolog system? And how would a polyfill
exactly be done?
I tried this in Ciao Prolog playground, but there seems a couple
of other problems:
:- use_module(library(lists)).
lists:subtract([], _, R) :- !,
R = [].
lists:subtract([E|T], D, R) :- !,
( memberchk(E, D)
lists:subtract(T, D, R)
; R = [E|R1],
lists:subtract(T, D, R1)
).
I get quite a funny bouquet of errors:
ERROR: (lns 6-11) Predicate memberchk/2 undefined in source
ERROR: (lns 6-11) Bad module qualification of subtract/3,
predicate not imported from module lists
ERROR: (lns 6-11) Bad module qualification of subtract/3,
predicate not imported from module lists
ERROR: Aborted module compilation
If I am not totally mistaken the subtract/3 mixing works in SWI-Prolog
and in Jekejeke Prolog. Have to try again. But there could be issues
with reconsult, in general it makes a few things more complicated
concerning the Prolog system tooling. But frankly I didn’t use it so often, there were a few use cases though.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Wed Aug 17 06:37:17 2022
So what would be the benefit of Novacore? It would solve
some of the bottlenecks in Prolog systems. Somebody wrote:
"Surely if SWI-Prolog is the outlier I’m happy to change that,
considering that the impact is most likely low."
How can you do **widescale change** and semantic confluence
without waiting for every Prolog system, even without waiting
for SWI-Prolog? Thats what Polyfills do in JavaScript. But I don’t
know how popular they are right now. In the past there
was Babel, and it is still there:
Babel is a JavaScript compiler
Use next generation JavaScript, today.
https://babeljs.io/
Logtalk is kind of the Prolog Babel, with the difference that
Logtalk doesn’t do existing Prolog system module system
injection. But the Bable toolchain consists of more than only
Polyfills, some are similar to Logtalk again (codemods):
- Transform syntax
- Polyfill features that are missing in your target environment
(through a third-party polyfill such as core-js)
^- Source code transformations (codemods)
- And more!
To some extend there is also a third option besides the alternative
of if-then-else conditional Prolog compilation. You could also
use goal_expansion/2 to do some things.
Mostowski Collapse schrieb am Mittwoch, 17. August 2022 um 14:18:25 UTC+2:
Now I have an idea for a novell Prolog core, called Novacore.
What should it be able to do? A few features from JavaScript:
a) Renaming Module Import
The have even renaming module import. For example one
can do in JavaScript:
const emitter = require('events');
But is there a Prolog system that has a renaming module import?
Like for example this here:
:- use_module(events as emitter).
b) Polyfills
In JavaScript new functionality can be added to old versions
via so called polyfills. On the module/class level, this requires
that you can do code injections, later mixins.
Although Prolog would be in a good position here, since for
example it has multifile predicates. But does this work for a
module system of a Prolog system? And how would a polyfill
exactly be done?
I tried this in Ciao Prolog playground, but there seems a couple
of other problems:
:- use_module(library(lists)).
lists:subtract([], _, R) :- !,
R = [].
lists:subtract([E|T], D, R) :- !,
( memberchk(E, D)
lists:subtract(T, D, R)
; R = [E|R1],
lists:subtract(T, D, R1)
).
I get quite a funny bouquet of errors:
ERROR: (lns 6-11) Predicate memberchk/2 undefined in source
ERROR: (lns 6-11) Bad module qualification of subtract/3,
predicate not imported from module lists
ERROR: (lns 6-11) Bad module qualification of subtract/3,
predicate not imported from module lists
ERROR: Aborted module compilation
If I am not totally mistaken the subtract/3 mixing works in SWI-Prolog
and in Jekejeke Prolog. Have to try again. But there could be issues
with reconsult, in general it makes a few things more complicated
concerning the Prolog system tooling. But frankly I didn’t use it so often, there were a few use cases though.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
All on Wed Aug 17 13:28:56 2022
Since I have already a prototype running, but it needs a little
bit more preparation, here is a new term coined. We have
already the new term Novacore, and now comes the following:
One could pursue a new approach, based on a Novacore
with what could be coined Liblets. A Liblet would be kind of package,
that would switch in what is normally more cohesively connected
inside a Prolog system. But the Prolog systems that would aim at
supporting Novacore and Liblets, would need some refactoring
and deossification. So that the Prolog system specific Liblet
becomes switchable. One way to do it, is to have the Prolog
system depend on an internal Liblet not visible to the outside, so
that the switchable Liblets become possible. One could then
experiment with a least common multiple (LCM) Liblet in
each Prolog system that has a Novacore. The LCM Liblet
would be the fusion of various Liblets or even a totally different
setup concerning the name space of this LCM Liblet and the
content of this LCM Liblet. LCM Liblet would be the new name
for Common Prolog. Why is a Novacore needed, and not the
ISO core standard suitable. Various reasons, a) intollerant syntax of
some ISO core implementations, b) other intollerant features of some
ISO core implementations, that prohibit Liblets modelled after or
directly loaded from existing more tollerant Prolog systems.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Wed Aug 31 03:10:28 2022
I guess the SWI-Prolog implementation of call_nth/2 can
be used with multi-threading. So does the formerly Jekejeke
Prolog implementation, can be used with multi-threading
as well. Performance for formerly Jekejeke Prolog with
JDK 1.8, even bettern than that for SWI-Prolog:
?- time((call_nth((between(1,1000,_),call_nth(between(1,1000,_),_)),_), fail; true)).
% Threads 359 ms, GC 6 ms, Up 372 ms (Current 08/31/22 12:07:16)
true.
Cannot test Ciao Prolog since it doesn't have call_nth/2.
Same for ECLiPSe Prolog, I don't find a predicate that goes
exactly by the name call_nth/2,
maybe there is a substitute?
Mostowski Collapse schrieb am Mittwoch, 31. August 2022 um 12:04:36 UTC+2:
The implementation goes:
bb_put(Key, Value) :-
( atom(Key) ->
'$store_global_var'(Key, Value)
; type_error(atom, Key, bb_put/2)
).
And then bb_put/2 is used in Scryer Prologs call_nth/2.
How do you want to use this in a multi-threaded Prolog system?
LMAO!
Mostowski Collapse schrieb am Mittwoch, 31. August 2022 um 11:59:37 UTC+2:
Was refactoring Dogelog Player. It has now a couple
of libraries, making use of the new system_url to fetch them.
- library(compat): New idea of a library, has things like tab/1.
- library(sequence): Reduced library(adanced/sequence) from formerly Jekejeke Prolog.
- library(aggregate): Reduced library(adanced/aggregate) from formerly Jekejeke Prolog.
- library(lists): Like library(basic/lists) from formerly Jekejeke Prolog.
library(sequence) and library(aggregate) are implemented via
the new change_arg/3 in Dogelog Player, unlike Jekejeke Prolog
which uses some Java pivot datastructure.
The new system_url to fetch does not change Dogelog Player
performance. Dogelog Player is still not an extremly fast
Prolog system, it might beat Tau Prolog but otherwise it has
rather modest performance. But change_arg/3 gives nice
performance. Its the better solution than bb_put/2 and bb_get/2,
which is module local, and BTW will not work in multi-threading,
if it has SICStus semantics it is for "blackboard" communication
between multiple threads. The bb_ stands for "blackboard". So its
not thread-local. What is Scryer Prolog thinking?
Anyway, here some performance:
/* Scryer Prolog "v0.9.0-175-g6b8e6204" */
?- use_module(library(iso_ext)).
true.
?- time((call_nth((between(1,1000,_),call_nth(between(1,1000,_),_)),_), fail; true)).
% CPU time: 4.719s
true.
/* Dogelog Player 1.0.2, nodejs */
?- ensure_loaded(library(sequence)).
true.
?- time((call_nth((between(1,1000,_),call_nth(between(1,1000,_),_)),_), fail; true)).
% Wall 1763 ms, gc 4 ms, 6250971 lips
true.
/* SWI-Prolog, 8.5.14 */
?- time((call_nth((between(1,1000,_),call_nth(between(1,1000,_),_)),_), fail; true)).
% 5,002,004 inferences, 0.484 CPU in 0.473 seconds (102% CPU, 10326718 Lips)
true.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
All on Wed Aug 31 02:59:36 2022
Was refactoring Dogelog Player. It has now a couple
of libraries, making use of the new system_url to fetch them.
- library(compat): New idea of a library, has things like tab/1.
- library(sequence): Reduced library(adanced/sequence) from formerly Jekejeke Prolog.
- library(aggregate): Reduced library(adanced/aggregate) from formerly Jekejeke Prolog.
- library(lists): Like library(basic/lists) from formerly Jekejeke Prolog.
library(sequence) and library(aggregate) are implemented via
the new change_arg/3 in Dogelog Player, unlike Jekejeke Prolog
which uses some Java pivot datastructure.
The new system_url to fetch does not change Dogelog Player
performance. Dogelog Player is still not an extremly fast
Prolog system, it might beat Tau Prolog but otherwise it has
rather modest performance. But change_arg/3 gives nice
performance. Its the better solution than bb_put/2 and bb_get/2,
which is module local, and BTW will not work in multi-threading,
if it has SICStus semantics it is for "blackboard" communication
between multiple threads. The bb_ stands for "blackboard". So its
not thread-local. What is Scryer Prolog thinking?
Anyway, here some performance:
/* Scryer Prolog "v0.9.0-175-g6b8e6204" */
?- use_module(library(iso_ext)).
true.
?- time((call_nth((between(1,1000,_),call_nth(between(1,1000,_),_)),_), fail; true)).
% CPU time: 4.719s
true.
/* Dogelog Player 1.0.2, nodejs */
?- ensure_loaded(library(sequence)).
true.
?- time((call_nth((between(1,1000,_),call_nth(between(1,1000,_),_)),_), fail; true)).
% Wall 1763 ms, gc 4 ms, 6250971 lips
true.
/* SWI-Prolog, 8.5.14 */
?- time((call_nth((between(1,1000,_),call_nth(between(1,1000,_),_)),_), fail; true)).
% 5,002,004 inferences, 0.484 CPU in 0.473 seconds (102% CPU, 10326718 Lips) true.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Wed Aug 31 03:04:35 2022
The implementation goes:
bb_put(Key, Value) :-
( atom(Key) ->
'$store_global_var'(Key, Value)
; type_error(atom, Key, bb_put/2)
).
And then bb_put/2 is used in Scryer Prologs call_nth/2.
How do you want to use this in a multi-threaded Prolog system?
LMAO!
Mostowski Collapse schrieb am Mittwoch, 31. August 2022 um 11:59:37 UTC+2:
Was refactoring Dogelog Player. It has now a couple
of libraries, making use of the new system_url to fetch them.
- library(compat): New idea of a library, has things like tab/1.
- library(sequence): Reduced library(adanced/sequence) from formerly Jekejeke Prolog.
- library(aggregate): Reduced library(adanced/aggregate) from formerly Jekejeke Prolog.
- library(lists): Like library(basic/lists) from formerly Jekejeke Prolog.
library(sequence) and library(aggregate) are implemented via
the new change_arg/3 in Dogelog Player, unlike Jekejeke Prolog
which uses some Java pivot datastructure.
The new system_url to fetch does not change Dogelog Player
performance. Dogelog Player is still not an extremly fast
Prolog system, it might beat Tau Prolog but otherwise it has
rather modest performance. But change_arg/3 gives nice
performance. Its the better solution than bb_put/2 and bb_get/2,
which is module local, and BTW will not work in multi-threading,
if it has SICStus semantics it is for "blackboard" communication
between multiple threads. The bb_ stands for "blackboard". So its
not thread-local. What is Scryer Prolog thinking?
Anyway, here some performance:
/* Scryer Prolog "v0.9.0-175-g6b8e6204" */
?- use_module(library(iso_ext)).
true.
?- time((call_nth((between(1,1000,_),call_nth(between(1,1000,_),_)),_), fail; true)).
% CPU time: 4.719s
true.
/* Dogelog Player 1.0.2, nodejs */
?- ensure_loaded(library(sequence)).
true.
?- time((call_nth((between(1,1000,_),call_nth(between(1,1000,_),_)),_), fail; true)).
% Wall 1763 ms, gc 4 ms, 6250971 lips
true.
/* SWI-Prolog, 8.5.14 */
?- time((call_nth((between(1,1000,_),call_nth(between(1,1000,_),_)),_), fail; true)).
% 5,002,004 inferences, 0.484 CPU in 0.473 seconds (102% CPU, 10326718 Lips) true.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Wed Aug 31 10:22:30 2022
So a Code Playground where you can
simply do the following, as currently
available from dogelog.js:
<script type="application/x-dogelog">
... Dogelog Player code goes here ...
</script>
Is much simpler. Thanks to the Novacore,
if I have time, I will maybe provide also:
<script type="application/x-swi">
... SWI-Prolog code goes here ...
</script>
<script type="application/x-ciao">
... Ciao Prolog code goes here ...
</script>
And if in 100 years from now, the stubborn
Prolog community has decided on some PEPs,
could maybe even do:
<script type="application/x-prolog">
... Prolog code goes here ...
</script>
Mostowski Collapse schrieb am Mittwoch, 31. August 2022 um 19:18:28 UTC+2:
End-users have really problems with embeding
Prolog into HTML pages by themself. For example
an simple advice as follows from Tau Prolog:
get_by_id(writeme, WriteMe),
open(WriteMe, write, Stream),
set_output(Stream),
...
write(Formula)
doesn't work, when the stream does a
innerHTML += for the writeme element. What
would then be needed is:
get_by_id(writeme, WriteMe),
open(WriteMe, write, Stream),
set_output(Stream),
...
term_atom(Formula, FormulaAtom),
xml_ecape(FormulaAtom, FormulaEscaped),
write(FormulaEscaped)
I guess xml_escape/2 exists already since
1990's when the world's first web server, was
developed and implemented by Berners-Lee
on a NeXTcube computer. But its even
worse, does Tau Prolog have a term_atom/2?
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
All on Wed Aug 31 10:18:27 2022
End-users have really problems with embeding
Prolog into HTML pages by themself. For example
an simple advice as follows from Tau Prolog:
get_by_id(writeme, WriteMe),
open(WriteMe, write, Stream),
set_output(Stream),
...
write(Formula)
doesn't work, when the stream does a
innerHTML += for the writeme element. What
would then be needed is:
get_by_id(writeme, WriteMe),
open(WriteMe, write, Stream),
set_output(Stream),
...
term_atom(Formula, FormulaAtom),
xml_ecape(FormulaAtom, FormulaEscaped),
write(FormulaEscaped)
I guess xml_escape/2 exists already since
1990's when the world's first web server, was
developed and implemented by Berners-Lee
on a NeXTcube computer. But its even
worse, does Tau Prolog have a term_atom/2?
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
All on Sun Oct 9 16:06:07 2022
I would like to have nice test cases for Novacore.
For sure floats would be part of Novacore. SWI-Prolog
publish its new release 8.5.18. And it says it does now
do to_nearest rouding more consequently. What does
that mean? Wiki tells me there are at least two “to nearest”:
- Round to nearest, ties to even – rounds to the nearest value;
if the number falls midway, it is rounded to the nearest value
with an even least significant digit.
- Round to nearest, ties away from zero (or ties to away) – rounds
to the nearest value; if the number falls midway, it is rounded to
the nearest value above (for positive numbers) or below (for negative numbers).
https://en.wikipedia.org/wiki/IEEE_754#Roundings_to_nearest 1
But then in Java BigDecimal there are even 3 “to nearest”,
HALF_EVEN, HALF_UP and HALF_DOWN.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Sun Oct 9 16:12:38 2022
I guess the to_nearest should be HALF_EVEN. Was
lazy making manual test cases, so used a fuzzer.
The fuzzer test cases might not be that good, especially
for HALF_EVEN, since they might not pick up the border
cases, but nevertheless its a first start. Might do more
test cases. The test cases are simply:
fuzzer :-
L is -(1<<100),
H is (1<<100)+1,
between(1, 100, N),
random(L, H, X),
Y is float(X),
write(case(N, X, Y)), write('.'), nl,
fail.
fuzzer.
My Prolog systems, formerly Jekejeke Prolog and
Dogelog Player on its various target platforms, all
pass these test cases.
Mostowski Collapse schrieb am Montag, 10. Oktober 2022 um 01:06:09 UTC+2:
I would like to have nice test cases for Novacore.
For sure floats would be part of Novacore. SWI-Prolog
publish its new release 8.5.18. And it says it does now
do to_nearest rouding more consequently. What does
that mean? Wiki tells me there are at least two “to nearest”:
- Round to nearest, ties to even – rounds to the nearest value;
if the number falls midway, it is rounded to the nearest value
with an even least significant digit.
- Round to nearest, ties away from zero (or ties to away) – rounds
to the nearest value; if the number falls midway, it is rounded to
the nearest value above (for positive numbers) or below (for negative numbers).
https://en.wikipedia.org/wiki/IEEE_754#Roundings_to_nearest 1
But then in Java BigDecimal there are even 3 “to nearest”,
HALF_EVEN, HALF_UP and HALF_DOWN.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Sun Oct 9 16:13:45 2022
Here are some very first results for other Prolog systems:
/* SWI-Prolog 8.5.18 (Windows and WASM) Ok */
?- case(N, X, Y), Y =\= float(X).
false.
/* Trealla Prolog 2.4.3 Ok */
?- case(N, X, Y), Y =\= float(X).
false.
/* Scryer Prolog 0.9.0 Nok */
?- case(N, X, Y), Y =\= float(X).
N = 1, X = -572504891324561953821040518484, Y = -5.7250489132456196e29
; N = 3, X = 884996183305110611102854483978, Y = 8.849961833051106e29
; N = 4, X = 1251939306673717603656775488197, Y = 1.2519393066737177e30
Etc..
So somehow these test cases already do their job!
Mostowski Collapse schrieb am Montag, 10. Oktober 2022 um 01:12:39 UTC+2:
I guess the to_nearest should be HALF_EVEN. Was
lazy making manual test cases, so used a fuzzer.
The fuzzer test cases might not be that good, especially
for HALF_EVEN, since they might not pick up the border
cases, but nevertheless its a first start. Might do more
test cases. The test cases are simply:
fuzzer :-
L is -(1<<100),
H is (1<<100)+1,
between(1, 100, N),
random(L, H, X),
Y is float(X),
write(case(N, X, Y)), write('.'), nl,
fail.
fuzzer.
My Prolog systems, formerly Jekejeke Prolog and
Dogelog Player on its various target platforms, all
pass these test cases.
Mostowski Collapse schrieb am Montag, 10. Oktober 2022 um 01:06:09 UTC+2:
I would like to have nice test cases for Novacore.
For sure floats would be part of Novacore. SWI-Prolog
publish its new release 8.5.18. And it says it does now
do to_nearest rouding more consequently. What does
that mean? Wiki tells me there are at least two “to nearest”:
- Round to nearest, ties to even – rounds to the nearest value;
if the number falls midway, it is rounded to the nearest value
with an even least significant digit.
- Round to nearest, ties away from zero (or ties to away) – rounds
to the nearest value; if the number falls midway, it is rounded to
the nearest value above (for positive numbers) or below (for negative numbers).
https://en.wikipedia.org/wiki/IEEE_754#Roundings_to_nearest 1
But then in Java BigDecimal there are even 3 “to nearest”,
HALF_EVEN, HALF_UP and HALF_DOWN.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Sun Oct 9 16:14:18 2022
More results:
/* Ciao Prolog 1.22.0 (WSL and WASM) Ok */
?- case(N, X, Y), Y =\= float(X).
no
/* ECLiPSe Prolog 7.0.61 Nok */
?- case(N, X, Y), Y =\= float(X).
N = 1
X = -572504891324561953821040518484
Y = -5.7250489132456196e+29
Etc..
Mostowski Collapse schrieb am Montag, 10. Oktober 2022 um 01:13:46 UTC+2:
Here are some very first results for other Prolog systems:
/* SWI-Prolog 8.5.18 (Windows and WASM) Ok */
?- case(N, X, Y), Y =\= float(X).
false.
/* Trealla Prolog 2.4.3 Ok */
?- case(N, X, Y), Y =\= float(X).
false.
/* Scryer Prolog 0.9.0 Nok */
?- case(N, X, Y), Y =\= float(X).
N = 1, X = -572504891324561953821040518484, Y = -5.7250489132456196e29
; N = 3, X = 884996183305110611102854483978, Y = 8.849961833051106e29
; N = 4, X = 1251939306673717603656775488197, Y = 1.2519393066737177e30 Etc..
So somehow these test cases already do their job!
Mostowski Collapse schrieb am Montag, 10. Oktober 2022 um 01:12:39 UTC+2:
I guess the to_nearest should be HALF_EVEN. Was
lazy making manual test cases, so used a fuzzer.
The fuzzer test cases might not be that good, especially
for HALF_EVEN, since they might not pick up the border
cases, but nevertheless its a first start. Might do more
test cases. The test cases are simply:
fuzzer :-
L is -(1<<100),
H is (1<<100)+1,
between(1, 100, N),
random(L, H, X),
Y is float(X),
write(case(N, X, Y)), write('.'), nl,
fail.
fuzzer.
My Prolog systems, formerly Jekejeke Prolog and
Dogelog Player on its various target platforms, all
pass these test cases.
Mostowski Collapse schrieb am Montag, 10. Oktober 2022 um 01:06:09 UTC+2:
I would like to have nice test cases for Novacore.
For sure floats would be part of Novacore. SWI-Prolog
publish its new release 8.5.18. And it says it does now
do to_nearest rouding more consequently. What does
that mean? Wiki tells me there are at least two “to nearest”:
- Round to nearest, ties to even – rounds to the nearest value;
if the number falls midway, it is rounded to the nearest value
with an even least significant digit.
- Round to nearest, ties away from zero (or ties to away) – rounds
to the nearest value; if the number falls midway, it is rounded to
the nearest value above (for positive numbers) or below (for negative numbers).
https://en.wikipedia.org/wiki/IEEE_754#Roundings_to_nearest 1
But then in Java BigDecimal there are even 3 “to nearest”, HALF_EVEN, HALF_UP and HALF_DOWN.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
All on Sun Oct 9 23:57:41 2022
Here is a better fuzzer, it has a higher mean lsb/1 value,
and therefore mostlikely tests more HALF_EVEN:
?- aggregate_all(sum(N), (case(_,X,_), N is lsb(abs(X))), S), A is S/100.
S = 94,
A = 0.94.
?- aggregate_all(sum(N), (case2(_,X,_), N is lsb(abs(X))), S), A is S/100.
S = 5050,
A = 50.5.
The fiuzzer reads as follows:
fuzzer2 :-
between(1, 100, N),
L is -(1<<N),
H is (1<<N)+1,
random(L, H, X),
Z is X<<(100-N),
Y is float(Z),
write(case2(N, Z, Y)), write('.'), nl,
fail.
fuzzer2.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Sun Oct 9 23:59:41 2022
It indeed trip wires the newest SWI-Prolog:
/* SWI-Prolog 8.5.18 Nok */
?- case2(N, X, Y), Z is float(X), Y =\= Z.
N = 56,
X = -1190359501396335678156200476672,
Y = -1.1903595013963357e+30,
Z = -1.1903595013963356e+30 ;
false.
The test case is ok in all my systems, like formerly
Jekejeke Prolog and Dogelog Player. The test
case is also ok here:
/* Trealla Prolog 2.4.3 Ok */
?- case2(N, X, Y), Y =\= float(X).
false.
/* Ciao Prolog 1.22.0 Ok */
?- case2(N, X, Y), Y =\= float(X).
no
Mostowski Collapse schrieb am Montag, 10. Oktober 2022 um 08:57:43 UTC+2:
Here is a better fuzzer, it has a higher mean lsb/1 value,
and therefore mostlikely tests more HALF_EVEN:
?- aggregate_all(sum(N), (case(_,X,_), N is lsb(abs(X))), S), A is S/100.
S = 94,
A = 0.94.
?- aggregate_all(sum(N), (case2(_,X,_), N is lsb(abs(X))), S), A is S/100.
S = 5050,
A = 50.5.
The fiuzzer reads as follows:
fuzzer2 :-
between(1, 100, N),
L is -(1<<N),
H is (1<<N)+1,
random(L, H, X),
Z is X<<(100-N),
Y is float(Z),
write(case2(N, Z, Y)), write('.'), nl,
fail.
fuzzer2.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Wed Oct 12 05:11:15 2022
There are much more tripwires, and its not
related to negative bigints per se:
/* SWI-Prolog 8.5.18 */
?- case3(N, X, Y), Y =\= float(X).
N = 12,
X = 548500250785140154065267720192,
Y = 5.485002507851401e+29 ;
N = 37,
X = 503487689179869862254742601728,
Y = 5.034876891798698e+29 ;
N = 44,
X = -828141981914306499269539921920,
Y = -8.281419819143066e+29 ;
N = 69,
X = -124851129191269336172294307840,
Y = -1.2485112919126934e+29 ;
N = 95,
X = 594779305038924597107611402240,
Y = 5.9477930503892456e+29 ;
false.
Interesting? Thats probably some material fur
further analysis. Need to reactivate my SWI-Prolog
based float_half_even/2. If you analyse the
float_half_even/2 you could find the execution
paths that these examples are using and whether
there is something in common. But this only works
if your system uses fast path float/1, if it uses
a rational number based bigint to float conversion,
the analysis possibly not so helpful. Although a
rational number based float conversion might
show some denominator in the form 2^k, for
some k, and yet all its logic could be translated
to getbit/1, lsb/1, etc..
Mostowski Collapse schrieb am Montag, 10. Oktober 2022 um 08:59:43 UTC+2:
It indeed trip wires the newest SWI-Prolog:
/* SWI-Prolog 8.5.18 Nok */
?- case2(N, X, Y), Z is float(X), Y =\= Z.
N = 56,
X = -1190359501396335678156200476672,
Y = -1.1903595013963357e+30,
Z = -1.1903595013963356e+30 ;
false.
The test case is ok in all my systems, like formerly
Jekejeke Prolog and Dogelog Player. The test
case is also ok here:
/* Trealla Prolog 2.4.3 Ok */
?- case2(N, X, Y), Y =\= float(X).
false.
/* Ciao Prolog 1.22.0 Ok */
?- case2(N, X, Y), Y =\= float(X).
no
Mostowski Collapse schrieb am Montag, 10. Oktober 2022 um 08:57:43 UTC+2:
Here is a better fuzzer, it has a higher mean lsb/1 value,
and therefore mostlikely tests more HALF_EVEN:
?- aggregate_all(sum(N), (case(_,X,_), N is lsb(abs(X))), S), A is S/100.
S = 94,
A = 0.94.
?- aggregate_all(sum(N), (case2(_,X,_), N is lsb(abs(X))), S), A is S/100. S = 5050,
A = 50.5.
The fiuzzer reads as follows:
fuzzer2 :-
between(1, 100, N),
L is -(1<<N),
H is (1<<N)+1,
random(L, H, X),
Z is X<<(100-N),
Y is float(Z),
write(case2(N, Z, Y)), write('.'), nl,
fail.
fuzzer2.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
All on Wed Oct 12 10:46:57 2022
Some suspicion about the random number skewing.
Mostlikely #define MAX_URANDOMM_ITER is too low. See
here what GMP does. And it then falls back to low quality result:
if (count == 0)
/* Too many iterations; return result mod n == result - n */
mpn_sub_n (rp, rp, np, size);
https://salsa.debian.org/science-team/gmp/-/blob/master/mpz/urandomm.c
Note that the example interval [0…2^n+1) is a very nasty non power
of 2 interval. That I was using a nasty interval was rather not planned,
when writing the fuzzer, just some accident.
In my implementation I have no MAX_URANDOMM_ITER limit.
My suspiciion, therefore it generates a better probability shaping
on my side, which can be even measured,
already for 100 bits? Is this the reason? Or its some other bug
in mpz_urandomm() caused by the last limb cmp juggling?
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Wed Oct 12 10:48:04 2022
I didn’t test the random/1 evaluable function in Trealla and Cliao yet. Cannot run the same test case in Trealla Prolog or Ciao Prolog,
too much stuff missing:
- Trealla Prolog: Didn’t find bigint random.
- Ciao Prolog: Found some random, with an incompatible
protocol to SWI-Prolog, different meaning of the parameters,
but there is so much other stuff missing, like
msb/1, aggregate_all/3, etc…
Mostowski Collapse schrieb am Mittwoch, 12. Oktober 2022 um 19:46:58 UTC+2:
Some suspicion about the random number skewing.
Mostlikely #define MAX_URANDOMM_ITER is too low. See
here what GMP does. And it then falls back to low quality result:
if (count == 0)
/* Too many iterations; return result mod n == result - n */
mpn_sub_n (rp, rp, np, size); https://salsa.debian.org/science-team/gmp/-/blob/master/mpz/urandomm.c
Note that the example interval [0…2^n+1) is a very nasty non power
of 2 interval. That I was using a nasty interval was rather not planned, when writing the fuzzer, just some accident.
In my implementation I have no MAX_URANDOMM_ITER limit.
My suspiciion, therefore it generates a better probability shaping
on my side, which can be even measured,
already for 100 bits? Is this the reason? Or its some other bug
in mpz_urandomm() caused by the last limb cmp juggling?
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Wed Oct 12 13:22:28 2022
On Ciao Prolog its:
random(0,M,...)
On SWI-Prolog its:
random(0,M+1,...)
Should there be a discussion about random/3, its protocoll?
I don’t know, what are the plans of Ciao Prolog and SWI-Prolog?
I don’t know? Is there a road map? I don’t know.
Recently SWI-Prolog deprecated random/3 and introduced
random_between/3 with a different protocoll. Maybe this can
point the way forward? I am more interested about the
skewness here, and not the protcoll of some random API.
Skewed shouldn’t mean screwed. Its quite possible that a
skewed random generator can be fixed.
Mostowski Collapse schrieb am Mittwoch, 12. Oktober 2022 um 19:48:05 UTC+2:
I didn’t test the random/1 evaluable function in Trealla and Cliao yet. Cannot run the same test case in Trealla Prolog or Ciao Prolog,
too much stuff missing:
- Trealla Prolog: Didn’t find bigint random.
- Ciao Prolog: Found some random, with an incompatible
protocol to SWI-Prolog, different meaning of the parameters,
but there is so much other stuff missing, like
msb/1, aggregate_all/3, etc…
Mostowski Collapse schrieb am Mittwoch, 12. Oktober 2022 um 19:46:58 UTC+2:
Some suspicion about the random number skewing.
Mostlikely #define MAX_URANDOMM_ITER is too low. See
here what GMP does. And it then falls back to low quality result:
if (count == 0)
/* Too many iterations; return result mod n == result - n */
mpn_sub_n (rp, rp, np, size); https://salsa.debian.org/science-team/gmp/-/blob/master/mpz/urandomm.c
Note that the example interval [0…2^n+1) is a very nasty non power
of 2 interval. That I was using a nasty interval was rather not planned, when writing the fuzzer, just some accident.
In my implementation I have no MAX_URANDOMM_ITER limit.
My suspiciion, therefore it generates a better probability shaping
on my side, which can be even measured,
already for 100 bits? Is this the reason? Or its some other bug
in mpz_urandomm() caused by the last limb cmp juggling?
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Thu Oct 13 05:53:44 2022
So maybe the requirement is eclectic? A non skewed
random ganerator for bigints. Often power of 2 is only
required or smallint is enough.
Ha Ha, a Casino website could be interested that their
random generators are not skewed. Or maybe they even
go for a particular skewed random generator?
What if the users of the Casino website figure out the
skewing and play accordingly? I am thinking of games
like roulette or card games. So its in their own interest?
Legitimacy & Regulation of the RNG
There are a number of independent companies which specialise in iGaming testing.
https://www.casinoguardian.co.uk/casino-guide/random-number-generator/
Mostowski Collapse schrieb am Mittwoch, 12. Oktober 2022 um 22:22:29 UTC+2:
On Ciao Prolog its:
random(0,M,...)
On SWI-Prolog its:
random(0,M+1,...)
Should there be a discussion about random/3, its protocoll?
I don’t know, what are the plans of Ciao Prolog and SWI-Prolog?
I don’t know? Is there a road map? I don’t know.
Recently SWI-Prolog deprecated random/3 and introduced
random_between/3 with a different protocoll. Maybe this can
point the way forward? I am more interested about the
skewness here, and not the protcoll of some random API.
Skewed shouldn’t mean screwed. Its quite possible that a
skewed random generator can be fixed.
Mostowski Collapse schrieb am Mittwoch, 12. Oktober 2022 um 19:48:05 UTC+2:
I didn’t test the random/1 evaluable function in Trealla and Cliao yet. Cannot run the same test case in Trealla Prolog or Ciao Prolog,
too much stuff missing:
- Trealla Prolog: Didn’t find bigint random.
- Ciao Prolog: Found some random, with an incompatible
protocol to SWI-Prolog, different meaning of the parameters,
but there is so much other stuff missing, like
msb/1, aggregate_all/3, etc…
Mostowski Collapse schrieb am Mittwoch, 12. Oktober 2022 um 19:46:58 UTC+2:
Some suspicion about the random number skewing.
Mostlikely #define MAX_URANDOMM_ITER is too low. See
here what GMP does. And it then falls back to low quality result:
if (count == 0)
/* Too many iterations; return result mod n == result - n */
mpn_sub_n (rp, rp, np, size); https://salsa.debian.org/science-team/gmp/-/blob/master/mpz/urandomm.c
Note that the example interval [0…2^n+1) is a very nasty non power
of 2 interval. That I was using a nasty interval was rather not planned, when writing the fuzzer, just some accident.
In my implementation I have no MAX_URANDOMM_ITER limit.
My suspiciion, therefore it generates a better probability shaping
on my side, which can be even measured,
already for 100 bits? Is this the reason? Or its some other bug
in mpz_urandomm() caused by the last limb cmp juggling?
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Thu Oct 13 07:32:07 2022
2 out of 3 Prolog system cannot generate uniform random
bigints? Don't know yet, have to dig deeper. Strange that
the below result has always 100.0:
The error in Ciao Prolog is much larger than in SWI-Prolog,
i.e. the distance to the expected value. Was using this query,
taking into account the different random/3 protocoll, and
manually compensating for the missing aggregate_all/3
and msb/1 evaluable function:
$ ciaosh
Ciao 1.22.0 (2022-09-28 21:20:35 +0200) [LINUXx86_64]
?- use_module(library(between)).
?- ['aggregate.p'].
?- E is (1<<100), M is (1<<101), K is (1<<20),
between(1,10,_), aggregate_all(sum(X),
(between(1,K,_), random(0,M,X)), S),
H is abs(S-E*K), msb(H,J), N is J-20, write(N), nl, fail; true.
100.0
100.0
100.0
100.0
100.0
100.0
100.0
100.0
100.0
100.0
And this helper code (file aggregate.p):
:- use_module(library(numlists)).
:- use_module(library(random)).
aggregate_all(sum(X), G, S) :-
findall(X, G, L),
sum_list(L, S).
msb(X, Y) :- Y is log(X)/log(2).
Mostowski Collapse schrieb am Donnerstag, 13. Oktober 2022 um 14:53:46 UTC+2:
So maybe the requirement is eclectic? A non skewed
random ganerator for bigints. Often power of 2 is only
required or smallint is enough.
Ha Ha, a Casino website could be interested that their
random generators are not skewed. Or maybe they even
go for a particular skewed random generator?
What if the users of the Casino website figure out the
skewing and play accordingly? I am thinking of games
like roulette or card games. So its in their own interest?
Legitimacy & Regulation of the RNG
There are a number of independent companies which specialise in iGaming testing.
https://www.casinoguardian.co.uk/casino-guide/random-number-generator/
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
All on Thu Oct 13 11:16:00 2022
Does the C floating point API have HALF_EVEN default?
Maybe, maybe not. Is there a test case to figure out
what rounding a system, Prolog or not, does, for its
floating point numbers, independent of some bigint
conversion issues? Was trying the folllowing test and got
some surprise. There was first quite some agreement:
/* SWI-Prolog 8.5.18 */
?- X is 665723957508124892951320985600.0+26388279066624.0.
X = 6.65723957508125e+29.
/* Ciao Prolog 1.22.0 */
?- X is 665723957508124892951320985600.0+26388279066624.0.
X = 6.65723957508125e29 ?
/* Trealla Prolog 2.4.3 */
?- X is 665723957508124892951320985600.0+26388279066624.0.
X = 6.65723957508125e+29.
/* Jekejeke Prolog 1.5.5 */
?- X is 665723957508124892951320985600.0+26388279066624.0.
X = 6.65723957508125E29.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Thu Oct 13 11:18:03 2022
But then suddently:
/* Scryer Prolog 0.9.0 */
?- X is 665723957508124892951320985600.0+26388279066624.0.
X = 6.657239575081248e29.
/* ECLiPSe Prolog 7.0.61 */
?- X is 665723957508124892951320985600.0+26388279066624.0.
X = 6.6572395750812482e+29
?- X is 6.6572395750812482e+29-6.65723957508125E29.
X = -140737488355328.0.
Maybe this also explains the divergence in bigint to float conversion.
Maybe they have by accident a misconfigured FPU? Some init call
to the runtime system missing? Or a cheap floating point library?
But one is WSL2 and the other Windows!
Mostowski Collapse schrieb am Donnerstag, 13. Oktober 2022 um 20:16:02 UTC+2:
Does the C floating point API have HALF_EVEN default?
Maybe, maybe not. Is there a test case to figure out
what rounding a system, Prolog or not, does, for its
floating point numbers, independent of some bigint
conversion issues? Was trying the folllowing test and got
some surprise. There was first quite some agreement:
/* SWI-Prolog 8.5.18 */
?- X is 665723957508124892951320985600.0+26388279066624.0.
X = 6.65723957508125e+29.
/* Ciao Prolog 1.22.0 */
?- X is 665723957508124892951320985600.0+26388279066624.0.
X = 6.65723957508125e29 ?
/* Trealla Prolog 2.4.3 */
?- X is 665723957508124892951320985600.0+26388279066624.0.
X = 6.65723957508125e+29.
/* Jekejeke Prolog 1.5.5 */
?- X is 665723957508124892951320985600.0+26388279066624.0.
X = 6.65723957508125E29.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Thu Oct 13 11:36:49 2022
Have to dig deeper, could be a parsing problem.
For the first summand, I get:
/* SWI-Prolog */
?- X is 665723957508124892951320985600.0.
X = 6.65723957508125e+29.
/* ECLiPSe Prolog */
X is 665723957508124892951320985600.0.
X = 6.6572395750812482e+29
I am not yet at a test case, which would give me
some information about rounding.
Mostowski Collapse schrieb am Donnerstag, 13. Oktober 2022 um 20:18:04 UTC+2:
But then suddently:
/* Scryer Prolog 0.9.0 */
?- X is 665723957508124892951320985600.0+26388279066624.0.
X = 6.657239575081248e29.
/* ECLiPSe Prolog 7.0.61 */
?- X is 665723957508124892951320985600.0+26388279066624.0.
X = 6.6572395750812482e+29
?- X is 6.6572395750812482e+29-6.65723957508125E29.
X = -140737488355328.0.
Maybe this also explains the divergence in bigint to float conversion.
Maybe they have by accident a misconfigured FPU? Some init call
to the runtime system missing? Or a cheap floating point library?
But one is WSL2 and the other Windows!
Mostowski Collapse schrieb am Donnerstag, 13. Oktober 2022 um 20:16:02 UTC+2:
Does the C floating point API have HALF_EVEN default?
Maybe, maybe not. Is there a test case to figure out
what rounding a system, Prolog or not, does, for its
floating point numbers, independent of some bigint
conversion issues? Was trying the folllowing test and got
some surprise. There was first quite some agreement:
/* SWI-Prolog 8.5.18 */
?- X is 665723957508124892951320985600.0+26388279066624.0.
X = 6.65723957508125e+29.
/* Ciao Prolog 1.22.0 */
?- X is 665723957508124892951320985600.0+26388279066624.0.
X = 6.65723957508125e29 ?
/* Trealla Prolog 2.4.3 */
?- X is 665723957508124892951320985600.0+26388279066624.0.
X = 6.65723957508125e+29.
/* Jekejeke Prolog 1.5.5 */
?- X is 665723957508124892951320985600.0+26388279066624.0.
X = 6.65723957508125E29.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Thu Oct 13 13:28:52 2022
Looks like my system belongs to the 2 system that
cannot generate good random numbers? I guess the
system with a smaller value is possible the less good
random generator, because some periodicity was hit.
Java uses a Lehmer algorithm which has a very short
period and uses very few bits in its state. On the other
hand the Twister uses quite some bits I guess, and has
a much larger periodicity. Twister would be therefore the
better randum number generator.
Mostowski Collapse schrieb am Donnerstag, 13. Oktober 2022 um 20:36:51 UTC+2:
Have to dig deeper, could be a parsing problem.
For the first summand, I get:
/* SWI-Prolog */
?- X is 665723957508124892951320985600.0.
X = 6.65723957508125e+29.
/* ECLiPSe Prolog */
X is 665723957508124892951320985600.0.
X = 6.6572395750812482e+29
I am not yet at a test case, which would give me
some information about rounding.
Mostowski Collapse schrieb am Donnerstag, 13. Oktober 2022 um 20:18:04 UTC+2:
But then suddently:
/* Scryer Prolog 0.9.0 */
?- X is 665723957508124892951320985600.0+26388279066624.0.
X = 6.657239575081248e29.
/* ECLiPSe Prolog 7.0.61 */
?- X is 665723957508124892951320985600.0+26388279066624.0.
X = 6.6572395750812482e+29
?- X is 6.6572395750812482e+29-6.65723957508125E29.
X = -140737488355328.0.
Maybe this also explains the divergence in bigint to float conversion. Maybe they have by accident a misconfigured FPU? Some init call
to the runtime system missing? Or a cheap floating point library?
But one is WSL2 and the other Windows!
Mostowski Collapse schrieb am Donnerstag, 13. Oktober 2022 um 20:16:02 UTC+2:
Does the C floating point API have HALF_EVEN default?
Maybe, maybe not. Is there a test case to figure out
what rounding a system, Prolog or not, does, for its
floating point numbers, independent of some bigint
conversion issues? Was trying the folllowing test and got
some surprise. There was first quite some agreement:
/* SWI-Prolog 8.5.18 */
?- X is 665723957508124892951320985600.0+26388279066624.0.
X = 6.65723957508125e+29.
/* Ciao Prolog 1.22.0 */
?- X is 665723957508124892951320985600.0+26388279066624.0.
X = 6.65723957508125e29 ?
/* Trealla Prolog 2.4.3 */
?- X is 665723957508124892951320985600.0+26388279066624.0.
X = 6.65723957508125e+29.
/* Jekejeke Prolog 1.5.5 */
?- X is 665723957508124892951320985600.0+26388279066624.0.
X = 6.65723957508125E29.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
All on Fri Oct 14 01:41:43 2022
Now turning my attention to (/)/2. SWI-Prolog wants me
to use set_prolog_flag(iso, true), to get the semantics
of the ISO core standard, page 116.
But the fuzzer still finds the needle in the haystack.
Using more bits to the numerator, and I find:
/* Jekejeke Prolog 1.5.5 */
?- X is -15915286457581575168 / -238455449856.
X = 6.674322800000001E7.
/* SWI-Prolog 8.5.18 */
?- current_prolog_flag(iso, X).
X = true.
?- X is -15915286457581575168 / -238455449856.
X = 66743227.99999999.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Fri Oct 14 01:43:30 2022
Now I have test cases so nasty, even Ciao Prolog and
SICStus Prolog are stumbling. Interestingly Ciao Prolog
and SICStus Prolog stumble at the exact same test cases.
/* Ciao Prolog 1.22.0 */
?- case4(N, P, Q, Y), Z is P/Q, Y =\= Z.
N = 3,
P = -138732791312937296168,
Q = 70775453,
Y = -1960182315087.9346,
Z = -1960182315087.9343 ? ;
no
/* SICStus Prolog 4.7.1 */
?- case4(N, P, Q, Y), Z is P/Q, Y =\= Z.
N = 3,
P = -138732791312937296168,
Q = 70775453,
Y = -1960182315087.9346,
Z = -1960182315087.9343 ? ;
no
Mostowski Collapse schrieb am Freitag, 14. Oktober 2022 um 10:41:45 UTC+2:
Now turning my attention to (/)/2. SWI-Prolog wants me
to use set_prolog_flag(iso, true), to get the semantics
of the ISO core standard, page 116.
But the fuzzer still finds the needle in the haystack.
Using more bits to the numerator, and I find:
/* Jekejeke Prolog 1.5.5 */
?- X is -15915286457581575168 / -238455449856.
X = 6.674322800000001E7.
/* SWI-Prolog 8.5.18 */
?- current_prolog_flag(iso, X).
X = true.
?- X is -15915286457581575168 / -238455449856.
X = 66743227.99999999.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Fri Oct 14 07:41:40 2022
Last chapter of the testing campaign. Testing (**)/2 now.
BTW, this is a little cringe what the fuzzer found for Dogelog
Player on Python. One can try Python 3.11 and will get:
Python 3.11.0rc1 (main, Aug 8 2022, 11:30:54)
396** -1
0.002525252525252525
1/396
0.0025252525252525255
Same test case that makes SICStus Prolog tumbling. Such
surprises lower the pain of testing, make it rather addictive.
Mostowski Collapse schrieb am Freitag, 14. Oktober 2022 um 10:43:32 UTC+2:
Now I have test cases so nasty, even Ciao Prolog and
SICStus Prolog are stumbling. Interestingly Ciao Prolog
and SICStus Prolog stumble at the exact same test cases.
/* Ciao Prolog 1.22.0 */
?- case4(N, P, Q, Y), Z is P/Q, Y =\= Z.
N = 3,
P = -138732791312937296168,
Q = 70775453,
Y = -1960182315087.9346,
Z = -1960182315087.9343 ? ;
no
/* SICStus Prolog 4.7.1 */
?- case4(N, P, Q, Y), Z is P/Q, Y =\= Z.
N = 3,
P = -138732791312937296168,
Q = 70775453,
Y = -1960182315087.9346,
Z = -1960182315087.9343 ? ;
no
Mostowski Collapse schrieb am Freitag, 14. Oktober 2022 um 10:41:45 UTC+2:
Now turning my attention to (/)/2. SWI-Prolog wants me
to use set_prolog_flag(iso, true), to get the semantics
of the ISO core standard, page 116.
But the fuzzer still finds the needle in the haystack.
Using more bits to the numerator, and I find:
/* Jekejeke Prolog 1.5.5 */
?- X is -15915286457581575168 / -238455449856.
X = 6.674322800000001E7.
/* SWI-Prolog 8.5.18 */
?- current_prolog_flag(iso, X).
X = true.
?- X is -15915286457581575168 / -238455449856.
X = 66743227.99999999.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
All on Sat Oct 15 14:30:26 2022
Next challenge, how to keep my comparison matrice
small. There are so many JavaScript platforms, nodeJS,
browsers, and WTF they differ:
/* Chrome Windows Nok */
?- X is 1889**29.
X = 1.0250068783051206E95.
/* FireFox Windows Ok */
?- X is 1889**29.
X = 1.0250068783051207E95.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Wed Oct 19 07:50:22 2022
Theoretically in the intersection, when the arguments are already
52 bit mantissa, there should be no difference in speed and also
no difference in accuracy, except if the second mode is
also required to return more bits. So we also have for the
first mode the result is **always** required to be only a float.
Then there is mostlikely always a speed difference, and the
first mode is always faster and less accurate.
Mostowski Collapse schrieb am Mittwoch, 19. Oktober 2022 um 16:42:37 UTC+2:
Whats the Novacore bigint versus float mantra? The difference
between the two notions “less precise and more speed” versus
“more precise and less speed” can be maybe capture as follows:
- Less Precise and More Speed: Even if the arguments are bigint, and
have potentially more than 52 bit mantissa, they are always first
converted to float. So that the operation is only performed with 52
bit arguments, allow for faster processing.
- More Precise and Less Speed: If the arguments are bigint or if
the arguments are rational numbers or arbitrary floats, all bits are
taken into account. So that the operation is performed with more bits
than only 52 bits, resulting in slower processing.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
All on Wed Oct 19 07:42:35 2022
Whats the Novacore bigint versus float mantra? The difference
between the two notions “less precise and more speed” versus
“more precise and less speed” can be maybe capture as follows:
- Less Precise and More Speed: Even if the arguments are bigint, and
have potentially more than 52 bit mantissa, they are always first
converted to float. So that the operation is only performed with 52
bit arguments, allow for faster processing.
- More Precise and Less Speed: If the arguments are bigint or if
the arguments are rational numbers or arbitrary floats, all bits are
taken into account. So that the operation is performed with more bits
than only 52 bits, resulting in slower processing.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Wed Oct 19 07:51:44 2022
Ok did some performance measurement. Basically used this harness.
Was reusing the test data, that was used for accuracy testing, so its
based on the same cases.p file:
% swi_perf
swi_perf :-
write('case, swi: '), time((between(1,20000,_),
case(_, X, Y), Y =\= float(X), fail; true)),
write('case2, swi: '), time((between(1,20000,_),
case2(_, X, Y), Y =\= float(X), fail; true)),
write('case3, swi: '), time((between(1,20000,_),
case3(_, X, Y), Y =\= float(X), fail; true)),
write('case4, swi: '), time((between(1,20000,_),
case4(_, P, Q, Y), Y =\= P/Q, fail; true)),
write('case5, swi: '), time((between(1,20000,_),
case5(_, P, Q, Y), Y =\= P/Q, fail; true)),
write('case6, swi: '), time((between(1,20000,_),
case6(_, P, Q, Y), Y =\= P**Q, fail; true)).
Mostowski Collapse schrieb am Mittwoch, 19. Oktober 2022 um 16:42:37 UTC+2:
Whats the Novacore bigint versus float mantra? The difference
between the two notions “less precise and more speed” versus
“more precise and less speed” can be maybe capture as follows:
- Less Precise and More Speed: Even if the arguments are bigint, and
have potentially more than 52 bit mantissa, they are always first
converted to float. So that the operation is only performed with 52
bit arguments, allow for faster processing.
- More Precise and Less Speed: If the arguments are bigint or if
the arguments are rational numbers or arbitrary floats, all bits are
taken into account. So that the operation is performed with more bits
than only 52 bits, resulting in slower processing.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Wed Oct 19 07:52:40 2022
Woa! My Jekejeke Prolog (was using JDK 1.8) is quite a number cruncher,
on the other hand Dogelog Player (was using nodeJS) is lacking behind. Inbetween the result of Prolog systems that I tested, results in milliseconds.
System case case2 case3 case4 case5 case6
jekejeke 270 266 255 305 361 539
ciao 344 343 343 386 386 544
eclipse 414 388 396 518 541 939
trealla 553 547 549 569 565 605
swi 989 941 979 528 532 861
scryer 889 857 872 1177 1188 1147
sicstus 1087 1083 1104 1221 1218 1226
dogelog 1171 1163 1171 1241 1300 1330
Mostowski Collapse schrieb am Mittwoch, 19. Oktober 2022 um 16:51:45 UTC+2:
Ok did some performance measurement. Basically used this harness.
Was reusing the test data, that was used for accuracy testing, so its
based on the same cases.p file:
% swi_perf
swi_perf :-
write('case, swi: '), time((between(1,20000,_),
case(_, X, Y), Y =\= float(X), fail; true)),
write('case2, swi: '), time((between(1,20000,_),
case2(_, X, Y), Y =\= float(X), fail; true)),
write('case3, swi: '), time((between(1,20000,_),
case3(_, X, Y), Y =\= float(X), fail; true)),
write('case4, swi: '), time((between(1,20000,_),
case4(_, P, Q, Y), Y =\= P/Q, fail; true)),
write('case5, swi: '), time((between(1,20000,_),
case5(_, P, Q, Y), Y =\= P/Q, fail; true)),
write('case6, swi: '), time((between(1,20000,_),
case6(_, P, Q, Y), Y =\= P**Q, fail; true)).
Mostowski Collapse schrieb am Mittwoch, 19. Oktober 2022 um 16:42:37 UTC+2:
Whats the Novacore bigint versus float mantra? The difference
between the two notions “less precise and more speed” versus
“more precise and less speed” can be maybe capture as follows:
- Less Precise and More Speed: Even if the arguments are bigint, and
have potentially more than 52 bit mantissa, they are always first converted to float. So that the operation is only performed with 52
bit arguments, allow for faster processing.
- More Precise and Less Speed: If the arguments are bigint or if
the arguments are rational numbers or arbitrary floats, all bits are
taken into account. So that the operation is performed with more bits
than only 52 bits, resulting in slower processing.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Wed Oct 19 18:58:36 2022
Explanation of the defect:
Mostly based on code from Torbjorn Granlund, Johan Andersson,
and Mats Carlsson (Ref: Knuth vol. 2 sec. 4.3.1)
flt64_t bn_to_float(bignum_t *bn) {
while (i > 1) {
f = f*norm2 + u;
https://github.com/ciao -lang/ciao/blob/master/core/engine/eng_bignum.c#L1043
I think a defect could be if HALF_EVEN prematurely
rounds down the value of f, and then later a value of u,
would indicate that this rounding down was not legit,
but float addition cannot help it.
Mostowski Collapse schrieb am Donnerstag, 20. Oktober 2022 um 03:55:47 UTC+2:
Code inspection sometimes helps find defects:
/* Jekejeke Prolog Ok */
?- X is (2^53+1)*2^64+1, Y is float(X).
X = 166153499473114502559719956244594689, Y = 1.6615349947311452E35.
/* SWI-Prolog 8.5.20 Ok */
?- X is float(166153499473114502559719956244594689).
X = 1.6615349947311452e+35.
/* Ciao Prolog Nok */
?- X is float(166153499473114502559719956244594689).
X = 1.661534994731145e35 ?
Pitty my fuzzer didn't find it. But I guess I will manually add it.
Mostowski Collapse schrieb am Mittwoch, 19. Oktober 2022 um 16:52:41 UTC+2:
Woa! My Jekejeke Prolog (was using JDK 1.8) is quite a number cruncher,
on the other hand Dogelog Player (was using nodeJS) is lacking behind. Inbetween the result of Prolog systems that I tested, results in milliseconds.
System case case2 case3 case4 case5 case6
jekejeke 270 266 255 305 361 539
ciao 344 343 343 386 386 544
eclipse 414 388 396 518 541 939
trealla 553 547 549 569 565 605
swi 989 941 979 528 532 861
scryer 889 857 872 1177 1188 1147
sicstus 1087 1083 1104 1221 1218 1226
dogelog 1171 1163 1171 1241 1300 1330
Mostowski Collapse schrieb am Mittwoch, 19. Oktober 2022 um 16:51:45 UTC+2:
Ok did some performance measurement. Basically used this harness.
Was reusing the test data, that was used for accuracy testing, so its based on the same cases.p file:
% swi_perf
swi_perf :-
write('case, swi: '), time((between(1,20000,_),
case(_, X, Y), Y =\= float(X), fail; true)),
write('case2, swi: '), time((between(1,20000,_),
case2(_, X, Y), Y =\= float(X), fail; true)),
write('case3, swi: '), time((between(1,20000,_),
case3(_, X, Y), Y =\= float(X), fail; true)),
write('case4, swi: '), time((between(1,20000,_),
case4(_, P, Q, Y), Y =\= P/Q, fail; true)),
write('case5, swi: '), time((between(1,20000,_),
case5(_, P, Q, Y), Y =\= P/Q, fail; true)),
write('case6, swi: '), time((between(1,20000,_),
case6(_, P, Q, Y), Y =\= P**Q, fail; true)).
Mostowski Collapse schrieb am Mittwoch, 19. Oktober 2022 um 16:42:37 UTC+2:
Whats the Novacore bigint versus float mantra? The difference
between the two notions “less precise and more speed” versus “more precise and less speed” can be maybe capture as follows:
- Less Precise and More Speed: Even if the arguments are bigint, and have potentially more than 52 bit mantissa, they are always first converted to float. So that the operation is only performed with 52 bit arguments, allow for faster processing.
- More Precise and Less Speed: If the arguments are bigint or if
the arguments are rational numbers or arbitrary floats, all bits are taken into account. So that the operation is performed with more bits than only 52 bits, resulting in slower processing.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Wed Oct 19 18:55:45 2022
Code inspection sometimes helps find defects:
/* Jekejeke Prolog Ok */
?- X is (2^53+1)*2^64+1, Y is float(X).
X = 166153499473114502559719956244594689, Y = 1.6615349947311452E35.
/* SWI-Prolog 8.5.20 Ok */
?- X is float(166153499473114502559719956244594689).
X = 1.6615349947311452e+35.
/* Ciao Prolog Nok */
?- X is float(166153499473114502559719956244594689).
X = 1.661534994731145e35 ?
Pitty my fuzzer didn't find it. But I guess I will manually add it.
Mostowski Collapse schrieb am Mittwoch, 19. Oktober 2022 um 16:52:41 UTC+2:
Woa! My Jekejeke Prolog (was using JDK 1.8) is quite a number cruncher,
on the other hand Dogelog Player (was using nodeJS) is lacking behind. Inbetween the result of Prolog systems that I tested, results in milliseconds.
System case case2 case3 case4 case5 case6
jekejeke 270 266 255 305 361 539
ciao 344 343 343 386 386 544
eclipse 414 388 396 518 541 939
trealla 553 547 549 569 565 605
swi 989 941 979 528 532 861
scryer 889 857 872 1177 1188 1147
sicstus 1087 1083 1104 1221 1218 1226
dogelog 1171 1163 1171 1241 1300 1330
Mostowski Collapse schrieb am Mittwoch, 19. Oktober 2022 um 16:51:45 UTC+2:
Ok did some performance measurement. Basically used this harness.
Was reusing the test data, that was used for accuracy testing, so its based on the same cases.p file:
% swi_perf
swi_perf :-
write('case, swi: '), time((between(1,20000,_),
case(_, X, Y), Y =\= float(X), fail; true)),
write('case2, swi: '), time((between(1,20000,_),
case2(_, X, Y), Y =\= float(X), fail; true)),
write('case3, swi: '), time((between(1,20000,_),
case3(_, X, Y), Y =\= float(X), fail; true)),
write('case4, swi: '), time((between(1,20000,_),
case4(_, P, Q, Y), Y =\= P/Q, fail; true)),
write('case5, swi: '), time((between(1,20000,_),
case5(_, P, Q, Y), Y =\= P/Q, fail; true)),
write('case6, swi: '), time((between(1,20000,_),
case6(_, P, Q, Y), Y =\= P**Q, fail; true)).
Mostowski Collapse schrieb am Mittwoch, 19. Oktober 2022 um 16:42:37 UTC+2:
Whats the Novacore bigint versus float mantra? The difference
between the two notions “less precise and more speed” versus
“more precise and less speed” can be maybe capture as follows:
- Less Precise and More Speed: Even if the arguments are bigint, and have potentially more than 52 bit mantissa, they are always first converted to float. So that the operation is only performed with 52
bit arguments, allow for faster processing.
- More Precise and Less Speed: If the arguments are bigint or if
the arguments are rational numbers or arbitrary floats, all bits are taken into account. So that the operation is performed with more bits than only 52 bits, resulting in slower processing.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Wed Oct 19 19:46:48 2022
I added some hand picked test cases, from the
Ciao Prolog blooper, including some negative bigints.
Interestingly other Prolog systems are also pray to the
same blooper. In total I found that 3 Prolog systems have
this blooper, whereas Trealla only for 50%. Here are now
the number of failures from the new test cases:
% case3, trealla: 5
% case3, ciao: 10
% case3, sicstus: 10
Mostowski Collapse schrieb am Donnerstag, 20. Oktober 2022 um 03:58:38 UTC+2:
Explanation of the defect:
Mostly based on code from Torbjorn Granlund, Johan Andersson,
and Mats Carlsson (Ref: Knuth vol. 2 sec. 4.3.1)
flt64_t bn_to_float(bignum_t *bn) {
while (i > 1) {
f = f*norm2 + u;
https://github.com/ciao -lang/ciao/blob/master/core/engine/eng_bignum.c#L1043
I think a defect could be if HALF_EVEN prematurely
rounds down the value of f, and then later a value of u,
would indicate that this rounding down was not legit,
but float addition cannot help it.
Mostowski Collapse schrieb am Donnerstag, 20. Oktober 2022 um 03:55:47 UTC+2:
Code inspection sometimes helps find defects:
/* Jekejeke Prolog Ok */
?- X is (2^53+1)*2^64+1, Y is float(X).
X = 166153499473114502559719956244594689, Y = 1.6615349947311452E35.
/* SWI-Prolog 8.5.20 Ok */
?- X is float(166153499473114502559719956244594689).
X = 1.6615349947311452e+35.
/* Ciao Prolog Nok */
?- X is float(166153499473114502559719956244594689).
X = 1.661534994731145e35 ?
Pitty my fuzzer didn't find it. But I guess I will manually add it. Mostowski Collapse schrieb am Mittwoch, 19. Oktober 2022 um 16:52:41 UTC+2:
Woa! My Jekejeke Prolog (was using JDK 1.8) is quite a number cruncher, on the other hand Dogelog Player (was using nodeJS) is lacking behind. Inbetween the result of Prolog systems that I tested, results in milliseconds.
System case case2 case3 case4 case5 case6
jekejeke 270 266 255 305 361 539
ciao 344 343 343 386 386 544
eclipse 414 388 396 518 541 939
trealla 553 547 549 569 565 605
swi 989 941 979 528 532 861
scryer 889 857 872 1177 1188 1147
sicstus 1087 1083 1104 1221 1218 1226
dogelog 1171 1163 1171 1241 1300 1330
Mostowski Collapse schrieb am Mittwoch, 19. Oktober 2022 um 16:51:45 UTC+2:
Ok did some performance measurement. Basically used this harness.
Was reusing the test data, that was used for accuracy testing, so its based on the same cases.p file:
% swi_perf
swi_perf :-
write('case, swi: '), time((between(1,20000,_),
case(_, X, Y), Y =\= float(X), fail; true)),
write('case2, swi: '), time((between(1,20000,_),
case2(_, X, Y), Y =\= float(X), fail; true)),
write('case3, swi: '), time((between(1,20000,_),
case3(_, X, Y), Y =\= float(X), fail; true)),
write('case4, swi: '), time((between(1,20000,_),
case4(_, P, Q, Y), Y =\= P/Q, fail; true)),
write('case5, swi: '), time((between(1,20000,_),
case5(_, P, Q, Y), Y =\= P/Q, fail; true)),
write('case6, swi: '), time((between(1,20000,_),
case6(_, P, Q, Y), Y =\= P**Q, fail; true)).
Mostowski Collapse schrieb am Mittwoch, 19. Oktober 2022 um 16:42:37 UTC+2:
Whats the Novacore bigint versus float mantra? The difference between the two notions “less precise and more speed” versus “more precise and less speed” can be maybe capture as follows:
- Less Precise and More Speed: Even if the arguments are bigint, and have potentially more than 52 bit mantissa, they are always first converted to float. So that the operation is only performed with 52 bit arguments, allow for faster processing.
- More Precise and Less Speed: If the arguments are bigint or if
the arguments are rational numbers or arbitrary floats, all bits are taken into account. So that the operation is performed with more bits
than only 52 bits, resulting in slower processing.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Tue Oct 25 05:59:10 2022
I have SWIPL on Unix platform only since weekend,
could not do this testing beforehand, so I guess I
need to update case6/3 test cases,
because they showed Unix platform completely
passing, which seems to be wrong. I used in the old
fuzzer 12 bits + 6 bits, the above uses 15 bits + 3 bits,
and new nasty test cases pop up. Its a test case where
JDK 19 non-strict also fails. Cool! I couldn’t believe that
it is that good. It was too good to be true.
So its also not that good!
/* Jekejeke Prolog 1.5.5, JDK 19 non-strict Nok */
?- X is -18573** -7.
X = -1.3116730299820408E-30.
Mostowski Collapse schrieb am Dienstag, 25. Oktober 2022 um 14:56:11 UTC+2:
Woa! My testing campaign has not yet ended. Now I
found a test case, where the Unix platform also fails.
Was increasing the bits in the case6/3 fuzzer:
pow2(B, E, X) :- E < 0, integer(E), !, X is 1/(B^(-E)).
pow2(B, E, X) :- X is B^E.
?- current_prolog_flag(iso, X).
X = false.
/* SWI-Prolog 8.5.20 WLS2 Nok */
?- repeat, L is -(1<<15), H is (1<<15)+1,
M is -(1<<3), J is (1<<3)+1, random(L, H, P),
random(M, J, Q), pow2(P, Q, A), B is P**Q, A=\=B.
P = -18573,
Q = -7,
A = -1.3116730299820406e-30,
B = -1.3116730299820408e-30 .
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
All on Tue Oct 25 05:55:59 2022
Woa! My testing campaign has not yet ended. Now I
found a test case, where the Unix platform also fails.
Was increasing the bits in the case6/3 fuzzer:
pow2(B, E, X) :- E < 0, integer(E), !, X is 1/(B^(-E)).
pow2(B, E, X) :- X is B^E.
?- current_prolog_flag(iso, X).
X = false.
/* SWI-Prolog 8.5.20 WLS2 Nok */
?- repeat, L is -(1<<15), H is (1<<15)+1,
M is -(1<<3), J is (1<<3)+1, random(L, H, P),
random(M, J, Q), pow2(P, Q, A), B is P**Q, A=\=B.
P = -18573,
Q = -7,
A = -1.3116730299820406e-30,
B = -1.3116730299820408e-30 .
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
the Mostowski Collapse on Tue Oct 25 08:36:45 2022
Nope the JDK 19 is correct here. Bug in long division?
/* SWI-Prolog 8.5.20 WSL2 */
?- current_prolog_flag(iso, X).
X = false.
?- X is 1/(18573^7).
X = 1.3116730299820406e-30.
?- X is float(1 rdiv (18573^7)).
X = 1.3116730299820408e-30.
the Mostowski Collapse schrieb am Dienstag, 25. Oktober 2022 um 14:59:11 UTC+2:
I have SWIPL on Unix platform only since weekend,
could not do this testing beforehand, so I guess I
need to update case6/3 test cases,
because they showed Unix platform completely
passing, which seems to be wrong. I used in the old
fuzzer 12 bits + 6 bits, the above uses 15 bits + 3 bits,
and new nasty test cases pop up. Its a test case where
JDK 19 non-strict also fails. Cool! I couldn’t believe that
it is that good. It was too good to be true.
So its also not that good!
/* Jekejeke Prolog 1.5.5, JDK 19 non-strict Nok */
?- X is -18573** -7.
X = -1.3116730299820408E-30.
Mostowski Collapse schrieb am Dienstag, 25. Oktober 2022 um 14:56:11 UTC+2:
Woa! My testing campaign has not yet ended. Now I
found a test case, where the Unix platform also fails.
Was increasing the bits in the case6/3 fuzzer:
pow2(B, E, X) :- E < 0, integer(E), !, X is 1/(B^(-E)).
pow2(B, E, X) :- X is B^E.
?- current_prolog_flag(iso, X).
X = false.
/* SWI-Prolog 8.5.20 WLS2 Nok */
?- repeat, L is -(1<<15), H is (1<<15)+1,
M is -(1<<3), J is (1<<3)+1, random(L, H, P),
random(M, J, Q), pow2(P, Q, A), B is P**Q, A=\=B.
P = -18573,
Q = -7,
A = -1.3116730299820406e-30,
B = -1.3116730299820408e-30 .
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Tue Oct 25 10:53:19 2022
Enhanced test cases, new viewpoint. Now WASM is
the more accurate platform, both for SWI and Ciao.
JDK 19 is still ultra accurate. But I cant say that it
is always correctly rounded. For non-integer arguments
I found a faulty example for (**)/2, but the below test
cases only test integer arguments of (**)/2:
System (=:=)/2 (/)/2 (**)/2 Total Variant
jekejeke 0 0 0 0 JDK 19
dogelog 0 0 2 2 PyPy
swi 0 0 4 4 WASM
sicstus 10 0 2 12 Windows
trealla 5 0 11 16 WSL2
ciao 10 0 10 20 WASM
scryer 33 46 11 90 WSL2
eclipse 33 45 68 146 Windows
Mostowski Collapse schrieb am Dienstag, 25. Oktober 2022 um 17:36:46 UTC+2:
Nope the JDK 19 is correct here. Bug in long division?
/* SWI-Prolog 8.5.20 WSL2 */
?- current_prolog_flag(iso, X).
X = false.
?- X is 1/(18573^7).
X = 1.3116730299820406e-30.
?- X is float(1 rdiv (18573^7)).
X = 1.3116730299820408e-30.
the Mostowski Collapse schrieb am Dienstag, 25. Oktober 2022 um 14:59:11 UTC+2:
I have SWIPL on Unix platform only since weekend,
could not do this testing beforehand, so I guess I
need to update case6/3 test cases,
because they showed Unix platform completely
passing, which seems to be wrong. I used in the old
fuzzer 12 bits + 6 bits, the above uses 15 bits + 3 bits,
and new nasty test cases pop up. Its a test case where
JDK 19 non-strict also fails. Cool! I couldn’t believe that
it is that good. It was too good to be true.
So its also not that good!
/* Jekejeke Prolog 1.5.5, JDK 19 non-strict Nok */
?- X is -18573** -7.
X = -1.3116730299820408E-30.
Mostowski Collapse schrieb am Dienstag, 25. Oktober 2022 um 14:56:11 UTC+2:
Woa! My testing campaign has not yet ended. Now I
found a test case, where the Unix platform also fails.
Was increasing the bits in the case6/3 fuzzer:
pow2(B, E, X) :- E < 0, integer(E), !, X is 1/(B^(-E)).
pow2(B, E, X) :- X is B^E.
?- current_prolog_flag(iso, X).
X = false.
/* SWI-Prolog 8.5.20 WLS2 Nok */
?- repeat, L is -(1<<15), H is (1<<15)+1,
M is -(1<<3), J is (1<<3)+1, random(L, H, P),
random(M, J, Q), pow2(P, Q, A), B is P**Q, A=\=B.
P = -18573,
Q = -7,
A = -1.3116730299820406e-30,
B = -1.3116730299820408e-30 .
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
All on Wed Oct 26 07:01:00 2022
Here is a trick to force Python compatibility mode, I guess
works for SWI-Prolog 8.5.20 which has improved rational
number rounding? Thats the incorrectly rounded result:
/* incorrectly rounded of the real number quotient */
?- X is 1267650600228229401496703205376 /
762385119722780192080867194597.
X = 1.662743103759914.
Now do switch on Python compatibility mode, and
watch the result getting correctly rounded:
/* Use this combo for Python compatibility:
prefer_rationals=true,
max_rational_size=0,
max_rational_size_action=float */
?- set_prolog_flag(prefer_rationals, true).
true.
?- set_prolog_flag(max_rational_size, 0).
true.
?- set_prolog_flag(max_rational_size_action, float).
true.
/* Correctly rounded of the real number quotient, via
detour over rational numbers, which are correctly
rounded since release 8.5.20 of SWI-Prolog? */
?- X is 1267650600228229401496703205376 /
762385119722780192080867194597.
X = 1.6627431037599143.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Wed Oct 26 07:02:13 2022
BTW the real number quotient is this real number:
1267650600228229401496703205376 /
762385119722780192080867194597 =
1.66274310375991431383116365048...
Was using microsoft calculator desk accessory. But
maybe should do more testing of this new Python
mode trick. Nasty test cases might lure everywhere.
Mostowski Collapse schrieb am Mittwoch, 26. Oktober 2022 um 16:01:01 UTC+2:
Here is a trick to force Python compatibility mode, I guess
works for SWI-Prolog 8.5.20 which has improved rational
number rounding? Thats the incorrectly rounded result:
/* incorrectly rounded of the real number quotient */
?- X is 1267650600228229401496703205376 /
762385119722780192080867194597.
X = 1.662743103759914.
Now do switch on Python compatibility mode, and
watch the result getting correctly rounded:
/* Use this combo for Python compatibility:
prefer_rationals=true,
max_rational_size=0,
max_rational_size_action=float */
?- set_prolog_flag(prefer_rationals, true).
true.
?- set_prolog_flag(max_rational_size, 0).
true.
?- set_prolog_flag(max_rational_size_action, float).
true.
/* Correctly rounded of the real number quotient, via
detour over rational numbers, which are correctly
rounded since release 8.5.20 of SWI-Prolog? */
?- X is 1267650600228229401496703205376 /
762385119722780192080867194597.
X = 1.6627431037599143.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
All on Mon Nov 14 14:21:10 2022
My latest take on msb/2, in case a Prolog system
doesn't have this built-in. Some hi lo search:
% msb(+Integer, -Integer)
msb(0, N) :- !, N = -1.
msb(X, N) :-
msb(X, 1, N).
% msb(+Integer, +Integer, -Integer)
msb(X, H, N) :-
X < (1<<H), !,
L is H>>1,
msb(X, L, H, N).
msb(X, H, N) :-
J is H<<1,
msb(X, J, N).
% msb(+Integer, +Integer, +Integer, -Integer)
msb(_, L, H, N) :- L+1 =:= H, !,
N = L.
msb(X, L, H, N) :- M is (L+H) >> 1,
X < (1<<M), !,
msb(X, L, M, N).
msb(X, L, H, N) :- M is (L+H) >> 1,
msb(X, M, H, N).
But it is not a replacement for the real thing.
An msb/1 evaluable function still performs better.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Mon Nov 14 14:31:27 2022
So when will all Prolog system have these basic
evaluable functions and predicates?
msb/1: Return most significant bit of an integer
lsb/1: Return least significant bit of an integer
testbit/2: Succeed if bit of integer is set, otherwise fail.
divmod/4: Succeed with div and mod.
Scryer Prolog doesn't have these built-ins. So emulating
them makes it utterly slow. Using the hi lo approach for msb:
/* Scryer Prolog 0.9.1 WSL2 */
?- member((N,K),[(53,2600),(1024,150),(8192,9)]),
time((between(1,K,_), mp_pi(N, _), fail; true)), fail; true.
% CPU time: 4.240s
% CPU time: 5.621s
% CPU time: 7.718s
% true.
But it seems that bigints are not that fast, with ECLiPSe Prolog
which does not have these built-ins the hi lo isn't that bad:
/* ECLiPSe Prolog 7.1.12 Windows */
?- member((N,K),[(53,2600),(1024,150),(8192,9)]),
time_eclipse((between(1,K,_), mp_pi(N, _), fail; true)), fail; true. 0.904113500000676 sec
1.78132879998884 sec
1.56477859998995 sec
The best is always SWI-Prolog. It picks up trends and provides
functionallity so that the end-user can profit:
/* SWI-Prolog 8.5.20 Windows GMP */
?- member((N,K),[(53,2600),(1024,150),(8192,9)]),
time((between(1,K,_), mp_pi(N, _), fail; true)), fail; true.
% 8,699,603 inferences, 0.875 CPU in 0.879 seconds (100% CPU, 9942403 Lips)
% 7,952,250 inferences, 1.047 CPU in 1.064 seconds (98% CPU, 7596179 Lips)
% 3,771,657 inferences, 0.656 CPU in 0.673 seconds (97% CPU, 5747287 Lips) true.
Whats wrong with the other Prolog systems, such as Scryer
Prolog and ECLiPSe Prolog that don't provide these built-ins?
Are they in a comatose sleeping beauty sleep?
Mostowski Collapse schrieb am Montag, 14. November 2022 um 23:21:11 UTC+1:
My latest take on msb/2, in case a Prolog system
doesn't have this built-in. Some hi lo search:
% msb(+Integer, -Integer)
msb(0, N) :- !, N = -1.
msb(X, N) :-
msb(X, 1, N).
% msb(+Integer, +Integer, -Integer)
msb(X, H, N) :-
X < (1<<H), !,
L is H>>1,
msb(X, L, H, N).
msb(X, H, N) :-
J is H<<1,
msb(X, J, N).
% msb(+Integer, +Integer, +Integer, -Integer)
msb(_, L, H, N) :- L+1 =:= H, !,
N = L.
msb(X, L, H, N) :- M is (L+H) >> 1,
X < (1<<M), !,
msb(X, L, M, N).
msb(X, L, H, N) :- M is (L+H) >> 1,
msb(X, M, H, N).
But it is not a replacement for the real thing.
An msb/1 evaluable function still performs better.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Thu Nov 17 06:08:49 2022
The best I can do for Dogelog Player, concerning
msb/1 and the JavaScript platform. Just imagine
the speed if JavaScript would have a real msb/1
or bitlength/1, so that we don't need this nonsense?
function bigint_msb(alpha) {
alpha = alpha.toString(16);
return 31 - Math.clz32(hexvalue(alpha.codePointAt(0))) + (alpha.length - 1)*4;
}
This is a known problem that bigint has no msb/1 or
bitlength/1 in JavaScript as of now. Nevertheless I now
easily beat Scryer Prolog even with Dogelog Player.
Comparing to the hi lo search msb I get these results:
/* Dogelog Player 1.0.3 Windows nodeJS */
?- member((N,K),[(53,2600),(1024,150),(8192,9)]),
time((between(1,K,_), mp_pi(N, _), fail; true)), fail; true.
% Wall 4136 ms, gc 10 ms, 2539128 lips
% Wall 4346 ms, gc 104 ms, 2219962 lips
% Wall 3876 ms, gc 88 ms, 1180529 lips
true.
Also unlike Scryer Prolog, for larger bigints, i.e. 8192
the timing doesn't go up, it rather goes down. Probably some
alternative bigint multiplication methods etc.. kick in for
larger bigints, and they are missing in Scryer Prolog for
the Rust based bigints? They are still in its fancy? Also
Scryer Prolog would fare better if it had a native msb/1.
Mostowski Collapse schrieb am Montag, 14. November 2022 um 23:31:28 UTC+1:
Scryer Prolog doesn't have these built-ins. So emulating
them makes it utterly slow. Using the hi lo approach for msb:
/* Scryer Prolog 0.9.1 WSL2 */
?- member((N,K),[(53,2600),(1024,150),(8192,9)]),
time((between(1,K,_), mp_pi(N, _), fail; true)), fail; true.
% CPU time: 4.240s
% CPU time: 5.621s
% CPU time: 7.718s
% true.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Thu Nov 17 06:21:31 2022
The effect that computation gets faster for larger bigint
is also seen for Python, when I use the PyPy interpreter.
I guess it has also to do with the effort needed to
promote a smallint to a bigint, either before an operation
or after an operation. Another speculation would be, that
the bigint operations slow down the frequency of my
Dogelog Player garbage collection, since this frequency
is not yet adaptive. But the larger bit test case even
beats Scryer Prolog, now beaten by Python/PyPy:
/* Dogelog Player 1.0.3 Windows PyPy */
?- member((N,K),[(53,2600),(1024,150),(8192,9)]),
time((between(1,K,_), mp_pi(N, _), fail; true)), fail; true.
% Wall 18696 ms, gc 799 ms, 561771 lips
% Wall 12737 ms, gc 730 ms, 757550 lips
% Wall 7126 ms, gc 339 ms, 642182 lips
true.
The 7126 ms (Dogelog Player on PyPy) compared to the
7.718s (Scryer Prolog) is ca. 10% faster. I never though
that Dogelog Prolog on the Python platform could do
that, since Python is rather annonyingly slow.
Mostowski Collapse schrieb am Donnerstag, 17. November 2022 um 15:08:51 UTC+1:
The best I can do for Dogelog Player, concerning
msb/1 and the JavaScript platform. Just imagine
the speed if JavaScript would have a real msb/1
or bitlength/1, so that we don't need this nonsense?
function bigint_msb(alpha) {
alpha = alpha.toString(16);
return 31 - Math.clz32(hexvalue(alpha.codePointAt(0))) + (alpha.length - 1)*4;
}
This is a known problem that bigint has no msb/1 or
bitlength/1 in JavaScript as of now. Nevertheless I now
easily beat Scryer Prolog even with Dogelog Player.
Comparing to the hi lo search msb I get these results:
/* Dogelog Player 1.0.3 Windows nodeJS */
?- member((N,K),[(53,2600),(1024,150),(8192,9)]),
time((between(1,K,_), mp_pi(N, _), fail; true)), fail; true.
% Wall 4136 ms, gc 10 ms, 2539128 lips
% Wall 4346 ms, gc 104 ms, 2219962 lips
% Wall 3876 ms, gc 88 ms, 1180529 lips
true.
Also unlike Scryer Prolog, for larger bigints, i.e. 8192
the timing doesn't go up, it rather goes down. Probably some
alternative bigint multiplication methods etc.. kick in for
larger bigints, and they are missing in Scryer Prolog for
the Rust based bigints? They are still in its fancy? Also
Scryer Prolog would fare better if it had a native msb/1.
Mostowski Collapse schrieb am Montag, 14. November 2022 um 23:31:28 UTC+1:
Scryer Prolog doesn't have these built-ins. So emulating
them makes it utterly slow. Using the hi lo approach for msb:
/* Scryer Prolog 0.9.1 WSL2 */
?- member((N,K),[(53,2600),(1024,150),(8192,9)]),
time((between(1,K,_), mp_pi(N, _), fail; true)), fail; true.
% CPU time: 4.240s
% CPU time: 5.621s
% CPU time: 7.718s
% true.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Wed Jan 11 12:52:44 2023
Ha Ha ChatGPT is trolling me. You can search last_child
in Tau Prolog current GitHub, not a single find.
https://github.com/tau-prolog/tau-prolog/search?q=last_child
Or try this:
:- use_module(library(dom)).
?- last_child(foo, bar).
uncaught exception: error(existence_error(procedure,last_child/2),top_level/0)
Nevertheless ChatGPT halucinates something perfectly plausible:
Q: How get DOM last child in Tau Prolog programming language.
A: In Tau Prolog, you can use the built-in predicate
"last_child/2" to get the last child of a DOM element.
The predicate takes two arguments:
The DOM element for which you want to get
the last child (the parent element)
A variable that will be bound to the last child element
Example usage:
Copy code
last_child(parent_element, LastChild),
You have to unify the parent element with a variable
that has been initialized as a DOM element .
Please note that my knowledge cut off on Tau-Prolog is
from 2021 and this predicates could be deprecated or
changed so I recommend to check in the documentation
of the library you're using or check the version of
Tau-Prolog you're working with.
LoL
Mostowski Collapse schrieb am Mittwoch, 11. Januar 2023 um 21:45:30 UTC+1:
I guess its time to talk about DOM APIs inside Prolog,
and making them mature and portable. I am planning
to adopt the Tau Prolog DOM API.
But I have two DOM APIs in mind:
- Stateless DOM API: Basically Tau Prolog is a stateless
DOM API. All API calls have all the necessary parameters,
there is nothing implicit right?
- Statefull DOM API: On the other hand so far, in Dogelog
Player, I have used a statefull DOM API. With a notion
of cursor, you can imagine Turtle graphics, only the Turtle
is not a Turtle with location and orientation, but a node
somewhere in a DOM tree.
My plan is to give the Statefull DOM API a new try, but
bootstrapping it from the a Stateless DOM API. Eh voila
I am already banging my head:
DOM API: How get last child efficiently? https://github.com/tau-prolog/tau-prolog/issues/340
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
All on Wed Jan 11 12:45:28 2023
I guess its time to talk about DOM APIs inside Prolog,
and making them mature and portable. I am planning
to adopt the Tau Prolog DOM API.
But I have two DOM APIs in mind:
- Stateless DOM API: Basically Tau Prolog is a stateless
DOM API. All API calls have all the necessary parameters,
there is nothing implicit right?
- Statefull DOM API: On the other hand so far, in Dogelog
Player, I have used a statefull DOM API. With a notion
of cursor, you can imagine Turtle graphics, only the Turtle
is not a Turtle with location and orientation, but a node
somewhere in a DOM tree.
My plan is to give the Statefull DOM API a new try, but
bootstrapping it from the a Stateless DOM API. Eh voila
I am already banging my head:
DOM API: How get last child efficiently?
https://github.com/tau-prolog/tau-prolog/issues/340
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
All on Wed Jan 11 14:24:32 2023
Looks like Ciao Prolog Playground totally
forgot about some library(dom)? Nada?
Is it more harder to make library(dom) for
a WASM based Prolog than a JavaScript based
Prolog? What about SWI-Prolog WASM?
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
All on Fri Jan 13 01:56:45 2023
An other can of worms format/2, related to DOM generation.
The Prolog community could standardisize it voluntarily
without the need of the ISO body. Just have a common place,
where somebody puts up a kind of specification document.
Something like a format/2 Prolog Enhancement Proposals (PEP).
Why look into format/2 ? Because Tau Prolog suggests funny stuff:
add_item(Item, Count) :-
...
format(Stream, "~a (~d)", [Item, Count]),
...
Web development with Tau Prolog - Riazaa
https://biblioteca.sistedes.es/submissions/descargas/2022/PROLE/2022-PROLE-006.pdf
Mostlikely the above is not a very optimal idea, since
there are so many other issues in DOM text generation,
like XML Escape or URL Encoding. But nevertheless
worth investigating as a means for DOM text generation.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Fri Jan 13 01:58:10 2023
A middle ground could be to standardisized only float formatting.
So that there are some primitives that do float formatting,
and various string interpolations and portraying could be
bootstrapped from it. I find some rudimentaries here from ROK:
float_codes(Float, Codes, Format) :-
% like number_codes/2 but only for floats
http://www.cs.otago.ac.nz/staffpriv/ok/pllib.htm
So the standardisation would takle what the ‘%’ operator can
do in Python, when the left argument is a string and the right
argument is a float. But there is much to be demanded, what
if the right argument is an integer, especially a bigint and not
a smallint, a bigint that cannot be converted to float. So ROKs
take is a little outdated, since is not bigint aware.
Mostowski Collapse schrieb am Freitag, 13. Januar 2023 um 10:56:46 UTC+1:
An other can of worms format/2, related to DOM generation.
The Prolog community could standardisize it voluntarily
without the need of the ISO body. Just have a common place,
where somebody puts up a kind of specification document.
Something like a format/2 Prolog Enhancement Proposals (PEP).
Why look into format/2 ? Because Tau Prolog suggests funny stuff:
add_item(Item, Count) :-
...
format(Stream, "~a (~d)", [Item, Count]),
...
Web development with Tau Prolog - Riazaa https://biblioteca.sistedes.es/submissions/descargas/2022/PROLE/2022-PROLE-006.pdf
Mostlikely the above is not a very optimal idea, since
there are so many other issues in DOM text generation,
like XML Escape or URL Encoding. But nevertheless
worth investigating as a means for DOM text generation.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Fri Jan 13 01:59:21 2023
SWI-Prolog is currently bigint aware:
?- format("abc ~2f def", [123123123123123123123]).
abc 123123123123123123123.00 def
?- format("abc ~2f def", [123123123123123123123.0]).
abc 123123123123123126272.00 def
Trealla Prolog doesn’t tolerate integer:
?- format("abc ~2f def", [123123123123123123123]).
error(type_error(float,123123123123123123123),format/2).
Scryer Prolog does sometimes nonsense for float:
?- format("abc ~2f def", [123123123123123123123.0]).
abc 1.23 def true.
Mostowski Collapse schrieb am Freitag, 13. Januar 2023 um 10:58:12 UTC+1:
A middle ground could be to standardisized only float formatting.
So that there are some primitives that do float formatting,
and various string interpolations and portraying could be
bootstrapped from it. I find some rudimentaries here from ROK:
float_codes(Float, Codes, Format) :-
% like number_codes/2 but only for floats http://www.cs.otago.ac.nz/staffpriv/ok/pllib.htm
So the standardisation would takle what the ‘%’ operator can
do in Python, when the left argument is a string and the right
argument is a float. But there is much to be demanded, what
if the right argument is an integer, especially a bigint and not
a smallint, a bigint that cannot be converted to float. So ROKs
take is a little outdated, since is not bigint aware.
Mostowski Collapse schrieb am Freitag, 13. Januar 2023 um 10:56:46 UTC+1:
An other can of worms format/2, related to DOM generation.
The Prolog community could standardisize it voluntarily
without the need of the ISO body. Just have a common place,
where somebody puts up a kind of specification document.
Something like a format/2 Prolog Enhancement Proposals (PEP).
Why look into format/2 ? Because Tau Prolog suggests funny stuff:
add_item(Item, Count) :-
...
format(Stream, "~a (~d)", [Item, Count]),
...
Web development with Tau Prolog - Riazaa https://biblioteca.sistedes.es/submissions/descargas/2022/PROLE/2022-PROLE-006.pdf
Mostlikely the above is not a very optimal idea, since
there are so many other issues in DOM text generation,
like XML Escape or URL Encoding. But nevertheless
worth investigating as a means for DOM text generation.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Fri Jan 13 02:01:01 2023
My conclusion, to reach the level of SWI-Prolog,
a number_codes with a format parameters is needed, and
not a float_codes that is restricted to floats.
With a number_codes that also accepts integers, it will go
smooth to also format integers, as SWI-Prolog does.
On my side I started defining a new built-in:
atom_number(-Atom, +Atom, +Integer, +Number)
The above built-in takes a slightly different turn, not codes
but atom is the currency for number conversion. The
input atom is ‘f’ or ‘e’, and the input integer is the requested
precision. But it is currently too stupid for bigint, working on it.
Mostowski Collapse schrieb am Freitag, 13. Januar 2023 um 10:58:12 UTC+1:
A middle ground could be to standardisized only float formatting.
So that there are some primitives that do float formatting,
and various string interpolations and portraying could be
bootstrapped from it. I find some rudimentaries here from ROK:
float_codes(Float, Codes, Format) :-
% like number_codes/2 but only for floats http://www.cs.otago.ac.nz/staffpriv/ok/pllib.htm
So the standardisation would takle what the ‘%’ operator can
do in Python, when the left argument is a string and the right
argument is a float. But there is much to be demanded, what
if the right argument is an integer, especially a bigint and not
a smallint, a bigint that cannot be converted to float. So ROKs
take is a little outdated, since is not bigint aware.
Mostowski Collapse schrieb am Freitag, 13. Januar 2023 um 10:56:46 UTC+1:
An other can of worms format/2, related to DOM generation.
The Prolog community could standardisize it voluntarily
without the need of the ISO body. Just have a common place,
where somebody puts up a kind of specification document.
Something like a format/2 Prolog Enhancement Proposals (PEP).
Why look into format/2 ? Because Tau Prolog suggests funny stuff:
add_item(Item, Count) :-
...
format(Stream, "~a (~d)", [Item, Count]),
...
Web development with Tau Prolog - Riazaa https://biblioteca.sistedes.es/submissions/descargas/2022/PROLE/2022-PROLE-006.pdf
Mostlikely the above is not a very optimal idea, since
there are so many other issues in DOM text generation,
like XML Escape or URL Encoding. But nevertheless
worth investigating as a means for DOM text generation.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Fri Jan 13 04:49:26 2023
PEPs are probably anyway a dead end. Best would be if Prolog
systems were designed around a Novacore. So atom_number/4
would probably fit into a **Novacore**, but format/[2,3] not.
format/[2,3] would have a pure Prolog implementation, that
can be shared across Prolog systems. Same for locales, a pure
Prolog implementation, or some Semantic Net from ChatGPT.
LoL
Mostowski Collapse schrieb am Freitag, 13. Januar 2023 um 11:01:03 UTC+1:
My conclusion, to reach the level of SWI-Prolog,
a number_codes with a format parameters is needed, and
not a float_codes that is restricted to floats.
With a number_codes that also accepts integers, it will go
smooth to also format integers, as SWI-Prolog does.
On my side I started defining a new built-in:
atom_number(-Atom, +Atom, +Integer, +Number)
The above built-in takes a slightly different turn, not codes
but atom is the currency for number conversion. The
input atom is ‘f’ or ‘e’, and the input integer is the requested
precision. But it is currently too stupid for bigint, working on it. Mostowski Collapse schrieb am Freitag, 13. Januar 2023 um 10:58:12 UTC+1:
A middle ground could be to standardisized only float formatting.
So that there are some primitives that do float formatting,
and various string interpolations and portraying could be
bootstrapped from it. I find some rudimentaries here from ROK:
float_codes(Float, Codes, Format) :-
% like number_codes/2 but only for floats http://www.cs.otago.ac.nz/staffpriv/ok/pllib.htm
So the standardisation would takle what the ‘%’ operator can
do in Python, when the left argument is a string and the right
argument is a float. But there is much to be demanded, what
if the right argument is an integer, especially a bigint and not
a smallint, a bigint that cannot be converted to float. So ROKs
take is a little outdated, since is not bigint aware.
Mostowski Collapse schrieb am Freitag, 13. Januar 2023 um 10:56:46 UTC+1:
An other can of worms format/2, related to DOM generation.
The Prolog community could standardisize it voluntarily
without the need of the ISO body. Just have a common place,
where somebody puts up a kind of specification document.
Something like a format/2 Prolog Enhancement Proposals (PEP).
Why look into format/2 ? Because Tau Prolog suggests funny stuff:
add_item(Item, Count) :-
...
format(Stream, "~a (~d)", [Item, Count]),
...
Web development with Tau Prolog - Riazaa https://biblioteca.sistedes.es/submissions/descargas/2022/PROLE/2022-PROLE-006.pdf
Mostlikely the above is not a very optimal idea, since
there are so many other issues in DOM text generation,
like XML Escape or URL Encoding. But nevertheless
worth investigating as a means for DOM text generation.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Mon Jan 16 15:03:08 2023
Thats a defect of Markus Triskas library(format).
The defect is found in Scryer Prolog:
?- format("foo ~w bar ~w baz", [p(A,B),q(B,C)]), nl.
foo p(A,B) bar q(B,C) baz
?- format("foo ~w bar", [p(A,B)]), format(" ~w baz", [q(B,C)]), nl.
foo p(A,B) bar q(A,B) baz
One should be able to chop up format/[2,3]. Other
Prolog systems are able to do that. Either with small
variable gensym or with large variable gensym:
/* Trealla, Jekejeke etc.. --> small variable gensym */
?- format('foo ~w bar ~w baz', [p(A,B),q(B,C)]), nl.
foo p(_0, _1) bar q(_1, _2) baz
?- format('foo ~w bar', [p(A,B)]), format(' ~w baz', [q(B,C)]), nl.
foo p(_0, _1) bar q(_1, _2) baz
/* SWI-Prolog, Dogelog etc.. --> large variable gensym */
?- format('foo ~w bar ~w baz', [p(A,B),q(B,C)]), nl.
foo p(_23041, _23042) bar q(_23042, _23043) baz
?- format('foo ~w bar', [p(A,B)]), format(' ~w baz', [q(B,C)]), nl.
foo p(_25699, _25700) bar q(_25700, _25701) baz
I don't know whether Trealla and Jekejeke use the
same gensym strategy, but phenotype is similar.
Same for the genotype of SWI-Prolog and Dogelog,
mostlikely not the same realization under the hood,
but similar outcome again.
Mostowski Collapse schrieb am Freitag, 13. Januar 2023 um 13:49:28 UTC+1:
PEPs are probably anyway a dead end. Best would be if Prolog
systems were designed around a Novacore. So atom_number/4
would probably fit into a **Novacore**, but format/[2,3] not.
format/[2,3] would have a pure Prolog implementation, that
can be shared across Prolog systems. Same for locales, a pure
Prolog implementation, or some Semantic Net from ChatGPT.
LoL
Mostowski Collapse schrieb am Freitag, 13. Januar 2023 um 11:01:03 UTC+1:
My conclusion, to reach the level of SWI-Prolog,
a number_codes with a format parameters is needed, and
not a float_codes that is restricted to floats.
With a number_codes that also accepts integers, it will go
smooth to also format integers, as SWI-Prolog does.
On my side I started defining a new built-in:
atom_number(-Atom, +Atom, +Integer, +Number)
The above built-in takes a slightly different turn, not codes
but atom is the currency for number conversion. The
input atom is ‘f’ or ‘e’, and the input integer is the requested
precision. But it is currently too stupid for bigint, working on it. Mostowski Collapse schrieb am Freitag, 13. Januar 2023 um 10:58:12 UTC+1:
A middle ground could be to standardisized only float formatting.
So that there are some primitives that do float formatting,
and various string interpolations and portraying could be
bootstrapped from it. I find some rudimentaries here from ROK:
float_codes(Float, Codes, Format) :-
% like number_codes/2 but only for floats http://www.cs.otago.ac.nz/staffpriv/ok/pllib.htm
So the standardisation would takle what the ‘%’ operator can
do in Python, when the left argument is a string and the right
argument is a float. But there is much to be demanded, what
if the right argument is an integer, especially a bigint and not
a smallint, a bigint that cannot be converted to float. So ROKs
take is a little outdated, since is not bigint aware.
Mostowski Collapse schrieb am Freitag, 13. Januar 2023 um 10:56:46 UTC+1:
An other can of worms format/2, related to DOM generation.
The Prolog community could standardisize it voluntarily
without the need of the ISO body. Just have a common place,
where somebody puts up a kind of specification document.
Something like a format/2 Prolog Enhancement Proposals (PEP).
Why look into format/2 ? Because Tau Prolog suggests funny stuff:
add_item(Item, Count) :-
...
format(Stream, "~a (~d)", [Item, Count]),
...
Web development with Tau Prolog - Riazaa https://biblioteca.sistedes.es/submissions/descargas/2022/PROLE/2022-PROLE-006.pdf
Mostlikely the above is not a very optimal idea, since
there are so many other issues in DOM text generation,
like XML Escape or URL Encoding. But nevertheless
worth investigating as a means for DOM text generation.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Mon Jan 16 15:07:04 2023
It seems that Tau Prolog has a hickup somewhere:
?- format("foo ~w bar ~w baz", [p(A,B),q(B,C)]), nl.
uncaught exception: error(instantiation_error,fabricate_var_name/3)
https://github.com/tau-prolog/tau-prolog/issues/342
Mostowski Collapse schrieb am Dienstag, 17. Januar 2023 um 00:03:10 UTC+1:
Thats a defect of Markus Triskas library(format).
The defect is found in Scryer Prolog:
?- format("foo ~w bar ~w baz", [p(A,B),q(B,C)]), nl.
foo p(A,B) bar q(B,C) baz
?- format("foo ~w bar", [p(A,B)]), format(" ~w baz", [q(B,C)]), nl.
foo p(A,B) bar q(A,B) baz
One should be able to chop up format/[2,3]. Other
Prolog systems are able to do that. Either with small
variable gensym or with large variable gensym:
/* Trealla, Jekejeke etc.. --> small variable gensym */
?- format('foo ~w bar ~w baz', [p(A,B),q(B,C)]), nl.
foo p(_0, _1) bar q(_1, _2) baz
?- format('foo ~w bar', [p(A,B)]), format(' ~w baz', [q(B,C)]), nl.
foo p(_0, _1) bar q(_1, _2) baz
/* SWI-Prolog, Dogelog etc.. --> large variable gensym */
?- format('foo ~w bar ~w baz', [p(A,B),q(B,C)]), nl.
foo p(_23041, _23042) bar q(_23042, _23043) baz
?- format('foo ~w bar', [p(A,B)]), format(' ~w baz', [q(B,C)]), nl.
foo p(_25699, _25700) bar q(_25700, _25701) baz
I don't know whether Trealla and Jekejeke use the
same gensym strategy, but phenotype is similar.
Same for the genotype of SWI-Prolog and Dogelog,
mostlikely not the same realization under the hood,
but similar outcome again.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Tue Jan 17 00:49:24 2023
Interesting find, hooking into Java printf gives:
?- catch(printf('abc %s def', []), error(E,_), true).
Error: Unknown template: representation_error('Format specifier ''%s''')
/* java.util.MissingFormatArgumentException extends IllegalFormatException */ ?- catch(printf('abc %s def', [p,q]), error(E,_), true).
abc p def
So too many arguments are tolerated. On the other
hand SWI-Prolog does check too many arguments:
?- catch(format('abc ~w def', []), error(E,_), true).
E = format('not enough arguments').
?- catch(format('abc ~w def', [p,q]), error(E,_), true).
E = format('too many arguments').
Oki Doki
Mostowski Collapse schrieb am Dienstag, 17. Januar 2023 um 00:07:06 UTC+1:
It seems that Tau Prolog has a hickup somewhere:
?- format("foo ~w bar ~w baz", [p(A,B),q(B,C)]), nl.
uncaught exception: error(instantiation_error,fabricate_var_name/3)
https://github.com/tau-prolog/tau-prolog/issues/342
Mostowski Collapse schrieb am Dienstag, 17. Januar 2023 um 00:03:10 UTC+1:
Thats a defect of Markus Triskas library(format).
The defect is found in Scryer Prolog:
?- format("foo ~w bar ~w baz", [p(A,B),q(B,C)]), nl.
foo p(A,B) bar q(B,C) baz
?- format("foo ~w bar", [p(A,B)]), format(" ~w baz", [q(B,C)]), nl.
foo p(A,B) bar q(A,B) baz
One should be able to chop up format/[2,3]. Other
Prolog systems are able to do that. Either with small
variable gensym or with large variable gensym:
/* Trealla, Jekejeke etc.. --> small variable gensym */
?- format('foo ~w bar ~w baz', [p(A,B),q(B,C)]), nl.
foo p(_0, _1) bar q(_1, _2) baz
?- format('foo ~w bar', [p(A,B)]), format(' ~w baz', [q(B,C)]), nl.
foo p(_0, _1) bar q(_1, _2) baz
/* SWI-Prolog, Dogelog etc.. --> large variable gensym */
?- format('foo ~w bar ~w baz', [p(A,B),q(B,C)]), nl.
foo p(_23041, _23042) bar q(_23042, _23043) baz
?- format('foo ~w bar', [p(A,B)]), format(' ~w baz', [q(B,C)]), nl.
foo p(_25699, _25700) bar q(_25700, _25701) baz
I don't know whether Trealla and Jekejeke use the
same gensym strategy, but phenotype is similar.
Same for the genotype of SWI-Prolog and Dogelog,
mostlikely not the same realization under the hood,
but similar outcome again.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Tue Jan 17 03:22:55 2023
Interesting find, Ciao Prologs does sometimes boxing:
/* Ciao Prolog 1.22.0 */
?- format('abc ~w def', [p]). %%% no-boxing exception [_]
abc p def
?- format('abc ~w def', p).
abc p def
I guess this makes the format/2 predicate a little brittle,
when used to print lists. One cannot distinguish [p] and
p in the output, not sure whether is a tolerable flaw?
It is tolerable in as far as there exists a work around. The
work around is to avoid boxing when there is only
one item to print:
?- format('abc ~w def', [[p]]).
abc [p] def
?- format('abc ~w def', [p]).
abc p def
So when you are Pavlov’s dog and have learned to use
and enjoy Ciao Prologs feature, because of some positive
feedback where it works, you have to unlearn this feature
nevertheless, which needs the administration of electric
shocks to the programmer.
Mostowski Collapse schrieb am Dienstag, 17. Januar 2023 um 09:49:25 UTC+1:
Interesting find, hooking into Java printf gives:
?- catch(printf('abc %s def', []), error(E,_), true).
Error: Unknown template: representation_error('Format specifier ''%s''')
/* java.util.MissingFormatArgumentException extends IllegalFormatException */
?- catch(printf('abc %s def', [p,q]), error(E,_), true).
abc p def
So too many arguments are tolerated. On the other
hand SWI-Prolog does check too many arguments:
?- catch(format('abc ~w def', []), error(E,_), true).
E = format('not enough arguments').
?- catch(format('abc ~w def', [p,q]), error(E,_), true).
E = format('too many arguments').
Oki Doki
Mostowski Collapse schrieb am Dienstag, 17. Januar 2023 um 00:07:06 UTC+1:
It seems that Tau Prolog has a hickup somewhere:
?- format("foo ~w bar ~w baz", [p(A,B),q(B,C)]), nl.
uncaught exception: error(instantiation_error,fabricate_var_name/3)
https://github.com/tau-prolog/tau-prolog/issues/342
Mostowski Collapse schrieb am Dienstag, 17. Januar 2023 um 00:03:10 UTC+1:
Thats a defect of Markus Triskas library(format).
The defect is found in Scryer Prolog:
?- format("foo ~w bar ~w baz", [p(A,B),q(B,C)]), nl.
foo p(A,B) bar q(B,C) baz
?- format("foo ~w bar", [p(A,B)]), format(" ~w baz", [q(B,C)]), nl.
foo p(A,B) bar q(A,B) baz
One should be able to chop up format/[2,3]. Other
Prolog systems are able to do that. Either with small
variable gensym or with large variable gensym:
/* Trealla, Jekejeke etc.. --> small variable gensym */
?- format('foo ~w bar ~w baz', [p(A,B),q(B,C)]), nl.
foo p(_0, _1) bar q(_1, _2) baz
?- format('foo ~w bar', [p(A,B)]), format(' ~w baz', [q(B,C)]), nl.
foo p(_0, _1) bar q(_1, _2) baz
/* SWI-Prolog, Dogelog etc.. --> large variable gensym */
?- format('foo ~w bar ~w baz', [p(A,B),q(B,C)]), nl.
foo p(_23041, _23042) bar q(_23042, _23043) baz
?- format('foo ~w bar', [p(A,B)]), format(' ~w baz', [q(B,C)]), nl.
foo p(_25699, _25700) bar q(_25700, _25701) baz
I don't know whether Trealla and Jekejeke use the
same gensym strategy, but phenotype is similar.
Same for the genotype of SWI-Prolog and Dogelog,
mostlikely not the same realization under the hood,
but similar outcome again.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
All on Mon Feb 27 03:08:11 2023
Could a Novacore also be a Worker Prolog? One coul
imagine a Prolog system where all predicates are by
default thread local, and where threads can only
share information through message passing. You would
more or less get JavaScript Workers. Such a Prolog system
would not anymore need synchronization of predicates,
neither needed for static nor dynamic predicates. I am
currently wondering whether I can build such a Prolog variant
and what the performance would be? But a special form of
thread local would be needed, since the predicate needs not be
visible among multiple workers.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Mon Feb 27 03:08:59 2023
A bonus would be if the Prolog system had event
loops in its Workers by default, so that kind of fibers
would be available, and one would still have some benefits
of a multi-threaded Prolog system, just do it async
in the same thread. Maybe a couple service threads besides
the workers threads nevertheless, so that for example
things like call_with_time_limit/2 still work. Maybe such a
Worker Prolog could be bootstrapped from a multi-threaded
Prolog system by changing some defaults, for example
that predicates are by default this new form of thread local.
Mostowski Collapse schrieb am Montag, 27. Februar 2023 um 12:08:12 UTC+1:
Could a Novacore also be a Worker Prolog? One coul
imagine a Prolog system where all predicates are by
default thread local, and where threads can only
share information through message passing. You would
more or less get JavaScript Workers. Such a Prolog system
would not anymore need synchronization of predicates,
neither needed for static nor dynamic predicates. I am
currently wondering whether I can build such a Prolog variant
and what the performance would be? But a special form of
thread local would be needed, since the predicate needs not be
visible among multiple workers.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Mon Feb 27 10:33:04 2023
Relatively straight forward using Python fibers. Only they are not
called fibers, the are call coroutines. For example the new
built-in to schedule an alarm is implemented as follows in Python:
loop = asyncio.get_running_loop()
res = loop.call_later(delay/1000.0, alarm_abort)
The same works also for JavaScript now, using an API with some
different names, but also based on an event loop I guess. Thats
the magic of fibers, they are inbetween single threaded and
multi-threaded. The alarm_abort callback in the above posts a
signal, which gets taken note by the auto-yielding interpreter. The
behaviour is very similar to a multi-threaded Prolog alarm,
or a single-threaded Prolog alarm that uses some operating
system service for the signalling.
Mostowski Collapse schrieb am Montag, 27. Februar 2023 um 19:31:36 UTC+1:
If you have fibers, you also don’t need any locking. At least not for basic operations like assert/1, retract/1, etc… since they still run single
threaded if you don’t yield during these operations. But on
the other hand try this in the current SWI-Prolog WASM shell:
?- call_with_time_limit(0.5, (repeat, fail)).
ERROR: Unhandled exception: toplevel: Unknown procedure: call_with_time_limit/2 (DWIM could not correct goal) https://dev.swi-prolog.org/wasm/shell
Surprisingly, since this weekend, I can do the following
in Dogelog Player for Python, the predicate time_out/2 accepts
milliseconds and has the arguments in different order:
?- time_out((repeat, fail), 500).
Error: system_error(timelimit_exceeded)
user:1
And I didn’t use threads, so how did I do it? BTW: I don’t know
whether Tau Prolog can demonstrate it. They have demonstrated
something else, multiple Prolog threads trying to reach a finish line.
I am not yet there at the Tau Prolog calibre of fibers, step by step wondering currently how signal handling can be done.
Mostowski Collapse schrieb am Montag, 27. Februar 2023 um 12:09:01 UTC+1:
A bonus would be if the Prolog system had event
loops in its Workers by default, so that kind of fibers
would be available, and one would still have some benefits
of a multi-threaded Prolog system, just do it async
in the same thread. Maybe a couple service threads besides
the workers threads nevertheless, so that for example
things like call_with_time_limit/2 still work. Maybe such a
Worker Prolog could be bootstrapped from a multi-threaded
Prolog system by changing some defaults, for example
that predicates are by default this new form of thread local.
Mostowski Collapse schrieb am Montag, 27. Februar 2023 um 12:08:12 UTC+1:
Could a Novacore also be a Worker Prolog? One coul
imagine a Prolog system where all predicates are by
default thread local, and where threads can only
share information through message passing. You would
more or less get JavaScript Workers. Such a Prolog system
would not anymore need synchronization of predicates,
neither needed for static nor dynamic predicates. I am
currently wondering whether I can build such a Prolog variant
and what the performance would be? But a special form of
thread local would be needed, since the predicate needs not be
visible among multiple workers.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Mon Feb 27 10:31:34 2023
If you have fibers, you also don’t need any locking. At least not for
basic operations like assert/1, retract/1, etc… since they still run single threaded if you don’t yield during these operations. But on
the other hand try this in the current SWI-Prolog WASM shell:
?- call_with_time_limit(0.5, (repeat, fail)).
ERROR: Unhandled exception: toplevel: Unknown procedure:
call_with_time_limit/2 (DWIM could not correct goal)
https://dev.swi-prolog.org/wasm/shell
Surprisingly, since this weekend, I can do the following
in Dogelog Player for Python, the predicate time_out/2 accepts
milliseconds and has the arguments in different order:
?- time_out((repeat, fail), 500).
Error: system_error(timelimit_exceeded)
user:1
And I didn’t use threads, so how did I do it? BTW: I don’t know
whether Tau Prolog can demonstrate it. They have demonstrated
something else, multiple Prolog threads trying to reach a finish line.
I am not yet there at the Tau Prolog calibre of fibers, step by step
wondering currently how signal handling can be done.
Mostowski Collapse schrieb am Montag, 27. Februar 2023 um 12:09:01 UTC+1:
A bonus would be if the Prolog system had event
loops in its Workers by default, so that kind of fibers
would be available, and one would still have some benefits
of a multi-threaded Prolog system, just do it async
in the same thread. Maybe a couple service threads besides
the workers threads nevertheless, so that for example
things like call_with_time_limit/2 still work. Maybe such a
Worker Prolog could be bootstrapped from a multi-threaded
Prolog system by changing some defaults, for example
that predicates are by default this new form of thread local.
Mostowski Collapse schrieb am Montag, 27. Februar 2023 um 12:08:12 UTC+1:
Could a Novacore also be a Worker Prolog? One coul
imagine a Prolog system where all predicates are by
default thread local, and where threads can only
share information through message passing. You would
more or less get JavaScript Workers. Such a Prolog system
would not anymore need synchronization of predicates,
neither needed for static nor dynamic predicates. I am
currently wondering whether I can build such a Prolog variant
and what the performance would be? But a special form of
thread local would be needed, since the predicate needs not be
visible among multiple workers.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Mon Feb 27 16:05:11 2023
Is this Worker Prolog part of Novacore. Well Yes and
No. Novacore is supposed to be a core without any libraries,
reduced to the minimum. So it can be the basis for
a multitude of things, like:
Multi-Threaded Prolog ----\
Single-Threaded Prolog ---+-----> Novacore
Worker Fiber Prolog ------/
Thats why I am currently moving all kind of
libraries out of formerly Jekejeke Prolog Runtime,
to a different place, threads are gone, locks are
gone, pipes are gone, directories are gone, everything
is gone. Maybe Workers will come? Who knows.
Maybe Worker Fibers will come?
I am not 100% sure whether Workers always need
Fibers? Well there is one use case. If a Worker
needs to be abortable, this could be done
by a auto-yielding Prolog system running inside
the Worker. See Prolog of Ciao Playground. So
I guess one has to think as a Worker Prolog not
as a Multi-Threaded Prolog rather as a Multi-Single-
Threaded Prolog, where each Thread is Single in
that it is isolated from the other Threads, doesn't
see their predicates, and the fiber makes an easy
solution to abort such a Thread. In Java its done
differently. There most all Multi-Threaded APIs are
abortable from the outside, but to abort a Prolog
interpreter you still need something else, since
you don't necessarily call Multi-Threaded APIs
all the time. So polling some signal or auto-yielding
is essentially the same.
Mostowski Collapse schrieb am Montag, 27. Februar 2023 um 19:33:05 UTC+1:
Relatively straight forward using Python fibers. Only they are not
called fibers, the are call coroutines. For example the new
built-in to schedule an alarm is implemented as follows in Python:
loop = asyncio.get_running_loop()
res = loop.call_later(delay/1000.0, alarm_abort)
The same works also for JavaScript now, using an API with some
different names, but also based on an event loop I guess. Thats
the magic of fibers, they are inbetween single threaded and
multi-threaded. The alarm_abort callback in the above posts a
signal, which gets taken note by the auto-yielding interpreter. The behaviour is very similar to a multi-threaded Prolog alarm,
or a single-threaded Prolog alarm that uses some operating
system service for the signalling.
Mostowski Collapse schrieb am Montag, 27. Februar 2023 um 19:31:36 UTC+1:
If you have fibers, you also don’t need any locking. At least not for basic operations like assert/1, retract/1, etc… since they still run single
threaded if you don’t yield during these operations. But on
the other hand try this in the current SWI-Prolog WASM shell:
?- call_with_time_limit(0.5, (repeat, fail)).
ERROR: Unhandled exception: toplevel: Unknown procedure: call_with_time_limit/2 (DWIM could not correct goal) https://dev.swi-prolog.org/wasm/shell
Surprisingly, since this weekend, I can do the following
in Dogelog Player for Python, the predicate time_out/2 accepts milliseconds and has the arguments in different order:
?- time_out((repeat, fail), 500).
Error: system_error(timelimit_exceeded)
user:1
And I didn’t use threads, so how did I do it? BTW: I don’t know whether Tau Prolog can demonstrate it. They have demonstrated
something else, multiple Prolog threads trying to reach a finish line.
I am not yet there at the Tau Prolog calibre of fibers, step by step wondering currently how signal handling can be done.
Mostowski Collapse schrieb am Montag, 27. Februar 2023 um 12:09:01 UTC+1:
A bonus would be if the Prolog system had event
loops in its Workers by default, so that kind of fibers
would be available, and one would still have some benefits
of a multi-threaded Prolog system, just do it async
in the same thread. Maybe a couple service threads besides
the workers threads nevertheless, so that for example
things like call_with_time_limit/2 still work. Maybe such a
Worker Prolog could be bootstrapped from a multi-threaded
Prolog system by changing some defaults, for example
that predicates are by default this new form of thread local.
Mostowski Collapse schrieb am Montag, 27. Februar 2023 um 12:08:12 UTC+1:
Could a Novacore also be a Worker Prolog? One coul
imagine a Prolog system where all predicates are by
default thread local, and where threads can only
share information through message passing. You would
more or less get JavaScript Workers. Such a Prolog system
would not anymore need synchronization of predicates,
neither needed for static nor dynamic predicates. I am
currently wondering whether I can build such a Prolog variant
and what the performance would be? But a special form of
thread local would be needed, since the predicate needs not be
visible among multiple workers.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
All on Wed Mar 1 09:01:18 2023
Are lazy streams fibers? Not really.
If you preform engine yield, you just land in the parent
context of the current execution. You don’t temporarily
suspend the current execution. You need an event loop
for that. But all the papers by Tarau, Wielemaker and
Schrijvers never discuss that. You could also imagine a
new Prolog language, with two new operators async/1
and await/1. For example one could write a bankteller
web worker only with fibers, and one could
produce code as follows:
:- async withdraw/2.
withdraw(Amount) :-
await do_something,
retact(account(Current)),
Current2 is Curent-Amount,
assertz(account(Current2)),
await do_something2.
Since the retract/assertz combo is not interleaved with an
await statement, we know that noting will yield while executing
the combo, and the effect is as if it were a critical region. But
locks or atomics are not needed. You have to switch off auto-
yielding for such a code as above, no auto-yielding is also the
default execution mode of JavaScript, and you could apply
the same reasoning to JavaScript.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Wed Mar 1 09:02:36 2023
Maybe good name for such a language would be
Fibertalk. It would have a linter with some style checks.
Like if a body goal has an await/1, but the head predicate
doesn’t have async/1, there would be a warning or error.
But you can implement async/1 and await/1 extremly simple.
They are only declarations as a kind of program documentation
and are also useful for the linter, but for execution they do nothing:
async(_).
await(G) :- G.
To implement them as above is possible for a Prolog
system with fibers that can yield anywhere. It might be
as well the case, that for JavaScript the keywords are
also only decoration? Not sure. The decoration goes also
into attributes of objects such as “Function” in JavaScript.
Mostowski Collapse schrieb am Mittwoch, 1. März 2023 um 18:01:19 UTC+1:
Are lazy streams fibers? Not really.
If you preform engine yield, you just land in the parent
context of the current execution. You don’t temporarily
suspend the current execution. You need an event loop
for that. But all the papers by Tarau, Wielemaker and
Schrijvers never discuss that. You could also imagine a
new Prolog language, with two new operators async/1
and await/1. For example one could write a bankteller
web worker only with fibers, and one could
produce code as follows:
:- async withdraw/2.
withdraw(Amount) :-
await do_something,
retact(account(Current)),
Current2 is Curent-Amount,
assertz(account(Current2)),
await do_something2.
Since the retract/assertz combo is not interleaved with an
await statement, we know that noting will yield while executing
the combo, and the effect is as if it were a critical region. But
locks or atomics are not needed. You have to switch off auto-
yielding for such a code as above, no auto-yielding is also the
default execution mode of JavaScript, and you could apply
the same reasoning to JavaScript.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Thu Mar 2 04:06:54 2023
So is there really a 3rd category Worker Fiber? Thanks for
challenging me explaning a concept over and over again.
Q: You shouldn’t, but you need between fibers on the same worker?
A: Do you mean shared atom and clause garbage collection is needed?
Yes. But only a single threaded version of it. Its not doing anything
between fibers inside the same worker. You don’t need locking or
atomics for fibers as I see it. With the JavaScript Worker model,
you land in single threaded Prolog system, although you are
multi-threaded. I don’t know how difficult it would be to build a
SWI-Prolog system that has Workers running single-threaded,
but nevertheless supports many of them over threads? You possibly
have to separate the Workers from a Workers monitor. Make the
Workers monitor a separately compiled component, where multi-threading
is enable. And compile the SWI-Prolog Workers Prolog runtime system single-threaded, i.e. with multi-threading disabled.
Mostowski Collapse schrieb am Dienstag, 28. Februar 2023 um 01:05:12 UTC+1:
Multi-Threaded Prolog ----\
Single-Threaded Prolog ---+-----> Novacore
Worker Fiber Prolog ------/
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Thu Mar 2 04:08:46 2023
I don’t know yet how to bake it. In formerly Jekejeke
Prolog I have ultra static but no yield or auto-yield yet,
despite that it has engines!
In Dogelog Player I have yield or auto-yield, but no
cooperative task spawning yet. One Prolog system that
has already fibers is Tau Prolog, but their system
doesn’t perform very well otherwise. SWI-Prolog is
in a good position in that it has already engines with
yield and recently auto-yield!
Mostowski Collapse schrieb am Donnerstag, 2. März 2023 um 13:06:55 UTC+1:
So is there really a 3rd category Worker Fiber? Thanks for
challenging me explaning a concept over and over again.
Q: You shouldn’t, but you need between fibers on the same worker?
A: Do you mean shared atom and clause garbage collection is needed?
Yes. But only a single threaded version of it. Its not doing anything between fibers inside the same worker. You don’t need locking or
atomics for fibers as I see it. With the JavaScript Worker model,
you land in single threaded Prolog system, although you are
multi-threaded. I don’t know how difficult it would be to build a
SWI-Prolog system that has Workers running single-threaded,
but nevertheless supports many of them over threads? You possibly
have to separate the Workers from a Workers monitor. Make the
Workers monitor a separately compiled component, where multi-threading
is enable. And compile the SWI-Prolog Workers Prolog runtime system single-threaded, i.e. with multi-threading disabled.
Mostowski Collapse schrieb am Dienstag, 28. Februar 2023 um 01:05:12 UTC+1:
Multi-Threaded Prolog ----\
Single-Threaded Prolog ---+-----> Novacore
Worker Fiber Prolog ------/
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Wed Mar 8 01:47:33 2023
Nice addition to the current API spec and already
implemented for JavaScript and Python. A callback
has now the context available of the task that scheduled it.
?- os_task_current(T), write('task='), write(T), nl.
task=main
?- call_later((os_task_current(T), write('task='),
write(T), nl), 100), sleep(500).
task=main
?- create_task((os_task_current(T), write('task='), write(T), nl)), sleep(500). task=[object Object]
?- create_task(call_later((os_task_current(T), write('task='),
write(T), nl), 100)), sleep(500).
task=[object Object]
And there is a new Prolog flag allow_yield, which can
be illustrated, you can query what the current API says:
?- current_prolog_flag(allow_yield, A), write('allow_yield='), write(A), nl. allow_yield=on
?- call_later((current_prolog_flag(allow_yield, A), write('allow_yield='), write(A), nl), 100), sleep(500).
allow_yield=off
Mostowski Collapse schrieb am Mittwoch, 8. März 2023 um 10:45:15 UTC+1:
Now I made a new version of my non-fibers and fibers API.
I removed the name “engine” from the API, so as to avoid
confusion. Engines are more lower level than the Python
idea of callbacks and tasks. The API now reads:
Part 1: Callbacks (non-fibers) (Changed)
They are Stackless and run in the <strike>main Engine</strike>
current Task of the Current Thread. In my current take, they run
without Auto-Yield and without Yield-Allowed.
os_call_later(G, D, T):
The predicate succeeds in T with a new timer. As a side effect
it schedules the goal G to be executed after D milliseconds.
os_call_cancel(T):
The predicate succeeds. As a side effect it cancels the timer T.
Part 2: Tasks (1:N fibers) (Changed)
They are Stackful and create their own <strike>Engine</strike> Task
in the Current Thread. In my current take, they run with
Auto-Yield and with Yield-Allowed.
os_task_current(E):
The predicate succeeds in E with the current <strike>engine</strike> task.
os_task_abort(E, M):
The predicate succeeds. As a side effect the <strike>engine</strike>
task E gets the message M signalled.
os_task_create(G, E):
The predicate succeeds in E with a new <strike>engine</strike> task
for the goal G. The task gets immediately scheduled to be executed.
Mostowski Collapse schrieb am Donnerstag, 2. März 2023 um 13:08:48 UTC+1:
I don’t know yet how to bake it. In formerly Jekejeke
Prolog I have ultra static but no yield or auto-yield yet,
despite that it has engines!
In Dogelog Player I have yield or auto-yield, but no
cooperative task spawning yet. One Prolog system that
has already fibers is Tau Prolog, but their system
doesn’t perform very well otherwise. SWI-Prolog is
in a good position in that it has already engines with
yield and recently auto-yield!
Mostowski Collapse schrieb am Donnerstag, 2. März 2023 um 13:06:55 UTC+1:
So is there really a 3rd category Worker Fiber? Thanks for
challenging me explaning a concept over and over again.
Q: You shouldn’t, but you need between fibers on the same worker?
A: Do you mean shared atom and clause garbage collection is needed?
Yes. But only a single threaded version of it. Its not doing anything between fibers inside the same worker. You don’t need locking or
atomics for fibers as I see it. With the JavaScript Worker model,
you land in single threaded Prolog system, although you are multi-threaded. I don’t know how difficult it would be to build a
SWI-Prolog system that has Workers running single-threaded,
but nevertheless supports many of them over threads? You possibly
have to separate the Workers from a Workers monitor. Make the
Workers monitor a separately compiled component, where multi-threading is enable. And compile the SWI-Prolog Workers Prolog runtime system single-threaded, i.e. with multi-threading disabled.
Mostowski Collapse schrieb am Dienstag, 28. Februar 2023 um 01:05:12 UTC+1:
Multi-Threaded Prolog ----\
Single-Threaded Prolog ---+-----> Novacore
Worker Fiber Prolog ------/
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Wed Mar 8 01:45:14 2023
Now I made a new version of my non-fibers and fibers API.
I removed the name “engine” from the API, so as to avoid
confusion. Engines are more lower level than the Python
idea of callbacks and tasks. The API now reads:
Part 1: Callbacks (non-fibers) (Changed)
They are Stackless and run in the <strike>main Engine</strike>
current Task of the Current Thread. In my current take, they run
without Auto-Yield and without Yield-Allowed.
os_call_later(G, D, T):
The predicate succeeds in T with a new timer. As a side effect
it schedules the goal G to be executed after D milliseconds.
os_call_cancel(T):
The predicate succeeds. As a side effect it cancels the timer T.
Part 2: Tasks (1:N fibers) (Changed)
They are Stackful and create their own <strike>Engine</strike> Task
in the Current Thread. In my current take, they run with
Auto-Yield and with Yield-Allowed.
os_task_current(E):
The predicate succeeds in E with the current <strike>engine</strike> task.
os_task_abort(E, M):
The predicate succeeds. As a side effect the <strike>engine</strike>
task E gets the message M signalled.
os_task_create(G, E):
The predicate succeeds in E with a new <strike>engine</strike> task
for the goal G. The task gets immediately scheduled to be executed.
Mostowski Collapse schrieb am Donnerstag, 2. März 2023 um 13:08:48 UTC+1:
I don’t know yet how to bake it. In formerly Jekejeke
Prolog I have ultra static but no yield or auto-yield yet,
despite that it has engines!
In Dogelog Player I have yield or auto-yield, but no
cooperative task spawning yet. One Prolog system that
has already fibers is Tau Prolog, but their system
doesn’t perform very well otherwise. SWI-Prolog is
in a good position in that it has already engines with
yield and recently auto-yield!
Mostowski Collapse schrieb am Donnerstag, 2. März 2023 um 13:06:55 UTC+1:
So is there really a 3rd category Worker Fiber? Thanks for
challenging me explaning a concept over and over again.
Q: You shouldn’t, but you need between fibers on the same worker?
A: Do you mean shared atom and clause garbage collection is needed?
Yes. But only a single threaded version of it. Its not doing anything between fibers inside the same worker. You don’t need locking or
atomics for fibers as I see it. With the JavaScript Worker model,
you land in single threaded Prolog system, although you are multi-threaded. I don’t know how difficult it would be to build a
SWI-Prolog system that has Workers running single-threaded,
but nevertheless supports many of them over threads? You possibly
have to separate the Workers from a Workers monitor. Make the
Workers monitor a separately compiled component, where multi-threading
is enable. And compile the SWI-Prolog Workers Prolog runtime system single-threaded, i.e. with multi-threading disabled.
Mostowski Collapse schrieb am Dienstag, 28. Februar 2023 um 01:05:12 UTC+1:
Multi-Threaded Prolog ----\
Single-Threaded Prolog ---+-----> Novacore
Worker Fiber Prolog ------/
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Sat Mar 18 05:56:22 2023
Interestingly with the above trick, a Prolog parser can
recognize Novacore Prolog Dicts. Since it would see this
production at the head of a Novacore Prolog Dict:
novacore_dict :== "{" string ":" term ... "}"
Which is unlike the ISO core definition of “{}”, since in
ISO core there are no strings, and even a qualified call in
ISO module assumes that we have atom “:” term. So
there would be no collision with this production:
set :== "{" term "}"
Mostowski Collapse schrieb am Samstag, 18. März 2023 um 13:55:21 UTC+1:
Inside Novacore we could reinvent Prolog Dicts. JavaScript
has a primitive data type for Symbols, so you can call Symbol.for(“key”), which will internalize the string, so that
you can use pointer equality on the result:
Symbol is a built-in object whose constructor returns a symbol primitive https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol
It wouldn’t match JSON usage, since the keys are not supposed
to be Symbols, only Strings. But maybe this is only superficially,
and internally they are Symbols. One could do the same for
Novacore Prolog Dicts. On the surface Novacore Prolog
Dicts would use Strings:
?- X = {"abc" : 123.45, "def": 67}.
But under the hood there would be a transition from String to Atom:
?- X = {"abc" : 123.45, "def": 67}, X =.. L.
L = [C'novacore_dict, abc, 123.45, def, 67]
The rational would be: The keys usually form a limited vocabulary.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Sat Mar 18 06:06:34 2023
But this other angle would only work inside JSON.
There is still a problem with ordinary Prolog code, and
for example the disabled setter. If we want to avoid some
bottle neck of translating structures back and forth.
Mostowski Collapse schrieb am Samstag, 18. März 2023 um 14:01:35 UTC+1:
Currently I get an error when I use string keys:
/* SWI-Prolog 9.1.4 */
?- current_prolog_flag(double_quotes, X).
X = string.
?- X = _{"abc": 123.46, "def": 67}.
ERROR: Syntax error: key_expected
Also there is the annoying need for an underscore functor.
With string keys I could directly embed JSON?
In this case null, false and true could be easily an atom.
Thats kind of solving the constant problem from another angle.
Mostowski Collapse schrieb am Samstag, 18. März 2023 um 13:56:23 UTC+1:
Interestingly with the above trick, a Prolog parser can
recognize Novacore Prolog Dicts. Since it would see this
production at the head of a Novacore Prolog Dict:
novacore_dict :== "{" string ":" term ... "}"
Which is unlike the ISO core definition of “{}”, since in
ISO core there are no strings, and even a qualified call in
ISO module assumes that we have atom “:” term. So
there would be no collision with this production:
set :== "{" term "}"
Mostowski Collapse schrieb am Samstag, 18. März 2023 um 13:55:21 UTC+1:
Inside Novacore we could reinvent Prolog Dicts. JavaScript
has a primitive data type for Symbols, so you can call Symbol.for(“key”), which will internalize the string, so that
you can use pointer equality on the result:
Symbol is a built-in object whose constructor returns a symbol primitive
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol
It wouldn’t match JSON usage, since the keys are not supposed
to be Symbols, only Strings. But maybe this is only superficially,
and internally they are Symbols. One could do the same for
Novacore Prolog Dicts. On the surface Novacore Prolog
Dicts would use Strings:
?- X = {"abc" : 123.45, "def": 67}.
But under the hood there would be a transition from String to Atom:
?- X = {"abc" : 123.45, "def": 67}, X =.. L.
L = [C'novacore_dict, abc, 123.45, def, 67]
The rational would be: The keys usually form a limited vocabulary.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
All on Sat Mar 18 05:55:20 2023
Inside Novacore we could reinvent Prolog Dicts. JavaScript
has a primitive data type for Symbols, so you can call
Symbol.for(“key”), which will internalize the string, so that
you can use pointer equality on the result:
Symbol is a built-in object whose constructor returns a symbol primitive https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol
It wouldn’t match JSON usage, since the keys are not supposed
to be Symbols, only Strings. But maybe this is only superficially,
and internally they are Symbols. One could do the same for
Novacore Prolog Dicts. On the surface Novacore Prolog
Dicts would use Strings:
?- X = {"abc" : 123.45, "def": 67}.
But under the hood there would be a transition from String to Atom:
?- X = {"abc" : 123.45, "def": 67}, X =.. L.
L = [C'novacore_dict, abc, 123.45, def, 67]
The rational would be: The keys usually form a limited vocabulary.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Sat Mar 18 06:01:33 2023
Currently I get an error when I use string keys:
/* SWI-Prolog 9.1.4 */
?- current_prolog_flag(double_quotes, X).
X = string.
?- X = _{"abc": 123.46, "def": 67}.
ERROR: Syntax error: key_expected
Also there is the annoying need for an underscore functor.
With string keys I could directly embed JSON?
In this case null, false and true could be easily an atom.
Thats kind of solving the constant problem from another angle.
Mostowski Collapse schrieb am Samstag, 18. März 2023 um 13:56:23 UTC+1:
Interestingly with the above trick, a Prolog parser can
recognize Novacore Prolog Dicts. Since it would see this
production at the head of a Novacore Prolog Dict:
novacore_dict :== "{" string ":" term ... "}"
Which is unlike the ISO core definition of “{}”, since in
ISO core there are no strings, and even a qualified call in
ISO module assumes that we have atom “:” term. So
there would be no collision with this production:
set :== "{" term "}"
Mostowski Collapse schrieb am Samstag, 18. März 2023 um 13:55:21 UTC+1:
Inside Novacore we could reinvent Prolog Dicts. JavaScript
has a primitive data type for Symbols, so you can call Symbol.for(“key”), which will internalize the string, so that
you can use pointer equality on the result:
Symbol is a built-in object whose constructor returns a symbol primitive https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol
It wouldn’t match JSON usage, since the keys are not supposed
to be Symbols, only Strings. But maybe this is only superficially,
and internally they are Symbols. One could do the same for
Novacore Prolog Dicts. On the surface Novacore Prolog
Dicts would use Strings:
?- X = {"abc" : 123.45, "def": 67}.
But under the hood there would be a transition from String to Atom:
?- X = {"abc" : 123.45, "def": 67}, X =.. L.
L = [C'novacore_dict, abc, 123.45, def, 67]
The rational would be: The keys usually form a limited vocabulary.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
All on Sat May 13 06:36:03 2023
Now I have already removed the following predicates from
Novacore, they landed in library(compat):
- numbervars/2
- subsumes/2
- subsumes_term/2
Now wonder where variant/2 would land? SWI-Prolog wants to tell me
that variant/2 might need library(compat), because of numbervars/2.
Assuming A and B have already distinct variables I get the following solution:
A =@= B :-
\+ \+ (numbervars(Ac, 0, N),
numbervars(Bc, 0, N),
Ac == Bc).
https://www.swi-prolog.org/pldoc/doc_for?object=%28%3D@%3D%29/2
On the other hand this solution gives me also a library(compat)
dependency, since its based on subsumes_term/2. Again assuming A and
B have already distinct variables I get the following solution:
A =@= B :-
subsumes_term(A, B),
subsumes_term(B, A).
https://www.complang.tuwien.ac.at/ulrich/iso-prolog/built-in_predicates
Isn't there something simpler?
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
Mostowski Collapse on Sat May 13 06:41:09 2023
This is cute, has quite some different dependencies,
inspired by the use of term_variables/3 in bagof/3,
again assuming that A and B have already disjoint variables:
A =@= B :-
term_variables(A, L),
term_variables(B, R),
\+ \+ (L=R, A==B).
Can be bootstrapped from a much smaler Novacore.
Mostowski Collapse schrieb am Samstag, 13. Mai 2023 um 15:36:04 UTC+2:
Now I have already removed the following predicates from
Novacore, they landed in library(compat):
- numbervars/2
- subsumes/2
- subsumes_term/2
Now wonder where variant/2 would land? SWI-Prolog wants to tell me
that variant/2 might need library(compat), because of numbervars/2.
Assuming A and B have already distinct variables I get the following solution:
A =@= B :-
\+ \+ (numbervars(A, 0, N),
numbervars(B, 0, N),
A == B).
https://www.swi-prolog.org/pldoc/doc_for?object=%28%3D@%3D%29/2
On the other hand this solution gives me also a library(compat)
dependency, since its based on subsumes_term/2. Again assuming A and
B have already distinct variables I get the following solution:
A =@= B :-
subsumes_term(A, B),
subsumes_term(B, A). https://www.complang.tuwien.ac.at/ulrich/iso-prolog/built-in_predicates
Isn't there something simpler?
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mostowski Collapse@21:1/5 to
All on Sun May 21 03:54:41 2023
Now I have implemented the new open/4 options method/1,
headers/1 and body/1 also for Dogelog Player. There is a first
take that works in the browser. More platforms to follow.
Its such a thin extension, API wise, want to have it as part of
Novacore. What do other Prolog systems do? Here is what
SWI-Prolog in their offering.
- method/1: Accepts the method name in lower case,
so far I use the option with an upper case value.
- headers/1: Doesn't use our Key-Value pair format,
instead the format is Key(Value). Has separate option
for auth/1 and inside auth/1 for bearer/1.
- body/1: Not available in SWI-Prolog, must use post/1,
and post/1 accepts quite a bulk of formats.
and then I find that Trealla Prolog does something else
Signature wise:
- offers some convenience like http_post/4, http_delete/3,
bootstrapped from http_get/3.
- http_get/3 has options method/1, post/1 and header/2,
quite amazing, mostly written in 100% Prolog!
- might also support HTTPS, depends on client/5.
- this was checked into GitHub 9 months ago
and Scryer Prolog does again something else
Signature wise:
- http_open/3 had a 100% Prolog solution in 2020,
but became something else 12 months ago.
- http_open/3 has options method/1, data/1 and
request_headers/1, goes into CallHttpOpen instruction,
which then uses hyper_tls.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
All on Sat Jul 29 04:51:11 2023
The new multilingual strings are also an exercise in
Novacore. There were a few issues that needed novel
Prolog solutions, to make a Novacore solution.
One problem was I didn't want to use library(format)
and format/3 to format multilingual strings when
generating error messages. This addresses more
the later multilingual strings processing than the
multilingual strings store itself. So how resolve this
paradox? Here is my take, a mini format/3 boostraped
from the Dogelog Player specific atom_split/3:
% sys_inter_polate(+Stream, +Atom, +List)
sys_inter_polate(Stream, Template, Args) :-
atom_split(Template, '~', [Head|Tail]),
put_atom(Stream, Head),
sys_zipper_output(Args, Tail, Stream).
% sys_zipper_output(+List, +List, +Stream)
sys_zipper_output([Arg|Args], [Head|Tail], Stream) :-
writeq(Stream, Arg),
put_atom(Stream, Head),
sys_zipper_output(Args, Tail, Stream).
sys_zipper_output([], [], _).
It only understands format specifier '~', but is sufficient:
/* German Text */
strings('syntax_error.singleton_var', de, 'Alleinstehende Variable(n) ~, anonyme Variable(n) (_) benutzen.').
/* English and Fallback Text */
strings('syntax_error.singleton_var', '', 'Singleton variable(s) ~, use anonymous variable(s) (_).').
LoL
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
All on Thu Sep 7 17:15:20 2023
Did you know that Novacore has change_arg/3?
Works for Dogelog Player and formerly Jekejeke Prolog.
It is similar like nb_linkarg/3 in SWI-Prolog.
So we can implement countall/3 in a blink:
countall(G, N) :-
functor(Holder, v, 1),
change_arg(1, Holder, 0),
(G,
arg(1, Holder, H),
J is H+1,
change_arg(1, Holder, J),
fail; true),
arg(1, Holder, N).
Works find:
?- countall(between(10,20,_), N).
N = 11.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
All on Sun Nov 19 19:56:32 2023
We are now exploring file systems with novacore.
And here and then we have a couple of primitives
and then do some bootstrapping. It currently lands
in library(random) until we find a better place:
% directory_member(+Atom, -Atom)
directory_member(F, N) :-
directory_files(F, L),
member(N, L).
% ensure_directory(+Atom)
ensure_directory(F) :-
file_exists(F),
file_property(F, type(directory)),
!.
ensure_directory(F) :-
make_directory(F).
Guess what, finding semantic and support of
directory_files/2, file_exists/1 and file_property/2
is already non trivial.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
All on Sun Nov 19 10:54:28 2023
We are now exploring file systems with novacore.
And here and then we have a couple of primitives
and then do some bootstrapping. It currently lands
in library(random) until we find a better place:
% directory_member(+Atom, -Atom)
directory_member(F, N) :-
directory_files(F, L),
member(N, L).
% ensure_directory(+Atom)
ensure_directory(F) :-
file_exists(F),
file_property(F, type(directory)),
!.
ensure_directory(F) :-
make_directory(F).
Guess what, finding semantic and support of
directory_files/2, file_exists/1 and file_property/2
is already non trivial.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
Mild Shock on Sun Nov 19 19:59:07 2023
LogNonsenseTalk with its brainwash is totally
useless. This here is already wrong:
file_exists(File) :-
absolute_file_name(File, ExpandedPath),
{exists_file(ExpandedPath)}.
https://github.com/LogtalkDotOrg/logtalk3/blob/master/library/os/os.lgt
Becaue for example exists_file/1 in SWI-Prolog
means exists regular file. But file_exists/1
should mean exists file of any type. Just
lookup what GNU Prolog provides. In OS lingua
file means often regular, directory, etc..
Mild Shock schrieb:
We are now exploring file systems with novacore.
And here and then we have a couple of primitives
and then do some bootstrapping. It currently lands
in library(random) until we find a better place:
% directory_member(+Atom, -Atom)
directory_member(F, N) :-
directory_files(F, L),
member(N, L).
% ensure_directory(+Atom)
ensure_directory(F) :-
file_exists(F),
file_property(F, type(directory)),
!.
ensure_directory(F) :-
make_directory(F).
Guess what, finding semantic and support of
directory_files/2, file_exists/1 and file_property/2
is already non trivial.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
Mild Shock on Sun Nov 19 20:01:48 2023
You see the OS jargon meaning in directory_member/2
which is bootstrapped from directory_files/2.
directory_files/2 should of course list any files
inside the directory, regular, directory, etc..
not only regular files. So "files" means any
file of type regular, directory, etc..
Mild Shock schrieb:
LogNonsenseTalk with its brainwash is totally
useless. This here is already wrong:
file_exists(File) :-
absolute_file_name(File, ExpandedPath),
{exists_file(ExpandedPath)}.
https://github.com/LogtalkDotOrg/logtalk3/blob/master/library/os/os.lgt
Becaue for example exists_file/1 in SWI-Prolog
means exists regular file. But file_exists/1
should mean exists file of any type. Just
lookup what GNU Prolog provides. In OS lingua
file means often regular, directory, etc..
Mild Shock schrieb:
We are now exploring file systems with novacore.
And here and then we have a couple of primitives
and then do some bootstrapping. It currently lands
in library(random) until we find a better place:
% directory_member(+Atom, -Atom)
directory_member(F, N) :-
directory_files(F, L),
member(N, L).
% ensure_directory(+Atom)
ensure_directory(F) :-
file_exists(F),
file_property(F, type(directory)),
!.
ensure_directory(F) :-
make_directory(F).
Guess what, finding semantic and support of
directory_files/2, file_exists/1 and file_property/2
is already non trivial.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
Mild Shock on Sun Jul 28 14:32:58 2024
Hi,
To capture some critical examples of float to string
conversion I went with this kind of little excess
precision and had this float to string conversion:
return shape_number(num.toPrecision(17));
Which gives this unfortunate result, still in release
1.2.1 of Dogelog Player for JavaScript seen:
?- between(1,10,N), X is (20+N)/10, write(X), nl, fail; true. 2.1000000000000001
2.2000000000000002
2.2999999999999998
2.3999999999999999
2.5
2.6000000000000001
2.7000000000000002
2.7999999999999998
2.8999999999999999
3.0
One work around is to check whether precision 16 would
also work. Like this code here:
let res = num.toPrecision(16);
if (Number(res) === num) {
return shape_number(res);
} else {
return shape_number(num.toPrecision(17));
}
The results are much more eye friendly:
?- between(1,10,N), X is (20+N)/10, write(X), nl, fail; true.
2.1
2.2
2.3
2.4
2.5
2.6
2.7
2.8
2.9
3.0
true.
Can we accept this solution? Will it slow down printing?
Mild Shock schrieb:
The new multilingual strings are also an exercise in
Novacore. There were a few issues that needed novel
Prolog solutions, to make a Novacore solution.
One problem was I didn't want to use library(format)
and format/3 to format multilingual strings when
generating error messages. This addresses more
the later multilingual strings processing than the
multilingual strings store itself. So how resolve this
paradox? Here is my take, a mini format/3 boostraped
from the Dogelog Player specific atom_split/3:
% sys_inter_polate(+Stream, +Atom, +List)
sys_inter_polate(Stream, Template, Args) :-
atom_split(Template, '~', [Head|Tail]),
put_atom(Stream, Head),
sys_zipper_output(Args, Tail, Stream).
% sys_zipper_output(+List, +List, +Stream)
sys_zipper_output([Arg|Args], [Head|Tail], Stream) :-
writeq(Stream, Arg),
put_atom(Stream, Head),
sys_zipper_output(Args, Tail, Stream).
sys_zipper_output([], [], _).
It only understands format specifier '~', but is sufficient:
/* German Text */
strings('syntax_error.singleton_var', de, 'Alleinstehende Variable(n) ~, anonyme Variable(n) (_) benutzen.').
/* English and Fallback Text */
strings('syntax_error.singleton_var', '', 'Singleton variable(s) ~, use anonymous variable(s) (_).').
LoL
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
All on Tue Sep 24 17:10:05 2024
Here are two test cases for memory
management of a Prolog system:
/* bomb */
app([], X, X).
app([X|Y], Z, [X|T]) :- app(Y, Z, T).
garbage(0, [0]) :- !.
garbage(N, L) :- M is N-1, garbage(M, R), app(R, R, L).
foo :- garbage(12,_), foo.
/* xbetween */
xbetween1(L, _, L).
xbetween1(L, U, N) :- L < U, M is L+1, xbetween1(M, U, N).
They test possibly something different. xbetween does
not produce a lot of objects during tail recursion,
it only decrements one integer. The xbetween example
might be ok, wherea the bomb example might be neverthelesss
not ok, especially since unlike in the xbetween example,
the bomb example has also an "intermediate" variables.
The "intermediate" variable is "_":
foo :- garbage(12,_), foo.
The xbetween example has no such variable. All
variables in the xbetween example are either in
the head or in the tail recursive call, making
it a more trivial example than the bomb example.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
All on Wed Oct 9 09:43:56 2024
How about some of these PIPs:
PIP401: library(lists)
Provide predicates such as nth1/3, last/2, etc…
PIP402: library(sets)
Provide predicates such as union/3, subset/2, etc…
PIP403: library(sequence)
Provide predicates such as call_nth/2, limit/2, etc…
PIP404: library(aggregate)
Provide predicates such as aggregate_all/3, aggregate/3, etc…
There was once an effort Prolog Commons, which has
some overlap with the above PIPs:
The Prolog Commons Group - PART I - Library
https://prolog-commons.org/PrologCommons.html/part_library.html
But its more modularized than just a Prologue to Prolog,
which has a few list predicates and miscellaneous.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
Mild Shock on Wed Oct 9 09:45:25 2024
Also interesting development, there is something
like “Prologue to Prolog C”, where C possibly
stands for cryptography. So maybe a further PIP:
PIP301: library(crypto)
Predicates such as crypto_data_hash/3, etc…
PIP302: library(charsio)
Predicates such as open_memory_file/2, etc…
PIP303: library(format)
Predicates such as format/3, etc…
In the above I have also added charsio and format,
which is useful in many contexts. Some remark about
the 30x modules, they usually a more based on
additional native routines. This is unlike the 40x
modules, which can have a pure Prolog reference
implementation.
Mild Shock schrieb:
How about some of these PIPs:
PIP401: library(lists)
Provide predicates such as nth1/3, last/2, etc…
PIP402: library(sets)
Provide predicates such as union/3, subset/2, etc…
PIP403: library(sequence)
Provide predicates such as call_nth/2, limit/2, etc…
PIP404: library(aggregate)
Provide predicates such as aggregate_all/3, aggregate/3, etc…
There was once an effort Prolog Commons, which has
some overlap with the above PIPs:
The Prolog Commons Group - PART I - Library https://prolog-commons.org/PrologCommons.html/part_library.html
But its more modularized than just a Prologue to Prolog,
which has a few list predicates and miscellaneous.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
Mild Shock on Wed Oct 9 10:00:44 2024
And this one:
PIP304: library(math)
Evaluable functions such as popcount/1, etc…
The idea of a library(math) is brand new,
I first had it named library(random) and
then it got out of hands, exploded and
had many bitwise operations.
Mild Shock schrieb:
Also interesting development, there is something
like “Prologue to Prolog C”, where C possibly
stands for cryptography. So maybe a further PIP:
PIP301: library(crypto)
Predicates such as crypto_data_hash/3, etc…
PIP302: library(charsio)
Predicates such as open_memory_file/2, etc…
PIP303: library(format)
Predicates such as format/3, etc…
In the above I have also added charsio and format,
which is useful in many contexts. Some remark about
the 30x modules, they usually a more based on
additional native routines. This is unlike the 40x
modules, which can have a pure Prolog reference
implementation.
Mild Shock schrieb:
How about some of these PIPs:
PIP401: library(lists)
Provide predicates such as nth1/3, last/2, etc…
PIP402: library(sets)
Provide predicates such as union/3, subset/2, etc…
PIP403: library(sequence)
Provide predicates such as call_nth/2, limit/2, etc…
PIP404: library(aggregate)
Provide predicates such as aggregate_all/3, aggregate/3, etc…
There was once an effort Prolog Commons, which has
some overlap with the above PIPs:
The Prolog Commons Group - PART I - Library
https://prolog-commons.org/PrologCommons.html/part_library.html
But its more modularized than just a Prologue to Prolog,
which has a few list predicates and miscellaneous.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
Mild Shock on Wed Oct 9 11:22:08 2024
Ok, Scryer Prolog calls it library(arithmetic).
I prefer library(math), since many other programming
languages have Math.random(). But if I remember
well Scryer Prolog has a separate library for
random numbers. The library(arithemtic) might
provide a popcount/2 predicate, but it doesn't
provide a popcount/2 evaluable function. I get this error:
?- ['gridn.p'].
error(type_error(evaluable,popcount/1),load/1).
Thats a pitty, one more obstacle in portable Prolog code.
P.S.: I know it is hard to make evaluable functions
definable in modules or Prolog text more general.
Especially since executing a Prolog defined evaluable
functions can be non-trivial in terms of stack etc..,
since evaluable functions just like unification etc..
might use other stacks, and therefore mixing with
the Prolog stack can lead to bad performance, because
of some impedence mismatch. But there is a nice compromise,
for native libraries it might be easier to register
a new evaluable function.
Mild Shock schrieb:
And this one:
PIP304: library(math)
Evaluable functions such as popcount/1, etc…
The idea of a library(math) is brand new,
I first had it named library(random) and
then it got out of hands, exploded and
had many bitwise operations.
Mild Shock schrieb:
Also interesting development, there is something
like “Prologue to Prolog C”, where C possibly
stands for cryptography. So maybe a further PIP:
PIP301: library(crypto)
Predicates such as crypto_data_hash/3, etc…
PIP302: library(charsio)
Predicates such as open_memory_file/2, etc…
PIP303: library(format)
Predicates such as format/3, etc…
In the above I have also added charsio and format,
which is useful in many contexts. Some remark about
the 30x modules, they usually a more based on
additional native routines. This is unlike the 40x
modules, which can have a pure Prolog reference
implementation.
Mild Shock schrieb:
How about some of these PIPs:
PIP401: library(lists)
Provide predicates such as nth1/3, last/2, etc…
PIP402: library(sets)
Provide predicates such as union/3, subset/2, etc…
PIP403: library(sequence)
Provide predicates such as call_nth/2, limit/2, etc…
PIP404: library(aggregate)
Provide predicates such as aggregate_all/3, aggregate/3, etc…
There was once an effort Prolog Commons, which has
some overlap with the above PIPs:
The Prolog Commons Group - PART I - Library
https://prolog-commons.org/PrologCommons.html/part_library.html
But its more modularized than just a Prologue to Prolog,
which has a few list predicates and miscellaneous.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
All on Wed Oct 9 15:29:12 2024
@herme wrote:
Just a quick comment: note that you can make
and discuss the PIP proposals directly on
the PIPs discourse.
Here my response:
I will probably never go there since somebody
tried censoring my comments and said I don’t
work towards the Prolog cause. The good thing
about SWI-Prolog discourse, it has become
quite calm cocerning attempts to censor people,
possibly because some particular people left.
Which is in my opinion the best thing that
could happen to this forum. There is no
guarantee in other forums to really have free speech.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
Mild Shock on Thu Oct 10 00:14:49 2024
The implementation to allow native libraries to register
new evaluable functions is the same as how predicates
are consulted. Take these two files:
$ cat > foo.p
test :- hello.
$ cat > bar.p
hello :- write('hello'), nl.
If I consult foo.p before bar.p there is a forward reference.
But if I ultimately consult bar.p the forward reference is
resolved. How does a Prolog system do that?
$ target/release/scryer-prolog
?- ['foo.p'].
true.
?- test.
error(existence_error(procedure,hello/0),hello/0).
?- ['bar.p'].
true.
?- test.
hello
true.
Now enhance is/2, etc... so that it uses the same resultion
meachanism, but only for the evaluable function namespace,
and provide a FFI where one can register evaluable functions,
in the evaluable function namespace, eh voila you are done,
makeing your Prolog extensible. Allowing to register evaluable
functions like gdc/2, popcount/1, etc.. outside of the core.
Mild Shock schrieb:
The new multilingual strings are also an exercise in
Novacore. There were a few issues that needed novel
Prolog solutions, to make a Novacore solution.
One problem was I didn't want to use library(format)
and format/3 to format multilingual strings when
generating error messages. This addresses more
the later multilingual strings processing than the
multilingual strings store itself. So how resolve this
paradox? Here is my take, a mini format/3 boostraped
from the Dogelog Player specific atom_split/3:
% sys_inter_polate(+Stream, +Atom, +List)
sys_inter_polate(Stream, Template, Args) :-
atom_split(Template, '~', [Head|Tail]),
put_atom(Stream, Head),
sys_zipper_output(Args, Tail, Stream).
% sys_zipper_output(+List, +List, +Stream)
sys_zipper_output([Arg|Args], [Head|Tail], Stream) :-
writeq(Stream, Arg),
put_atom(Stream, Head),
sys_zipper_output(Args, Tail, Stream).
sys_zipper_output([], [], _).
It only understands format specifier '~', but is sufficient:
/* German Text */
strings('syntax_error.singleton_var', de, 'Alleinstehende Variable(n) ~, anonyme Variable(n) (_) benutzen.').
/* English and Fallback Text */
strings('syntax_error.singleton_var', '', 'Singleton variable(s) ~, use anonymous variable(s) (_).').
LoL
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
Mild Shock on Thu Oct 10 00:16:29 2024
In the proposal Name resolution is a blackbox.
It can be anything, atom table, dynamic lookup,
etc.. etc.. There should be a lot of synergy in
every Prolog system using the same approach for
predicates and evaluable functions concerning
their existence. But of course evaluable
functions need special attention to have
efficient evaluation.
Mild Shock schrieb:
The implementation to allow native libraries to register
new evaluable functions is the same as how predicates
are consulted. Take these two files:
$ cat > foo.p
test :- hello.
$ cat > bar.p
hello :- write('hello'), nl.
If I consult foo.p before bar.p there is a forward reference.
But if I ultimately consult bar.p the forward reference is
resolved. How does a Prolog system do that?
$ target/release/scryer-prolog
?- ['foo.p'].
true.
?- test.
error(existence_error(procedure,hello/0),hello/0).
?- ['bar.p'].
true.
?- test.
hello
true.
Now enhance is/2, etc... so that it uses the same resultion
meachanism, but only for the evaluable function namespace,
and provide a FFI where one can register evaluable functions,
in the evaluable function namespace, eh voila you are done,
makeing your Prolog extensible. Allowing to register evaluable
functions like gdc/2, popcount/1, etc.. outside of the core.
Mild Shock schrieb:
The new multilingual strings are also an exercise in
Novacore. There were a few issues that needed novel
Prolog solutions, to make a Novacore solution.
One problem was I didn't want to use library(format)
and format/3 to format multilingual strings when
generating error messages. This addresses more
the later multilingual strings processing than the
multilingual strings store itself. So how resolve this
paradox? Here is my take, a mini format/3 boostraped
from the Dogelog Player specific atom_split/3:
% sys_inter_polate(+Stream, +Atom, +List)
sys_inter_polate(Stream, Template, Args) :-
atom_split(Template, '~', [Head|Tail]),
put_atom(Stream, Head),
sys_zipper_output(Args, Tail, Stream).
% sys_zipper_output(+List, +List, +Stream)
sys_zipper_output([Arg|Args], [Head|Tail], Stream) :-
writeq(Stream, Arg),
put_atom(Stream, Head),
sys_zipper_output(Args, Tail, Stream).
sys_zipper_output([], [], _).
It only understands format specifier '~', but is sufficient:
/* German Text */
strings('syntax_error.singleton_var', de, 'Alleinstehende Variable(n)
~, anonyme Variable(n) (_) benutzen.').
/* English and Fallback Text */
strings('syntax_error.singleton_var', '', 'Singleton variable(s) ~,
use anonymous variable(s) (_).').
LoL
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
All on Sat Oct 12 22:02:21 2024
The ISO core standard probably set the
stage for a couple of performance sins.
In 7.1.6.1 Variants of a term we find
these test cases:
- f(A, B, A) is a variant of f(X, Y, X).
- g(A, B) is a variant of g(_, _).
- P+Q is a variant of P+Q.
What is doubious here, is the last test
case with P+Q. Do we need to test terms
that have common variables?
Lets assume we have situations where we
don't need variant working with common
variables in the two argument terms, what
about then using this bootstrapping:
variant_term(X, Y) :-
subsumes_term(X, Y),
subsumes_term(Y, X).
Here some testing, does it work ok? Take this code:
enum_arg(_, 1).
enum_arg(_, _).
enum_arg(X, X).
enum_list(_, []).
enum_list(X, [H|T]) :- enum_arg(X, H), enum_list(X, T).
boole(G, 1) :- G, !.
boole(_, 0).
nok(L, R) :- length(L, 6), length(R, 6),
enum_list(_, L), enum_list(_, R),
boole(variant(L, R), A), boole(variant_term(L, R), B),
A \== B.
Seems to work fine:
?- nok(L, R).
false.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
Mild Shock on Sat Oct 12 23:16:30 2024
How much faster is it?
Here some test harness:
test :- length(L, 6), length(R, 6),
enum_list(_, L), enum_list(_, R),
variant(L, R), fail; true.
test2 :- length(L, 6), length(R, 6),
enum_list(_, L), enum_list(_, R),
variant_term(L, R), fail; true.
Here some results:
- SWI-Prolog 9.3.11:
?- time(test).
% 2,126,498 inferences, 0.734 CPU in 0.752 seconds
(98% CPU, 2895657 Lips)
true.
?- time(test2).
% 2,159,795 inferences, 0.234 CPU in 0.236 seconds
(99% CPU, 9215125 Lips)
true.
- Trealla Prolog 2.57.16:
?- time(test).
% Time elapsed 3.128s, 14827949 Inferences, 4.741 MLips
true.
?- time(test2).
% Time elapsed 1.079s, 7775516 Inferences, 7.206 MLips
true.
- Scryer Prolog :
?- time(test3).
% CPU time: 5.653s, 5_192_831 inferences
true.
?- time(test2).
% CPU time: 1.544s, 6_116_163 inferences
true.
Note: test3 is like test, only it uses builtins:variant/2.
Mild Shock schrieb:
The ISO core standard probably set the
stage for a couple of performance sins.
In 7.1.6.1 Variants of a term we find
these test cases:
- f(A, B, A) is a variant of f(X, Y, X).
- g(A, B) is a variant of g(_, _).
- P+Q is a variant of P+Q.
What is doubious here, is the last test
case with P+Q. Do we need to test terms
that have common variables?
Lets assume we have situations where we
don't need variant working with common
variables in the two argument terms, what
about then using this bootstrapping:
variant_term(X, Y) :-
subsumes_term(X, Y),
subsumes_term(Y, X).
Here some testing, does it work ok? Take this code:
enum_arg(_, 1).
enum_arg(_, _).
enum_arg(X, X).
enum_list(_, []).
enum_list(X, [H|T]) :- enum_arg(X, H), enum_list(X, T).
boole(G, 1) :- G, !.
boole(_, 0).
nok(L, R) :- length(L, 6), length(R, 6),
enum_list(_, L), enum_list(_, R),
boole(variant(L, R), A), boole(variant_term(L, R), B),
A \== B.
Seems to work fine:
?- nok(L, R).
false.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
Mild Shock on Sat Oct 12 23:34:33 2024
So what can we do with this insight. Here is
a little performance of a new distinct/1,
that is eager und non-variant enumerating:
/* eagerness */
?- distinct(repeat), !.
true.
d(f(A,A)).
d(f(a,a)).
d(f(B,B)).
/* non-variant enumerating */
?- distinct(d(X)).
X = f(_70321, _70321);
X = f(a, a);
fail.
It is implemented with variant_term/2, since the
remembered list of archived witnesses so far,
is anyway copies of terms. So variant_term/2
is appropriate, we never have to check
two terms that have variables in common.
Cool!
Mild Shock schrieb:
How much faster is it?
Here some test harness:
test :- length(L, 6), length(R, 6),
enum_list(_, L), enum_list(_, R),
variant(L, R), fail; true.
test2 :- length(L, 6), length(R, 6),
enum_list(_, L), enum_list(_, R),
variant_term(L, R), fail; true.
Here some results:
- SWI-Prolog 9.3.11:
?- time(test).
% 2,126,498 inferences, 0.734 CPU in 0.752 seconds
(98% CPU, 2895657 Lips)
true.
?- time(test2).
% 2,159,795 inferences, 0.234 CPU in 0.236 seconds
(99% CPU, 9215125 Lips)
true.
- Trealla Prolog 2.57.16:
?- time(test).
% Time elapsed 3.128s, 14827949 Inferences, 4.741 MLips
true.
?- time(test2).
% Time elapsed 1.079s, 7775516 Inferences, 7.206 MLips
true.
- Scryer Prolog :
?- time(test3).
% CPU time: 5.653s, 5_192_831 inferences
true.
?- time(test2).
% CPU time: 1.544s, 6_116_163 inferences
true.
Note: test3 is like test, only it uses builtins:variant/2.
Mild Shock schrieb:
The ISO core standard probably set the
stage for a couple of performance sins.
In 7.1.6.1 Variants of a term we find
these test cases:
- f(A, B, A) is a variant of f(X, Y, X).
- g(A, B) is a variant of g(_, _).
- P+Q is a variant of P+Q.
What is doubious here, is the last test
case with P+Q. Do we need to test terms
that have common variables?
Lets assume we have situations where we
don't need variant working with common
variables in the two argument terms, what
about then using this bootstrapping:
variant_term(X, Y) :-
subsumes_term(X, Y),
subsumes_term(Y, X).
Here some testing, does it work ok? Take this code:
enum_arg(_, 1).
enum_arg(_, _).
enum_arg(X, X).
enum_list(_, []).
enum_list(X, [H|T]) :- enum_arg(X, H), enum_list(X, T).
boole(G, 1) :- G, !.
boole(_, 0).
nok(L, R) :- length(L, 6), length(R, 6),
enum_list(_, L), enum_list(_, R),
boole(variant(L, R), A), boole(variant_term(L, R), B),
A \== B.
Seems to work fine:
?- nok(L, R).
false.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
Mild Shock on Sun Oct 13 00:54:18 2024
Ok, I have to redo my nok/2 test for Scryer Prolog,
since Scryer Prolog doesn't work as per ISO spec:
/* Scryer Prolog Playground */
?- builtins:variant(f(A,B), f(C,D)).
A = A, B = A, C = A, D = A.
It should not leave some bindings. At least this is
what other Prolog systems do:
/* Trealla Prolog */
?- variant(f(A,B), f(C,D)).
true.
/* SWI-Prolog */
?- variant(f(A,B), f(C,D)).
true.
The performance tests are not affected, but I guess
it is better to test nok/2 like this:
nok2(L, R) :- length(L, 6), length(R, 6),
enum_list(_, L), enum_list(_, R),
boole(variant_term(L, R), A), boole(builtins:variant(L, R), B),
A \== B.
Besides the binding glitch, it seems to be ok:
?- nok2(L, R).
false.
Mild Shock schrieb:
So what can we do with this insight. Here is
a little performance of a new distinct/1,
that is eager und non-variant enumerating:
/* eagerness */
?- distinct(repeat), !.
true.
d(f(A,A)).
d(f(a,a)).
d(f(B,B)).
/* non-variant enumerating */
?- distinct(d(X)).
X = f(_70321, _70321);
X = f(a, a);
fail.
It is implemented with variant_term/2, since the
remembered list of archived witnesses so far,
is anyway copies of terms. So variant_term/2
is appropriate, we never have to check
two terms that have variables in common.
Cool!
Mild Shock schrieb:
How much faster is it?
Here some test harness:
test :- length(L, 6), length(R, 6),
enum_list(_, L), enum_list(_, R),
variant(L, R), fail; true.
test2 :- length(L, 6), length(R, 6),
enum_list(_, L), enum_list(_, R),
variant_term(L, R), fail; true.
Here some results:
- SWI-Prolog 9.3.11:
?- time(test).
% 2,126,498 inferences, 0.734 CPU in 0.752 seconds
(98% CPU, 2895657 Lips)
true.
?- time(test2).
% 2,159,795 inferences, 0.234 CPU in 0.236 seconds
(99% CPU, 9215125 Lips)
true.
- Trealla Prolog 2.57.16:
?- time(test).
% Time elapsed 3.128s, 14827949 Inferences, 4.741 MLips
true.
?- time(test2).
% Time elapsed 1.079s, 7775516 Inferences, 7.206 MLips
true.
- Scryer Prolog :
?- time(test3).
% CPU time: 5.653s, 5_192_831 inferences
true.
?- time(test2).
% CPU time: 1.544s, 6_116_163 inferences
true.
Note: test3 is like test, only it uses builtins:variant/2.
Mild Shock schrieb:
The ISO core standard probably set the
stage for a couple of performance sins.
In 7.1.6.1 Variants of a term we find
these test cases:
- f(A, B, A) is a variant of f(X, Y, X).
- g(A, B) is a variant of g(_, _).
- P+Q is a variant of P+Q.
What is doubious here, is the last test
case with P+Q. Do we need to test terms
that have common variables?
Lets assume we have situations where we
don't need variant working with common
variables in the two argument terms, what
about then using this bootstrapping:
variant_term(X, Y) :-
subsumes_term(X, Y),
subsumes_term(Y, X).
Here some testing, does it work ok? Take this code:
enum_arg(_, 1).
enum_arg(_, _).
enum_arg(X, X).
enum_list(_, []).
enum_list(X, [H|T]) :- enum_arg(X, H), enum_list(X, T).
boole(G, 1) :- G, !.
boole(_, 0).
nok(L, R) :- length(L, 6), length(R, 6),
enum_list(_, L), enum_list(_, R),
boole(variant(L, R), A), boole(variant_term(L, R), B),
A \== B.
Seems to work fine:
?- nok(L, R).
false.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
All on Sun Nov 3 00:52:30 2024
I have dropped the idea to realize and use variant/2.
The idea is to use only numbervars/3. Here is a test,
testing the newest release of SWI-Prolog as well:
/* SWI-Prolog 9.3.14 */
?- time(test5).
% 39,918,731 inferences, 9.031 CPU in 9.022 seconds (100% CPU, 4420067 Lips) true.
/* Dogelog Player 1.2.4 */
?- time(test5).
% Zeit 5696 ms, GC 0 ms, Lips 10186409, Uhr 03.11.2024 00:44
true.
The test code is:
test5 :-
(between(1,1000,_),
aggregate_all(count, distinct(gen3(_)), _),
fail; true).
gen3(X) :-
length(L, 25),
between(1,1000,_),
random(Y),
Z is floor(Y*1000),
X = [Z|L].
Ok, I tried a native implementation of variant/2.
I did it in Dogelog Player for Java. Thats a
Prolog system that doesn't have unification for
cyclic terms. So the situation is a little simpler.
Comparing on the same machine and with the data
we have already gathered it is shockingly fast!
/* Dogelog Player 1.2.4, JDK 22 */
?- time(test).
% Zeit 211 ms, GC 0 ms, Lips 7567459, Uhr 15.10.2024 01:30
true.
?- time(test2).
% Zeit 413 ms, GC 0 ms, Lips 10703217, Uhr 15.10.2024 01:30
true.
Here some results:
- SWI-Prolog 9.3.11:
?- time(test).
% 2,126,498 inferences, 0.734 CPU in 0.752 seconds
(98% CPU, 2895657 Lips)
true.
?- time(test2).
% 2,159,795 inferences, 0.234 CPU in 0.236 seconds
(99% CPU, 9215125 Lips)
true.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
Mild Shock on Wed Nov 6 09:33:11 2024
Hi,
Not only are the fucking PIPs behind a
login wall that doesn't work:
Dictionaries in Prolog
https://gitlab.software.imdea.org/prolog-lang/pip-0102
I cannot read gitlab.software.imdea.org,
since it redirects to some internal server
during login.
Also formal verification doesn't have the
same track record as fuzzying. Take the SWI-Prolog
red-black trees. Are they really red-black trees?
I used fuzzy testing to find the test case.
Exhaustive enumeration of permutation seemed to
be out of reach computationally.
So I used these random permutations to find a
discrepancy in resulting tree depth:
fuzzer(R) :-
numlist(1, 16, L),
between(1, 1000, _),
random_permutation(L, R).
Maybe the same technique can use to find smaller
discrepancies, and then use the smaller examples to
pin down difference in implemented balance
rules or implement rebalancing strategy.
Bye
Mild Shock schrieb:
@herme wrote:
Just a quick comment: note that you can make
and discuss the PIP proposals directly on
the PIPs discourse.
Here my response:
I will probably never go there since somebody
tried censoring my comments and said I don’t
work towards the Prolog cause. The good thing
about SWI-Prolog discourse, it has become
quite calm cocerning attempts to censor people,
possibly because some particular people left.
Which is in my opinion the best thing that
could happen to this forum. There is no
guarantee in other forums to really have free speech.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
Mild Shock on Wed Nov 6 09:35:17 2024
So what is the spec. Well one can use:
Red-Black Trees in a Functional Setting
https://www.cs.tufts.edu/~nr/cs257/archive/chris-okasaki/redblack99.pdf
insert :: (Ord a) => a -> Tree a -> Tree a
insert x s = makeBlack $ ins s
where ins E = T R E x E
ins (T color a y b)
| x < y = balance color (ins a) y b
| x == y = T color a y b
| x > y = balance color a y (ins b)
makeBlack (T _ a y b) = T B a y b
The balancing would be as follows, again Haskell code:
balance :: Color -> Tree a -> a -> Tree a -> Tree a
balance B (T R (T R a x b) y c) z d = T R (T B a x b) y (T B c z d)
balance B (T R a x (T R b y c)) z d = T R (T B a x b) y (T B c z d)
balance B a x (T R (T R b y c) z d) = T R (T B a x b) y (T B c z d)
balance B a x (T R b y (T R c z d)) = T R (T B a x b) y (T B c z d)
balance color a x b = T color a x b
Does SWI-Prolog implement somewhere Okasaki red-black trees.
Mild Shock schrieb:
Hi,
Not only are the fucking PIPs behind a
login wall that doesn't work:
Dictionaries in Prolog
https://gitlab.software.imdea.org/prolog-lang/pip-0102
I cannot read gitlab.software.imdea.org,
since it redirects to some internal server
during login.
Also formal verification doesn't have the
same track record as fuzzying. Take the SWI-Prolog
red-black trees. Are they really red-black trees?
I used fuzzy testing to find the test case.
Exhaustive enumeration of permutation seemed to
be out of reach computationally.
So I used these random permutations to find a
discrepancy in resulting tree depth:
fuzzer(R) :-
numlist(1, 16, L),
between(1, 1000, _),
random_permutation(L, R).
Maybe the same technique can use to find smaller
discrepancies, and then use the smaller examples to
pin down difference in implemented balance
rules or implement rebalancing strategy.
Bye
Mild Shock schrieb:
@herme wrote:
Just a quick comment: note that you can make
and discuss the PIP proposals directly on
the PIPs discourse.
Here my response:
I will probably never go there since somebody
tried censoring my comments and said I don’t
work towards the Prolog cause. The good thing
about SWI-Prolog discourse, it has become
quite calm cocerning attempts to censor people,
possibly because some particular people left.
Which is in my opinion the best thing that
could happen to this forum. There is no
guarantee in other forums to really have free speech.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
Mild Shock on Wed Nov 6 09:51:45 2024
Hi,
Spain is one of the main recipients of EU recovery funds,
with a total of 163 billion euros ($178 billion) earmarked
for the country, approximately half in grants and the rest
in loans. It has already received 37 billion euros.
Madrid and software.imdea.org is no exception. Probably
the same disaster as the Valencia floods. The money
is just siphoned into some crooks pockets. The biggest
crooks are at the moment ALP & friends,
just publishing a series of failure reports. Every
paper just reports some problems, never solutions.
Most recent cringe example:
BoostRLR: The beauty of Prolog for statistical
relational learning
https://www.informatik.uni-wuerzburg.de/fileadmin/10030600/2024/KI_2004_paper_174.pdf
What the fuck does this mean:
In SWI-Prolog, this can rely on an efficient specialised
implementation of aggregate_all(count,_,_), while we provide
a dedicated low-level XSB implementation in a count module
that we include with our program, courtesy of David S.
Warren (personal communication).
Why is change_arg/3 not common among Prolog systems.
Why do we deal with aggregates like we are still in
stone age. Aggregates are a well known discipline
of database technology.
Why only aggregate_all/2 and not also a memory savy
solutions of aggregate/3. Aggregates are the bread
and butter of statistics.
Bye
Mild Shock schrieb:> Results of a fuzzer comparison:
library(nb_rbtrees) from 2014 in SWI-Prolog:
/* SWI-Prolog 9.3.14 */
?- L = [16,10,12,13,15,5,11,8,14,1,7,6,3,2,4,9], rb_new(T),
(member(X,L), nb_rb_insert(T, X, true),
fail; true), rb_display(T, 0).
$BLK 12-true
$RED 5-true
$BLK 2-true
$BLK 1-true
$NIL
$NIL
$BLK 3-true
$NIL
$RED 4-true
$NIL
$NIL
$BLK 10-true
$RED 7-true
$BLK 6-true
$NIL
$NIL
$BLK 8-true
$NIL
$RED 9-true
$NIL
$NIL
$BLK 11-true
$NIL
$NIL
$BLK 15-true
$BLK 13-true
$NIL
$RED 14-true
$NIL
$NIL
$BLK 16-true
$NIL
$NIL
On the other hand the rules by Okasaki give a
different resulting tree, which is better balanced,
has less overall depth and doesn’t have a root 12,
rather the root 8. Implementation based on change_arg/3:
/* Dogelog Player 1.2.5 */
?- L = [16,10,12,13,15,5,11,8,14,1,7,6,3,2,4,9], tree_new(T),
(member(X,L), tree_set(T, X, true),
fail; true), tree_display(T, 0).
$BLK 8-true
$BLK 6-true
$RED 3-true
$BLK 1-true
$NIL
$RED 2-true
$NIL
$NIL
$BLK 5-true
$RED 4-true
$NIL
$NIL
$NIL
$BLK 7-true
$NIL
$NIL
$BLK 12-true
$BLK 10-true
$RED 9-true
$NIL
$NIL
$RED 11-true
$NIL
$NIL
$RED 15-true
$BLK 13-true
$NIL
$RED 14-true
$NIL
$NIL
$BLK 16-true
$NIL
$NIL
I think Okasaki is the more common red-black
trees implementation, if I am not mistaken Java’s
method fixAfterInsertion() from the class TreeMap,
does also implement the Okasaki rules. Bug or
Feature that SWI-Prolog doesn’t use Okasaki?
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
Mild Shock on Wed Nov 6 09:37:33 2024
Results of a fuzzer comparison:
library(nb_rbtrees) from 2014 in SWI-Prolog:
/* SWI-Prolog 9.3.14 */
?- L = [16,10,12,13,15,5,11,8,14,1,7,6,3,2,4,9], rb_new(T),
(member(X,L), nb_rb_insert(T, X, true),
fail; true), rb_display(T, 0).
$BLK 12-true
$RED 5-true
$BLK 2-true
$BLK 1-true
$NIL
$NIL
$BLK 3-true
$NIL
$RED 4-true
$NIL
$NIL
$BLK 10-true
$RED 7-true
$BLK 6-true
$NIL
$NIL
$BLK 8-true
$NIL
$RED 9-true
$NIL
$NIL
$BLK 11-true
$NIL
$NIL
$BLK 15-true
$BLK 13-true
$NIL
$RED 14-true
$NIL
$NIL
$BLK 16-true
$NIL
$NIL
On the other hand the rules by Okasaki give a
different resulting tree, which is better balanced,
has less overall depth and doesn’t have a root 12,
rather the root 8. Implementation based on change_arg/3:
/* Dogelog Player 1.2.5 */
?- L = [16,10,12,13,15,5,11,8,14,1,7,6,3,2,4,9], tree_new(T),
(member(X,L), tree_set(T, X, true),
fail; true), tree_display(T, 0).
$BLK 8-true
$BLK 6-true
$RED 3-true
$BLK 1-true
$NIL
$RED 2-true
$NIL
$NIL
$BLK 5-true
$RED 4-true
$NIL
$NIL
$NIL
$BLK 7-true
$NIL
$NIL
$BLK 12-true
$BLK 10-true
$RED 9-true
$NIL
$NIL
$RED 11-true
$NIL
$NIL
$RED 15-true
$BLK 13-true
$NIL
$RED 14-true
$NIL
$NIL
$BLK 16-true
$NIL
$NIL
I think Okasaki is the more common red-black
trees implementation, if I am not mistaken Java’s
method fixAfterInsertion() from the class TreeMap,
does also implement the Okasaki rules. Bug or
Feature that SWI-Prolog doesn’t use Okasaki?
Mild Shock schrieb:
So what is the spec. Well one can use:
Red-Black Trees in a Functional Setting https://www.cs.tufts.edu/~nr/cs257/archive/chris-okasaki/redblack99.pdf
insert :: (Ord a) => a -> Tree a -> Tree a
insert x s = makeBlack $ ins s
where ins E = T R E x E
ins (T color a y b)
| x < y = balance color (ins a) y b
| x == y = T color a y b
| x > y = balance color a y (ins b)
makeBlack (T _ a y b) = T B a y b
The balancing would be as follows, again Haskell code:
balance :: Color -> Tree a -> a -> Tree a -> Tree a
balance B (T R (T R a x b) y c) z d = T R (T B a x b) y (T B c z d)
balance B (T R a x (T R b y c)) z d = T R (T B a x b) y (T B c z d)
balance B a x (T R (T R b y c) z d) = T R (T B a x b) y (T B c z d)
balance B a x (T R b y (T R c z d)) = T R (T B a x b) y (T B c z d)
balance color a x b = T color a x b
Does SWI-Prolog implement somewhere Okasaki red-black trees.
Mild Shock schrieb:
Hi,
Not only are the fucking PIPs behind a
login wall that doesn't work:
Dictionaries in Prolog
https://gitlab.software.imdea.org/prolog-lang/pip-0102
I cannot read gitlab.software.imdea.org,
since it redirects to some internal server
during login.
Also formal verification doesn't have the
same track record as fuzzying. Take the SWI-Prolog
red-black trees. Are they really red-black trees?
I used fuzzy testing to find the test case.
Exhaustive enumeration of permutation seemed to
be out of reach computationally.
So I used these random permutations to find a
discrepancy in resulting tree depth:
fuzzer(R) :-
numlist(1, 16, L),
between(1, 1000, _),
random_permutation(L, R).
Maybe the same technique can use to find smaller
discrepancies, and then use the smaller examples to
pin down difference in implemented balance
rules or implement rebalancing strategy.
Bye
Mild Shock schrieb:
@herme wrote:
Just a quick comment: note that you can make
and discuss the PIP proposals directly on
the PIPs discourse.
Here my response:
I will probably never go there since somebody
tried censoring my comments and said I don’t
work towards the Prolog cause. The good thing
about SWI-Prolog discourse, it has become
quite calm cocerning attempts to censor people,
possibly because some particular people left.
Which is in my opinion the best thing that
could happen to this forum. There is no
guarantee in other forums to really have free speech.
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
Mild Shock on Wed Nov 6 10:09:07 2024
Hi,
My experience with change_arg/3 so far,
one that is akin to nb_linkarg/3 from SWI-Prolog
is as follows:
- The lack of purity in that there is one
more side effect, is compensated in that we
don't need a FFI and dozen foreign function
implemented gadgets, like this gadget,
termed "dedicated low-level implementation".
In SWI-Prolog, this can rely on an efficient specialised
implementation of aggregate_all(count,_,_), while we provide
a dedicated low-level XSB implementation in a count module
that we include with our program, courtesy of David S.
Warren (personal communication).
- Instead of million different gadgets, there
is only one gadget, which is change_arg/3 itself.
One can integrate it with the Prolog garbage collection.
I could demonstrated the same that change_arg/3
can fully participate in minor and major garbage collections
of the Prolog system using a write barrier.
- Having only this gadget, one can implement nb_XXX
datastructures such as findall/3 bag. The big advantage
since it will rely on Prolog garbage collection, is
that no slow setup_call_cleanup/3 is needed. You can
complemently forget about an infrastructure for this
monster, its all superseeded by garbage collection,
you also don't need to call some free()
- You can spin it further and implement more nb_XXX
datastructures profiting from the same advantages
again, this is ongoing work right now. Example
datastrutures are library(util/hash) and the
brand new library(util/tree).
- You can spin it even further to the ultimate goal.
You can then use these nb_XXX datastructures to
have memory savy aggregates. And thats one of the
plateaus we want to reach. We want to compete
with Pandas from Python and participate in Billion
Row Challenges.
Bye
Mild Shock schrieb:
Hi,
Spain is one of the main recipients of EU recovery funds,
with a total of 163 billion euros ($178 billion) earmarked
for the country, approximately half in grants and the rest
in loans. It has already received 37 billion euros.
Madrid and software.imdea.org is no exception. Probably
the same disaster as the Valencia floods. The money
is just siphoned into some crooks pockets. The biggest
crooks are at the moment ALP & friends,
just publishing a series of failure reports. Every
paper just reports some problems, never solutions.
Most recent cringe example:
BoostRLR: The beauty of Prolog for statistical
relational learning https://www.informatik.uni-wuerzburg.de/fileadmin/10030600/2024/KI_2004_paper_174.pdf
What the fuck does this mean:
In SWI-Prolog, this can rely on an efficient specialised
implementation of aggregate_all(count,_,_), while we provide
a dedicated low-level XSB implementation in a count module
that we include with our program, courtesy of David S.
Warren (personal communication).
Why is change_arg/3 not common among Prolog systems.
Why do we deal with aggregates like we are still in
stone age. Aggregates are a well known discipline
of database technology.
Why only aggregate_all/2 and not also a memory savy
solutions of aggregate/3. Aggregates are the bread
and butter of statistics.
Bye
Mild Shock schrieb:> Results of a fuzzer comparison:
library(nb_rbtrees) from 2014 in SWI-Prolog:
/* SWI-Prolog 9.3.14 */
?- L = [16,10,12,13,15,5,11,8,14,1,7,6,3,2,4,9], rb_new(T),
(member(X,L), nb_rb_insert(T, X, true),
fail; true), rb_display(T, 0).
$BLK 12-true
$RED 5-true
$BLK 2-true
$BLK 1-true
$NIL
$NIL
$BLK 3-true
$NIL
$RED 4-true
$NIL
$NIL
$BLK 10-true
$RED 7-true
$BLK 6-true
$NIL
$NIL
$BLK 8-true
$NIL
$RED 9-true
$NIL
$NIL
$BLK 11-true
$NIL
$NIL
$BLK 15-true
$BLK 13-true
$NIL
$RED 14-true
$NIL
$NIL
$BLK 16-true
$NIL
$NIL
On the other hand the rules by Okasaki give a
different resulting tree, which is better balanced,
has less overall depth and doesn’t have a root 12,
rather the root 8. Implementation based on change_arg/3:
/* Dogelog Player 1.2.5 */
?- L = [16,10,12,13,15,5,11,8,14,1,7,6,3,2,4,9], tree_new(T),
(member(X,L), tree_set(T, X, true),
fail; true), tree_display(T, 0).
$BLK 8-true
$BLK 6-true
$RED 3-true
$BLK 1-true
$NIL
$RED 2-true
$NIL
$NIL
$BLK 5-true
$RED 4-true
$NIL
$NIL
$NIL
$BLK 7-true
$NIL
$NIL
$BLK 12-true
$BLK 10-true
$RED 9-true
$NIL
$NIL
$RED 11-true
$NIL
$NIL
$RED 15-true
$BLK 13-true
$NIL
$RED 14-true
$NIL
$NIL
$BLK 16-true
$NIL
$NIL
I think Okasaki is the more common red-black
trees implementation, if I am not mistaken Java’s
method fixAfterInsertion() from the class TreeMap,
does also implement the Okasaki rules. Bug or
Feature that SWI-Prolog doesn’t use Okasaki?
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Julio Di Egidio@21:1/5 to
Mild Shock on Wed Nov 6 10:43:26 2024
On 06/11/2024 09:51, Mild Shock wrote:
What the fuck does this mean:
The Nazi-retarded shithole is all but going to fix itself.
Why is change_arg/3 not common among Prolog systems.
Only poisoned meatballs for the public.
https://github.com/SWI-Prolog/swipl-devel/issues/1328
-Julio
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
Julio Di Egidio on Wed Nov 6 12:57:55 2024
SICStus Prolog is overrated. A lot of things
in Prolog logic programming are overrated, so
that it has lost it to a lot of turf over
the last decade. But of course clinging to
an old code base, and reselling the same old
shit over and over again, is a very lucrative
business compared to real innovation.
Until OpenAI comes and does LLM. I am pretty
sure we will see some blocks stumbling. For
example the paper I was citing was traditional
machine lerning, it was even not deep learning.
Mostlikely Prolog will be hit much more than
it is already hit with Python & Co. taking over
a lot of data science turf.
LoL
Julio Di Egidio schrieb:
On 06/11/2024 09:51, Mild Shock wrote:
What the fuck does this mean:
The Nazi-retarded shithole is all but going to fix itself.
Why is change_arg/3 not common among Prolog systems.
Only poisoned meatballs for the public.
https://github.com/SWI-Prolog/swipl-devel/issues/1328
-Julio
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
Mild Shock on Wed Nov 6 13:03:56 2024
Hi,
Whats also extremly cringe is the
struggel that Scryer Prolog is experiencing.
It has adopted a bloat of post Herbrand
Prolog nonsense, due to Colmerauer, namely
fucking cyclic term unification. Its
crashing under its own bloath of nonsense,
just go to GitHub and count the issues.
Last time I looked it had like 200 issues,
and now after a blink its already at 300 issues.
335 Open - Scryer Prolog - Issues
https://github.com/mthom/scryer-prolog/issues
WTF?
Bye
Mild Shock schrieb:
SICStus Prolog is overrated. A lot of things
in Prolog logic programming are overrated, so
that it has lost it to a lot of turf over
the last decade. But of course clinging to
an old code base, and reselling the same old
shit over and over again, is a very lucrative
business compared to real innovation.
Until OpenAI comes and does LLM. I am pretty
sure we will see some blocks stumbling. For
example the paper I was citing was traditional
machine lerning, it was even not deep learning.
Mostlikely Prolog will be hit much more than
it is already hit with Python & Co. taking over
a lot of data science turf.
LoL
Julio Di Egidio schrieb:
On 06/11/2024 09:51, Mild Shock wrote:
What the fuck does this mean:
The Nazi-retarded shithole is all but going to fix itself.
Why is change_arg/3 not common among Prolog systems.
Only poisoned meatballs for the public.
https://github.com/SWI-Prolog/swipl-devel/issues/1328
-Julio
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)
-
From
Mild Shock@21:1/5 to
Mild Shock on Thu Nov 7 00:59:04 2024
Ok, it seems that SWI-Prolog implements
something else than Okasaki Red-Black Trees.
I tried to find worst cases:
/* Okasaki Red-Black Trees */
?- between(16,32,N), fuzzer(N,D), write(N-D),
write(' '), flush_output, fail; nl.
16-6 17-6 18-6 19-6 20-6 21-6 22-7 23-7 24-7 25-7
26-7 27-7 28-7 29-7 30-7 31-8 32-8
/* SWI-Prolog Red-Black Trees */
?- between(16,32,N), fuzzer(N,D), write(N-D),
write(' '), flush_output, fail; nl.
16-6 17-6 18-6 19-6 20-6 21-6 22-6 23-6 24-6 25-6
26-6 27-7 28-7 29-7 30-7 31-7 32-7
In the above the pairs indicate number of nodes
and worst depth of tree. SWI-Prolog has shorter
trees! For example depth 6 is found up to 26 elements,
whereas Okasaki already gives up after 21 elements.
Mild Shock schrieb:
The new multilingual strings are also an exercise in
Novacore. There were a few issues that needed novel
Prolog solutions, to make a Novacore solution.
One problem was I didn't want to use library(format)
and format/3 to format multilingual strings when
generating error messages. This addresses more
the later multilingual strings processing than the
multilingual strings store itself. So how resolve this
paradox? Here is my take, a mini format/3 boostraped
from the Dogelog Player specific atom_split/3:
% sys_inter_polate(+Stream, +Atom, +List)
sys_inter_polate(Stream, Template, Args) :-
atom_split(Template, '~', [Head|Tail]),
put_atom(Stream, Head),
sys_zipper_output(Args, Tail, Stream).
% sys_zipper_output(+List, +List, +Stream)
sys_zipper_output([Arg|Args], [Head|Tail], Stream) :-
writeq(Stream, Arg),
put_atom(Stream, Head),
sys_zipper_output(Args, Tail, Stream).
sys_zipper_output([], [], _).
It only understands format specifier '~', but is sufficient:
/* German Text */
strings('syntax_error.singleton_var', de, 'Alleinstehende Variable(n) ~, anonyme Variable(n) (_) benutzen.').
/* English and Fallback Text */
strings('syntax_error.singleton_var', '', 'Singleton variable(s) ~, use anonymous variable(s) (_).').
LoL
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)