lm 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/exe/lm +17 -0
- data/lib/lm/minimizer.rb +43 -1
- data/lib/lm/output_string.rb +6 -1
- data/lib/lm/petrick.rb +7 -1
- data/lib/lm/pos.rb +4 -7
- data/lib/lm/sum.rb +14 -2
- data/lib/lm/version.rb +1 -1
- data/spec/lm_spec.rb +20 -0
- data/spec/sum_spec.rb +57 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: abf6ece1cf43b82167d54d7081335b3566d554015cb1bb2fd047fe8b1f660a9d
|
4
|
+
data.tar.gz: f87359a2ae880959e2f222040715f2cbb1f948d38423bcd8b4002252c4c0e066
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fab1cf7ae17461222f1522672ac5cfa59e4e435bfb38e9e80fda14ff9ac8d96c2ee31daf0c184a46efcc15392311068a22deb26b7c2fe4a1f69e3536ef46a77a
|
7
|
+
data.tar.gz: 14c83e23640306290f38f593f2474e90ee0e9690e23c592ea6792d093215fd2ab98ba77bf20c7a4e2c13119e2ab7641e066bd8f8cb4f2085ce592c6fea2562fe
|
data/exe/lm
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "lm"
|
5
|
+
|
6
|
+
args = ARGV[0]
|
7
|
+
|
8
|
+
if args.nil?
|
9
|
+
puts "USAGE: lm <bitpattern>"
|
10
|
+
puts "For example, to provide a bitpattern for an AND gate its 0001"
|
11
|
+
puts "The number of bits are inferred"
|
12
|
+
puts "You can use x for don't care, like lm 0xx1"
|
13
|
+
exit 1
|
14
|
+
end
|
15
|
+
|
16
|
+
min = Lm::Minimizer.new(args)
|
17
|
+
puts min.shortest.to_s(verilog: "a")
|
data/lib/lm/minimizer.rb
CHANGED
@@ -1,6 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Lm
|
4
|
+
class Degenerate
|
5
|
+
def initialize(val)
|
6
|
+
@val = val
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_s(_ = nil)
|
10
|
+
@val.to_s
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
4
14
|
class Minimizer
|
5
15
|
def initialize(output_str)
|
6
16
|
@output_str = output_str
|
@@ -11,6 +21,8 @@ module Lm
|
|
11
21
|
end
|
12
22
|
|
13
23
|
def canonical
|
24
|
+
return degenerate if degenerate?
|
25
|
+
|
14
26
|
output_string.sop
|
15
27
|
end
|
16
28
|
|
@@ -31,22 +43,52 @@ module Lm
|
|
31
43
|
end
|
32
44
|
|
33
45
|
def reduced_sum
|
34
|
-
pos.expand
|
46
|
+
sum = pos.apply_factorize.expand
|
47
|
+
loop do
|
48
|
+
newsum = sum.reduce
|
49
|
+
return newsum if sum.to_s.length == newsum.to_s.length
|
50
|
+
|
51
|
+
sum = newsum
|
52
|
+
end
|
53
|
+
sum
|
35
54
|
end
|
36
55
|
|
37
56
|
def calculator
|
38
57
|
String122ResultSelector.new(implicants, reduced_sum)
|
39
58
|
end
|
40
59
|
|
60
|
+
def variation
|
61
|
+
@variation ||= @output_str.split("").uniq
|
62
|
+
end
|
63
|
+
|
64
|
+
# degenerate case
|
65
|
+
def degenerate?
|
66
|
+
variation.length == 1
|
67
|
+
end
|
68
|
+
|
69
|
+
def degenerate
|
70
|
+
Degenerate.new(variation.first)
|
71
|
+
end
|
72
|
+
|
41
73
|
def shortest
|
74
|
+
return degenerate if degenerate?
|
75
|
+
|
42
76
|
calculator.shortest
|
43
77
|
end
|
44
78
|
|
79
|
+
def inputlen
|
80
|
+
output_string.bitcount
|
81
|
+
end
|
82
|
+
|
45
83
|
def evaluate(input)
|
84
|
+
return degenerate.to_s.to_i if degenerate?
|
85
|
+
|
46
86
|
BinFunc.new(shortest).evaluate(input)
|
47
87
|
end
|
48
88
|
|
49
89
|
def canonical_evaluate(input)
|
90
|
+
return degenerate.to_s.to_i if degenerate?
|
91
|
+
|
50
92
|
BinFunc.new(output_string.sop).evaluate(input)
|
51
93
|
end
|
52
94
|
end
|
data/lib/lm/output_string.rb
CHANGED
@@ -4,10 +4,14 @@ module Lm
|
|
4
4
|
class OutputString
|
5
5
|
def initialize(str)
|
6
6
|
@str = str
|
7
|
+
|
8
|
+
return unless @str.length < 2
|
9
|
+
|
10
|
+
@str = @str.rjust(2, "0")
|
7
11
|
end
|
8
12
|
|
9
13
|
def bitcount
|
10
|
-
Math.log(@str.length, 2).ceil
|
14
|
+
[Math.log(@str.length, 2).ceil, 1].max
|
11
15
|
end
|
12
16
|
|
13
17
|
def sop
|
@@ -19,6 +23,7 @@ module Lm
|
|
19
23
|
prod = Product.new(bitbreak)
|
20
24
|
res << prod
|
21
25
|
end
|
26
|
+
|
22
27
|
res
|
23
28
|
end
|
24
29
|
|
data/lib/lm/petrick.rb
CHANGED
@@ -67,7 +67,13 @@ module Lm
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def string122
|
70
|
-
factors
|
70
|
+
factors
|
71
|
+
.map do |sums|
|
72
|
+
sums.map do |prducts|
|
73
|
+
prducts.map { |x| (x.ord + 48).chr }.join("")
|
74
|
+
end.join("+")
|
75
|
+
end
|
76
|
+
.join(",")
|
71
77
|
end
|
72
78
|
end
|
73
79
|
end
|
data/lib/lm/pos.rb
CHANGED
@@ -21,7 +21,7 @@ module Lm
|
|
21
21
|
@termhash ||= begin
|
22
22
|
res = {}
|
23
23
|
sum_array.each do |sum|
|
24
|
-
terms = sum.split("+")
|
24
|
+
terms = sum.split("+", 2)
|
25
25
|
terms.each do |term|
|
26
26
|
res[term] ||= Set.new
|
27
27
|
terms.each do |x|
|
@@ -40,13 +40,10 @@ module Lm
|
|
40
40
|
seenkeys = Set.new
|
41
41
|
|
42
42
|
termhash.each do |key, value|
|
43
|
-
next if seenkeys.include?
|
43
|
+
next if seenkeys.include?(([key] + value.to_a).sort.join("|").to_s)
|
44
44
|
|
45
|
-
seenkeys << key
|
46
|
-
value.
|
47
|
-
seenkeys << factor
|
48
|
-
end
|
49
|
-
newarray << "#{key}+#{value.to_a.join("")}"
|
45
|
+
seenkeys << ([key] + value.to_a).sort.join("|")
|
46
|
+
newarray << "#{key}+#{value.map { |x| Sum.new(x) }.inject(:multiply)}"
|
50
47
|
end
|
51
48
|
|
52
49
|
POS.new(newarray.join(","))
|
data/lib/lm/sum.rb
CHANGED
@@ -8,12 +8,21 @@ module Lm
|
|
8
8
|
@str = str
|
9
9
|
end
|
10
10
|
|
11
|
+
def multiply(other_sum)
|
12
|
+
raise "Not a sum" unless other_sum.is_a? Sum
|
13
|
+
|
14
|
+
newarr = product_list.map(&:to_a).product(other_sum.product_list.map(&:to_a))
|
15
|
+
|
16
|
+
newstr = newarr.map { |x| x.join("") }.join("+")
|
17
|
+
Sum.new(newstr)
|
18
|
+
end
|
19
|
+
|
11
20
|
def product_list
|
12
21
|
@str.split("+").map { |x| Set.new(x.split("")) }
|
13
22
|
end
|
14
23
|
|
15
24
|
def by_length
|
16
|
-
product_list.
|
25
|
+
product_list.sort_by(&:length)
|
17
26
|
end
|
18
27
|
|
19
28
|
def reduce
|
@@ -36,8 +45,11 @@ module Lm
|
|
36
45
|
break if arr.length.zero?
|
37
46
|
end
|
38
47
|
|
39
|
-
res
|
40
48
|
Sum.new(res.map { |x| x.to_a.join("") }.join("+"))
|
41
49
|
end
|
50
|
+
|
51
|
+
def to_s
|
52
|
+
@str
|
53
|
+
end
|
42
54
|
end
|
43
55
|
end
|
data/lib/lm/version.rb
CHANGED
data/spec/lm_spec.rb
CHANGED
@@ -37,4 +37,24 @@ RSpec.describe Lm do
|
|
37
37
|
min = Lm::Minimizer.new("1110")
|
38
38
|
expect(min.canonical.to_s(verilog: "a")).to eq "~a[0] & ~a[1] | ~a[0] & a[1] | a[0] & ~a[1]"
|
39
39
|
end
|
40
|
+
|
41
|
+
it "returns degenerate case 0" do
|
42
|
+
min = Lm::Minimizer.new("0")
|
43
|
+
expect(min.shortest.to_s(verilog: "a")).to eq "0"
|
44
|
+
end
|
45
|
+
|
46
|
+
it "returns degenerate case 00000" do
|
47
|
+
min = Lm::Minimizer.new("00000")
|
48
|
+
expect(min.shortest.to_s(verilog: "a")).to eq "0"
|
49
|
+
end
|
50
|
+
|
51
|
+
it "returns degenerate case 11" do
|
52
|
+
min = Lm::Minimizer.new("11")
|
53
|
+
expect(min.shortest.to_s(verilog: "a")).to eq "1"
|
54
|
+
end
|
55
|
+
|
56
|
+
it "returns degenerate case 1111111" do
|
57
|
+
min = Lm::Minimizer.new("1111111")
|
58
|
+
expect(min.shortest.to_s(verilog: "a")).to eq "1"
|
59
|
+
end
|
40
60
|
end
|
data/spec/sum_spec.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Lm::Sum do
|
4
|
+
describe "#multiply" do
|
5
|
+
it "does simple multiply" do
|
6
|
+
sop1 = Lm::Sum.new("1")
|
7
|
+
sop2 = Lm::Sum.new("2")
|
8
|
+
|
9
|
+
expect(sop1.multiply(sop2).product_list).to eq [Set.new(%w[1 2])]
|
10
|
+
end
|
11
|
+
|
12
|
+
it "does distribute multiply" do
|
13
|
+
sop1 = Lm::Sum.new("1")
|
14
|
+
sop2 = Lm::Sum.new("2+3")
|
15
|
+
|
16
|
+
expect(sop1.multiply(sop2).product_list).to eq [Set.new(%w[1 2]), Set.new(%w[1 3])]
|
17
|
+
end
|
18
|
+
|
19
|
+
it "does fully multiply" do
|
20
|
+
sop1 = Lm::Sum.new("1+4")
|
21
|
+
sop2 = Lm::Sum.new("2+3")
|
22
|
+
|
23
|
+
expect(sop1.multiply(sop2).product_list).to eq [
|
24
|
+
Set.new(%w[1 2]), Set.new(%w[1 3]),
|
25
|
+
Set.new(%w[4 2]), Set.new(%w[4 3])
|
26
|
+
]
|
27
|
+
end
|
28
|
+
|
29
|
+
it "does fully multiply with more" do
|
30
|
+
sop1 = Lm::Sum.new("1+4")
|
31
|
+
sop2 = Lm::Sum.new("2+3+5")
|
32
|
+
|
33
|
+
expect(sop1.multiply(sop2).product_list).to eq [
|
34
|
+
Set.new(%w[1 2]), Set.new(%w[1 3]), Set.new(%w[1 5]),
|
35
|
+
Set.new(%w[4 2]), Set.new(%w[4 3]), Set.new(%w[4 5])
|
36
|
+
]
|
37
|
+
end
|
38
|
+
|
39
|
+
it "does fully multiply inner" do
|
40
|
+
sop1 = Lm::Sum.new("1+45")
|
41
|
+
sop2 = Lm::Sum.new("2+3")
|
42
|
+
|
43
|
+
expect(sop1.multiply(sop2).product_list).to eq [
|
44
|
+
Set.new(%w[1 2]), Set.new(%w[1 3]),
|
45
|
+
Set.new(%w[4 5 2]), Set.new(%w[4 5 3])
|
46
|
+
]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#to_s" do
|
51
|
+
it "does the right thing" do
|
52
|
+
sop1 = Lm::Sum.new("1+45")
|
53
|
+
sop2 = Lm::Sum.new("2+3").multiply(sop1)
|
54
|
+
expect(sop2.to_s).to eq "21+245+31+345"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
metadata
CHANGED
@@ -1,25 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Siaw
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-12-
|
11
|
+
date: 2022-12-26 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Logic Minimizer Library
|
14
14
|
email:
|
15
15
|
- davidsiaw@gmail.com
|
16
|
-
executables:
|
16
|
+
executables:
|
17
|
+
- lm
|
17
18
|
extensions: []
|
18
19
|
extra_rdoc_files: []
|
19
20
|
files:
|
20
21
|
- Gemfile
|
21
22
|
- bin/console
|
22
23
|
- bin/setup
|
24
|
+
- exe/lm
|
23
25
|
- lib/lm.rb
|
24
26
|
- lib/lm/bin_func.rb
|
25
27
|
- lib/lm/implicant_chart.rb
|
@@ -37,6 +39,7 @@ files:
|
|
37
39
|
- lm.gemspec
|
38
40
|
- spec/lm_spec.rb
|
39
41
|
- spec/spec_helper.rb
|
42
|
+
- spec/sum_spec.rb
|
40
43
|
homepage: https://github.com/davidsiaw/lm
|
41
44
|
licenses:
|
42
45
|
- MIT
|
@@ -67,3 +70,4 @@ summary: Logic Minimizer
|
|
67
70
|
test_files:
|
68
71
|
- spec/lm_spec.rb
|
69
72
|
- spec/spec_helper.rb
|
73
|
+
- spec/sum_spec.rb
|