239 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Prolog
		
	
	
	
	
	
			
		
		
	
	
			239 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Prolog
		
	
	
	
	
	
| /**
 | |
|  * @file   exo_interval.yap
 | |
|  * @author VITOR SANTOS COSTA <vsc@VITORs-MBP.lan>
 | |
|  * @date   2013
 | |
|  * 
 | |
|  * @brief  This file implements a very simple interval solver
 | |
|  * designed to interact with the exo
 | |
|  * data-base.
 | |
|  * It assumes simple queries and a contiguous interval,
 | |
|  * and does not really expect to do non-trivial
 | |
|  * constraint propagation and solving.
 | |
|  * 
 | |
|  * 
 | |
| */
 | |
| :- module(exo_interval,
 | |
| 	[max/2,
 | |
| 	 min/2,
 | |
| 	 any/2,
 | |
| 	 max/1,
 | |
| 	 min/1,
 | |
| 	 maximum/1,
 | |
| 	 minimum/1,
 | |
| 	 any/1,
 | |
| 	 (#<)/2,
 | |
| 	 (#>)/2,
 | |
| 	 (#=<)/2,
 | |
| 	 (#>=)/2,
 | |
| 	 (#=)/2,
 | |
| 	 op(700, xfx, (#>)),
 | |
| 	 op(700, xfx, (#<)),
 | |
| 	 op(700, xfx, (#>=)),
 | |
| 	 op(700, xfx, (#=<)),
 | |
| 	 op(700, xfx, (#=))]).
 | |
| 
 | |
| 
 | |
| /** @defgroup exo_interval Exo Intervals
 | |
| @ingroup library
 | |
| @{
 | |
| 
 | |
| This package assumes you use exo-compilation, that is, that you loaded
 | |
| the pedicate using the `exo` option to load_files/2, In this
 | |
| case, YAP includes a package for improved search on  intervals of
 | |
| integers.
 | |
| 
 | |
| The package is activated by `udi` declarations that state what is
 | |
| the argument of interest:
 | |
| 
 | |
| ~~~~~{.prolog}
 | |
| :- udi(diagnoses(exo_interval,?,?)).
 | |
| 
 | |
| :- load_files(db, [consult(exo)]).
 | |
| ~~~~~
 | |
| It is designed to optimise the following type of queries:
 | |
| 
 | |
| ~~~~~{.prolog}
 | |
| ?- max(X, diagnoses(X, 9, Y), X).
 | |
| 
 | |
| ?- min(X, diagnoses(X, 9, 36211117), X).
 | |
| 
 | |
| ?- X #< Y, min(X, diagnoses(X, 9, 36211117), X ), diagnoses(Y, 9, _).
 | |
| ~~~~~
 | |
| The first argument gives the time, the second the patient, and the
 | |
| third the condition code. The first query should find the last time
 | |
| the patient 9 had any code reported, the second looks for the first
 | |
| report of code 36211117, and the last searches for reports after this
 | |
| one. All queries run in  constant or log(n) time.
 | |
| 
 | |
| 
 | |
|  */
 | |
| 
 | |
| /** @pred max( _X_,  _Vs_)
 | |
| First Argument is the greatest element of a list.
 | |
| 
 | |
| + lex_order( _Vs_)
 | |
| All elements must be ordered.
 | |
| 
 | |
| 
 | |
| 
 | |
| The following predicates control search:
 | |
| 
 | |
|  
 | |
| */
 | |
| /** @pred max(+ _Expression_)
 | |
| Maximizes  _Expression_ within the current constraint store. This is
 | |
| the same as computing the supremum and equating the expression to that
 | |
| supremum.
 | |
| 
 | |
|  
 | |
| */
 | |
| /** @pred min( _X_,  _Vs_)
 | |
| First Argument is the least element of a list.
 | |
| 
 | |
|  
 | |
| */
 | |
| /** @pred min(+ _Expression_)
 | |
| Minimizes  _Expression_ within the current constraint store. This is
 | |
| the same as computing the infimum and equation the expression to that
 | |
| infimum.
 | |
| 
 | |
|  
 | |
| */
 | |
| :- meta_predicate max(?,0), min(?,0), any(?,0).
 | |
| 
 | |
| max(X, G) :-
 | |
| 	insert_atts(X, i(_,_,max)),
 | |
| 	call(G).
 | |
| 
 | |
| min(X, G) :-
 | |
| 	insert_atts(X, i(_,_,min)),
 | |
| 	call(G).
 | |
| 
 | |
| max(X) :-
 | |
| 	insert_atts(X, i(_,_,max)).
 | |
| 
 | |
| maximum(X) :-
 | |
| 	insert_atts(X, i(_,_,maximum)).
 | |
| 
 | |
| any(X) :-
 | |
| 	insert_atts(X, i(_,_,any)).
 | |
| 
 | |
| min(X) :-
 | |
| 	insert_atts(X, i(_,_,min)).
 | |
| 
 | |
| minimum(X) :-
 | |
| 	insert_atts(X, i(_,_,minimum)).
 | |
| 
 | |
| least(X) :-
 | |
| 	insert_atts(X, i(_,_,least)).
 | |
| 
 | |
| X #> Y :-
 | |
| 	( var(X) -> insert_atts(X, i(Y,_,_))
 | |
|                   ;
 | |
| 	          ( var(Y) -> insert_atts(Y, i(_,X,_) ) ; 
 | |
| 		      true
 | |
| 		  )
 | |
| 	      ;
 | |
| 	  var(Y) -> insert_atts(Y, i(_,X,_))
 | |
|         ;
 | |
| 	  X > Y
 | |
|         ).
 | |
| 
 | |
| X #>= Y :-
 | |
| 	( var(X) -> insert_atts(X, i(Y-1,_,_))
 | |
|         ;
 | |
| 	  X >= Y
 | |
|         ).
 | |
| 
 | |
| X #< Y :-
 | |
| 	( var(X) -> insert_atts(X, i(_,Y,_))
 | |
|         ;
 | |
| 	  X < Y
 | |
|         ).
 | |
| 
 | |
| X #=< Y :-
 | |
| 	( var(X) -> insert_atts(X, i(Y+1,_,_))
 | |
|         ;
 | |
| 	  X =< Y
 | |
|         ).
 | |
| 
 | |
| X #= Y :-
 | |
| 	( var(X) -> insert_atts(X, i(Y-1,Y+1,_)) ;
 | |
| 	  X =:= Y
 | |
|         ).
 | |
| 
 | |
| 
 | |
| attribute_goals(X) -->
 | |
|         { get_attr(X, exo_interval, Op) },
 | |
|         ( { Op = max } -> [max(X)] ;
 | |
| 	  { Op = min } -> [min(X)] ;
 | |
|           { Op = '>'(Y) } -> [X #> Y] ;
 | |
|           { Op = '<'(Y) } -> [X #< Y] ;
 | |
|           { Op = range(A,B,C) } -> 
 | |
| 	        range_min(A,X),
 | |
| 		range_max(B,X),
 | |
| 		range_op(C, X)
 | |
| 	).
 | |
| 
 | |
| range_min(Y, _X) -->
 | |
| 	{ var(Y) }, !,
 | |
| 	[].
 | |
| range_min(Y, X) -->
 | |
| 	[X #> Y].
 | |
| 
 | |
| range_max(Y, _X) -->
 | |
| 	{ var(Y) }, !,
 | |
| 	[].
 | |
| range_max(Y, X) -->
 | |
| 	[X #< Y].
 | |
| 
 | |
| range_op(Y, _X) -->
 | |
| 	{ var(Y) }, !,
 | |
| 	[].
 | |
| range_op(Y, X) -->
 | |
| 	{ Op =.. [Y, X] },
 | |
| 	[Op].
 | |
| 
 | |
| insert_atts(V, Att) :-
 | |
| 	( nonvar(V) ->
 | |
| 	    throw( error(uninstantion_error(V), exo_interval) )
 | |
| 	; attvar(V) ->
 | |
| 	    get_attr(V, exo_interval, Att0),
 | |
| 	    expand_atts(Att, Att0, NAtt)
 | |
| 	;
 | |
| 	  NAtt = Att
 | |
| 	),
 | |
| 	put_attr(V, exo_interval, NAtt).
 | |
| 
 | |
| expand_atts(i(A1, B1, C1), i(A2, B2, C2), i(A3,B3,C3)) :-
 | |
| 	expand_min(A1, A2, A3),
 | |
| 	expand_max(B1, B2, B3),
 | |
| 	expand_op(C1, C2, C3).
 | |
| 
 | |
| expand_min(A1, A2, A3) :-
 | |
| 	(var(A1) -> A3 = A2;
 | |
| 	 var(A2) -> A3 = A1;
 | |
| 	 ground(A1), ground(A2) -> A3 is max(A1,A2) ;
 | |
| 	 A3 = max(A1,A2)
 | |
|         ).
 | |
| 
 | |
| expand_max(A1, A2, A3) :-
 | |
| 	(var(A1) -> A3 = A2;
 | |
| 	 var(A2) -> A3 = A1;
 | |
| 	 ground(A1), ground(A2) -> A3 is min(A1,A2) ;
 | |
| 	 A3 = min(A1,A2)
 | |
|         ).
 | |
| 
 | |
| expand_op(A1, A2, A3) :-
 | |
| 	(var(A1) -> A3 = A2;
 | |
| 	 var(A2) -> A3 = A1;
 | |
| 	 A1 == A2 -> A3 = A1;
 | |
| 	 A1 == unique -> A3 = unique;
 | |
| 	 A2 == unique -> A3 = unique;
 | |
| 	 A2 == min, A1 = max -> A3 = unique;
 | |
| 	 A1 == min, A2 = max -> A3 = unique;
 | |
| 	 A1 == min -> A3 = min;	 A2 == min -> A3 = min;
 | |
| 	 A1 == max -> A3 = max;	 A2 == max -> A3 = max;
 | |
| 	 A3 = any
 | |
|         ).
 |