How to remove unsafety in a conditional Clingo rule? - conditional-statements

I would like to define the set of nodes in a directed graph reachable from all nodes in a given set of start nodes in Clingo. To my understanding, this can be done via conditions in a rule body: in a rule
p(X) :- q(X) : r(X).
a conjunction of rules q(a) is dynamically generated in the body of p/1 for grounded facts a, for which the rule r(a) also holds. Now for some reason, the following set of rules results in an "unsafe" variable X being discovered on the last line:
% Test case
arc(1,4). arc(2,4). arc(3,5). arc(4,1). arc(4,2). arc(4,3).
start(1). start(4). start(5).
% Define a path inductively, with the base case being path of length 1:
path(A, B) :- arc(A, B).
path(A, B) :- arc(A, X), arc(X, B).
path(A, B) :- arc(A, X), path(X, Y), arc(Y, B).
% A node X is simply reachable/1, if there is a possibly empty path to it
% from a start node or reachable/2 from A, if there is a path to it from A:
reachable(X) :- start(X).
reachable(X) :- start(A), path(A, X).
reachable(X, A) :- path(A, X).
% Predicate all_reach defined by the reachable relation:
all_reach(X) :- reachable(X, A) : start(A).
I wanted to ask, what is meant by an "unsafe" variable, and how might I amend this situation? One source claims that an unsafe variable is a variable, which appears in the head of a rule but not in the body, which makes sense as the symbols :- denote a reverse implication. However, this does not seem to be the case here, so I'm confused.
Could it be that there might not be a grounded fact a for which start(a) holds, and hence the body of the implication or rule becomes empty, causing the unsafety. Is that it? Is there a standard way of avoiding this?

The issue was that there wasn't a positive rule in the body of all_reach/1 that was satisfied for at least some grounded instance of X. Adding the lines
% Project nodes from arcs
node(X) :- arc(X,Y).
node(Y) :- arc(X,Y).
and reformulating the all_reach/1 rule as
all_reach(X) :- reachable(X, A) : start(A); node(X).
solved the issue. The desired conjunction
∧[i=1 → ∞] reachable(d, s[i])
for all start nodes s[i] and destination nodes d is then generated as the
body of allreach/1.
In other words, when using conditionals in the body b/m of a rule r/n,
there must still be a predicate p in b that is unconditionally grounded
for any variables present in the head of the rule. Otherwise we might end up
with an ambiguity or an ever-expanding rule during grounding, which is unsafe.

Related

Prolog: consider clauses from a dynamic module when calling a predicate

In the SWI Prolog manual, I found the following remark:
For example, assume an application that can reason about multiple worlds. It is attractive to store the data of a particular world in a module, so we extract information from a world simply by invoking goals in this world.
This is actually a very good description of what I'm trying to achieve. However I ran into a problem. While I do want to model many different worlds, there are also things that I want to share across all of them. So my idea is to have an allworlds module for things that are true in every world, and one module for every world that I want to reason about, and the latter imports from the former. So I'd do something like this in the REPL:
allworlds:asserta(grandparent(X, Z) :- (parent(X, Y), parent(Y, Z))).
allworlds:dynamic(parent/2).
add_import_module(greece, allworlds, start).
greece:asserta(parent(kronos, zeus)).
greece:asserta(parent(zeus, ares)).
Now I'd like to query greece:grandparent(kronos, X) and get X = ares, but all I get is false. When allworlds:grandparent calls parent, it doesn't call greece:parent like I want it to, but allworlds:parent. My research seems to indicate that I need to make the grandparent predicate module-transparent. But calling allworlds:module_transparent(grandparent/2). didn't fix the issue, and it's also deprecated. This is where I'm stuck. How can I get this working? Is meta_predicate/1 part of the solution? Unfortunately I can't make heads or tails of its documentation.
Prolog modules don't provide a good solution for the "many worlds" design pattern. Notably, making the predicates meta-predicates (or module transparent or multifile) would be a problematic hack. But this pattern is trivial with Logtalk, which is a language extends Prolog and can use most Prolog systems as a backend compiler. A minimal (but not unique) solution for your problem is:
:- object(allworlds).
:- public(grandparent/2).
grandparent(X, Z) :-
::parent(X, Y),
::parent(Y, Z).
:- public(parent/2).
:- end_object.
:- object(greece,
extends(allworlds)).
parent(kronos, zeus).
parent(zeus, ares).
:- end_object.
Here, we use inheritance (the individual worlds inherit the common knowledge) and messages to self (the ::/1 control construct) when common predicates need to access world specific predicate definitions (self is the object/world that received the message - grandparent/2 in the example).
Assuming the code is saved in a worlds.lgt file and that you're using SWI-Prolog as the backend:
$ swilgt
...
?- {worlds}.
% [ /Users/pmoura/worlds.lgt loaded ]
% (0 warnings)
true.
?- greece::grandparent(kronos, X).
X = ares.
P.S. If running on windows, use the "Logtalk - SWI-Prolog" shortcut from the Start Menu after installing Logtalk.
I ultimately solved this by passing the module around explicitly and invoking predicates in it with the : operator. It reminds me a bit of doing OOP in C, where you do things like obj->vtable->method(obj, params) (note how obj is mentioned twice, just like the M in my code below).
Similar to the Logtalk solution, I need to explicitly call into the imported module when I want to consider its clauses. As an example, I've added the fact that a father is also a parent to the allworlds module.
allworlds:assertz(grandparent(M, X, Z) :- (M:parent(M, X, Y), M:parent(M, Y, Z))).
allworlds:assertz(parent(M, X, Y) :- M:father(M, X, Y)).
add_import_module(greece, allworlds, start).
greece:assertz(parent(_, kronos, zeus)).
% need to call into allworlds explicitly
greece:assertz(parent(M, X, Y) :- allworlds:parent(M, X, Y)).
greece:assertz(father(_, zeus, ares)).
After making these assertions, I can call greece:grandparent(greece, kronos, X). and get the expected result X = ares.

