• Can we do this with ancestral cuts or something?

    From Julio Di Egidio@julio@diegidio.name to comp.lang.prolog on Mon Dec 9 14:35:20 2024
    From Newsgroup: comp.lang.prolog

    Given a list of goals representing a conjunction, I would like it to
    fail as soon as any goal fails, but I would like *not* to cut on the
    search space otherwise.

    Here is my actual test case, only considering ground goals (otherwise
    too many ways to play with it that seem immaterial to the problem):

    ```
    red(1).
    red(1).

    and([]) :- !. % with Xs ground!
    and([H:B|Xs]) :-
    red(B), writeln(H:B),
    and(Xs).

    /*

    Actual:
    -------

    ?- and([x:1,y:1]), fail. % ok: full search space
    x:1
    y:1
    y:1
    x:1
    y:1
    y:1
    false.

    ?- and([x:1,y:0]), fail. % KO: could fail earlier
    x:1
    x:1
    false.

    Expected:
    ---------

    ?- and([x:1,y:0]), fail. % ok: fails early!
    x:1
    false.

    */
    ```

    Am I just missing something obvious? I am trying with "ancestral cuts" (SWI-Prolog has these), but I have not yet found a solution.

    -Julio
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Mon Dec 9 15:14:50 2024
    From Newsgroup: comp.lang.prolog

    First create a conjunction:

    A1,...,An

    Wrap each goal Aj into a soft cut:

    (Aj *-> true; !).

    The cut will abort all previous goals.

    Julio Di Egidio schrieb:
    Given a list of goals representing a conjunction, I would like it to
    fail as soon as any goal fails, but I would like *not* to cut on the
    search space otherwise.

    Here is my actual test case, only considering ground goals (otherwise
    too many ways to play with it that seem immaterial to the problem):

    ```
    red(1).
    red(1).

    and([]) :- !.  % with Xs ground!
    and([H:B|Xs]) :-
        red(B), writeln(H:B),
        and(Xs).

    /*

    Actual:
    -------

    ?- and([x:1,y:1]), fail.  % ok: full search space
    x:1
    y:1
    y:1
    x:1
    y:1
    y:1
    false.

    ?- and([x:1,y:0]), fail.  % KO: could fail earlier
    x:1
    x:1
    false.

    Expected:
    ---------

    ?- and([x:1,y:0]), fail.  % ok: fails early!
    x:1
    false.

    */
    ```

    Am I just missing something obvious?  I am trying with "ancestral cuts" (SWI-Prolog has these), but I have not yet found a solution.

    -Julio

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Mon Dec 9 15:22:33 2024
    From Newsgroup: comp.lang.prolog

    Or use Dogelog Player:

    /* Dogelog Player */

    '$MARK'(CP) : Get a choicen point.

    '$CUT'(CP) : Cut to a choice point.

    But I don't have soft cut. But you can do
    ancestral cut with it. SWI-Prolog has something
    similar burried somewhere, they are called:

    /* SWI-Prolog */

    prolog_current_choice(CP) : Get a choicen point

    prolog_cut_to(CP) : Cut to a choice point

    See also, the pair is used here:

    '$meta_call'(:Goal) https://github.com/SWI-Prolog/swipl-devel/blob/master/boot/init.pl

    Mild Shock schrieb:
    First create a conjunction:

       A1,...,An

    Wrap each goal Aj into a soft cut:

      (Aj *-> true; !).

    The cut will abort all previous goals.

    Julio Di Egidio schrieb:
    Given a list of goals representing a conjunction, I would like it to
    fail as soon as any goal fails, but I would like *not* to cut on the
    search space otherwise.

    Here is my actual test case, only considering ground goals (otherwise
    too many ways to play with it that seem immaterial to the problem):

    ```
    red(1).
    red(1).

    and([]) :- !.  % with Xs ground!
    and([H:B|Xs]) :-
         red(B), writeln(H:B),
         and(Xs).

    /*

    Actual:
    -------

    ?- and([x:1,y:1]), fail.  % ok: full search space
    x:1
    y:1
    y:1
    x:1
    y:1
    y:1
    false.

    ?- and([x:1,y:0]), fail.  % KO: could fail earlier
    x:1
    x:1
    false.

    Expected:
    ---------

    ?- and([x:1,y:0]), fail.  % ok: fails early!
    x:1
    false.

    */
    ```

    Am I just missing something obvious?  I am trying with "ancestral
    cuts" (SWI-Prolog has these), but I have not yet found a solution.

    -Julio


    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Julio Di Egidio@julio@diegidio.name to comp.lang.prolog on Mon Dec 9 15:38:05 2024
    From Newsgroup: comp.lang.prolog

    On 09/12/2024 15:22, Mild Shock wrote:
    Or use Dogelog Player:

    /* Dogelog Player */
    '$MARK'(CP) : Get a choicen point.
    '$CUT'(CP) : Cut to a choice point.

    But I don't have soft cut. But you can do
    ancestral cut with it. SWI-Prolog has something
    similar burried somewhere, they are called:

    <https://www.swi-prolog.org/pldoc/man?section=ancestral-cut>

    Not per chance I have mentioned SWI-Prolog in the OP. I have also
    mentioned that I cannot seem to do it with ancestral cuts (only).

    But thanks for mentioning soft-cuts, I had completely forgotten about
    those...

    -Julio

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Julio Di Egidio@julio@diegidio.name to comp.lang.prolog on Mon Dec 9 16:47:50 2024
    From Newsgroup: comp.lang.prolog

    On 09/12/2024 15:14, Mild Shock wrote:
    Julio Di Egidio schrieb:

    Given a list of goals representing a conjunction, I would like it to
    fail as soon as any goal fails, but I would like *not* to cut on the
    search space otherwise.

    Here is my actual test case, only considering ground goals (otherwise
    too many ways to play with it that seem immaterial to the problem):

    First create a conjunction:
       A1,...,An
    Wrap each goal Aj into a soft cut:
      (Aj *-> true; !).
    The cut will abort all previous goals.

    Indeed soft-cuts do it, thank you very much!

    Though with this scheme: `(Aj *-> true; !, fail)`.

    I have also managed to abstract the recursive scheme away to a
    meta-predicate, by combining soft with ancestral cuts. But I am not
    sure how good it is, especially since term rewriting also can do the
    trick and quite more simply so...

    ```
    red(1).
    red(1).

    and(Xs) :- % with Xs ground!
    scut(and__do(Xs)).

    and__do([], _) :- !.
    and__do([H:B|Xs], ChF) :-
    red(B), writeln(H:B),
    scut(and__do(Xs), ChF).

    :- meta_predicate
    scut(1),
    scut(1, +).

    scut(G) :-
    prolog_current_choice(ChF),
    call(G, ChF).

    scut(G, ChF) :-
    ( call(G, ChF)
    true
    ; prolog_cut_to(ChF),
    fail
    ).

    /*

    ?- and([x:1,y:1]), fail. % ok: full search space
    x:1
    y:1
    y:1
    x:1
    y:1
    y:1
    false.

    ?- and([x:1,y:0,z:1]), fail. % ok: fails early
    x:1
    false.

    */
    ```

    -Julio

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Julio Di Egidio@julio@diegidio.name to comp.lang.prolog on Mon Dec 9 17:15:25 2024
    From Newsgroup: comp.lang.prolog

    On 09/12/2024 16:47, Julio Di Egidio wrote:
    On 09/12/2024 15:14, Mild Shock wrote:
    Julio Di Egidio schrieb:

    Given a list of goals representing a conjunction, I would like it to
    fail as soon as any goal fails, but I would like *not* to cut on the
    search space otherwise.

    Here is my actual test case, only considering ground goals (otherwise
    too many ways to play with it that seem immaterial to the problem):

    First create a conjunction:
        A1,...,An
    Wrap each goal Aj into a soft cut:
       (Aj *-> true; !).
    The cut will abort all previous goals.

    Indeed soft-cuts do it, thank you very much!

    Though with this scheme: `(Aj *-> true; !, fail)`.

    I have also managed to abstract the recursive scheme away to a meta-predicate, by combining soft with ancestral cuts.  But I am not
    sure how good it is, especially since term rewriting also can do the
    trick and quite more simply so...

    Actually, this one works (no need for a soft cut in `scut`), and it at
    least starts making sense:

    ```
    :- meta_predicate
    scut(1),
    scut(1, +).

    scut(G) :-
    prolog_current_choice(ChF),
    call(G, ChF).

    scut(G, ChF) :-
    ( call(G, ChF), !
    ; prolog_cut_to(ChF),
    fail
    ).
    ```

    -Julio

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Julio Di Egidio@julio@diegidio.name to comp.lang.prolog on Mon Dec 9 17:19:28 2024
    From Newsgroup: comp.lang.prolog

    On 09/12/2024 17:15, Julio Di Egidio wrote:
    On 09/12/2024 16:47, Julio Di Egidio wrote:
    On 09/12/2024 15:14, Mild Shock wrote:
    Julio Di Egidio schrieb:

    Given a list of goals representing a conjunction, I would like it to
    fail as soon as any goal fails, but I would like *not* to cut on the
    search space otherwise.

    Here is my actual test case, only considering ground goals
    (otherwise too many ways to play with it that seem immaterial to the
    problem):

    First create a conjunction:
        A1,...,An
    Wrap each goal Aj into a soft cut:
       (Aj *-> true; !).
    The cut will abort all previous goals.

    Indeed soft-cuts do it, thank you very much!

    Though with this scheme: `(Aj *-> true; !, fail)`.

    I have also managed to abstract the recursive scheme away to a
    meta-predicate, by combining soft with ancestral cuts.  But I am not
    sure how good it is, especially since term rewriting also can do the
    trick and quite more simply so...

    Actually, this one works (no need for a soft cut in `scut`), and it at
    least starts making sense:

    ```
    scut(G, ChF) :-
        (    call(G, ChF), !
        ;    prolog_cut_to(ChF),
            fail
        ).
    ```

    No no, forget that: that is cutting on the search space. The previous solution is it.

    -Julio

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Julio Di Egidio@julio@diegidio.name to comp.lang.prolog on Mon Dec 9 18:26:48 2024
    From Newsgroup: comp.lang.prolog

    On 09/12/2024 16:47, Julio Di Egidio wrote:

    term rewriting also can do the
    trick and quite more simply so...

    I take that back, too. I cannot find a way out of ancestral cuts in the recursive case. Some term rewriting could rather be useful *in
    conjunction* with that `scut`, since that as written messes up with the
    stack trace... Anyway, that's another story.

    -Julio

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Mon Dec 9 20:58:50 2024
    From Newsgroup: comp.lang.prolog

    A Timeless Confluence

    By the banks of thought where rivers entwine,
    Emmy Noether walked through a realm divine.
    Her algebra wove the fabric of laws,
    While echoes of logic gave her pause.

    There stood Michael Kohlhase, a seeker of form,
    Shaping machines through a digital storm.
    “Madame,” he began, with respect in his tone,
    “Your ideals still guide what we’ve come to own.

    Noetherian rings, your towering art,
    Anchor the systems of which I’m a part.
    In rewriting paths, your truth remains,
    Simplifying chaos, dissolving chains.”

    Emmy smiled, her brilliance aglow,
    "Through eras, the seeds of knowledge grow.
    Yet tell me, dear traveler, in your machine’s frame,
    Do ideals endure, or fade like a flame?”

    Michael replied, “Your vision holds,
    In logic’s rewrite, it gently unfolds.
    Past meets the present where structures align,
    A confluence of thought, eternal, divine.”

    And so they stood, two eras combined,
    Bound by the currents of the infinite mind.

    https://en.m.wikipedia.org/wiki/Emmy_Noether

    https://en.m.wikipedia.org/wiki/Michael_Kohlhase

    Julio Di Egidio schrieb:
    On 09/12/2024 16:47, Julio Di Egidio wrote:

    term rewriting also can do the trick and quite more simply so...

    I take that back, too.  I cannot find a way out of ancestral cuts in the recursive case.  Some term rewriting could rather be useful *in conjunction* with that `scut`, since that as written messes up with the stack trace...  Anyway, that's another story.

    -Julio


    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Mon Dec 9 21:00:17 2024
    From Newsgroup: comp.lang.prolog


    Ok Confluence does indeed ring a bell. Lets show
    Declarative (What) versus Procedural (How) in
    @emiruz example, as a rewriting problem.

    Lets permit that we write the input as [1,2,a,4,5,
    b,c,8,9,10] and then have rewriting rules [a->3,b->6,
    7,d->8] applied, by this little Declarative (What) code:

    step(L,R) :- nth1(K,L,a,H), nth1(K,R,3,H).
    step(L,R) :- nth1(K,L,b,H), nth1(K,R,6,H).
    step(L,R) :- nth1(K,L,c,H), nth1(K,R,7,H).
    step(L,R) :- nth1(K,L,d,H), nth1(K,R,8,H).

    find(L,L) :- \+ step(L,_).
    find(L,R) :- step(L,H), find(H,R).

    Each derivation is a Procedural (How) execution:

    ?- find([1,2,a,4,5,b,c,8,9,10],X).
    X = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    X = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    X = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    Etc..

    Can we count the number of Hows to solve the What?

    ?- aggregate_all(count, find([1,2,a,4,5,b,c,8,9,10],X), C).
    C = 6.

    So there are 6 different Procedures that tell
    us which steps to exactly use when, to solve the
    Declaratively given problem which leaves open

    when to use each step.

    Mild Shock schrieb:
    A Timeless Confluence

    By the banks of thought where rivers entwine,
    Emmy Noether walked through a realm divine.
    Her algebra wove the fabric of laws,
    While echoes of logic gave her pause.

    There stood Michael Kohlhase, a seeker of form,
    Shaping machines through a digital storm.
    “Madame,” he began, with respect in his tone,
    “Your ideals still guide what we’ve come to own.

    Noetherian rings, your towering art,
    Anchor the systems of which I’m a part.
    In rewriting paths, your truth remains,
    Simplifying chaos, dissolving chains.”

    Emmy smiled, her brilliance aglow,
    "Through eras, the seeds of knowledge grow.
    Yet tell me, dear traveler, in your machine’s frame,
    Do ideals endure, or fade like a flame?”

    Michael replied, “Your vision holds,
    In logic’s rewrite, it gently unfolds.
    Past meets the present where structures align,
    A confluence of thought, eternal, divine.”

    And so they stood, two eras combined,
    Bound by the currents of the infinite mind.

    https://en.m.wikipedia.org/wiki/Emmy_Noether

    https://en.m.wikipedia.org/wiki/Michael_Kohlhase

    Julio Di Egidio schrieb:
    On 09/12/2024 16:47, Julio Di Egidio wrote:

    term rewriting also can do the trick and quite more simply so...

    I take that back, too.  I cannot find a way out of ancestral cuts in
    the recursive case.  Some term rewriting could rather be useful *in
    conjunction* with that `scut`, since that as written messes up with
    the stack trace...  Anyway, that's another story.

    -Julio



    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Mon Dec 9 21:09:56 2024
    From Newsgroup: comp.lang.prolog


    For confluence see here:

    https://en.wikipedia.org/wiki/Confluence_(abstract_rewriting)

    Mild Shock schrieb:

    Ok Confluence does indeed ring a bell. Lets show
    Declarative (What) versus Procedural (How) in
    @emiruz example, as a rewriting problem.

    Lets permit that we write the input as [1,2,a,4,5,
    b,c,8,9,10] and then have rewriting rules [a->3,b->6,
    7,d->8] applied, by this little Declarative (What) code:

    step(L,R) :- nth1(K,L,a,H), nth1(K,R,3,H).
    step(L,R) :- nth1(K,L,b,H), nth1(K,R,6,H).
    step(L,R) :- nth1(K,L,c,H), nth1(K,R,7,H).
    step(L,R) :- nth1(K,L,d,H), nth1(K,R,8,H).

    find(L,L) :- \+ step(L,_).
    find(L,R) :- step(L,H), find(H,R).

    Each derivation is a Procedural (How) execution:

    ?- find([1,2,a,4,5,b,c,8,9,10],X).
    X = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    X = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
    X = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    Etc..

    Can we count the number of Hows to solve the What?

    ?- aggregate_all(count, find([1,2,a,4,5,b,c,8,9,10],X), C).
    C = 6.

    So there are 6 different Procedures that tell
    us which steps to exactly use when, to solve the
    Declaratively given problem which leaves open

    when to use each step.

    Mild Shock schrieb:
    A Timeless Confluence

    By the banks of thought where rivers entwine,
    Emmy Noether walked through a realm divine.
    Her algebra wove the fabric of laws,
    While echoes of logic gave her pause.

    There stood Michael Kohlhase, a seeker of form,
    Shaping machines through a digital storm.
    “Madame,” he began, with respect in his tone,
    “Your ideals still guide what we’ve come to own.

    Noetherian rings, your towering art,
    Anchor the systems of which I’m a part.
    In rewriting paths, your truth remains,
    Simplifying chaos, dissolving chains.”

    Emmy smiled, her brilliance aglow,
    "Through eras, the seeds of knowledge grow.
    Yet tell me, dear traveler, in your machine’s frame,
    Do ideals endure, or fade like a flame?”

    Michael replied, “Your vision holds,
    In logic’s rewrite, it gently unfolds.
    Past meets the present where structures align,
    A confluence of thought, eternal, divine.”

    And so they stood, two eras combined,
    Bound by the currents of the infinite mind.

    https://en.m.wikipedia.org/wiki/Emmy_Noether

    https://en.m.wikipedia.org/wiki/Michael_Kohlhase

    Julio Di Egidio schrieb:
    On 09/12/2024 16:47, Julio Di Egidio wrote:

    term rewriting also can do the trick and quite more simply so...

    I take that back, too.  I cannot find a way out of ancestral cuts in
    the recursive case.  Some term rewriting could rather be useful *in
    conjunction* with that `scut`, since that as written messes up with
    the stack trace...  Anyway, that's another story.

    -Julio




    --- Synchronet 3.20a-Linux NewsLink 1.114