It almost works, but I have some problems with the all quantifier.
The code is:
:- dynamic done/1.
:- op(900, xfx, =>).
:- op(800, xfy, &).
:- op(300, xfx, :).
% black_edge and so black_conn connecting two processes
black_conn(X,Y) :- black_edge(X,Z), black_conn(Z,Y).
black_conn(X,Y) :- black_edge(X,Y).
% red_conn connecting two processes
red_conn(X,Y) :- red_edge(X,Y).
% Now A shall also be required in order to execute C:
% A -black-> B -red-> C ==implies==> A -red-> C
red_conn(X,Z) :- black_conn(X,Y), red_conn(Y,Z).
% Is a process executable?
executable(X) :- black_conn(X,_).
executable(Y) :- black_conn(_,Y).
executable(X) :- red_conn(X,_).
% Now I need that executable(c) is only possible if done(a) AND done(b)
% holds
% Something with all?
% all(X):(red_conn(X,Y) & done(X) => executable(Y)).
% The following works in the way that done(a) OR done(b) is sufficient
% for executable(c) but not both what I want
executable(Y) :- red_conn(X,Y), done(X).
% MODEL FLOW
% A -black-> B -red-> C
black_edge(a,b).
red_edge(b,c).
% QUERIES
% executable(c). --> NO
% assert(done(a)).
% executable(c). --> Shall be NO but is YES
% assert(done(b)).
% executable(c). --> Shall be YES after done(b)
Best reagrds,
Michael
Perhaps,
executable(Y) :- \+ (red_conn(X,Y),\+ done(X)).
---
Geoff
yes, that's it. Many thanxs.
The working code:
:- dynamic done/1.
% black_edge and so black_conn connecting two processes
black_conn(X,Y) :- black_edge(X,Z), black_conn(Z,Y).
black_conn(X,Y) :- black_edge(X,Y).
% red_conn connecting two processes
red_conn(X,Y) :- red_edge(X,Y).
% Now A shall also be required in order to execute C:
% A -black-> B -red-> C ==implies==> A -red-> C
red_conn(X,Z) :- black_conn(X,Y), red_conn(Y,Z).
% Is a process executable?
executable(X) :- black_conn(X,_).
executable(Y) :- black_conn(_,Y).
executable(X) :- red_conn(X,_).
% A process that is connected through a red edge
% shall only be executable if all preceding processes
% have been executed
executable(Y) :- \+ (red_conn(X,Y),\+ done(X)).
% MODEL FLOW
% A -black-> B -black-> C -black-> D -red-> E
black_edge(a,b).
black_edge(b,c).
black_edge(c,d).
red_edge(d,e).
% QUERIES
% executable(e). --> NO
% assert(done(a)).
% assert(done(b)).
% assert(done(c)).
% assert(done(d)).
% executable(e). --> YES
Michael
Try removing the other executable declarations.
:- dynamic done/1.
black_conn(X,Y) :- black_edge(X,Z), black_conn(Z,Y).
black_conn(X,Y) :- black_edge(X,Y).
red_conn(X,Y) :- red_edge(X,Y).
red_conn(X,Z) :- black_conn(X,Y), red_conn(Y,Z).
executable(Y) :- \+ (red_conn(X,Y),\+ done(X)).
black_edge(a,b).
black_edge(b,c).
black_edge(c,d).
red_edge(d,e).
And make sure that executable/1 does what you
want it to, it allows more than you might think.
Try executable(f).
----
Geoff
Yes it is still working.
I wonder for 2 days now what the meaning of \+ is.
Sicstus Manual says:
\+ P : Fails if the goal P has a solution, and succeeds otherwise.
This is not real negation ("P is false"), but a kind of pseudo-negation
meaning "P is not provable".
But I have no idea how it is applicable to my case.
Michael
I have modified my program and added a statement that gives me a set of
processes that I can execute :
:- dynamic done/1.
% black_edge and so black_conn connecting two processes
black_conn(X,Y) :- black_edge(X,Z), black_conn(Z,Y).
black_conn(X,Y) :- black_edge(X,Y).
% red_conn connecting two processes
red_conn(X,Y) :- red_edge(X,Y).
% Now A shall also be required in order to execute C:
% A -black-> B -red-> C ==implies==> A -red-> C
red_conn(X,Z) :- black_conn(X,Y), red_conn(Y,Z).
% Is a process executable?
executable(X) :- black_conn(X,_).
executable(Y) :- black_conn(_,Y).
executable(X) :- red_conn(X,_).
% Now I need that executable(c) is only possible if done(a) AND done(b)
holds
executable(X) :- \+ (red_conn(W,X),\+ done(W)).
% Give a list of processes that are excutable
canDo :- setof(X, executable(X), Ausfuehrbar), write('You can do = '),
write(Ausfuehrbar),nl.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% INSTANCE
% MODEL FLOW
% A -black-> B -red-> C
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
black_edge(a,b).
red_edge(b,c).
The following prolog session illustrates my problem:
?- canDo.
You can do = [a, b]
true.
?- assert(done(a)).
true.
?- assert(done(b)).
true.
?- canDo.
You can do = [_G327, a, b]
true.
Why is there a _G327 and not 'c', and how can I resolve this problem?
Thanks for tips,
Michael
Because executable(X) :- \+ (red_conn(W,X),\+ done(W)). says
EVERYTHING is executable unless X has a red predecessor which
isn't done.
If X is unified before calling executable/1, it will always
succeed unless it fails that restriction. If X is always
unified before calling executable/1, there is no need for
the other clauses. This is the way the clause was designed.
In fact, there may be a bit of a problem leaving the other clauses
intact. Consider [black_edge(a,c). red_edge(b,c).], executable(c).
will succeed due to the black connection to a when you most
likely want it to fail without done(b).
But that's hard to say without a better idea of what red and
black edges are supposed to mean. I'll also mention the case of a
solid set of red edges.
i.e.
Given
red_edge(a,b).
red_edge(b,c).
done(b).
Should executable(c). pass or fail?
If X isn't unified when calling executable/1 is a trickier case
for the last clause, but if it can find one unification that fails
the whole clause fails, if it cannot find one then X can be anything
and the generic place (_G###) returned is actually correct.
So unifying to a possible X first, then going through the
rest of the clause, one solution.
process(a).
process(b).
process(c).
% one clause for executable
executable(X) :- process(X), \+ (red_conn(W,X),\+ done(W)).
The advantage to this is that processes that are unconnected
will show up as executable.
Another approach:
% changed from executable/1
connected(X) :- black_conn(X,_).
connected(Y) :- black_conn(_,Y).
connected(X) :- red_conn(X,_).
connected(X) :- red_conn(_,X). % added case
% one clause for executable
executable(X) :- connected(X), \+ (red_conn(W,X),\+ done(W)).
---
Geoff
Now everything is working as I want to. Thanks!
By the way, I choosed your second approach, beacuse all processes
shall always be connected.
Is it possible to put some quantifications on the processes, e.g.
process a may be executed minimum twice and maximum 3 times,
A : {2,3}
Now when I take :
A --red--> B beside the constraint that A has to be executed before B,
the quantification constraint that A is in 2..3 has to be fullfilled
too.
So I need to do assert(done(a)) twice in order that executale(b) says
"true".
I wonder which data-structure I shall take. Model {2,3} as interval and
check if the counter of process A is in that interval?
And when I do a assert(done(a)) and A is already done 3 times the it
shall say "fail".
Michael