creep error in Prolog when I find a route - recursion

I'm learning Prolog, and I'm getting creep error when I try to find a route.
I think what I did is recursion because that's the way to find a route when there's not a straight path.
Here is the code:
route(london,paris).
route(paris,rome).
route(rome,spain).
route(london,berlin).
route(berlin,praga).
route(london,dublin).
route(dublin,berlin).
path(X,Y,[X,Y]):- straight(X,Y).
path(X,Z,[X | other]):- straight(X,Y), path(Y,Z,other).
when I try to find, let's say the route from London to Rome
path(london,rome,Store).
I get this error:
Exception: (8) straight(london, rome) ? creep
Exception: (7) path(london, rome, _G4705) ? creep
What am I doing wrong?
Should I define something else?
Thanks in advance!

Your predicate is almost correct. You just need to write the tail of the list as a variable Other instead of an atom other and secondly use your facts route/2 for a straight connection:
path(X,Y,[X,Y]) :-
route(X,Y).
path(X,Z,[X | Other]) :-
route(X,Y),
path(Y,Z,Other).
Now your query works:
?- path(london,rome,S).
S = [london,paris,rome] ? ;
no

Related

update array elements with try catch

I'm trying to update large complexe json files and exit with detailled error message when detecting incoherent data (with jq 1.6).
I started to use functions and try/catch to produce a kind of java stacktrace containing input data from each level => easy, thank you JQ
But when I started to update array elements (using |=), I didn't find the solution
Here is a very simple example :
echo '{"array": [{"foo":"bar"}]}' | jq -c '.array[] |= try . catch (.)'
output : {"array":[{"__jq":0}]}
Do I made a mistake ? Is it a normal behaviour ?
Thanks for your help
The try-catch isn't really an expression, it yields no meaningful value, it merely executes some expression:
try-catch
Errors can be caught by using try EXP catch EXP. The first expression is executed, and if it fails then the second is executed with the error message. The output of the handler, if any, is output as if it had been the output of the expression to try.
emphasis mine.
So it would be wrong to use the value, you should perform the assignment within the try expression.
$ echo '{"array": [{"foo":"bar"}]}' | jq -c 'try (.array[] |= .) catch (.)'
You have stumbled upon a bug in jq 1.6. Using jq 1.5, one obtains the correct output:
{"array":[{"foo":"bar"}]}
However, the expression .array[] |= try . catch (.) is not one would ever use in practice, because if .array is a JSON array or JSON object, it just says: do nothing.
To understand try ... catch ..., it might help to consider this example:
$ jq -n 'try error("abc") catch ("The error message was " + .)'
"The error message was abc"

Why doesnt' probe execute?

Why does Probe not execute? This is not the whole program, but should be sufficient code to find an answer. Yes, I already scoured Stack Overflow for an answer but there is not much help for Prolog. It is part of a minesweeper game.
play :-
play(0).
play(M) :-
N is M + 1,
Suf <- N,
display_board(visible), nl,
format("Your ~d~a move~n", [N,Suf]),
retrieve('Coordinates? ', [A,B]),
format("DEBUG: probing at coordinates [~d,~d]~n", [A, B]),
!, probe(A,B),
play(N).
probe(X, Y) :-
write("enter probe"),
located_at(Who, X, Y, C),
C = 'b',
write('should probe '),
write('at ['),
write(X), write(','), write(Y), write(']'), nl.
:- style_check(+singleton).
Let us step back and first try to find out: Why does the program not even compile?
When consulting the program you posted, I get:
ERROR: file.pl:6:6: Syntax error: Operator expected
This is the line that says:
Suf <- N
That's not valid Prolog syntax.
Therefore, I suggest to fix this first.
In fact, I further get:
Warning: file.pl:14: Singleton variables: [Who]
That's also not a good sign. But the ERROR is more severe, preventing compilation of the whole clause.

Finding ? operator in AST

I'm doing some exercise in Rascal. When I try to determine the Cyclomatic complexity of a Java method getting methods from an AST. I would like to evaluate the ? operator.
As it is not determined by '/if(_, _, )', I tried to determine it using postfix(, _); (infix works fine finding || or &&)
Still no success.
Anybody who can unhide this secret to me?
Thanks in Advance
Use the force; the source for the AST definition is here https://github.com/cwi-swat/rascal/blob/master/src/org/rascalmpl/library/lang/java/m3/AST.rsc, also mentioning the conditional constructor Mark pointed out in his comment.
If you use iprintln on the AST for a small example, like iprintln(ast) or import util::ValueUI; and then text(ast) for an editor with the formatted AST it's easy to find out what ASTs look like.

issues regarding prolog backtracking to find other solution

