strengthof(_ * N,N) :- !.
strengthof(_    ,1).

nameof(X * _,Y) :- !, nameof(X,Y).
nameof($ X  ,Y) :- !, nameof(X,Y).
nameof(> X  ,Y) :- !, nameof(X,Y).
nameof(< X  ,Y) :- !, nameof(X,Y).
nameof(X    ,X).

nump($ _   ). 
nump(X     ) :- goalp(X).
nump( X * _) :- nump(X).
nump(> X   ) :- nump(X).  
nump(< X   ) :- nump(X).

maxp(> _   ). 
maxp(X * _ ) :- maxp(X).
maxp($ X   ) :- maxp(X).             

minp(< _   ). 
minp(X * _ ) :- minp(X).
minp($ X   ) :- minp(X). 

goalp(X    ) :- maxp(X) ; minp(X).

:- discontiguous about/4, eat/7.

headers((Table is Header,Headers),
             [about(Table,Names,MaxsInit,MinsInit)
             ,(eat(Table,Ins,Mins0,Mins,Maxs0,Maxs,X) :- 
                      X is 1 - sqrt(Dist)/sqrt(Dim),
                      Body)
             ]) :-
	demand(last,Table),
	c2l((Header,Headers),List),
	length(List,Arity),	
	functors([Ins,MaxsInit,MinsInit,
             Mins0,Maxs0,Mins,Maxs],db,Arity),
	sets(MaxsInit, -1*10^32),
	sets(MinsInit,    10^32),
	headers1(List,Names,0,Dim,Dist,Ins
             ,Mins0,Mins,Maxs0,Maxs,Body).

functors([],_,_).
functors([H|T],F,A) :- functor(H,F,A), functors(T,F,A).

sets(T,D) :- T =.. [_|A], maplist(sets1(D),A,A).

sets1(D,D,D).
headers1([],[],_,0,0,_,_,_,_,_,true).
headers1([Header|Headers],[Name|Names],
            N0,Dim+Dims,Dist+Dists,
            Ins,Mins0,Mins,Maxs0,Maxs,
            (Goal,Goals)) :-
	nameof(Header,Name),
	N is N0 + 1,	
	arg(N,Ins,  In),
	arg(N,Mins0,Min0),
	arg(N,Maxs0,Max0),
	arg(N,Mins, Min),
	arg(N,Maxs, Max),
	headerGoal(Header,In,Min0,Min,Max0,Max,Goal),
	headerDist(Header,In,Min0,Max0,Dim,Dist),
	headers1(Headers,Names,N,Dims,Dists,
                 Ins,Mins0,Mins,Maxs0,Maxs,Goals).

headerGoal(Header,  In,Min0,Min,Max0,Max,
         maxMin(In,Min0,Min,Max0,Max)) :- nump(Header),!.
headerGoal(_,_,_,_,_,_,true).

headerDist(Header,In,Min0,Max0,Strength,(Strength*Norm1)^2) :-
	goalp(Header),!,
    strengthof(Header,Strength),
    print(strengthof(Header,Strength)),nl,
	Norm = ((In - Min0)/(Max0 - Min0 + 0.000001)),
	(minp(header) -> Norm1 = ( 1 - Norm);  Norm1 =  Norm).
headerDist(_, _,_,_,0,0).

minMax((?),Min,Min,Max,Max) :- !.
minMax(New,Min0,Min,Max0,Max) :- 
	Min is min(New,Min0), 
	Max  is max(New,Max0). 
