8 ms·
Yeah, my "gives one answer" was an incredibly misleading phrasing - I meant the encoding should be greedy and so [7,7,7,8,8,9] should have just the one answer o
by ghusbands 3y ago
Yeah, my "gives one answer" was an incredibly misleading phrasing - I meant the encoding should be greedy and so [7,7,7,8,8,9] should have just the one answer of [[7,3], [8,2], [9,1]] and not also become [[7,2], [7,1], [8,2], [9,1]] or any other variant.
I feel like Prolog is sold by many as being able to solve predicates in both/many directions, with all the grandfather/ancestor/append examples, and my apparent frustration is in trying to use it that way in general and finding that doesn't work and that trying to produce working predicates that do work that way is seemingly impossible (without clpfd or cuts).
My most recent foray into Prolog was in starting with solving the Countdown numbers game (without clpfd or cuts) and then trying to use the predicates from that to answer further questions like what sets of tiles can reach all target numbers or what the highest necessary intermediate result is, or similar. I didn't just fail; I failed to learn anything useful. Getting those answers in a few imperative languages was trivial and educational.
Since then, I've reduced the goal to writing an any-mode rle that can return just correct answers and not infloop, without cuts or meta-programming. Simpler things seem easy enough. Rle seems just complex enough to make it impossible but is still logically trivial.
Your rle definition looks good to me, of course, but I'm not sure I can work out how to usefully compare it to other (+,-) answers. Certainly, I've only been checking for correctness in all modes, including a lack of infloops and a lack of extra answers.
I'd be happy to engage in offline conversation about it, but I'd likely just be yelling at clouds. I am interested in discovering which logic languages can trivially provide an any-mode rle and in working up from there to larger problems. Clearly, from this thread, prolog+clpfd is one.
- YeGoblynQueenne 3y ago>> I feel like Prolog is sold by many as being able to solve predicates in both/many directions, with all the grandfather/ancestor/append examples, and my apparent frustration is in trying to use it that way in general and finding that doesn't work and that trying to produce working predicates that do work that way is seemingly impossible (without clpfd or cuts). You're not wrong about that and it's not your fault, or any misunderstanding. Certainly Prolog has been "sold" this way, by some. I can't name those "some" because I'm not sure who they are exactly (although I have a few specific people in mind). I don't think it's something that's made a big issue of in the usually recommended textbooks (Clocksin and Mellish, Sterling and Shapiro, O'Keefe, Bratko) but I can't be sure. Obviously, you can run some programs in multiple modes, in Prolog. You can't always write every program to be all-modes. Pretending that it's possible to do so is overselling the language. What's more it's trying to sell a nice feature, as a defining feature. The idea I think is that First-Order Logic predicates are relations and so should not have "inputs" and "outputs". But Prolog predicates are not FOL predicates. If they were, they'd be simultaneously capable of being run in all modes, and less expressive than they are now (because Prolog is higher-order, as I say in other comments, trying not to sound like a dangerous loon). I think this is the age-old debate about purity and formal rigour in Prolog, that has never done the language any good. There has always been a part of the Prolog community who wanted Prolog to be some kind of pure and perfect jewel, that should remain untouched from the real world. There's always been another part, who wanted to treat Prolog as a programming language to do real work with. I get the feeling that the latter, more practically-minded, folks have slowly weeded themselves out and now the majority of those who remain are of the "purist" camp. Entirely coincidentally, the number of people picking up Prolog has also constantly dwindled. Entirely coincidentally. You can probably tell which camp I'm on. Actually, I'm not. I got a foot in each. I serve two masters and all that. I just want to know that things work, that's my schtick. Sometimes you need formal rigor, sometimes you just need to bodge some codes together. And use the cut :P >> I'd be happy to engage in offline conversation about it, but I'd likely just be yelling at clouds. I am interested in discovering which logic languages can trivially provide an any-mode rle and in working up from there to larger problems. Clearly, from this thread, prolog+clpfd is one. You're welcome to get in touch: eIA!patsantzis17CTHULHUimperialIA!acIA!uk But first open vim and praise Cthulhu: s/IA!/./g s/CTHULHU/@/g
- superdisk 3y agoIf you're not trying to make your programs as close to logic as possible (that is, support as many modes as possible and make it so you can model your program as a logical expression) then what's even the point of using Prolog? Settling for having to reimplement the same logic in multiple directions completely defeats the purpose, you're just writing imperative code at that point. I think "pragmatic therefore non-logical" versus "ivory tower therefore useless" is a false dichotomy. In my experience it's nearly impossible to make green cuts, and once you know a few tricks and rules of thumb, you can get pretty far writing logical code.
- falsissime 3y agoSupport of as many modes as possible is an aim that is often too ambitious. Instead, unsupported modes should be indicated with an instantiation error or (much rarer) an uninstantiation_error. In this manner the logic remains intact as long as no error occurs and the program does not loop. And yes, this may come at the expense of its usefulness, think of (is)/2. YeGoblynQueenne omitted what the mode +,- actually means. And the program does not check it. Does it mean that the first argument must be ground or is it OK, to leave some variables inside? Think of `[a,f(X),b]`. Also the - has sometimes the meaning of being descriptive (that is a completely steadfast argument) or prescriptive (meaning that the program may be incorrect if the argument is not an unaliased variable). Would errors be used for the unintended cases things would be much clearer.
- YeGoblynQueenne 3y agoGood points and I have to hang my head in shame. Prolog doesn't enforce mode declarations in documentation and I don't either, most of the time, in my code. I also use modes imprecisely and never define them, before I use them, in my documentation, which if anyone ever looks at my code and tries to run it, would create confusion. For instance, I use "-" to indicate both a term that's an unbound variable on entry and one that can be partially instantiated on entry. Obviously that will cover different behaviour in different programs. That's not very nice of me. At least, since I've been bitten many times myself by this I try to document the structure of arguments and to give an example or two of calling in different modes, when that is not too hard to do. I've been complimented many times about the good documentation of my projects, but I feel so embarrassed when people do that. My documentation sucks. It's worse to have half-done documentation than to have no documentation at all :(
- superdisk 3y agoHere's an implementation using Peano numbers as you mentioned which seems to work the same as the CLP(FD) one for me. rle2([], []). rle2([H],[[H, add1(zero)]]). rle2([H | T], [[H, CountPlus1] | More]) :- Count = add1(_), CountPlus1 = add1(Count), rle2(T, [[H, Count] | More]). rle2([H | T], [[H, add1(zero)], [Element, Count] | More]) :- Count = add1(_), dif(Element, H), rle2(T, [[Element, Count] | More]). ?- rle2([1,1,1,2,2,3],X), rle2(Y,X). X = [[1, add1(add1(add1(zero)))], [2, add1(add1(zero))], [3, add1(zero)]], Y = [1, 1, 1, 2, 2, 3] ; false. It even works in the completely general case: ?- rle2(X,Y). X = Y, Y = [] ; X = [_A], Y = [[_A, add1(zero)]] ; X = [_A, _A], Y = [[_A, add1(add1(zero))]] . As I understand it, Prolog itself is CLP(H), that is CLP over the Herbrand terms (that is, atoms and functors and stuff). CLP(FD) just extends the capability with numbers (FD = finite domains). Although I do sort of understand how you'd consider it not "pure" Prolog, I don't see it as that different especially with things like `dif/2` in Prolog which is a constraint just like any other.
- YeGoblynQueenne 3y agoNice! >> As I understand it, Prolog itself is CLP(H), that is CLP over the Herbrand terms (that is, atoms and functors and stuff). That's an interesting way to see it. Quite an unorthodox one, mind. I learned recently that it was Alain Colmerauer, co-creator of Prolog, who also came up with the idea of Constraint Logic Programming, specifically to address Prolog's er difficulties with numbers and arithmetic. See: https://youtu.be/74Ig_QKndvE?t=1046 https://youtu.be/74Ig_QKndvE?t=1046 I was recently asked a question about the use of Peano notation in some stuff I was working on. I didn't think of it that way at the time, but one big advantage of Peano notation compared to is/2 is that it is... well, in a nutshell it's declarative integer arithmetic, just like CLP(FD). Boy I hate saying jargon-y things like that. But Peano numbers as Prolog terms in predicate's heads can be backtracked-over, and unwound when recursion unwinds, just like you do in your rle2/2 above. The downside is that they get hard to read once they get too big. Then again, you can easily do this sort of thing: %! peano(?Arabic,?Peano) is nondet. % % Convert between Arabic and Peano number notations. % % Use this program to quickly convert between Peano notation and % Arabic notation. % % Accepted modes are (+,-) and (-,+). In mode (?,?) this predicate % returns only 0 deterministically. % % Examples: % == % ?- peano(1,P). % P = s(0). % % ?- peano(I,s(0)). % I = 1. % % ?- peano(N,P). % N = P, P = 0. % == % peano(N,P):- peano(P,0,N). peano(0,N,N):- !. peano(s(P),N,Acc):- succ(N,N_) ,peano(P,N_,Acc). Expects Peano numbers with the functor "s"! Runs both ways :P