logic_tools 0.2.2 → 0.2.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.
- checksums.yaml +4 -4
- data/README.md +37 -30
- data/lib/logic_tools.rb +8 -1
- data/lib/logic_tools/logicinput.rb +43 -0
- data/lib/logic_tools/logicparse.rb +13 -14
- data/lib/logic_tools/logicsimplify.rb +93 -85
- data/lib/logic_tools/logictree.rb +327 -324
- data/lib/logic_tools/simplify_bug.txt +16 -5
- data/lib/logic_tools/simplify_qm.rb +31 -21
- data/lib/logic_tools/std_conj.rb +40 -21
- data/lib/logic_tools/std_dij.rb +40 -21
- data/lib/logic_tools/truth_tbl.rb +43 -22
- data/lib/logic_tools/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a2329d237d7038309287c2907d60d5a383760642
|
4
|
+
data.tar.gz: d24b42399dcc9f835856e7ede9a539414f703dc1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 34433d985130bf65444113bc969347925f65d427b8400613f1daa0a2598a62158467abcd87c9c4fc67143faf2698dc5dbdb7c35d385222e906ec8ceeb0780c0b
|
7
|
+
data.tar.gz: ac8e94c8d5ebd78c7cffa01c14dbd7fa626cd88a4af95be1a2cfebcbd26fa9ff3a8b058fb940495a177ed845b8348d72e5c474e00252a4581c5a56bf6600595c
|
data/README.md
CHANGED
@@ -2,14 +2,12 @@
|
|
2
2
|
|
3
3
|
LogicTools is a set of command-line tools for processing logic expressions.
|
4
4
|
The tools include:
|
5
|
-
* simplify\_qm: for simplifying a logic expression.
|
6
|
-
* std\_conj: for computing the conjunctive normal form of a logic expression.
|
7
|
-
* std\_dij: for computing the disjunctive normal form a of logic expression.
|
8
|
-
* truth\_tbl: for generating the truth table of a logic expression.
|
9
5
|
|
10
|
-
|
6
|
+
* __simplify\_qm__: for simplifying a logic expression.
|
7
|
+
* __std\_conj__: for computing the conjunctive normal form of a logic expression.
|
8
|
+
* __std\_dij__: for computing the disjunctive normal form a of logic expression.
|
9
|
+
* __truth\_tbl__: for generating the truth table of a logic expression.
|
11
10
|
|
12
|
-
There is still a nasty bug in the logic simplifying tool (simplify_qm) which makes it give a wrong result. Fortunately, it seems to happen in some rare cases only.
|
13
11
|
|
14
12
|
## Installation
|
15
13
|
|
@@ -29,10 +27,16 @@ Or install it yourself as:
|
|
29
27
|
|
30
28
|
## Usage
|
31
29
|
|
32
|
-
LogicTools is a command line-based set of tool. Each tool is used as follows:
|
33
|
-
|
30
|
+
LogicTools is a command line-based set of tool. Each tool is used as follows for processing a single expression:
|
31
|
+
|
32
|
+
$ tool_name "single logical expression"
|
33
|
+
|
34
|
+
Multiple expressions stored into a file can also be processed as follows:
|
35
|
+
|
36
|
+
$ tool_name -f <filename>
|
34
37
|
|
35
38
|
The logical expression is an expression where:
|
39
|
+
|
36
40
|
* a logical variable is represented by a single alphabetical character (hence there is in total 56 possible variables);
|
37
41
|
* a logical OR is represented by a '+' character;
|
38
42
|
* a logical AND is represented by a '.' character (but it can be omitted);
|
@@ -40,32 +44,41 @@ The logical expression is an expression where:
|
|
40
44
|
* opening and closing parenthesis are represented by, respectively, '(' and ')' characters.
|
41
45
|
|
42
46
|
Important notice:
|
47
|
+
|
43
48
|
* the priority among logical operators is as follows: NOT > AND > OR
|
44
49
|
* logical expressions must be put between quotes (the '"' character).
|
45
50
|
|
46
51
|
For instance the followings are valid logical expression using the a,b and c variables:
|
47
|
-
|
48
|
-
"
|
49
|
-
"a
|
50
|
-
"a
|
52
|
+
|
53
|
+
"ab+ac"
|
54
|
+
"a.b.c"
|
55
|
+
"a+b+!c"
|
56
|
+
"a~(b+~c)"
|
51
57
|
|
52
58
|
Finally, here are a few examples of LogicTool usage:
|
59
|
+
|
53
60
|
* simplifying the expression a+ab:
|
54
|
-
|
55
|
-
|
61
|
+
|
62
|
+
$ simplify_qm "a+ab"
|
63
|
+
-> a
|
56
64
|
* compute the conjunctive normal form of the expression a+ab:
|
57
|
-
|
58
|
-
|
65
|
+
|
66
|
+
$ std_conj "a+ab"
|
67
|
+
-> ab+a~b
|
68
|
+
|
59
69
|
* compute the disjunctive normal form of the expression a+ab:
|
60
|
-
|
61
|
-
|
70
|
+
|
71
|
+
$ std_dij "a+ab"
|
72
|
+
-> (a+b)(a+~b)
|
73
|
+
|
62
74
|
* compute the truth table of the expression a+ab:
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
75
|
+
|
76
|
+
$ truth_tbl "a+ab"
|
77
|
+
-> a b
|
78
|
+
0 0 0
|
79
|
+
0 1 0
|
80
|
+
1 0 1
|
81
|
+
1 1 1
|
69
82
|
|
70
83
|
## Development
|
71
84
|
|
@@ -84,12 +97,6 @@ The gem is available as open source under the terms of the [MIT License](http://
|
|
84
97
|
|
85
98
|
|
86
99
|
## To do
|
87
|
-
### High priority
|
88
|
-
* Fix the bug that makes simplify\_qm produce sometimes a wrong result.
|
89
|
-
* Downgrade the user interface: actually the interface can do much more than what is described in the documentation, but this is not really useful, so it should better to remove these features.
|
90
|
-
|
91
|
-
### Low priority
|
92
|
-
|
93
100
|
* Add a more efficient alternative command to simplify_qm, based on the Espresso algorithm for example.
|
94
101
|
|
95
102
|
|
data/lib/logic_tools.rb
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
require "logic_tools/version"
|
2
2
|
|
3
|
+
######################################################################
|
4
|
+
#
|
5
|
+
# == LogicTools
|
6
|
+
# This module includes all the classes and methods used
|
7
|
+
# by the *logic_tools* set of tools.
|
8
|
+
#
|
9
|
+
######################################################################
|
10
|
+
|
3
11
|
module LogicTools
|
4
|
-
# Your code goes here...
|
5
12
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
|
2
|
+
module LogicTools
|
3
|
+
|
4
|
+
|
5
|
+
#########################################################################
|
6
|
+
# Common command line interface for all Logic Tools
|
7
|
+
#########################################################################
|
8
|
+
|
9
|
+
|
10
|
+
## Displays a short help message.
|
11
|
+
def help_short
|
12
|
+
name = File.basename($0)
|
13
|
+
puts "Usage: #{name} <\"logic expression\">"
|
14
|
+
puts " or: #{name} -f <file name>"
|
15
|
+
end
|
16
|
+
|
17
|
+
## Gets an iterator over the input expression
|
18
|
+
# (obtained either through options or a through file).
|
19
|
+
def each_input
|
20
|
+
# No block? Return an enumerator
|
21
|
+
return enum_for(:each_input) unless block_given?
|
22
|
+
# A block? Interrate with it
|
23
|
+
# Process the arguments
|
24
|
+
if ($*.empty?) then
|
25
|
+
# No arguments, shows the help and end.
|
26
|
+
help_short
|
27
|
+
exit(1)
|
28
|
+
end
|
29
|
+
if $*[0] == "-f" or $*[0] == "--file" then
|
30
|
+
# Work from a file, iterate on each line
|
31
|
+
exprs = File.read($*[1])
|
32
|
+
exprs.gsub!(/\r\n?/, "\n")
|
33
|
+
exprs.each_line do |line|
|
34
|
+
yield(line)
|
35
|
+
end
|
36
|
+
elsif $*[0] == "-h" or $*[0] == "--help" then
|
37
|
+
help_short
|
38
|
+
else
|
39
|
+
# Work directly on the arguments as an expression
|
40
|
+
yield($*.join)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
|
2
|
-
#
|
3
|
-
|
1
|
+
########################################################
|
2
|
+
# Parse a string and convert to a logic tree #
|
3
|
+
########################################################
|
4
4
|
|
5
5
|
# For parsing the inputs
|
6
6
|
require 'parslet'
|
@@ -11,24 +11,25 @@ require "logic_tools/logictree.rb"
|
|
11
11
|
|
12
12
|
|
13
13
|
|
14
|
-
########################################################
|
15
|
-
# Parse a string and convert to a logic tree
|
16
14
|
|
17
15
|
|
18
16
|
module LogicTools
|
19
17
|
|
20
|
-
## The parser of logic expressions
|
18
|
+
## The parser of logic expressions.
|
21
19
|
class Parser < Parslet::Parser
|
22
20
|
|
23
21
|
# True / false
|
24
22
|
rule(:tru) { str("1") }
|
25
23
|
rule(:fal) { str("0") }
|
26
24
|
# Variable
|
27
|
-
rule(:var) { match('[A-Za-uw-z]') }
|
25
|
+
# rule(:var) { match('[A-Za-uw-z]') }
|
26
|
+
rule(:var) { match('[A-Za-z]') }
|
28
27
|
# And operator
|
29
|
-
rule(:andop) { str("&&") | match('[&\.\*^]') }
|
28
|
+
# rule(:andop) { str("&&") | match('[&\.\*^]') }
|
29
|
+
rule(:andop) { str(".") }
|
30
30
|
# Or operator
|
31
|
-
rule(:orop) { match('[+|v]') }
|
31
|
+
# rule(:orop) { match('[+|v]') }
|
32
|
+
rule(:orop) { str("+") }
|
32
33
|
# Not operator
|
33
34
|
rule(:notop) { match('[~!]') }
|
34
35
|
|
@@ -43,7 +44,7 @@ module LogicTools
|
|
43
44
|
end
|
44
45
|
|
45
46
|
|
46
|
-
## The logic tree generator from the syntax tree
|
47
|
+
## The logic tree generator from the syntax tree.
|
47
48
|
class Transform < Parslet::Transform
|
48
49
|
|
49
50
|
# Terminal rules
|
@@ -77,10 +78,8 @@ module LogicTools
|
|
77
78
|
end
|
78
79
|
|
79
80
|
|
80
|
-
## The parser/gerator main fuction: converts
|
81
|
-
#
|
82
|
-
# +str+:: the string to parse
|
83
|
-
# Return: the resulting logic tree
|
81
|
+
## The parser/gerator main fuction: converts the text in +str+ to a
|
82
|
+
# logic tree.
|
84
83
|
def string2logic(str)
|
85
84
|
# Remove the spaces
|
86
85
|
str = str.gsub(/\s+/, "")
|
@@ -10,8 +10,8 @@ require 'set'
|
|
10
10
|
module LogicTools
|
11
11
|
|
12
12
|
|
13
|
-
## Converts
|
14
|
-
#
|
13
|
+
## Converts the array of variables +var+ to a bit vector according to
|
14
|
+
# their values
|
15
15
|
def vars2int(vars)
|
16
16
|
res = ""
|
17
17
|
vars.each_with_index do |var,i|
|
@@ -24,24 +24,33 @@ module LogicTools
|
|
24
24
|
|
25
25
|
|
26
26
|
|
27
|
-
|
27
|
+
##
|
28
|
+
# Represents a logic implicant
|
28
29
|
class Implicant
|
29
30
|
include Enumerable
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
31
|
+
|
32
|
+
## The positions of the *X* in the implicant.
|
33
|
+
attr_reader :mask
|
34
|
+
## The bit vector of the implicant.
|
35
|
+
attr_reader :bits
|
36
|
+
## The number of *1* of the implicant.
|
37
|
+
attr_reader :count
|
38
|
+
## The bit values covered by the implicant.
|
39
|
+
attr_reader :covers
|
40
|
+
## Tell if the implicant is prime or not.
|
41
|
+
attr_reader :prime
|
42
|
+
## The variable associated with the implicant
|
43
|
+
# Do not interfer at all with the class, so
|
44
|
+
# public and fully accessible
|
45
|
+
attr_accessor :var
|
46
|
+
|
38
47
|
protected
|
39
48
|
attr_writer :covers
|
40
49
|
public
|
41
50
|
|
42
|
-
##
|
43
|
-
#
|
44
|
-
#
|
51
|
+
## Creates a new implicant from +base+.
|
52
|
+
#
|
53
|
+
# Argument +base+ can be either another implicant or a bit string.
|
45
54
|
def initialize(base)
|
46
55
|
if base.is_a?(Implicant)
|
47
56
|
@covers = base.covers.dup
|
@@ -51,7 +60,7 @@ module LogicTools
|
|
51
60
|
else
|
52
61
|
@bits = base.to_s
|
53
62
|
unless @bits.match(/^[01]*$/)
|
54
|
-
raise "Invalid bit string for an initial implicant: "
|
63
|
+
raise "Invalid bit string for an initial implicant: "+ @bits
|
55
64
|
end
|
56
65
|
@mask = " " * @bits.size
|
57
66
|
@count = @bits.count("1")
|
@@ -60,50 +69,44 @@ module LogicTools
|
|
60
69
|
@prime = true # By default assumed prime
|
61
70
|
end
|
62
71
|
|
63
|
-
##
|
64
|
-
def to_s
|
72
|
+
## Converts to a string
|
73
|
+
def to_s # :nodoc:
|
65
74
|
@bits
|
66
75
|
end
|
67
76
|
|
68
|
-
|
69
|
-
def inspect
|
77
|
+
def inspect #:nodoc:
|
70
78
|
@bits.dup
|
71
79
|
end
|
72
80
|
|
73
|
-
##
|
74
|
-
# @param st the new status (true or false)
|
81
|
+
## Sets the prime status to +st+ (true or false).
|
75
82
|
def prime=(st)
|
76
83
|
@prime = st ? true : false
|
77
84
|
end
|
78
85
|
|
79
|
-
##
|
86
|
+
## Iterates over the bits of the implicant.
|
80
87
|
def each(&blk)
|
81
88
|
@bits.each_char(&blk)
|
82
89
|
end
|
83
90
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
@bits == imp.to_s
|
91
|
+
## Compares with +implicant+
|
92
|
+
def ==(implicant) # :nodoc:
|
93
|
+
@bits == implicant.to_s
|
88
94
|
end
|
89
|
-
def <=>(
|
90
|
-
@bits <=>
|
95
|
+
def <=>(implicant) #:nodoc:
|
96
|
+
@bits <=> implicant.to_s
|
91
97
|
end
|
92
98
|
|
93
|
-
|
94
|
-
def dup
|
99
|
+
## duplicates the implicant.
|
100
|
+
def dup # :nodoc:
|
95
101
|
Implicant.new(self)
|
96
102
|
end
|
97
103
|
|
98
|
-
##
|
99
|
-
# @param i the index in the bit string of the implicant
|
104
|
+
## Gets the value of bit +i+.
|
100
105
|
def [](i)
|
101
106
|
@bits[i]
|
102
107
|
end
|
103
108
|
|
104
|
-
##
|
105
|
-
# @param i the index in the bit string of the implicant
|
106
|
-
# @param b the bit to set
|
109
|
+
## Sets the value of bit +i+ to +b+.
|
107
110
|
def []=(i,b)
|
108
111
|
raise "Invalid bit value: #{b}" unless ["0","1","x"].include?(b)
|
109
112
|
return if @bits[i] == b # Already set
|
@@ -117,16 +120,14 @@ module LogicTools
|
|
117
120
|
end
|
118
121
|
|
119
122
|
|
120
|
-
##
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
# Has imp the same mask?
|
125
|
-
return nil unless imp.mask == @mask
|
123
|
+
## Creates a new implicant merging current implicant with +imp+.
|
124
|
+
def merge(implicant)
|
125
|
+
# Has implicant the same mask?
|
126
|
+
return nil unless implicant.mask == @mask
|
126
127
|
# First look for a 1-0 or 0-1 difference
|
127
128
|
found = nil
|
128
129
|
@bits.each_char.with_index do |b0,i|
|
129
|
-
b1 =
|
130
|
+
b1 = implicant.bits[i]
|
130
131
|
# Bits are different
|
131
132
|
if (b0 != b1) then
|
132
133
|
# Stop if there where already a difference
|
@@ -146,7 +147,7 @@ module LogicTools
|
|
146
147
|
# And update its x
|
147
148
|
merged[found] = "x"
|
148
149
|
# Finally update its covers
|
149
|
-
merged.covers = @covers |
|
150
|
+
merged.covers = @covers | implicant.covers
|
150
151
|
return merged
|
151
152
|
end
|
152
153
|
# No merge
|
@@ -154,67 +155,72 @@ module LogicTools
|
|
154
155
|
end
|
155
156
|
end
|
156
157
|
|
157
|
-
|
158
|
-
|
158
|
+
|
159
|
+
##
|
160
|
+
# Represents a group of implicants with only singletons, sortable
|
161
|
+
# by number of ones.
|
159
162
|
class SameXImplicants
|
160
163
|
include Enumerable
|
161
164
|
|
162
|
-
##
|
165
|
+
## Creates a group of implicants.
|
163
166
|
def initialize
|
164
167
|
@implicants = []
|
165
168
|
@singletons = Set.new # Set used for ensuring each implicant is
|
166
169
|
# present only once in the group
|
167
170
|
end
|
168
171
|
|
169
|
-
##
|
172
|
+
## Gets the number of implicants of the group.
|
170
173
|
def size
|
171
174
|
@implicants.size
|
172
175
|
end
|
173
176
|
|
174
|
-
##
|
177
|
+
## Iterates over the implicants of the group.
|
175
178
|
def each(&blk)
|
176
179
|
@implicants.each(&blk)
|
177
180
|
end
|
178
181
|
|
179
|
-
##
|
180
|
-
# @param i the index
|
182
|
+
## Gets implicant +i+.
|
181
183
|
def [](i)
|
182
184
|
@implicants[i]
|
183
185
|
end
|
184
186
|
|
185
|
-
##
|
186
|
-
|
187
|
-
|
188
|
-
return if @singletons.include?(
|
189
|
-
@implicants <<
|
190
|
-
@singletons.add(
|
187
|
+
## Adds +implicant+ to the group.
|
188
|
+
def add(implicant)
|
189
|
+
# Nothing to do if +implicant+ is already present.
|
190
|
+
return if @singletons.include?(implicant.bits)
|
191
|
+
@implicants << implicant
|
192
|
+
@singletons.add(implicant.bits.dup)
|
191
193
|
end
|
194
|
+
|
192
195
|
alias :<< :add
|
193
196
|
|
194
|
-
|
197
|
+
## Sort the implicants by number of ones.
|
195
198
|
def sort!
|
196
|
-
@implicants.sort_by! {|
|
199
|
+
@implicants.sort_by! {|implicant| implicant.count }
|
197
200
|
end
|
198
201
|
|
199
|
-
|
200
|
-
def to_s
|
202
|
+
## Converts to a string
|
203
|
+
def to_s # :nodoc:
|
201
204
|
@implicants.to_s
|
202
205
|
end
|
203
|
-
|
206
|
+
|
207
|
+
def inspect # :nodoc:
|
204
208
|
to_s
|
205
209
|
end
|
206
210
|
end
|
207
211
|
|
208
|
-
##
|
212
|
+
##
|
213
|
+
# Describes a pseudo variable associated to an implicant.
|
214
|
+
#
|
209
215
|
# Used for the Petrick's method
|
210
216
|
class VarImp < Variable
|
211
217
|
@@base = 0 # The index of the VarImp for building the variable names
|
212
218
|
|
219
|
+
## The implicant the pseudo variable is associated to.
|
213
220
|
attr_reader :implicant
|
214
221
|
|
215
|
-
##
|
216
|
-
|
217
|
-
def initialize(imp)
|
222
|
+
## Creates a pseudo variable assoctiated to an +implicant+.
|
223
|
+
def initialize(implicant)
|
218
224
|
# Create the name of the variable
|
219
225
|
name = nil
|
220
226
|
begin
|
@@ -224,19 +230,20 @@ module LogicTools
|
|
224
230
|
# Create the variable
|
225
231
|
super(name)
|
226
232
|
# Associate it with the implicant
|
227
|
-
@implicant =
|
228
|
-
|
233
|
+
@implicant = implicant
|
234
|
+
implicant.var = self
|
229
235
|
end
|
230
236
|
end
|
231
237
|
|
232
238
|
|
233
239
|
|
234
|
-
|
240
|
+
## Enhances the Node class with expression simplifying.
|
235
241
|
class Node
|
236
242
|
|
237
243
|
## Generates an equivalent but simplified representation of the
|
238
|
-
#
|
239
|
-
#
|
244
|
+
# expression represented by the tree rooted by the current node.
|
245
|
+
#
|
246
|
+
# Uses the Quine-Mc Cluskey method.
|
240
247
|
def simplify
|
241
248
|
# Step 1: get the generators
|
242
249
|
|
@@ -254,8 +261,8 @@ module LogicTools
|
|
254
261
|
|
255
262
|
# Convert the minterms to implicants without x
|
256
263
|
minterms.each do |term|
|
257
|
-
|
258
|
-
implicants[
|
264
|
+
implicant = Implicant.new(term)
|
265
|
+
implicants[implicant.mask] << implicant
|
259
266
|
end
|
260
267
|
|
261
268
|
# print "implicants = #{implicants}\n"
|
@@ -272,17 +279,18 @@ module LogicTools
|
|
272
279
|
group.sort! # Sort by number of one
|
273
280
|
size = group.size
|
274
281
|
# print "size = #{size}\n"
|
275
|
-
group.each_with_index do |
|
276
|
-
# print "
|
282
|
+
group.each_with_index do |implicant0,i0|
|
283
|
+
# print "implicant0 = #{implicant0}, i0=#{i0}\n"
|
277
284
|
((i0+1)..(size-1)).each do |i1|
|
278
285
|
# Get the next implicant
|
279
|
-
|
280
|
-
# print "
|
281
|
-
# No need to look further if the number of 1 of
|
282
|
-
# is more than one larger than
|
283
|
-
|
286
|
+
implicant1 = group[i1]
|
287
|
+
# print "implicant1 = #{implicant1}, i1=#{i1}\n"
|
288
|
+
# No need to look further if the number of 1 of
|
289
|
+
# implicant1 is more than one larger than
|
290
|
+
# implicant0's
|
291
|
+
break if implicant1.count > implicant0.count+1
|
284
292
|
# Try to merge
|
285
|
-
mrg =
|
293
|
+
mrg = implicant0.merge(implicant1)
|
286
294
|
# print "mrg = #{mrg}\n"
|
287
295
|
# Can merge
|
288
296
|
if mrg then
|
@@ -290,14 +298,14 @@ module LogicTools
|
|
290
298
|
# Indicate than a merged happend
|
291
299
|
has_merged = true
|
292
300
|
# Mark the initial generators as not prime
|
293
|
-
|
301
|
+
implicant0.prime = implicant1.prime = false
|
294
302
|
end
|
295
303
|
end
|
296
304
|
# Is the term prime?
|
297
|
-
if
|
298
|
-
# print "
|
305
|
+
if implicant0.prime then
|
306
|
+
# print "implicant0 is prime\n"
|
299
307
|
# Yes add it to the generators
|
300
|
-
generators <<
|
308
|
+
generators << implicant0
|
301
309
|
end
|
302
310
|
end
|
303
311
|
end
|
@@ -359,7 +367,7 @@ module LogicTools
|
|
359
367
|
end
|
360
368
|
|
361
369
|
# Sort by variable order
|
362
|
-
selected.sort_by! { |
|
370
|
+
selected.sort_by! { |implicant| implicant.bits }
|
363
371
|
|
364
372
|
# print "Selected prime implicants are: #{selected}\n"
|
365
373
|
# Generate the resulting tree
|