quine_mc 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.DS_Store +0 -0
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Rakefile +1 -0
- data/bin/quine_mc +21 -0
- data/lib/quine_mc.rb +41 -0
- data/lib/quine_mc/.DS_Store +0 -0
- data/lib/quine_mc/cube.rb +39 -0
- data/lib/quine_mc/epi_list.rb +80 -0
- data/lib/quine_mc/pi_list.rb +59 -0
- data/lib/quine_mc/version.rb +3 -0
- data/quine_mc.gemspec +24 -0
- metadata +58 -0
data/.DS_Store
ADDED
Binary file
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/quine_mc
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'quine_mc'
|
3
|
+
|
4
|
+
puts "Welcome. This is Erik Formella's Quine McClusky Logic Minimizer."
|
5
|
+
puts
|
6
|
+
puts "Eneter the minterms of your function. Exclude dont cares"
|
7
|
+
|
8
|
+
minterms = gets.chomp
|
9
|
+
m_a = minterms.scan(/\d+/).map {|x| x.to_i}
|
10
|
+
|
11
|
+
puts "Now enter the don't cares please"
|
12
|
+
dont_cares = gets.chomp
|
13
|
+
dc_a = dont_cares.scan(/\d+/).map {|x| x.to_i}
|
14
|
+
|
15
|
+
solution = QuineMc::Quine_McClusky.new(m_a, dc_a)
|
16
|
+
puts
|
17
|
+
puts
|
18
|
+
puts "The solution for:"
|
19
|
+
print "f = m(", minterms, ") + d(", dont_cares, ") is:"
|
20
|
+
puts
|
21
|
+
solution.display_sol
|
data/lib/quine_mc.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require "quine_mc/version"
|
2
|
+
require 'quine_mc/epi_list'
|
3
|
+
|
4
|
+
module QuineMc
|
5
|
+
class Quine_McClusky
|
6
|
+
|
7
|
+
def initialize(m, d)
|
8
|
+
@nl = find_num_lit(m, d)
|
9
|
+
if (m+d) == (0..2**(@nl)-1).to_a or (m+d).empty?
|
10
|
+
@sop = []
|
11
|
+
@pos = []
|
12
|
+
else
|
13
|
+
maxterms = (0...2**@nl).to_a - (m+d)
|
14
|
+
@sop = EPi_List.new(m, d, @nl)
|
15
|
+
@pos = EPi_List.new(maxterms, d, @nl)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def find_num_lit(m, d)
|
20
|
+
return (m+d).max.to_s(2).size
|
21
|
+
end
|
22
|
+
|
23
|
+
def display_sol
|
24
|
+
if !@sop.empty? and !@pos.empty?
|
25
|
+
print "f = "
|
26
|
+
@sop.each do |t|
|
27
|
+
print (t == @sop.last)? t.to_prod(@nl) : t.to_prod(@nl)+" + "
|
28
|
+
end
|
29
|
+
puts
|
30
|
+
print "f = "
|
31
|
+
@pos.each do |t|
|
32
|
+
print t.to_sum(@nl)
|
33
|
+
end
|
34
|
+
puts
|
35
|
+
else
|
36
|
+
puts "f = 1"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
Binary file
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module QuineMc
|
2
|
+
class Cube < Array
|
3
|
+
|
4
|
+
def num_ones
|
5
|
+
n = inject {|m,o| m & o}
|
6
|
+
count = 0
|
7
|
+
count += n & 1 and n >>= 1 until n == 0
|
8
|
+
return count
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_prod(n_l)
|
12
|
+
ls = (n_l > 26)? (0..n_l).to_a.map {|n| n = "A" << n.to_s} : ('A'..'Z').to_a[0,n_l]
|
13
|
+
p = ""
|
14
|
+
ls.each_with_index do |l, i|
|
15
|
+
if all? {|x| first[n_l-i-1] == x[n_l-i-1]}
|
16
|
+
p << (first[n_l-i-1] == 1 ? l : l+"'")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
return p
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_sum(n_l)
|
23
|
+
ls = (n_l > 26)? (0..n_l).to_a.map {|n| n = "A" << n.to_s} : ('A'..'Z').to_a[0,n_l]
|
24
|
+
s = "("
|
25
|
+
ls.each_with_index do |l, i|
|
26
|
+
if all? {|x| first[n_l-i-1] == x[n_l-i-1]}
|
27
|
+
s << (first[n_l-i-1] == 1 ? l+"'+" : l+"+")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
s[s.size-1] = ")"
|
31
|
+
return s
|
32
|
+
end
|
33
|
+
|
34
|
+
def strict_subset?(b)
|
35
|
+
self & b == self and length < b.length
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'quine_mc/pi_list'
|
2
|
+
|
3
|
+
module QuineMc
|
4
|
+
|
5
|
+
class EPi_List < Array
|
6
|
+
attr_accessor :pi_table, :pi_list
|
7
|
+
|
8
|
+
def initialize(m, d, n_l)
|
9
|
+
@n_l = n_l
|
10
|
+
@pi_list = Pi_List.new(m, d)
|
11
|
+
get_solution(m)
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_solution(m)
|
15
|
+
@pi_table = Hash.new {|h,k| h[k] = @pi_list.reject {|e| !e.include?(k)}}
|
16
|
+
m.each {|i| @pi_table[i]}
|
17
|
+
reduce
|
18
|
+
end
|
19
|
+
|
20
|
+
def reduce
|
21
|
+
(@pi_table.empty?)? (return true) : size = 0
|
22
|
+
|
23
|
+
while size != @pi_table.size
|
24
|
+
size = @pi_table.size
|
25
|
+
@pi_table.each do |k,v|
|
26
|
+
if v.length == 1
|
27
|
+
push(v[0])
|
28
|
+
v[0].each {|i| @pi_table.delete(i)}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
(@pi_table.empty?)? (return true) : dominated_rows
|
34
|
+
end
|
35
|
+
|
36
|
+
def dominated_rows
|
37
|
+
removed = false
|
38
|
+
#puts @pi_table.inspect
|
39
|
+
(@pi_table.values.flatten(1) - self).each do |c1|
|
40
|
+
(@pi_table.values.flatten(1) - self).each do |c2|
|
41
|
+
if QuineMc::Cube.new(c1 & @pi_table.keys).strict_subset?(Cube.new(c2 & @pi_table.keys))
|
42
|
+
@pi_table.each {|k,v| v.delete_if {|i| i == c1}}
|
43
|
+
removed = true
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
(removed)? reduce : petrick
|
48
|
+
end
|
49
|
+
|
50
|
+
def petrick
|
51
|
+
cube_i = Hash[@pi_table.values.flatten(1).uniq.zip((0...@pi_table.values.flatten(1).uniq.length).to_a)]
|
52
|
+
product = []
|
53
|
+
@pi_table.each do |k,v|
|
54
|
+
temp = []
|
55
|
+
v.each {|x| temp << cube_i[x]}
|
56
|
+
product << temp
|
57
|
+
end
|
58
|
+
choices = expand_s(product).uniq
|
59
|
+
cube_i = cube_i.invert
|
60
|
+
answer = choices.min {|a,b| cost(a, cube_i) <=> cost(b, cube_i)}
|
61
|
+
answer.each {|i| push(cube_i[i])}
|
62
|
+
end
|
63
|
+
|
64
|
+
def cost(c, h)
|
65
|
+
price = c.size
|
66
|
+
c.each {|i| price += @n_l - Math.log(h[i].length)/Math.log(2)}
|
67
|
+
return price
|
68
|
+
end
|
69
|
+
|
70
|
+
def expand_s (sum)
|
71
|
+
expand_r(sum).each {|x| x.flatten!; x.sort!; x.uniq!}
|
72
|
+
end
|
73
|
+
|
74
|
+
def expand_r(exp)
|
75
|
+
if exp.length == 1 then return [[exp[0][0]],[exp[0][1]]] end
|
76
|
+
exp.length == 2 ? exp[0].product(exp[1]) : exp[0].product(expand_r(exp[1..exp.length]))
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'quine_mc/cube'
|
2
|
+
|
3
|
+
module QuineMc
|
4
|
+
class Pi_List < Array
|
5
|
+
|
6
|
+
def initialize(m, d)
|
7
|
+
@cube_table = order_terms((m + d).sort)
|
8
|
+
#puts @cube_table.inspect
|
9
|
+
get_pis()
|
10
|
+
end
|
11
|
+
|
12
|
+
#orders terms by number of set bits
|
13
|
+
def order_terms(uo_terms)
|
14
|
+
h = {}
|
15
|
+
uo_terms.each do |t|
|
16
|
+
t = Cube.new([t])
|
17
|
+
b = t.num_ones
|
18
|
+
h[b] = h[b] || Array.new
|
19
|
+
h[b].push(t)
|
20
|
+
end
|
21
|
+
return h
|
22
|
+
end
|
23
|
+
|
24
|
+
def power_of_2?(x)
|
25
|
+
((x != 0) and (x & (x-1) == 0))
|
26
|
+
end
|
27
|
+
|
28
|
+
def makes_cube?(a, b)
|
29
|
+
a.zip(b).all? { |x,y| power_of_2?(y-x) } and a.all? {|x| b.all? {|y| y>x} }
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
def get_pis()
|
34
|
+
next_table = {}
|
35
|
+
while !@cube_table.empty?
|
36
|
+
#puts @cube_table.inspect
|
37
|
+
@cube_table.each do |k,v|
|
38
|
+
if v
|
39
|
+
v.each do |c1|
|
40
|
+
if @cube_table[k+1]
|
41
|
+
@cube_table[k+1].each do |c2|
|
42
|
+
if makes_cube?(c1, c2)
|
43
|
+
if !next_table[k] then next_table[k] = [] end
|
44
|
+
next_table[k].push(Cube.new(c1+c2))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
if c1.any? {|x| !next_table.values.flatten.include?(x)} then push(Cube.new(c1)) end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
@cube_table = next_table
|
53
|
+
next_table = {}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
data/quine_mc.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "quine_mc/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "quine_mc"
|
7
|
+
s.version = QuineMc::VERSION
|
8
|
+
s.authors = ["Erik Formella"]
|
9
|
+
s.email = ["erik.formella@tufts.edu"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{Quine-McCluskey algorithm}
|
12
|
+
s.description = %q{Pretty much only for command line use}
|
13
|
+
|
14
|
+
s.rubyforge_project = "quine_mc"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
# s.add_development_dependency "rspec"
|
23
|
+
# s.add_runtime_dependency "rest-client"
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: quine_mc
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Erik Formella
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-03-06 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Pretty much only for command line use
|
15
|
+
email:
|
16
|
+
- erik.formella@tufts.edu
|
17
|
+
executables:
|
18
|
+
- quine_mc
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- .DS_Store
|
23
|
+
- .gitignore
|
24
|
+
- Gemfile
|
25
|
+
- Rakefile
|
26
|
+
- bin/quine_mc
|
27
|
+
- lib/quine_mc.rb
|
28
|
+
- lib/quine_mc/.DS_Store
|
29
|
+
- lib/quine_mc/cube.rb
|
30
|
+
- lib/quine_mc/epi_list.rb
|
31
|
+
- lib/quine_mc/pi_list.rb
|
32
|
+
- lib/quine_mc/version.rb
|
33
|
+
- quine_mc.gemspec
|
34
|
+
homepage: ''
|
35
|
+
licenses: []
|
36
|
+
post_install_message:
|
37
|
+
rdoc_options: []
|
38
|
+
require_paths:
|
39
|
+
- lib
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
+
none: false
|
48
|
+
requirements:
|
49
|
+
- - ! '>='
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
requirements: []
|
53
|
+
rubyforge_project: quine_mc
|
54
|
+
rubygems_version: 1.8.15
|
55
|
+
signing_key:
|
56
|
+
specification_version: 3
|
57
|
+
summary: Quine-McCluskey algorithm
|
58
|
+
test_files: []
|