Re: [eclipse-clp-users] Out of range error

From: Mick Hallward <mick1792_at_...75...>
Date: Fri, 3 Dec 2010 10:55:20 -0800 (PST)
Dear Joachim,

Many thanks for the prompt reply, which was very helpful.
Due to the nature of the problem, I cannot impose initial 
bounds to the variables (these are not generally known
ahead of time), so I'm inclined to go with the second option,
the use of propia. My only concern is the replacement of
"or" with the semicolon operator. I need to deal with
arbitrary boolean constraints, potentially containing 
negations of disjunctions, and I'm not sure if that's
compatible with the "infers ic" syntax. In fact I tried
it but it doesn't seem to work, e.g. with the definition
foo(X) :-
    ((X #>= 20 and X #=< 20) or (X #>= 100,X #=< 150)) infers ic,
    labeling([X]).
the query foo(A) gives the same error: "out of range in 
indomain(A{-1.0Inf .. 1.0Inf})". 

While I could put the boolean conditions in DNF and then 
use the semicolon operator as in your example, I'd rather not, 
since the transformation to DNF could take too long.

Any suggestions? Many thanks again! 

P.S. Sorry I can't reply to this thread directly, I'm unable
to join the users mailing list because my yahoo email
account is apparently deemed unsafe.


Mick Hallward wrote:
> Hi all,
> 
> I'm an Eclipse beginner with a simple (I hope :>) question.
> 
> With ic loaded, I define a constraint on X such that
> X is either in the 20..30 range or in the 100...150
> range:
> 
> foo(X) :- integers([X]), (X #>= 20 and X #=< 20) or 
>                        (X #>= 100 and X #=< 150), labeling([X]).
> 
> Now, I would expect a query like foo(A) to result in an
> answer like A = 20 or something like that - any value,
> really, that respects the constraints of foo. Yet the
> query results in the error:
> 
> "out of range in indomain(A{-1.0Inf .. 1.0Inf}) when evaluating 
> the query foo(A)."
> 
> I wonder why that is.


There are two things involved:

1. labeling/1 and indomain/1 refuse to enumerate infinite domains:

	?- integers([X]), labeling([X]).
	out of range in indomain(X{-1.0Inf .. 1.0Inf})
	Abort

2. or/2 is implemented via reified constraints which are not strong
   enough to extract finite bounds for X from your disjunction:

	?- X #>= 20 and X #=< 20 or X #>= 100 and X #=< 150.
	X = X{-1.0Inf .. 1.0Inf}
	There are 7 delayed goals.
	Yes (0.00s cpu)


One way to make it work is to add initial bounds to X:

foo(X) :-
    integers([X]), X :: 0..200,
    (X #>= 20 and X #=< 20) or (X #>= 100 and X #=< 150),
    labeling([X]).

?- foo(X).
X = 20
Yes (0.00s cpu, solution 1, maybe more)
X = 100
Yes (0.01s cpu, solution 2, maybe more)
X = 101
Yes (0.02s cpu, solution 3, maybe more)


An alternative solution is to use a stronger implementation for the
disjunctive constraint:

:- lib(ic).
:- lib(propia).

foo(X) :-
    (X #>= 20,X #=< 20 ; X #>= 100,X #=< 150) infers ic,
    labeling([X]).

?- foo(X).
X = 20
Yes (0.00s cpu, solution 1, maybe more)
X = 100
Yes (0.01s cpu, solution 2, maybe more)
X = 101
Yes (0.02s cpu, solution 3, maybe more)

This works because a finite domain is now inferred from the disjunction:

?- (X #>= 20, X #=< 20 ; X #>= 100, X #=< 150) infers ic.
X = X{[20, 100 .. 150]}
Yes (0.00s cpu)



-- Joachim







      
Received on Fri Dec 03 2010 - 19:02:08 CET

This archive was generated by hypermail 2.3.0 : Tue Apr 16 2024 - 09:13:20 CEST