/* Part of INCLP(R) Author: Leslie De Koninck E-mail: Leslie.DeKoninck@cs.kuleuven.be WWW: http://www.swi-prolog.org Copyright (c) 2006-2011, K.U. Leuven All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ :- module(inclpr_consistency, [ check/8, check_projection/5, create_base_form/4, create_partial_evaluation/5, get_direct_full_evaluation/4, get_full_evaluation/5, instantiate_nat/2, instantiate_all_nat/1, max_reduced/3 ]). :- use_module(library(chr)). :- use_module(inclpr_interval_arithmetic, [ accepted_solution_domain/1, minimal_interval/3, eq_subdivide/3, uneq_subdivide/4, interval_center/2, interval_new_class/2 ]). :- use_module(inclpr_newton, [ interval_newton/6 ]). :- use_module(inclpr_natural_interval_extension, [ n_i_e_create_base_form/3, n_i_e_create_partial_evaluation/4, n_i_e_create_full_evaluation/4, n_i_e_create_direct_full_evaluation/3 ]). :- chr_constraint check/8. :- chr_option(debug,off). :- chr_option(optimize,full). :- chr_option(toplevel_show_store,off). % Module implementing consistency checking and domain narrowing for % box-consistency. % check(IE,FunctionPartialEvaluation,DerivativePartialEvaluation,Relation, % Variable,Interval,Direction,NewInterval) % % Checks whether the constraint 0 with % the partial evaluation of and % the partial evaluation of the derivative of % , is box-consistent with respect to variable and domain % of = in direction . is either % the atom `lower' or the atom `upper' and represents which bound of % is checked. is either =, =< or >=. If it is not box-consistent, % domain narrowing is applied until reaching box-consistency. The resulting % new domain is returned in . check(IE,FPE,DPE,Rel,V,Interval,Direction,NewInterval) <=> minimal_interval(Direction,Interval,Int), ( check_projection(Rel,IE,FPE,V,Int) -> NewInterval = Interval ; narrow(IE,FPE,DPE,Rel,V,Interval,Direction,Result) -> ( Direction == lower -> Interval = i(LOld,U), Result = i(L,_), F is L - LOld ; Interval = i(L,UOld), Result = i(_,U), F is UOld - U ), NewInterval = i(L,U) ). % narrow(IE,FunctionPartialEvaluation,DerivativePartialEvaluation,Relation, % Variable,Interval,Direction,Result) % % Narrows the domain of variable to reach box-consistency % for the constraint 0 with % the partial evaluation of and the % partial evaluation of the derivative of and in the direction % . is either the atom `lower' or the atom `upper' and % represents which bound of is narrowed. is either =, =< % or >=. The resulting new domain is returned in . narrow(IE,FPE,DPE,Rel,V,Interval,Direction,Result) :- interval_newton(IE,FPE,DPE,V,Interval,Answer), ( Answer = r(NewInterval) -> narrow(IE,FPE,DPE,Rel,V,NewInterval,Direction,Result) ; Answer = nr(Code) -> ( accepted_solution_domain(Interval) -> check_projection((=),IE,FPE,V,Interval), Result = Interval ; minimal_interval(Direction,Interval,MInt), check_projection((=),IE,FPE,V,MInt) -> Result = Interval ; ( Code == d -> eq_subdivide(Interval,Left,Right) ; uneq_subdivide(Direction,Interval,Left,Right) ), ( Direction == lower -> ( check_projection((=),IE,FPE,V,Left), narrow(IE,FPE,DPE,Rel,V,Left,lower,Result) -> true ; check_projection((=),IE,FPE,V,Right), narrow(IE,FPE,DPE,Rel,V,Right,lower,Result) ) ; ( check_projection((=),IE,FPE,V,Right), narrow(IE,FPE,DPE,Rel,V,Right,upper,Result) -> true ; check_projection((=),IE,FPE,V,Left), narrow(IE,FPE,DPE,Rel,V,Left,upper,Result) ) ) ) ; Answer = sr(Left,Right), ( Direction == lower -> ( check_projection((=),IE,FPE,V,Left), narrow(IE,FPE,DPE,Rel,V,Left,lower,Result) -> true ; check_projection((=),IE,FPE,V,Right), narrow(IE,FPE,DPE,Rel,V,Right,lower,Result) ) ; ( check_projection((=),IE,FPE,V,Right), narrow(IE,FPE,DPE,Rel,V,Right,upper,Result) -> true ; check_projection((=),IE,FPE,V,Left), narrow(IE,FPE,DPE,Rel,V,Left,upper,Result) ) ) ). % check_projection(Relation,IE,PartialEvaluation,Variable,Domain) % % Checks whether the full evaluation of with respect to % and , generated by get_full_evaluation/5, satisfies the % constraint 0. with one of =, =< and % >=. check_projection((=),IE,PE,V,D) :- get_full_evaluation(IE,PE,V,D,FE), interval_new_class(FE,z). check_projection((=<),IE,PE,V,D) :- get_full_evaluation(IE,PE,V,D,FE), \+ interval_new_class(FE,p). check_projection((>=),IE,PE,V,D) :- get_full_evaluation(IE,PE,V,D,FE), \+ interval_new_class(FE,n). % max_reduced(IE,BaseForm,Variables) % % Checks whether the domains of the variables in can be reduced by % domain narrowing with respect to the constraint with base form by % looking at the width of the full evaluation of with respect to % interval extension . This creates a stopping criterion for constraints % for which the derivative is near zero at a wide range around the solution % points. max_reduced(IE,BF,BFV) :- get_direct_full_evaluation(IE,BF,BFV,FE), accepted_solution_domain(FE). % get_full_evaluation(IE,PartialEvaluation,Variable,Domain,FullEvaluation) % % Computes the full evaluation of with respect to % and using create_full_evaluation/5, stores the resulting % interval in a nonbacktrackable way and backtracks the evaluation. This % enables us to use the partial evaluation multiple times. The resulting % interval is returned in . get_full_evaluation(IE,PE,V,D,FE) :- ( create_full_evaluation(IE,PE,V,D,FE), nb_setval(inclpr_eval,FE), fail ; nb_getval(inclpr_eval,FE), nb_delete(inclpr_eval) ). % get_direct_full_evaluation(IE,BaseForm,Variables,FullEvaluation) % % Computes the full evaluation of with variables by % using create_direct_full_evaluation/4, stores the resulting interval in a % nonbacktrackable way and backtracks the evaluation. This enables us to use % the base form multiple times. The resulting interval is returned in % . get_direct_full_evaluation(IE,BF,BFV,FE) :- ( create_direct_full_evaluation(IE,BF,BFV,FE), nb_setval(inclpr_eval,FE), fail ; nb_getval(inclpr_eval,FE), nb_delete(inclpr_eval) ). % create_base_form(IE,Function,BaseForm,Variables) % % Creates a base form for the interval extension denoted by of function % and returns it into . The variables of are % returned in . create_base_form(n,Term,BF,BFV) :- n_i_e_create_base_form(Term,BF,BFV). % create_partial_evaluation(IE,BaseForm,Variables,PartialEvaluation,Variable) % % Creates a partial evaluation of the interval extension % denoted by with base form . The variables of the function for % which is the base form, are in . A partial evaluation % consists of unifying all domain aliases by the domain of the related % variable and all center aliases by the center of the domain of the related % variable except for the variable . Partial evaluations are used % to speed up domain narrowing and consistency checking. create_partial_evaluation(n,BF,BFV,PE,V) :- n_i_e_create_partial_evaluation(BF,BFV,PE,V). % create_full_evaluation(IE,PartialEvaluation,Variable,Domain,FullEvaluation) % % Creates a full evaluation (i.e. an interval) of the interval % extension denoted by with partial evaluation . This % is done by unifying the domain alias and the center alias of variable % by and the center of respectively. create_full_evaluation(n,PE,V,D,FE) :- n_i_e_create_full_evaluation(PE,V,D,FE). % create_direct_full_evaluation(IE,BaseForm,Variables,FullEvaluation) % % Creates a full evaluation (i.e. an interval) of the interval % extension denoted by with base form . The variables of the % function for which is the base form, are in . All % domain aliases and center aliases of the variables in are % unified by the domain respectively the center of the domain of the related % variable. Direct full evaluations are used for inverted constraints which do % not benefit from partial evaluations. create_direct_full_evaluation(n,BF,BFV,FE) :- n_i_e_create_direct_full_evaluation(BF,BFV,FE). % instantiate_nat(VariableList,Variable) % % Instantiates all domain aliases of the variables in by the % domain of the respective variable except for the alias for variable % . This is specific for interval extensions that do are not based on % center values like the natural interval extension. instantiate_nat([],_). instantiate_nat([H|T],Var) :- ( Var == H -> instantiate_nat(T,Var) ; get_attr(H,inclpr_aliases,cd(_,D)), get_attr(H,inclpr_domain,D), instantiate_nat(T,Var) ). % instantiate_all_nat(VariableList) % % Instantiates all domain aliases of the variables in by the % domain of the respective variable. This is specific for interval extensions % that do are not based on center values like the natural interval extension. instantiate_all_nat([]). instantiate_all_nat([H|T]) :- get_attr(H,inclpr_aliases,cd(_,D)), get_attr(H,inclpr_domain,D), instantiate_all_nat(T).