| Did you know ... | Search Documentation: |
| Pack logicmoo_base -- prolog/logicmoo/plarkc/logicmoo_u_temporal.txt |
% NOTICE: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % COPYRIGHT (2009) University of Dallas at Texas. % % % % Developed at the Applied Logic, Programming Languages and Systems % % (ALPS) Laboratory at UTD by Feliks Kluzniak. % % % % Permission is granted to modify this file, and to distribute its % % original or modified contents for non-commercial purposes, on the % % condition that this notice is included in all copies in its % % original form. % % % % THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, % % EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES % % OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND % % NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR % % ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR % % OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING % % FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR % % OTHER DEALINGS IN THE SOFTWARE. % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Operators for expressing LTL formulae.
:- op( 10, fy , - ). % not
:- op( 20, xfy , & ). % and
:- op( 30, xfy , v ). % or
:- op( 10, fy , nextX ). % LTL: "next"
:- op( 10, fy , eventuallyF ). % LTL: "eventually"
:- op( 10, fy , alwaysG ). % LTL: "always"
:- op( 20, xfx , untilU ). % LTL: "until"
:- op( 20, xfx , releaseR ). % LTL: "release"
%%%%%
%--- Normalize an LTL formula by pushing negations to the level of propositions %--- and applying some absorption and idempotency laws.
normalize( X, Normalized ) :-
(
var( X )
->
write( '*** The formula is a Prolog variable!' ),
nl,
Normalized = ?
;
once( norm( X, Normalized, OK ) )
->
var( OK )
).
% If an error is found, OK will cease to be a variable.
norm( - ( A v B ) , Normalized, OK ) :-
once( norm( -A & -B , Normalized, OK ) ).
norm( - ( A & B ) , Normalized, OK ) :-
once( norm( -A v -B , Normalized, OK ) ).
norm( - -A , Normalized, OK ) :-
once( norm( A , Normalized, OK ) ).
norm( -nextX A , Normalized, OK ) :-
once( norm( nextX -A , Normalized, OK ) ).
norm( -eventuallyF A , Normalized, OK ) :-
once( norm( alwaysG -A , Normalized, OK ) ).
norm( -alwaysG A , Normalized, OK ) :-
once( norm( eventuallyF -A , Normalized, OK ) ).
norm( - ( A untilU B ) , Normalized, OK ) :- once( norm( -A releaseR -B , Normalized, OK ) ).
norm( - ( A releaseR B ) , Normalized, OK ) :- once( norm( -A untilU -B , Normalized, OK ) ).
norm( A v B , NA v NB, OK ) :-
once( norm( A, NA, OK ) ),
once( norm( B, NB, OK ) ).
norm( A & B , NA & NB, OK ) :-
once( norm( A, NA, OK ) ),
once( norm( B, NB, OK ) ).
norm( -A , -NA, OK ) :-
once( norm( A, NA, OK ) ).
norm( nextX A , nextX NA, OK ) :-
once( norm( A, NA, OK ) ).
norm( eventuallyF A , eventuallyF NA, OK ) :-
once( norm( A, NA, OK ) ).
norm( alwaysG A , alwaysG NA, OK ) :-
once( norm( A, NA, OK ) ).
norm( A untilU B , NA untilU NB, OK ) :-
once( norm( A, NA, OK ) ),
once( norm( B, NB, OK ) ).
norm( A releaseR B , NA releaseR NB, OK ) :-
once( norm( A, NA, OK ) ),
once( norm( B, NB, OK ) ).
norm( eventuallyF eventuallyF A , Normalized, OK ) :- once( norm( eventuallyF A , Normalized, OK ) ).
norm( alwaysG alwaysG A , Normalized, OK ) :- once( norm( alwaysG A , Normalized, OK ) ).
norm( A untilU (A untilU B) , Normalized, OK ) :- once( norm( A untilU B , Normalized, OK ) ).
norm( (A untilU B) untilU B , Normalized, OK ) :- once( norm( A untilU B , Normalized, OK ) ).
norm( eventuallyF alwaysG eventuallyF A , Normalized, OK ) :- once( norm( alwaysG eventuallyF A , Normalized, OK ) ).
norm( alwaysG eventuallyF alwaysG A , Normalized, OK ) :- once( norm( eventuallyF alwaysG A , Normalized, OK ) ).
norm( nextX A & nextX B , Normalized, OK ) :- once( norm( nextX (A & B) , Normalized, OK ) ).
norm( alwaysG A & alwaysG B , Normalized, OK ) :- once( norm( alwaysG (A & B) , Normalized, OK ) ).
norm( eventuallyF A v eventuallyF B , Normalized, OK ) :- once( norm( eventuallyF (A v B) , Normalized, OK ) ).
norm( -P, -P, _ ) :-
proposition( P ).
norm( P, P, _ ) :-
proposition( P ).
norm( X, ?, ? ) :-
write( '*** This is not a well-formed (sub)formula: \"' ),
write( X ),
write( '\"' ),
nl.
% NOTICE: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % COPYRIGHT (2009) University of Dallas at Texas. % % % % Developed at the Applied Logic, Programming Languages and Systems % % (ALPS) Laboratory at UTD by Feliks Kluzniak. % % % % Permission is granted to modify this file, and to distribute its % % original or modified contents for non-commercial purposes, on the % % condition that this notice is included in all copies in its % % original form. % % % % THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, % % EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES % % OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND % % NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR % % ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR % % OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING % % FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR % % OTHER DEALINGS IN THE SOFTWARE. % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% A consistency checker for automata. See "verifier.tlp".
% Check the consistency of the automaton's description.
:- [ 'partition_graph.pl' ].
% NOTE: The dynamic declaration is necessary for Eclipse.
:- dynamic automaton_error/0.
automaton_error. % Will be retracted: needed to suppress a warning from Sicstus
check_consistency :-
retractall( automaton_error ),
check_connectedness,
check_propositions,
check_transitions,
(
automaton_error
->
fail
;
true
).
% If the graph is not connected, print a warning.
check_connectedness :-
partition( Components ),
length( Components, NumberOfComponents ),
(
NumberOfComponents =:= 1 % connected
->
true
;
write( 'WARNING: The graph is not connected!' ),
nl,
write( 'The partitions are: ' ),
write( Components ),
nl
).
% Make sure propositions don't clash with operators.
check_propositions :-
proposition( P ),
(
\+ atom( P )
->
write( 'A proposition must be an atom: ' ),
write( '\"' ),
write( P ),
write( '\"' ),
nl,
assert( automaton_error )
;
true
),
(
member( P, [ 'v', 'nextX', 'eventuallyF', 'alwaysG', 'untilU', 'releaseR' ] )
->
write( '\"v\", \"nextX\", \"eventuallyF\", \"alwaysG\", \"untilU\" and \"releaseR\" ' ),
write( 'cannot be propositions: ' ),
write( '\"' ),
write( P ),
write( '\"' ),
nl,
assert( automaton_error )
;
true
),
fail.
check_propositions.
% Make sure that there is no state with no outgoing transitions, and that all % transitions are between states.
check_transitions :-
trans( S1, S2 ),
(
(var( S1 ) ; var( S2 ) ; \+ state( S1 ) ; \+ state( S2 ))
->
write( 'Transitions can only occur between states: ' ),
write( S1 ),
write( ' ---> ' ),
write( S2 ),
nl,
assert( automaton_error )
;
true
),
fail.
check_transitions :-
state( S ),
(
(\+ trans( S, _Set ) ; trans( S, [] ))
->
write( 'No transition out of state ' ),
write( S ),
nl,
assert( automaton_error )
;
true
),
fail.
check_transitions.
%------------------------------------------------------------------------------- % NOTICE: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % COPYRIGHT (2009) University of Dallas at Texas. % % % % Developed at the Applied Logic, Programming Languages and Systems % % (ALPS) Laboratory at UTD by Feliks Kluzniak. % % % % Permission is granted to modify this file, and to distribute its % % original or modified contents for non-commercial purposes, on the % % condition that this notice is included in all copies in its % % original form. % % % % THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, % % EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES % % OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND % % NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR % % ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR % % OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING % % FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR % % OTHER DEALINGS IN THE SOFTWARE. % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Some "higher order" predicates for Prolog. %%% %%% This particular version was %%% %%% written by Feliks Kluzniak at UTD (February 2009). %%% %%% %%% %%% Last update: 11 June 2009. %%% %%% %%%
%%% NOTE: Throughout the file "predicate name" will be used either for %% the name of a predicate, or for a predicate with an incomplete %% list of arguments (a partially applied predicate): see apply/2.
%%------------------------------------------------------------------------------
%% apply( + predicate name (possibly with arguments), + list of arguments ):
%% Extend the list of arguments of the first argument with the second argument
%% and invoke the result.
%% For example, if we have
%% sum( A, B, C ) :-C is A + B.
%% then
%% map( sum(5 ), [ 1, 2, 3 ], Result )
%% will bind Result to [ 6, 7, 8 ].
apply( PredNameArgs, Arguments ) :-
PredNameArgs =.. [ PredName | Args ],
append( Args, Arguments, AllArgs ),
Literal =.. [ PredName | AllArgs ],
call( Literal ).
%%------------------------------------------------------------------------------
%% map( + predicate name, + list, - mapped list ):
%% The predicate should implement a unary function, i.e.,
%% - it should take two arguments, the first of which is an input argument,
%% and the second of which is an output argument;
%% - it should always succeed, and the first result should be "what we want".
%% The predicate is applied to input arguments from the list, and the
%% corresponding outputs are returned in the second list.
%%
%% Example:
%% square( M, N ) :-N is M * M.
%%
%% ?- map( square, [ 1, 2, 3 ], Ans ).
%%
%% Ans = [ 1, 4, 9 ].
map( _, [], [] ).
map( PredName, [ H | T ], [ NH | NT ] ) :-
apply( PredName, [ H, NH ] ),
map( PredName, T, NT ).
%%------------------------------------------------------------------------------ %% filter( + predicate name, + list, - filtered list ): %% The predicate should take one argument. %% The output list will contain only those elements of the input list for which %% the predicate succeeds.
filter( _, [], [] ).
filter( PredName, [ H | T ], NL ) :-
(
apply( PredName, [ H ] )
->
NL = [ H | NT ]
;
NL = NT
),
filter( PredName, T, NT ).
%%------------------------------------------------------------------------------ %% filter2( + predicate name, + list, - yes list, - no list ): %% The predicate should take one argument. %% The first output list will contain only those elements of the input list for %% which the predicate succeeds; the second output list will contain only those %% elements of the input list for which the predicate fails.
filter2( _, [], [], [] ) :-!.
filter2( PredName, [ H | T ], [ H | Yes ], No ) :-
apply( PredName, [ H ] ),
!,
filter2( PredName, T, Yes, No ).
filter2( PredName, [ H | T ], Yes, [ H | No ] ) :-
% \+ apply( PredName, [ H ] ),
filter2( PredName, T, Yes, No ).
%%------------------------------------------------------------------------------
%% fold( + predicate name,+ initial value, + list, - final value ):
%% The predicate should implement a binary function, i.e.,
%% - it should take three arguments, the first two of which are input
%% arguments, and the third of which is an output argument;
%% - it should always succeed, and the first result should be "what we want".
%% If the list is empty, the initial value is returned; otherwise the predicate
%% is applied to the initial value and the first member of the list, and then
%% to the result and the third member, and so on.
%% For example, if "sum( A, B, C )" unifies "C" with the sum of "A" and "B",
%% then "fold( sum, 0, [1,2,3], S )" unifies "S" with "6".
fold( _, Initial, [], Initial ).
fold( PredName, Initial, [ H | T ], Result ) :-
apply( PredName, [ Initial, H, R ] ),
fold( PredName, R, T, Result ).
%%------------------------------------------------------------------------------
% NOTICE: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % COPYRIGHT (2009) University of Dallas at Texas. % % % % Developed at the Applied Logic, Programming Languages and Systems % % (ALPS) Laboratory at UTD by Feliks Kluzniak. % % % % Permission is granted to modify this file, and to distribute its % % original or modified contents for non-commercial purposes, on the % % condition that this notice is included in all copies in its % % original form. % % % % THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, % % EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES % % OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND % % NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR % % ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR % % OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING % % FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR % % OTHER DEALINGS IN THE SOFTWARE. % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% This is an experimental version of a pure Prolog counterpart of verifier.tlp. %% %% The approach is to visit each node at most once, and rewrite the expression %% to take into account the valuation of propositions in that node. %% The cost is O( number of nodes ) * O( length of formula ). %% We don't yet have a proof of correctness, but all the examples work. %% %% Written by Feliks Kluzniak at UTD (March 2009). %% Last update: 24 April 2009.
:- [ 'operators.pl' ]. :- [ 'normalize.pl' ]. :- [ 'looping_prefix.pl' ]. :- [ 'consistency_checker.pl' ]. :- [ '../../higher_order.pl' ].
:- ensure_loaded( library( lists ) ). % Sicstus, reverse/2.
%% Check whether the state satisfies the formula. %% This is done by checking that it does not satisfy the formula's negation. %% (We have to apply the conditional, because our tabling interpreter does not %% support the cut, and we don't yet support negation for coinduction.)
check( State, Formula ) :-
check_consistency,
(
state( State )
->
true
;
write( '\"' ),
write( State ),
write( '\" is not a state' ),
nl,
fail
),
write( 'Query for state ' ),
write( State ),
write( ': ' ),
write( Formula ),
nl,
once( normalize( -Formula, NormalizedNegationOfFormula ) ),
write( '(Negated and normalized: ' ),
write( NormalizedNegationOfFormula ),
write( ')' ),
nl,
(
once( verify( State, NormalizedNegationOfFormula, [] ) )
->
fail
;
true
).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% verify( + state, + formula, + path ) :
%% Verify whether the formula holds for this state (which we reached by this
%% path).
%% (The formula is our negated thesis, so we are looking for one path.)
verify( S, F, Path ) :-
rewrite( F, S, NF ),
(
NF = true
->
show_path( Path )
;
NF = false
->
fail
;
(
member( pair( S, F ), Path )
->
(
disjunct( alwaysG _, F )
->
show_path( Path )
;
fail
)
;
once( strip_off_x( NF, NNF ) ),
trans( S, NS ),
verify( NS, NNF, [ pair( S, F ) | Path ] )
)
).
%
show_path( Path ) :-
write( 'COUNTEREXAMPLE: ' ),
reverse( Path, RevPath ),
map( first, RevPath, TruePath ),
write( TruePath ),
nl.
%
first( pair( State, _ ), State ).
%% disjunct( +- disjunct, + formula ): %% Like member, only of an outermost disjunction rather than a list.
disjunct( A, A v _ ).
disjunct( A, _ v B ) :-disjunct( A, B ).
disjunct( A, A ).
%% strip_off_x( + formula, - formula ):
%% Strip off the "nextX" operator from every disjunct, raise an alarm and abort if
%% there are disjuncts that are not so wrapped.
strip_off_x( nextX A v B, A v NB ) :-strip_off_x( B, NB ).
strip_off_x( nextX F, F ).
strip_off_x( F, _ ) :-
F \= nextX F,
write( 'Formula not in X : ' ),
write( F ),
nl,
abort.
%% rewrite( + formula, + state, - new formula ): %% The formula has been normalized, so that negations are applied only to %% propositions.
rewrite( F, S, NF ) :-
once( releaseR( F, S, NF ) ).
releaseR( A, S, NA ), releaseR( B, S, NB ),
simplify( NA v NB, NF ).
releaseR( A & B, S, NF ) :-releaseR( A, S, NA ), releaseR( B, S, NB ),
simplify( NA & NB, NF ).
releaseR( nextX A , _, nextX A ).
releaseR( A, S, NA ),
simplify( NA v nextX eventuallyF A, NF ).
releaseR( A, S, NA ),
simplify( NA & nextX alwaysG A, NF ).
releaseR( A, S, NA ), releaseR( B, S, NB ),
simplify( NA & nextX (A untilU B), Conj ),
simplify( NB v Conj, NF ).
releaseR( A, S, NA ), releaseR( B, S, NB ),
simplify( NB & NA, Conj ),
simplify( Conj v nextX (A releaseR B), NF ).
releaseR( -P , S, NF ) :-proposition( P ),
( holds( S, P ) -> NF = false
; NF = true
).
releaseR( P , S, NF ) :-proposition( P ),
( holds( S, P ) -> NF = true
; NF = false
).
%% simplify( + formula, + state,- new formula ): %% The formula has now been rewritten: simplify the result.
simplify( F, NF ) :-
once( s( F, NF ) ).
%
s( true v _ , true ).
s( _ v true , true ).
s( false v A , NA ) :-s( A , NA ).
s( A v false, NA ) :-s( A , NA ).
s( A v A v B , NF ) :-s( A v B , NF ).
s( (A v B) v C , NF ) :-s( A v B v C, NF ).
s( false & _ , false ).
s( _ & false, false ).
s( true & A , NA ) :-s( A , NA ).
s( A & true , NA ) :-s( A , NA ).
s( A & A & B , NF ) :-s( A & B , NF ).
s( (A & B) & C , NF ) :-s( A & B & C, NF ).
s( nextX A & nextX B , nextX NF ) :-s( A & B , NF ).
s( F , F ).
%-------------------------------------------------------------------------------