Class: SY::Composition

Inherits:
Hash
  • Object
show all
Defined in:
lib/sy/composition.rb

Overview

Composition of quantities.

Constant Summary collapse

SR =

Simplification rules for quantity combinations.

SIMPLIFICATION_RULES = []
QUANTITY_TABLE =

Cache for quantity construction.

Hash.new { |

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.emptyObject



65
66
67
# File 'lib/sy/composition.rb', line 65

def empty
  self[]
end

.singular(quantity) ⇒ Object



61
62
63
# File 'lib/sy/composition.rb', line 61

def singular quantity
  self[ SY.Quantity( quantity ) => 1 ]
end

Instance Method Details

#*(number) ⇒ Object

Multiplication by a number.



168
169
170
# File 'lib/sy/composition.rb', line 168

def * number
  self.class[ self.with_values do |v| v * number end ]
end

#+(other) ⇒ Object

Merges two compositions.



156
157
158
# File 'lib/sy/composition.rb', line 156

def + other
  self.class[ self.merge( other ) { |_, v1, v2| v1 + v2 } ]
end

#+@Object

Returns a new instance with same hash.



144
145
146
# File 'lib/sy/composition.rb', line 144

def +@
  self.class[ self ]
end

#-(other) ⇒ Object

Subtracts two compositions.



162
163
164
# File 'lib/sy/composition.rb', line 162

def - other
  self + -other
end

#-@Object

Negates hash exponents.



150
151
152
# File 'lib/sy/composition.rb', line 150

def -@
  self.class[ self.with_values do |v| -v end ]
end

#/(number) ⇒ Object

Division by a number.



174
175
176
177
178
179
180
# File 'lib/sy/composition.rb', line 174

def / number
  self.class[ self.with_values do |val|
                    raise TErr, "Compositions with rational exponents " +
                      "not implemented!" if val % number != 0
                    val / number
                  end ]
end

#atomic?Boolean

Atomic compositions are singular compositions, whose quantity dimension is a base dimension.

Returns:

  • (Boolean)


109
110
111
112
113
# File 'lib/sy/composition.rb', line 109

def atomic?
  puts "composition is #{self}" if SY::DEBUG
  puts "first[0].dimension is #{first[0].dimension}" if SY::DEBUG
  singular? && first[0].dimension.base?
end

#coerces?(other) ⇒ Boolean

Whether this composition coerces another compotision.

Returns:

  • (Boolean)


117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/sy/composition.rb', line 117

def coerces? other
  # TODO: Think about caching. One way, ie. no way back, once something
  # coerces something else, so only false results would have to be re-checked,
  # and that only at most once each time after coerces / coerced_by method is
  # tampered.
  if singular? then
    other.singular? && self.first[0].coerces?( other.first[0] )
  else
    # simplify the compositions a bit
    rslt = [].tap do |ary|
      find { |qnt, e|
        other.find { |qnt2, e2|
          ( ( e > 0 && e2 > 0 || e < 0 && e2 < 0 ) && qnt.coerces?( qnt2 ) )
            .tap { |rslt| [] << qnt << qnt2 << ( e > 0 ? -1 : 1 ) if rslt }
        }
      }
    end
    # and ask recursively
    if rslt.empty? then return false else
      q, q2, e = rslt
      ( self + q.composition * e ).coerces? ( other + q2.composition * e )
    end
  end
end

#dimensionObject

Dimension of a composition is the sum of its member quantities’ dimensions.



208
209
210
# File 'lib/sy/composition.rb', line 208

def dimension
  map { |qnt, exp| qnt.dimension * exp }.reduce SY::Dimension.zero, :+
end

#expandObject

Try to simplify the composition by decomposing its quantities.



243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
# File 'lib/sy/composition.rb', line 243

def expand
  return self if irreducible?
  puts "#expand: #{self} not irreducible" if SY::DEBUG
  self.class[ reduce( self.class.empty ) { |c

#infer_measureObject

Infers the measure of the composition’s quantity. (‘Measure’ means measure of the pertinent standard quantity.)



215
216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'lib/sy/composition.rb', line 215

def infer_measure
  puts "#infer_measure; hash is #{self}" if SY::DEBUG
  map do |qnt, exp|
    puts "#infer_measure: doing quantity #{qnt} with exponent #{exp}!" if SY::DEBUG
    if qnt.standardish? then
      puts "#{qnt} standardish" if SY::DEBUG
      SY::Measure.identity
    else
      puts "#{qnt} not standardish" if SY::DEBUG
      puts "its measure is #{qnt.measure}, class #{qnt.measure.class}" if SY::DEBUG
      qnt.measure( of: qnt.standard ) ** exp
    end
  end.reduce( SY::Measure.identity, :* )
end

#irreducible?Boolean

Whether it is possible to expand this

Returns:

  • (Boolean)


237
238
239
# File 'lib/sy/composition.rb', line 237

def irreducible?
  all? { |qnt, exp| qnt.irreducible? }
end

#new_quantity(args = {}) ⇒ Object

Directly (without attempts to simplify) creates a new quantity from self. If self is empty or singular, SY::Amount, resp. the singular quantity in question is returned.



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

def new_quantity args={}
  SY::Quantity.new args.merge( composition: self )
end

#simple?Boolean

Simple composition is one that is either empty or singular.

Returns:

  • (Boolean)


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

def simple?
  empty? or singular?
end

#simplifyObject

Simplifies a quantity hash by applying simplification rules.



184
185
186
187
188
189
# File 'lib/sy/composition.rb', line 184

def simplify
  

#singular?Boolean

Singular compositions consist of only one quantity.

Returns:

  • (Boolean)


102
103
104
# File 'lib/sy/composition.rb', line 102

def singular?
  size == 1 && first[1] == 1
end

#to_quantity(args = {}) ⇒ Object

Returns the quantity appropriate to this composition.



193
194
195
196
# File 'lib/sy/composition.rb', line 193

def to_quantity args={}
  # All the work is delegated to the quantity table:
  QUANTITY_TABLE[ args.merge( self ) ]
end