logic_tools 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|