In passing, Ben also cryptically comments: "By testing the signs of the endpoints of the intervals, it is possible to break
mul-interval
into nine cases, only one of which requires more than two multiplications."' Rewrite this procedure using Ben's suggestion.Okay, so here Ben is suggesting that we don't need to calculate all of {
p1
, p2
, p3
, p4
} in order to calculate mul-interval
. Instead by looking at the signs of the lower and upper bounds of the two intervals it is possible, in the majority of cases, to know which two of {p1
, p2
, p3
, p4
} to use as the lower and upper bounds and so only need to calculate those. However, before we can produce such a procedure we need to determine the mapping from signs of bounds of intervals to pairs.Before we get into that though, in order to simplify the discussion here I'm going to introduce a shorthand for refering to lower and upper bounds of intervals: for any interval x I'm going to use lx to represent the lower bound of the interval and ux to represent the upper bound. I'll also note that the set of values {
p1
, p2
, p3
, p4
} corresponds to the set of products {lxly, lxuy, uxly, uxuy}. I'm going to use the latter in this discussion as we will no longer calculate the former set up front in the final procedure.Now, back to determining the mapping from signs of bounds of intervals to pairs... In order to do this we must first consider not just the signs of the bounds but also the relationship between their absolute values. We can easily show this to be important if we consider multiplying a pair of intervals where the bounds are all non-negative (non-negative intervals) and then compare this to multiplying a pair of intervals where the bounds are all negative (negative intervals):
- In the former case we know that lx and ly are the two smallest values from the two intervals and ux and uy are the two largest values from the two intervals. As a result we can deduce that lxly will be the minimum of the four values in the set, while uxuy will be the maximum.
- Looking at the latter case we can first observe that all four values in the set will be positive (as each value is the result of multiplying two negative numbers). However, looking at the absolute values of the bounds we can see that lx and ly have the two largest absolute values and ux and uy have the two smallest absolute values. As a result we can deduce that uxuy will be the minimum of the four values in the set, while lxly will be the maximum.
When we have a mixture of types of intervals things become slightly more complex, but there's an additional technique we can add to considering the signs and absolute values. Note that it is always possible to split up the set {lxly, lxuy, uxly, uxuy} into two subsets: one containing all the negative values and the other containing all the non-negative values. When there are a mixture of interval types (e.g. one is a negative interval, the other is a non-negative interval, or one is a non-negative interval and the other is a zero-spanning interval (where the lower bound is negative and the upper bound is non-negative)) we are guaranteed that both subsets will be non-empty. In such cases the lower bound will then be the value with the largest absolute value from the set of negative values, while the upper bound will be the value with the largest absolute value from the set of positive values.
For example, let's consider the case where the interval x spans zero and interval y is non-negative:
- In this case we can see that any value in the set that is a multuple of lx will be negative, while any value in the set that is a multuple of ux will be positive. This gives us our two subsets:
- {lxly, lxuy} contains the negative values.
- {uxly, uxuy} contains the non-negative values.
However, as Ben hinted, there's one case that we can't determine in this manner. It's the case when we have two zero-spanning intervals. In this case our two subsets are:
- {lxuy, uxly} for the negative values.
- {lxly, uxuy} for the non-negative values.
Okay, so let's work through each of the valid combinations of signs for the lower and upper bounds of x and y and determine how to calculate the lower and upper values for the result of multiplying x and y. I say "valid" as we need to remember that the lower bound is always less than or equal to the upper bound, so we'll never encounter an interval where the upper bound is negative, while the lower bound is non-negative. N.B. In the following table I'm using -ve to indicate a negative value and +ve to represent a non-negative value.
lx | ux | ly | uy | lxly | lxuy | uxly | uxuy | min | max |
---|---|---|---|---|---|---|---|---|---|
+ve | +ve | +ve | +ve | +ve | +ve | +ve | +ve | lxly | uxuy |
+ve | +ve | -ve | +ve | -ve | +ve | -ve | +ve | uxly | uxuy |
+ve | +ve | -ve | -ve | -ve | -ve | -ve | -ve | uxly | lxuy |
-ve | +ve | +ve | +ve | -ve | -ve | +ve | +ve | lxuy | uxuy |
-ve | +ve | -ve | +ve | +ve | -ve | -ve | +ve | min(lxuy,uxly) | max(lxly,uxuy) |
-ve | +ve | -ve | -ve | +ve | +ve | -ve | -ve | uxly | lxly |
-ve | -ve | +ve | +ve | -ve | -ve | -ve | -ve | lxuy | uxly |
-ve | -ve | -ve | +ve | +ve | -ve | +ve | -ve | lxuy | lxly |
-ve | -ve | -ve | -ve | +ve | +ve | +ve | +ve | uxuy | lxly |
Now we now know how to calculate the lower and upper bounds, here's my procedure for doing so:
(define (mul-interval x y) (define not-negative? (lambda (x) (not (negative? x)))) (let ((lx (lower-bound x)) (ux (upper-bound x)) (ly (lower-bound y)) (uy (upper-bound y))) (cond ((and (not-negative? lx) (not-negative? ux) (not-negative? ly) (not-negative? uy)) (make-interval (* lx ly) (* ux uy))) ((and (not-negative? lx) (not-negative? ux) (negative? ly) (not-negative? uy)) (make-interval (* ux ly) (* ux uy))) ((and (not-negative? lx) (not-negative? ux) (negative? ly) (negative? uy)) (make-interval (* ux ly) (* lx uy))) ((and (negative? lx) (not-negative? ux) (not-negative? ly) (not-negative? uy)) (make-interval (* lx uy) (* ux uy))) ((and (negative? lx) (not-negative? ux) (negative? ly) (not-negative? uy)) (make-interval (min (* lx uy) (* ux ly)) (max (* lx ly) (* ux uy)))) ((and (negative? lx) (not-negative? ux) (negative? ly) (negative? uy)) (make-interval (* ux ly) (* lx ly))) ((and (negative? lx) (negative? ux) (not-negative? ly) (not-negative? uy)) (make-interval (* lx uy) (* ux ly))) ((and (negative? lx) (negative? ux) (negative? ly) (not-negative? uy)) (make-interval (* lx uy) (* lx ly))) ((and (negative? lx) (negative? ux) (negative? ly) (negative? uy)) (make-interval (* ux uy) (* lx ly))) (else (error "Invalid Combination!")))))Finally, we can see this in action:
> (mul-interval (make-interval 1 2) (make-interval 2 3)) '(2 . 6) > (mul-interval (make-interval 1 2) (make-interval -2 3)) '(-4 . 6) > (mul-interval (make-interval 1 2) (make-interval -2 -1)) '(-4 . -1) > (mul-interval (make-interval -1 2) (make-interval 2 3)) '(-3 . 6) > (mul-interval (make-interval -1 2) (make-interval -2 3)) '(-4 . 6) > (mul-interval (make-interval -1 2) (make-interval -2 -1)) '(-4 . 2) > (mul-interval (make-interval -2 -1) (make-interval 2 3)) '(-6 . -2) > (mul-interval (make-interval -2 -1) (make-interval -2 3)) '(-6 . 4) > (mul-interval (make-interval -2 -1) (make-interval -2 -1)) '(1 . 4)
No comments:
Post a Comment