logic_tools 0.3.7 → 0.3.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/logic_tools/logicconvert.rb +1 -1
- data/lib/logic_tools/logiccover.rb +4 -4
- data/lib/logic_tools/logicgenerator.rb +55 -1
- data/lib/logic_tools/logictree.rb +39 -12
- data/lib/logic_tools/simplify_bug.txt +8 -0
- data/lib/logic_tools/test_logic_tools.rb +28 -4
- data/lib/logic_tools/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 37ffa5f837816fb1f10f87e520b5a1936bac7b66
|
4
|
+
data.tar.gz: 8035e691cd6d385d396a6e3d66395eae6ded6725
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 23eeb7a4e711ff0a72c11c68a58e183cd7718882e91e56e1189b2c5436c554f1b031ea6dcee13433505e618aa1b824a7ec878f2b4485a067d90a354376948a1c
|
7
|
+
data.tar.gz: 5202cd8cd9fac2dfea65f6d36c120f9e12bd64d1cb9ff22adaacb3502c15955d3b6498928c4c7ca1dfe8ef070331652c6bcf94edd816e24014172bb54bc54c35
|
@@ -36,7 +36,7 @@ module LogicTools
|
|
36
36
|
# print "vars=#{vars}\n"
|
37
37
|
# Converts the tree rooted by self to a sum of products
|
38
38
|
# (reduced to limit the number of cubes and their sizes).
|
39
|
-
tree = self.to_sum_product.
|
39
|
+
tree = self.to_sum_product.reduce
|
40
40
|
# print "tree=#{tree}\n"
|
41
41
|
|
42
42
|
# Create an empty cover.
|
@@ -60,7 +60,7 @@ module LogicTools
|
|
60
60
|
#
|
61
61
|
# +input+ is assumed to be an integer.
|
62
62
|
# Returns the evaluation result as a boolean.
|
63
|
-
def
|
63
|
+
def eval_input(input)
|
64
64
|
result = true
|
65
65
|
@bits.each_byte.with_index do |bit,i|
|
66
66
|
if bit == 49 then
|
@@ -446,9 +446,9 @@ module LogicTools
|
|
446
446
|
#
|
447
447
|
# +input+ is assumed to be an integer.
|
448
448
|
# Returns the evaluation result as a boolean.
|
449
|
-
def
|
449
|
+
def eval_input(input)
|
450
450
|
# Evaluates each cube, if one results in true the result is true.
|
451
|
-
return !!@cubes.each.find {|cube| cube.
|
451
|
+
return !!@cubes.each.find {|cube| cube.eval_input(input) }
|
452
452
|
end
|
453
453
|
|
454
454
|
## Converts to a string.
|
@@ -760,7 +760,7 @@ module LogicTools
|
|
760
760
|
# return false if num_minterms < 2**self.width
|
761
761
|
# # Last check: the truth table.
|
762
762
|
# (2**self.width).times do |input|
|
763
|
-
# return false if self.
|
763
|
+
# return false if self.eval_input(input) == 0
|
764
764
|
# end
|
765
765
|
else
|
766
766
|
# Compute the cofactors over the binate variables.
|
@@ -49,7 +49,7 @@ module LogicTools
|
|
49
49
|
@rate = rate
|
50
50
|
end
|
51
51
|
|
52
|
-
## Iterates over the variables of the
|
52
|
+
## Iterates over the variables of the generator.
|
53
53
|
#
|
54
54
|
# Returns an enumberator if no block is given
|
55
55
|
def each_variable(&blk)
|
@@ -60,6 +60,60 @@ module LogicTools
|
|
60
60
|
end
|
61
61
|
|
62
62
|
|
63
|
+
## Creates a random logic expression.
|
64
|
+
def random_expression
|
65
|
+
expression = ""
|
66
|
+
pre = :"(" # The previous element type: start of expression
|
67
|
+
# is equivalent to a opened parenthesis.
|
68
|
+
par = 0 # The number of opened parenthesis
|
69
|
+
@random.rand(0..(@max-1)).times do
|
70
|
+
choice = @random.rand(@variables.size+4)
|
71
|
+
# print "par=#{par} pre=#{pre}\n"
|
72
|
+
case choice
|
73
|
+
when 0 then
|
74
|
+
expression << "("
|
75
|
+
par += 1
|
76
|
+
pre = :"("
|
77
|
+
when 1 then
|
78
|
+
if ( par > 0 and ( pre==:v or pre==:")") )
|
79
|
+
expression << ")"
|
80
|
+
par -= 1
|
81
|
+
pre = :")"
|
82
|
+
end
|
83
|
+
when 3 then
|
84
|
+
if ( pre != :"(" and pre != :+ and pre != :~ )
|
85
|
+
expression << "+"
|
86
|
+
pre = :+
|
87
|
+
end
|
88
|
+
when 4 then
|
89
|
+
expression << "~"
|
90
|
+
pre = :~
|
91
|
+
else
|
92
|
+
var = @variables[choice-4]
|
93
|
+
if var.size > 1
|
94
|
+
expression << "{" + var + "}"
|
95
|
+
else
|
96
|
+
expression << var
|
97
|
+
end
|
98
|
+
pre = :v
|
99
|
+
end
|
100
|
+
# print "expression = #{expression}\n"
|
101
|
+
end
|
102
|
+
# Remove the last invalid character.
|
103
|
+
while ["~","(","+"].include?(expression[-1]) do
|
104
|
+
par -= 1 if expression[-1] == "("
|
105
|
+
expression.chop!
|
106
|
+
end
|
107
|
+
# Close the remaining opened parenthesis.
|
108
|
+
while par > 0 do
|
109
|
+
par -=1
|
110
|
+
expression << ")"
|
111
|
+
end
|
112
|
+
# Return the resulting expression.
|
113
|
+
return expression
|
114
|
+
end
|
115
|
+
|
116
|
+
|
63
117
|
## Creates a random truth table column value.
|
64
118
|
def random_column
|
65
119
|
return @random.rand(0..(2**(2**(@variables.size))-1))
|
@@ -105,6 +105,15 @@ module LogicTools
|
|
105
105
|
0
|
106
106
|
end
|
107
107
|
|
108
|
+
## Evalutes the tree on a binary +input+.
|
109
|
+
def eval_input(input)
|
110
|
+
self.get_variables.each_with_index do |var,i|
|
111
|
+
val = input[vars.size-i-1]
|
112
|
+
var.value = val
|
113
|
+
end
|
114
|
+
return self.eval
|
115
|
+
end
|
116
|
+
|
108
117
|
## Iterates on each line of the truth table obtained from the tree
|
109
118
|
# rooted by current node.
|
110
119
|
#
|
@@ -259,6 +268,7 @@ module LogicTools
|
|
259
268
|
#
|
260
269
|
# Argument +flattened+ tells if the tree is already flattend
|
261
270
|
def to_sum_product(flattened = false)
|
271
|
+
# print "NODE to_sum_product with tree=#{self}\n"
|
262
272
|
return self.dup
|
263
273
|
end
|
264
274
|
|
@@ -671,13 +681,17 @@ module LogicTools
|
|
671
681
|
|
672
682
|
## Flatten ands, ors and nots.
|
673
683
|
def flatten # :nodoc:
|
674
|
-
|
684
|
+
# print "flatten with #{self}\n"
|
685
|
+
res = NodeNary.make(@op,*(@children.reduce([]) do |nchildren,child|
|
675
686
|
if (child.op == self.op) then
|
676
|
-
nchildren.push(*child)
|
687
|
+
# nchildren.push(*child)
|
688
|
+
nchildren.push(*child.each)
|
677
689
|
else
|
678
690
|
nchildren << child
|
679
691
|
end
|
680
692
|
end)).reduce
|
693
|
+
# print "result #{res}\n"
|
694
|
+
return res
|
681
695
|
end
|
682
696
|
|
683
697
|
## Creates a new tree where all the *and*, *or* and *not* operators
|
@@ -688,7 +702,8 @@ module LogicTools
|
|
688
702
|
return NodeNary.make(@op,*(@children.reduce([]) do |nchildren,child|
|
689
703
|
child = child.flatten_deep
|
690
704
|
if (child.op == self.op) then
|
691
|
-
nchildren.push(*child)
|
705
|
+
# nchildren.push(*child)
|
706
|
+
nchildren.push(*child.each)
|
692
707
|
else
|
693
708
|
nchildren << child
|
694
709
|
end
|
@@ -698,7 +713,7 @@ module LogicTools
|
|
698
713
|
## Creates a new tree where the current node is distributed over +node+
|
699
714
|
# according to the +dop+ operator.
|
700
715
|
def distribute(dop,node) # :nodoc:
|
701
|
-
# print "
|
716
|
+
# print "distribute with self=#{self} and node=#{node}\n"
|
702
717
|
fop = dop == :and ? :or : :and
|
703
718
|
# print "dop=#{dop} fop=#{fop} self.op=#{@op}\n"
|
704
719
|
if (@op == dop) then
|
@@ -756,11 +771,18 @@ module LogicTools
|
|
756
771
|
#
|
757
772
|
# Argument +flattened+ tells if the tree is already flattend
|
758
773
|
def to_sum_product(flattened = false) # :nodoc:
|
774
|
+
# print "AND to_sum_product with tree=#{self}\n"
|
759
775
|
# Flatten if required
|
760
776
|
node = flattened ? self : self.flatten_deep
|
761
777
|
return node unless node.is_parent?
|
762
778
|
# Convert each child to sum of product
|
763
|
-
nchildren = node.map
|
779
|
+
nchildren = node.map do |child|
|
780
|
+
# print "recurse to_sum_product for child=#{child}\n"
|
781
|
+
# res = child.to_sum_product(true)
|
782
|
+
# print "child=#{child} -> res=#{res}\n"
|
783
|
+
# res
|
784
|
+
child.to_sum_product(true)
|
785
|
+
end
|
764
786
|
# Distribute
|
765
787
|
while(nchildren.size>1)
|
766
788
|
# print "nchildren=#{nchildren}\n"
|
@@ -773,14 +795,17 @@ module LogicTools
|
|
773
795
|
dist << left
|
774
796
|
end
|
775
797
|
end
|
798
|
+
# print "dist=#{dist}\n"
|
776
799
|
nchildren = dist
|
777
800
|
end
|
778
|
-
#
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
801
|
+
# print "result=#{nchildren}\n"
|
802
|
+
# # Generate the or
|
803
|
+
# if (nchildren.size > 1)
|
804
|
+
# return NodeOr.new(*nchildren)
|
805
|
+
# else
|
806
|
+
# return nchildren[0]
|
807
|
+
# end
|
808
|
+
return nchildren[0].flatten
|
784
809
|
end
|
785
810
|
|
786
811
|
## Converts to a string.
|
@@ -824,8 +849,9 @@ module LogicTools
|
|
824
849
|
#
|
825
850
|
# Argument +flattened+ tells if the tree is already flattend
|
826
851
|
def to_sum_product(flattened = false) # :nodoc:
|
852
|
+
# print "OR to_sum_product with tree=#{self}\n"
|
827
853
|
return NodeOr.new(
|
828
|
-
*@children.map {|child| child.to_sum_product(
|
854
|
+
*@children.map {|child| child.to_sum_product(flattened) } ).flatten
|
829
855
|
end
|
830
856
|
|
831
857
|
## Converts to a string.
|
@@ -963,6 +989,7 @@ module LogicTools
|
|
963
989
|
#
|
964
990
|
# Argument +flattened+ tells if the tree is already flattend
|
965
991
|
def to_sum_product(flattened = false) # :nodoc:
|
992
|
+
# print "NOT to_sum_product with tree=#{self}\n"
|
966
993
|
# return NodeNot.new(@child.to_sum_product(flatten))
|
967
994
|
# Flatten deeply if required.
|
968
995
|
nnode = flattened ? self : self.flatten_deep
|
@@ -7,6 +7,7 @@
|
|
7
7
|
# require 'minitest/autorun'
|
8
8
|
require "logic_tools/logicgenerator.rb"
|
9
9
|
require "logic_tools/logicconvert.rb"
|
10
|
+
require "logic_tools/logicparse.rb"
|
10
11
|
|
11
12
|
include LogicTools
|
12
13
|
|
@@ -30,7 +31,7 @@ class TestEspresso # < MiniTest::Unit::TestCase
|
|
30
31
|
def truth_tautology(cover)
|
31
32
|
## Generate each possible input and test it on the cover.
|
32
33
|
(2**(cover.width)).times do |i|
|
33
|
-
return false unless cover.
|
34
|
+
return false unless cover.eval_input(i)
|
34
35
|
end
|
35
36
|
return true
|
36
37
|
end
|
@@ -76,13 +77,36 @@ class TestEspresso # < MiniTest::Unit::TestCase
|
|
76
77
|
return true
|
77
78
|
end
|
78
79
|
|
80
|
+
# ## Tests the conversion to sum of product of an expression.
|
81
|
+
# def test_to_sum_product_random(dimensions = 4)
|
82
|
+
# # Create the variables.
|
83
|
+
# base = "`"
|
84
|
+
# variables = dimensions.times.map { |i| base.next!.clone }
|
85
|
+
# # Create the generator.
|
86
|
+
# generator = Generator.new(*variables)
|
87
|
+
# generator.seed = @seed
|
88
|
+
# # Creates the expression.
|
89
|
+
# expression = generator.random_expression
|
90
|
+
# # Convert it to a tree.
|
91
|
+
# tree = string2logic(expression)
|
92
|
+
# # Convert it.
|
93
|
+
# sumprod = tree.to_sum_product
|
94
|
+
# # Compare the truth tables.
|
95
|
+
# # check = same_truth_table?(tree,sumprod)
|
96
|
+
# # HOW TO CHECK? SOME VARIABLES MAY HAVE DISAPEARED...
|
97
|
+
# # assert_equal(true,check)
|
98
|
+
# print "check = #{check}\n"
|
99
|
+
# raise "Test failure" unless check
|
100
|
+
# return true
|
101
|
+
# end
|
102
|
+
|
79
103
|
|
80
104
|
## Checks if covers have the same truth table.
|
81
105
|
def same_truth_table?(cover0,cover1)
|
82
106
|
return false unless cover0.width == cover1.width
|
83
107
|
# Check for each entry.
|
84
108
|
(2**cover0.width).times do |i|
|
85
|
-
return false unless cover0.
|
109
|
+
return false unless cover0.eval_input(i) == cover1.eval_input(i)
|
86
110
|
end
|
87
111
|
return true
|
88
112
|
end
|
@@ -134,8 +158,8 @@ class TestEspresso # < MiniTest::Unit::TestCase
|
|
134
158
|
print "ESPRESSO on cover=[#{cover.to_s}]...\n"
|
135
159
|
simple = cover.simplify(@deadline,@volume)
|
136
160
|
print "result: [#{simple}]\n"
|
137
|
-
check0 = (cover + simple.complement).is_tautology?
|
138
|
-
|
161
|
+
# check0 = (cover + simple.complement).is_tautology?
|
162
|
+
check0 = same_truth_table?(cover,simple)
|
139
163
|
# assert_equal(true,check0)
|
140
164
|
print "check 0 = #{check0}\n"
|
141
165
|
raise "Test failure" unless check0
|
data/lib/logic_tools/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logic_tools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lovic Gauthier
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-01-
|
11
|
+
date: 2017-01-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|