Module: Setfu

Defined in:
lib/setfu.rb,
lib/setfu/version.rb

Overview

Version 3.1.0 and older

Constant Summary collapse

VERSION =
"3.1.0"

Class Method Summary collapse

Class Method Details

.bset_elements(ary) ⇒ Object



201
202
203
204
205
# File 'lib/setfu.rb', line 201

def self.bset_elements(ary)
  ary.count.times do |ii|
    ary[ii] = ary[ii].to_bset
  end
end

.find_tuple(ary, tup_size) ⇒ Object

assumes ary is comprised of sets



212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
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
279
280
281
# File 'lib/setfu.rb', line 212

def self.find_tuple(ary, tup_size)  # assumes ary is comprised of sets
  candidates = {}
  entropy = 0
  ary.count.times do |ii|
    entropy = ary[ii].entropy > entropy ? ary[ii].entropy : entropy
    unless ary[ii].setfu_count?
      ary[ii].setfu_count = ary[ii].count  # store this as #count is slow
    end
    next unless ary[ii].setfu_count == tup_size
    tup = ary[ii].to_i  # integer keys are good Hash keys, BitSets are not
    candidates[tup] = 0  # store integer version of set in candidate hash if size matches
    ary.count.times do |jj|
      candidates[tup] +=1 if ary[ii]==ary[jj]  # vote count each match
    end
  end
  valid = []
  error = []
  candidates.each_pair do |key,val|
    bset = BitSet.new
    bset.set_bits!(key)
    bset.entropy=entropy
    if val==tup_size
      bset.setfu_tag
      valid.push bset
    elsif val>tup_size
      error.push bset
    end
  end
  group = []
  ary.count.times do |ii|
    next if ary[ii].setfu_tag?
    next if ary[ii].setfu_count > tup_size
    next if ary[ii] <= valid
    next if ary[ii] <= error
    group.push ary[ii]
  end
  
  if (tup_size >=3) && (group.count >= tup_size)  # stardard match finds smaller things ...
    ptup = []
    group.combination(tup_size) do |combo|
      ta = combo.to_bset
      next unless ta.count == tup_size
      next if ta <= error
      if ta <= ptup  # we have an error! There can only be one tuple
        pp = []
        ptup.count.times do |ii|
          pp.push ptup[ii] unless ta==ptup[ii]
        end
        ptup = pp
        error.push ta
      else
        ptup.push ta
      end
    end    
    valid.concat ptup
  end
  
  # ok everything is in the bin ... what about the shorts of the previous calls?
  # let's just mark what we know for next time ...
  ary.count.times do |ii|
    next if ary[ii].setfu_tag?
    if ary[ii] <= valid
      ary[ii].setfu_tag = :valid
    elsif ary[ii] <= error
      ary[ii].setfu_tag = :error
    end
  end
  
  return [valid,error]
end

.reduce(ary) ⇒ Object



306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
# File 'lib/setfu.rb', line 306

def self.reduce(ary)
  elms = ary.count
  # process tupples ... first check for errors
  tups = tuples(ary)
  unless (tups.last.empty?)
    ary.setfu_tag = tups.last  # tag with broken set items
    return -1  # can't reduce a system of errors
  end
  if (tups.first.empty?)
    return 0
  end
  tups = tups[0].reverse  # we only need the good ones.
  reductions = 0
  loop do
    tup = tups.pop    
    elms.times do |idx|
      if (tup ** ary[idx]) && !(ary[idx] <= tup)
        ary[idx] -= tup
        reductions += 1
      end
    end
    break if tups.empty?
  end
  return reductions
end

.tuple(ary) ⇒ Object

returns the tuple, else nil



333
334
335
336
337
338
339
340
341
342
343
344
345
# File 'lib/setfu.rb', line 333

def self.tuple(ary)
  tup = ary.to_bset
  return nil unless tup.size==ary.count
  return tup if ary.size == 1 # trivial case
  if ary.size==2
    return tup if ary.first==ary.last
  end
  ary.count.times do |idx|
    ta = ary - [ary[idx]]
    return nil if tuple?(ta)
  end
  return tup
end

.tuple?(ary) ⇒ Boolean

the whole thing must be a tuple else false

Returns:

  • (Boolean)


348
349
350
351
352
353
354
355
356
357
358
359
360
361
# File 'lib/setfu.rb', line 348

def self.tuple?(ary)  # from documentation
  return false if ary.empty?
  tup = ary.to_bset
  return false unless tup.size==ary.count
  return true if ary.size == 1 # trivial case
  if ary.size==2
    return true if ary.first==ary.last
  end
  ary.count.times do |idx|
    ta = ary - [ary[idx]]
    return false if tuple?(ta)
  end
  return true
end

.tuples(ary) ⇒ Object

errors include empty sets



283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
# File 'lib/setfu.rb', line 283

def self.tuples(ary)  # errors include empty sets
  src = []
  valid = []
  error = []
  ary.each do |bs|
    if bs.empty?
      error.setfu_push_unique bs
    else
      src.push bs  
    end
  end
  src.count.times do |tup_no|
    rslt = find_tuple(src, tup_no)
    valid.concat rslt[0]
    error.concat rslt[1] # was 2 ... but removed short
  end
  src.count.times do |idx|
    next if src[idx] <= valid
    next if src[idx] <= error
  end
  return [valid,error] if true
end

.untag_bset_elements(ary) ⇒ Object



206
207
208
209
210
211
# File 'lib/setfu.rb', line 206

def self.untag_bset_elements(ary)
  ary.count.times do |ii|
    ary[ii].remove_instance_variable :@bo_setfu_tag rescue :never_mind
    ary[ii].remove_instance_variable :@bo_setfu_count rescue :never_mind
  end
end