%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % clp(q,r) version 1.3.3 % % % % (c) Copyright 1992,1993,1994,1995 % % Austrian Research Institute for Artificial Intelligence (OFAI) % % Schottengasse 3 % % A-1010 Vienna, Austria % % % % File: bb.pl % % Author: Christian Holzbaur christian@ai.univie.ac.at % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bb_inf( Is, Term, Inf) :- bb_inf( Is, Term, Inf, _, 0.001). bb_inf( Is, Term, Inf, Vertex, Eps) :- nf( Eps, ENf), nf_constant( ENf, EpsN), wait_linear( Term, Nf, bb_inf_internal(Is,Nf,EpsN,Inf,Vertex)). % --------------------------------------------------------------------- bb_inf_internal( Is, Lin, Eps, _, _) :- bb_intern( Is, IsNf), ( bb_delete( incumbent, _) -> true ; true ), repair( Lin, LinR), % bb_narrow ... deref( LinR, Lind), var_with_def_assign( Dep, Lind), determine_active_dec( Lind), bb_loop( Dep, IsNf, Eps), fail. bb_inf_internal( _, _, _, Inf, Vertex) :- bb_delete( incumbent, InfVal-Vertex), % GC { Inf =:= InfVal }. bb_loop( Opt, Is, Eps) :- bb_reoptimize( Opt, Inf), bb_better_bound( Inf), vertex_value( Is, Ivs), ( bb_first_nonint( Is, Ivs, Eps, Viol, Floor, Ceiling) -> bb_branch( Viol, Floor, Ceiling), bb_loop( Opt, Is, Eps) ; round_values( Ivs, RoundVertex), % print( incumbent( Inf-RoundVertex)), nl, bb_put( incumbent, Inf-RoundVertex) ). % % added ineqs may have led to binding % %vsc: added ! (01/06/06) bb_reoptimize( Obj, Inf) :- var( Obj), !, iterate_dec( Obj, Inf). bb_reoptimize( Obj, Inf) :- nonvar( Obj), Inf = Obj. bb_better_bound( Inf) :- bb_get( incumbent, Inc-_), !, arith_eval( Inf < Inc). bb_better_bound( _). % :- parallel(bb_branch/3). bb_branch( V, U, _) :- { V =< U }. bb_branch( V, _, L) :- { V >= L }. vertex_value( [], []). vertex_value( [X|Xs], [V|Vs]) :- rhs_value( X, V), vertex_value( Xs, Vs). %vsc: added ! (01/06/06) rhs_value( Xn, Value) :- nonvar(Xn), !, Value=Xn. rhs_value( Xn, Value) :- var(Xn), deref_var( Xn, Xd), decompose( Xd, _, R, I), arith_eval( R+I, Value). % % Need only one as we branch on the first anyway ... % bb_first_nonint( [I|Is], [Rhs|Rhss], Eps, Viol, F, C) :- ( arith_eval( floor(Rhs), Floor), arith_eval( ceiling(Rhs), Ceiling), arith_eval(min(Rhs-Floor,Ceiling-Rhs) > Eps) -> Viol = I, F = Floor, C = Ceiling ; bb_first_nonint( Is, Rhss, Eps, Viol, F, C) ). round_values( [], []). round_values( [X|Xs], [Y|Ys]) :- arith_eval( round(X), Y), round_values( Xs, Ys). bb_intern( [], []). bb_intern( [X|Xs], [Xi|Xis]) :- nf( X, Xnf), bb_intern( Xnf, Xi, X), bb_intern( Xs, Xis). % % allow more general expressions and conditions? integral(Exp) ??? % bb_intern( [], X, _) :- !, arith_eval( 0, X). bb_intern( [v(I,[])], X, _) :- !, X=I. bb_intern( [v(One,[X^1])], X, _) :- arith_eval(One=:=1), !, get_atts( X, [type(T),strictness(S)]), bb_narrow( T, S, X). bb_intern( _, _, Term) :- raise_exception( instantiation_error(bb_inf(Term,_,_),1)). bb_narrow( t_l(L), S, V) :- S /\ 2'10 =\= 0, !, arith_eval( floor(1+L), B), { V >= B }. bb_narrow( t_u(U), S, V) :- S /\ 2'01 =\= 0, !, arith_eval( ceiling(U-1), B), { V =< B }. bb_narrow( t_lu(L,U), S, V) :- !, bb_narrow( t_l(L), S, V), bb_narrow( t_u(U), S, V). bb_narrow( _, _, _).