I am beginner of Prolog.
what I have is a function traverse a list and return true when it satisfies the condition.
for example, check_version checks if the package version met the condition(eg. the version satisfies the condition such as greater than or less than the specific version) and check_all checks takes a list of versions and conditions to check one by one.
package('python', '2.6.5').
package('python', '2.5.4').
package('python', '1.5.2').
package('python', '3.1.0').
check_version(Pac, Ver, Cmp, V):-
package(Pac, V),
cmp_version(V, Ver, Cmp).
check_all( Pac, [], [], V):-
package(Pac, V).
check_all(Pac, [Ver], [Cmp], V):-
check_version(Pac, Ver, Cmp, V).
check_all(Pac, [Ver|VerS], [Cmp|CmpS], V):-
check_version(Pac, Ver, Cmp, V),
check_all(Pac, VerS, CmpS, V).
The problem I have is when try to find other solutions, it gives me duplicate solution.
I get:
check_all('python', ['3.0','2.4'], [lt,ge], V).
V = '2.6.5' ;
V = '2.6.5' ;
V = '2.5.4' ;
V = '2.5.4' .
expected:
check_all('python', ['3.0','2.4'], [lt,ge], V).
V = '2.6.5' ;
V = '2.5.4' .
I used trace to track it, and the problem I found, when it try to find another solution it back tracks and will return fail until find the right solution. Like the example above, apparently, it will return true for V='2.6.5' at first and take that to back track and run the functions, and we expect it returns false and then when it reach the beginning it run package('python', V) and V will take another value.
...
Exit: (7) check_all(python, ['3.0', '2.4'], [lt, ge], '2.6.5') ? creep
V = '2.6.5'
...
Fail: (9) check_version(python, '2.4', ge, '2.6.5') ? creep
Redo: (8) check_all(python, ['2.4'], [ge], '2.6.5') ? creep
Call: (9) check_version(python, '2.4', ge, '2.6.5') ? creep
Call: (10) package(python, '2.6.5') ? creep
Exit: (10) package(python, '2.6.5') ? creep
when back tracking, in check_all, it fails at check_all as we expected, but it returns true when it backtracks check_version and run package(python, '2.6.5') as V=2.6.5 a new value. so it return true again when V=2.6.5. is there any way to solve this problem?
To localize your problem, first reduce the size of your input. A single element suffices:
?- check_all('python', ['3.0'], [lt], V).
Now, which rules apply for a single element?
Both rules apply! So remove the more specialized one.
There is also another way how to localize such a problem. Simply compare the rules to each other and try to figure out a case where they both apply. The last rule applies for VerS = [] when also the first applies.
Applying a predicate to each element of a list is best done by a predicate that has the list as its first argument. Without going into detail, this makes the predicate succeed when the iteration is complete, if the argument is a list and not a variable (i.e. when it is an input argument). You should have two clauses: one to deal with the empty list and one for the general case:
foo([]). % succeed
foo([X|Xs]) :-
/* apply a predicate to X */
foo(Xs). % apply predicate to the rest of the list
An important thing here is that you don't need a third clause that deals with lists with one element only, since a list with one element is actually a list with an element and an empty list as its tail:
?- [a] == [a|[]].
true.
?- [a] = [a|[]].
true.
Another important thing is that there is nothing you should be doing in the base case, empty list (at least for your example).
To the problem now: your inputs are
the package name
two lists holding pairs of arguments to a predicate you have defined elsewhere (cmp_version/3). This is your list of conditions.
Implementation:
Known packages are available as facts: they can be enumerated by backtracking.
Conditions are an input arguments, provided as a list: you need to apply the condition to each element of the list(s).
The predicate:
check_all([], [], _, _).
check_all([V|Vs], [C|Cs], Name, Version) :-
package(Name, V), % enumerate all known packages by backtracking
cmp_version(Version, V, Cmp), % condition
check_all(Vs, Cs, Name, Version). % apply condition to the rest of the list(s)
You should read the documentation of maplist. You can express the query for example as:
?- maplist(check_version(python), ['3.0', '2.4'], [lt, ge], Versions).
where you have defined a predicate check_version/4 that looks something like:
check_version(Name, V, Cmp, Version) :-
package(Name, Version),
cmp_version(Version, V, Cmp).
As a side note, maplist will reorder its arguments to make it behave like the explicit iteration above.
EDIT
Naming issues, after #mat's comments: one very useful naming convention is to use a name that has descriptive one-word names for the arguments, delimited by underscores. For example, package/2 becomes package_version/2 since its first argument is the package and the second one the version.

Marklogic Xquery fn:data(<type>hello world</type>) giving Invalid lexical value error

My Marklogic XQuery fn:data(<type>hello world</type>) gives me Invalid lexical value error
This is the stack trace:
query evaluated in Documents at file::Docs/ as 1.0-ml (cq v4.1-1-EA)
[1.0-ml] XDMP-LEXVAL: xs:integer("hello world") -- Invalid lexical value "hello world"
Stack trace:
line 2:
1:
2: fn:data(<type>hello world</type>)
xdmp:eval("
fn:data(<type>hello world</type>)", (), <options xmlns="xdmp:eval"><isolation>different-transaction</isolation></options>)
in /cq/eval.xqy line 111:
And when I use fn:data(<p>hello world</p>) it is giving me expected answer (hello world).
Any help on this error would be appreciated.
Thanks.
Finally figured what was wrong.
Had an xsd which was defining element type as xs:integer thats why this error was coming. Removed that xsd and now everything is working fine :)
Glad you figured it out. It looks like the extra schema was targeting the empty namespace?
Here's a tip: avoid using a schema unless it also specifies a namespace. That makes it much easier to keep your schemas organized.

Resources