Class: AppMath::Iv

Inherits:
Object
  • Object
show all
Defined in:
lib/interval.rb

Overview

Class of real closed intervals. In most applications of intervals it is an advantage if single real values can be considered as intervals of length zero. This is possible only for closed intervals, and this is the rational for defining those in preference to open intervals. With the attributes @low and @upp, the values x which belong to interval are characterized by the formula

@low <= x <= @upp .

Hence the interval is empty (void) iff @low > @upp.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*arg) ⇒ Iv

Allowed are 0, 1, 2 arguments, which all have to be convertible to R. For no argument the empty interval is created. For one argument, an second argument 0 is understood. For two arguments, these are the boundaries of the interval and the order on input does not matter:

iv1 = Iv.new(2,3); iv2 = Iv.new(3,2)

are thus the same, non-empty, interval, which in mathematical notation would be

[2,3]

Finally

iv3 = Iv.new

is an empty interval.



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/interval.rb', line 60

def initialize(*arg)
  n = arg.size
  case n
  when 0
    @low = R.c1
    @upp = R.c0 # notice: epmpty since @low > @upp
  when 1
    x = R.c arg[0] 
    zero = R.c0
    if x < zero
      @low = x
      @upp = zero
    else
      @upp = x
      @low = zero
    end
  when 2
    x = R.c arg[0]
    y = R.c arg[1]
    if x < y
      @low = x
      @upp = y
    else
      @low = y 
      @upp = x
    end
  else
      fail "Iv.new takes 0 or 1 or 2 arguments, but not " + n.to_s
  end # case n
end

Instance Attribute Details

#lowObject (readonly)

Returns the value of attribute low.



47
48
49
# File 'lib/interval.rb', line 47

def low
  @low
end

#uppObject (readonly)

Returns the value of attribute upp.



47
48
49
# File 'lib/interval.rb', line 47

def upp
  @upp
end

Class Method Details

.from_array(anArray) ⇒ Object

using max and min of an array for defining an interval.

The values of the array components are then known to belong to
to a closed interval. The smallest such interval is what
his method returns.


97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/interval.rb', line 97

def Iv.from_array(anArray)
  n = anArray.size
  case n
  when 0
    Iv.new
  when 1 
    a0 = anArray[0]
    Iv.new(a0)
  else
    x0 = anArray[0]
    x1 = x0
    anArray.each{ |x|
      if x < x0 
        x0 = x
      elsif x > x1
        x1 = x
      else
      end
    }
    Iv.new(x0,x1)
  end
end

Instance Method Details

#&(anIv) ⇒ Object

section, intersection meet or g.l.b (greatest lower bound) in lattice terminology



224
225
226
227
228
229
230
# File 'lib/interval.rb', line 224

def &(anIv)
  return Iv.new if empty? || anIv.empty?
  return Iv.new if @upp < anIv.low || @low > anIv.upp
  amin = Basics.sup(@low, anIv.low)
  amax = Basics.inf(@upp, anIv.upp)
  Iv.new(amin, amax)
end

#*(a) ⇒ Object

multiplying size by a, while preserving the center



218
219
220
# File 'lib/interval.rb', line 218

def *(a)
  Iv.new(center-(center-@low)*a,center+(@upp-center)*a)
end

#+(a) ⇒ Object

shifting by a



215
# File 'lib/interval.rb', line 215

def +(a); Iv.new(@low + a,@upp + a); end

#axis_division(anPosInteger) ⇒ Object

The function creates a suitable axis sub-division for data ranging from @low to @upp. Let res be the return value of the function. Then res is a proposal for the difference between adjacent axis tics and res is an array of the values to which the proposed tics belong. Thus res.first <= @low and res.last >= @upp. All numbers are chosen such that they are simple when written down in normal scientific notation and the intention is to simulate the considerations that determine the axis subdivision of reasonable manually created diagrams. The argument of the function is a proposal for the number of tics to be used. Values from 5 to 10 are reasonable. To have a simple logic, we simply enforce that the interval between tics is a simple number. The initial and the final number of the axis division is chosen as an integer multiple of this inter-tic interval.



250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'lib/interval.rb', line 250

