Class: SY::Composition
- Inherits:
-
Hash
- Object
- Hash
- SY::Composition
- 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 { |ꜧ, args| if args.keys.include? [:name] || args.keys.include?( :ɴ ) then ɴ = args.delete( :name ) || args.delete( :ɴ ) # won't cache name ꜧ[args].tap { |ɪ| ɪ.name = ɴ } # recursion elsif args.keys.include? :mapping then ᴍ = args.delete( :mapping ) # won't cache mapping ꜧ[args].tap { |ɪ| ɪ.set_mapping ᴍ } # recursion elsif args.keys.include? :relative then ʀ = args.delete( :relative ) ? true : false # won't cache :relative ꜧ[args].send ʀ ? :relative : :absolute # recursion else cᴍ = SY::Composition[ args ].simplify ꜧ[args] = if cᴍ != args then ꜧ[ cᴍ ] # recursion while #simplify else x = cᴍ. # we'll try to #expand now if x != cᴍ then ꜧ[ x ] # recursion while #expand else if x.empty? then # use std. ∅ quantity SY.Dimension( :∅ ).standard_quantity elsif x.singular? then x.first[0] # unwrap the quantity else # create new quantity SY::Quantity.new composition: x end end end end }
Class Method Summary collapse
Instance Method Summary collapse
-
#*(number) ⇒ Object
Multiplication by a number.
-
#+(other) ⇒ Object
Merges two compositions.
-
#+@ ⇒ Object
Returns a new instance with same hash.
-
#-(other) ⇒ Object
Subtracts two compositions.
-
#-@ ⇒ Object
Negates hash exponents.
-
#/(number) ⇒ Object
Division by a number.
-
#atomic? ⇒ Boolean
Atomic compositions are singular compositions, whose quantity dimension is a base dimension.
-
#coerces?(other) ⇒ Boolean
Whether this composition coerces another compotision.
-
#dimension ⇒ Object
Dimension of a composition is the sum of its member quantities’ dimensions.
-
#expand ⇒ Object
Try to simplify the composition by decomposing its quantities.
-
#infer_measure ⇒ Object
Infers the measure of the composition’s quantity.
-
#irreducible? ⇒ Boolean
Whether it is possible to expand this.
-
#new_quantity(args = {}) ⇒ Object
Directly (without attempts to simplify) creates a new quantity from self.
-
#simple? ⇒ Boolean
Simple composition is one that is either empty or singular.
-
#simplify ⇒ Object
Simplifies a quantity hash by applying simplification rules.
-
#singular? ⇒ Boolean
Singular compositions consist of only one quantity.
-
#to_quantity(args = {}) ⇒ Object
Returns the quantity appropriate to this composition.
Class Method Details
.empty ⇒ Object
88 89 90 |
# File 'lib/sy/composition.rb', line 88 def empty self[] end |
.singular(quantity) ⇒ Object
84 85 86 |
# File 'lib/sy/composition.rb', line 84 def singular quantity self[ SY.Quantity( quantity ) => 1 ] end |
Instance Method Details
#*(number) ⇒ Object
Multiplication by a number.
191 192 193 |
# File 'lib/sy/composition.rb', line 191 def * number self.class[ self.with_values do |v| v * number end ] end |
#+(other) ⇒ Object
Merges two compositions.
179 180 181 |
# File 'lib/sy/composition.rb', line 179 def + other self.class[ self.merge( other ) { |_, v1, v2| v1 + v2 } ] end |
#+@ ⇒ Object
Returns a new instance with same hash.
167 168 169 |
# File 'lib/sy/composition.rb', line 167 def +@ self.class[ self ] end |
#-(other) ⇒ Object
Subtracts two compositions.
185 186 187 |
# File 'lib/sy/composition.rb', line 185 def - other self + -other end |
#-@ ⇒ Object
Negates hash exponents.
173 174 175 |
# File 'lib/sy/composition.rb', line 173 def -@ self.class[ self.with_values do |v| -v end ] end |
#/(number) ⇒ Object
Division by a number.
197 198 199 200 201 202 203 |
# File 'lib/sy/composition.rb', line 197 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.
132 133 134 135 136 |
# File 'lib/sy/composition.rb', line 132 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.
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/sy/composition.rb', line 140 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 |
#dimension ⇒ Object
Dimension of a composition is the sum of its member quantities’ dimensions.
231 232 233 |
# File 'lib/sy/composition.rb', line 231 def dimension map { |qnt, exp| qnt.dimension * exp }.reduce SY::Dimension.zero, :+ end |
#expand ⇒ Object
Try to simplify the composition by decomposing its quantities.
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
# File 'lib/sy/composition.rb', line 266 def return self if irreducible? puts "#expand: #{self} not irreducible" if SY::DEBUG self.class[ reduce( self.class.empty ) { |cᴍ, pair| qnt, exp = pair puts "#expand: qnt: #{qnt}, exp: #{exp}" if SY::DEBUG puts "cᴍ is #{cᴍ}" if SY::DEBUG ( cᴍ + if qnt.irreducible? then self.class.singular( qnt ) * exp else qnt.composition * exp end.tap { |x| puts "Adding #{x}." if SY::DEBUG } ).tap { |x| puts "Result is #{x}." if SY::DEBUG } } ] .tap{ |rslt| puts "#expand: result is #{rslt}" if SY::DEBUG } end |
#infer_measure ⇒ Object
Infers the measure of the composition’s quantity. (‘Measure’ means measure of the pertinent standard quantity.)
238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
# File 'lib/sy/composition.rb', line 238 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
260 261 262 |
# File 'lib/sy/composition.rb', line 260 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.
225 226 227 |
# File 'lib/sy/composition.rb', line 225 def new_quantity args={} SY::Quantity.new args.merge( composition: self ) end |
#simple? ⇒ Boolean
Simple composition is one that is either empty or singular.
255 256 257 |
# File 'lib/sy/composition.rb', line 255 def simple? empty? or singular? end |
#simplify ⇒ Object
Simplifies a quantity hash by applying simplification rules.
207 208 209 210 211 212 |
# File 'lib/sy/composition.rb', line 207 def simplify ꜧ = self.to_hash puts "simplifying #{ꜧ}" if SY::DEBUG SIMPLIFICATION_RULES.each { |rule| rule.( ꜧ ) } self.class[ ꜧ ].tap { |_| puts "result is #{_}" if SY::DEBUG } end |
#singular? ⇒ Boolean
Singular compositions consist of only one quantity.
125 126 127 |
# File 'lib/sy/composition.rb', line 125 def singular? size == 1 && first[1] == 1 end |
#to_quantity(args = {}) ⇒ Object
Returns the quantity appropriate to this composition.
216 217 218 219 |
# File 'lib/sy/composition.rb', line 216 def to_quantity args={} # All the work is delegated to the quantity table: QUANTITY_TABLE[ args.merge( self ) ] end |