Well typed and ill typed lambda terms

I have been trying to understand the applied lambda calculus. Up till now, I have understood how type inference works. But I am not able to follow what is the meaning of saying that a term is well-typed or ill-typed and then how can I determine whether a given term is well-typed or ill-typed.
For example, consider a lambda term tw defined as λx[(x x)] . How to conclude whether it is a well-typed or ill-typed term?
If we are talking about Simply Typed Lambda Calculus with some additional constants and basic types (i.e. applied lambda calculus), then the term λx:σ. (x x) is well-formed, but ill-typed.
'Well-formed' means syntactically correct, i.e. will be accepted by a parser for STLC. 'Ill-typed' means the type-checker would not pass it further.
Type-checker works according to the typing rules, which are usually expressed as a number of typing judgements (one typing scheme for each syntactic form).
Let me show that the term you provided is indeed ill-typed.
According to the rule (3) [see the typing rules link], λx:σ. (x x) must have type of general form σ -> τ (since it is a function, or more correctly abstraction). But that means the body (x x) must have some type τ (assuming x : σ). This is basically the same rule (3) expressed in a natural language. So, now we need to figure out the type of the function's body, which is an application.
Now, the rule for application (4) says that if we have an expression like this (e1 e2), then e1 must be some function e1 : α -> β and e2 : α must be an argument of the right type. Let's apply this rule to our expression for the body (x x). (1) x : α -> β and (2) x : α. Since an term in STLC can have only one type, we've got an equation: α -> β = α.
But there is no way we can unify both types together, since α is a subpart of α -> β. That's why this won't typecheck.
By the way, one of the major points of STLC was to forbid self-application (like (x x)), because it prevents from using (untyped) lambda calculus as a logic, since one can perform non-terminating calculations using self-application (see for instance Y-combinator).

Prolog- singleton variable in branch warning

Hello here is my code in Prolog:
arc(a,h).
arc(b,c).
related_to(X, Ys) :-
setof(Y, arc(X, Y), Ys).
cut([H|T],Y) :-
check(H,Y),
T = [] -> cut(T,Y).
check(X,Y) :-
related_to(X,Xs),
member(Y,Xs) -> write('There is a road');
cut(Xs,Y).
When I am trying to run check(a,b) it doesn't run. I get the message
Singleton variable in branch: Xs
When I am not using cut question, I don't get any error. I would be grateful for pointing me where I made a mistake and showing way to repair it.
TL;DR: Prolog is right. And you really are doing the best taking the messages seriously.
You are using if-then-else in an unconventional manner. For this reason it is not that simple to figure out what is happening. When I say listing(check) I get the following:
check(A, B) :-
( related_to(A, C),
member(B, C)
-> write('There is a road')
; cut(C, B)
).
So Prolog was not very impressed by your indentation style, instead, it just looked for operators. In fact, the C (which is your original Xs) occurs in the if-part which is unrelated to the else-part. What you probably wanted is:
check(X,Y) :-
related_to(X,Xs),
( member(Y,Xs)
-> write('There is a road')
; cut(Xs,Y)
).
Regardless of the concrete problem at hand, I very much doubt that your code makes sense: Xs is a list of connected nodes, but do you really need this in this context? I do not think so.
Why not use closure0/3 to determine connectedness:
?- closure0(arc, A, B).
BTW, it is not clear whether you consider a directed graph or an undirected one. Above works only for directed graphs, for undirected graphs rather use:
comm(P_2, A,B) :-
( call(P_2, A,B)
; call(P_2, B,A)
).
?- closure0(comm(arc), A, B).
If you are interested in the path as well, use path/4:
?- path(comm(arc), Path, A, B).

Check if variable is empty or filled