def axis_division(anPosInteger)
  fail "can't divide an empty interval" if empty?
  a = @low
  b = @upp
  n = anPosInteger.abs
  n += 1 if n == 0
  d = size/n
  d_ = Basics.cut(d) # this is the essential point
  fail "Zero division in function axis_division" if d_ == 0.0
  d_inv=d_.inv;
  epsilon = R.c 1e-6
  k_b=(b*d_inv - epsilon).ceil
    # without the epsilon correction it depends on roundoff 
    # errors whether b_ becomes too large
  k_a=(a*d_inv + epsilon).floor
    # without the epsilon correction it depends on roundoff 
    # errors whether a_ becomes too small
  b_=k_b * d_
  b__ = (k_b - 0.5) * d_
  a_=k_a * d_
  res=Array.new
  while a_ < b__
    res << a_
    a_ += d_
  end
  res << b_ # we know the last item exactly, and should
    # not spoil it by arithmetic errors
  [ d_ , res ]
end

#centerObject

Returns the midpoint of the interval.



169
170
171
172
# File 'lib/interval.rb', line 169

def center
  nil if empty?
  (@low + @upp) * R.i2
end

#empty?Boolean

Returns true iff the interval is empty

Returns:

  • (Boolean)


152
# File 'lib/interval.rb', line 152

def empty?; @low > @upp; end

#ind(x) ⇒ Object

Indicator function. Returns true if the point x belongs to self and false else.



182
183
184
185
186
187
# File 'lib/interval.rb', line 182

def ind(x)
  return false if empty?
  return false if x > @upp
  return false if x < @low
  true
end

#infObject

Returns the lower boundary if self is not empty and nil else.



156
157
158
159
# File 'lib/interval.rb', line 156

def inf
  return nil if empty?
  @low
end

#met_ind(x) ⇒ Object

Metrical indicator function. Returns the distance of x from the set self if x is outside of self. If it is inside, the return value is minus the distance to the complement of self (which is not an interval but a well-defined set).



193
194
195
196
197
198
# File 'lib/interval.rb', line 193

def met_ind(x)
  return nil if empty?
  y = R.c x
  dc = (y - center).abs
  dc - size * R.i2
end

#put(p) ⇒ Object

Returns a real number, which is self’s lower end for p == 0.0, self’s center for p == 0.5, and self’s upper end for p == 1.0 .



202
203
204
# File 'lib/interval.rb', line 202

def put(p)
  inf + size * p
end

#sizeObject

Returns the length of the interval, 0 for the empty one



175
176
177
178
# File 'lib/interval.rb', line 175

def size
  s = @upp - @low
  s >= R.c0 ? s : R.c0
end

#supObject

Returns the upper boundary if self is not empty and nil else.



163
164
165
166
# File 'lib/interval.rb', line 163

def sup
  return nil if empty?
  @upp
end

#to_array(a) ⇒ Object

Returns an ordered equidistant array of n numbers, where the first one is @low and the last one is @upp. The positive integer n is made from the argument a in a way which depends on whether this argument is integer or not. In the first case it is taken as n and in the second case, the argment is taken as a proposal for the lattice spacing. The actual lattice spacing will be chosen as a fraction of size.



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/interval.rb', line 126

def to_array(a)
  return nil if empty?
  if a.integer? # then we interpret the argument as an intended number
    # of lattice points
    n = a
  else # then we interprete the argument as an intended lattice spacing
    d = a.abs
    fail "can't build a lattice with spacing 0" if d.zero?
    n = (size/d).round + 1
  end
  fail "number of lattice points must be larger than 1" if n < 2
  res = Array.new
  res << @low
  if n > 2
    na = n - 2
    d = size / (n-1)
    x = @low
    for i in 1..na
      x += d
      res << x
    end
  end
  res << @upp
end

#to_sObject



232
233
234
# File 'lib/interval.rb', line 232

def to_s
  "Iv (" + @low.to_s + "," + @upp.to_s + ")"
end

#|(anIv) ⇒ Object

minimum closed interval that contains the union join or l.u.b. (lowest upper bound) in lattice terminology



208
209
210
211
212
# File 'lib/interval.rb', line 208

def |(anIv)
  return anIv if empty?
  return self if anIv.empty?
  Iv.from_array [@low, @upp, anIv.low, anIv.upp]
end