I have the following problem:
prolog prog:
man(thomas, 2010).
man(leon, 2011).
man(thomas, 2012).
man(Man) :- once(man(Man, _).
problem:
?- man(thomas).
true ; %i want only on true even if there are more "thomas" *working because of once()*
?- man(X).
X = thomas ; %i want all man to be listed *isn't working*
goal:
?- man(thomas).
true ;
?- man(X).
X = thomas ;
X = leon ;
X = thomas ;
I do unterstand why this happens, but still want to get the names of all man.
So my solution woud be to look if "Man" is initialized, if yes than "once.." else then... something like that:
man(Man) :- (->check<-,once(man(Man, _)); man(Man, _).
On "check" shoud be the code sniped that checks if the variable "Man" is filled.
Is this possible?
One way to achieve this is as follows:
man(X) :-
(nonvar(X), man(X, _)), !
;
man(X, _).
Or, more preferred, would be:
man(X) :-
( var(X)
-> man(X, _)
; once(man(X, _))
).
The cut will ensure only one solution (at most) to an instantiated X, whereas the non-instantiated case will run its course. Note that, with the cut, you don't need once/1. The reason once/1 doesn't work as expected without the cut is that backtracking will still come back and take the "or" condition and succeed there as well.
man(X) :-
setof(t,Y^man(X,Y),_).
Additionally to what you are asking this removes redundant answers/solutions.
The built-in setof/3 describes in its last argument the sorted list of solutions found in the first argument. And that for each different instantiation of the free variables of the goal.
Free variables are those which neither occur in the first argument nor as an existential variable – the term on the left of (^)/2.
In our case this means that the last argument will always be [t] which is uninteresting. Therefore the _.
Two variables occurring in the goal are X and Y. Or, to be more precise the variables contained in X and Y. Y is an existential variable.
The only free variable is X. So all solutions for X are enumerated without redundancies. Note that you cannot depend on the precise order which happens to be sorted in this concrete case in many implementations.

How to know whether a racket variable is defined or not

How you can have a different behaviour if a variable is defined or not in racket language?
There are several ways to do this. But I suspect that none of these is what you want, so I'll only provide pointers to the functions (and explain the problems with each one):
namespace-variable-value is a function that retrieves the value of a toplevel variable from some namespace. This is useful only with REPL interaction and REPL code though, since code that is defined in a module is not going to use these things anyway. In other words, you can use this function (and the corresponding namespace-set-variable-value!) to get values (if any) and set them, but the only use of these values is in code that is not itself in a module. To put this differently, using this facility is as good as keeping a hash table that maps symbols to values, only it's slightly more convenient at the REPL since you just type names...
More likely, these kind of things are done in macros. The first way to do this is to use the special #%top macro. This macro gets inserted automatically for all names in a module that are not known to be bound. The usual thing that this macro does is throw an error, but you can redefine it in your code (or make up your own language that redefines it) that does something else with these unknown names.
A slightly more sophisticated way to do this is to use the identifier-binding function -- again, in a macro, not at runtime -- and use it to get information about some name that is given to the macro and decide what to expand to based on that name.
The last two options are the more useful ones, but they're not the newbie-level kind of macros, which is why I suspect that you're asking the wrong question. To clarify, you can use them to write a kind of a defined? special form that checks whether some name is defined, but that question is one that would be answered by a macro, based on the rest of the code, so it's not really useful to ask it. If you want something like that that can enable the kind of code in other dynamic languages where you use such a predicate, then the best way to go about this is to redefine #%top to do some kind of a lookup (hashtable or global namespace) instead of throwing a compilation error -- but again, the difference between that and using a hash table explicitly is mostly cosmetic (and again, this is not a newbie thing).
First, read Eli's answer. Then, based on Eli's answer, you can implement the defined? macro this way:
#lang racket
; The macro
(define-syntax (defined? stx)
(syntax-case stx ()
[(_ id)
(with-syntax ([v (identifier-binding #'id)])
#''v)]))
; Tests
(define x 3)
(if (defined? x) 'defined 'not-defined) ; -> defined
(let ([y 4])
(if (defined? y) 'defined 'not-defined)) ; -> defined
(if (defined? z) 'defined 'not-defined) ; -> not-defined
It works for this basic case, but it has a problem: if z is undefined, the branch of the if that considers that it is defined and uses its value will raise a compile-time error, because the normal if checks its condition value at run-time (dynamically):
; This doesn't work because z in `(list z)' is undefined:
(if (defined? z) (list z) 'not-defined)
So what you probably want is a if-defined macro, that tells at compile-time (instead of at run-time) what branch of the if to take:
#lang racket
; The macro
(define-syntax (if-defined stx)
(syntax-case stx ()
[(_ id iftrue iffalse)
(let ([where (identifier-binding #'id)])
(if where #'iftrue #'iffalse))]))
; Tests
(if-defined z (list z) 'not-defined) ; -> not-defined
(if-defined t (void) (define t 5))
t ; -> 5
(define x 3)
(if-defined x (void) (define x 6))
x ; -> 3