logic_tools 0.2.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env ruby
2
+ #########################################################################
3
+ # Simplifies a logic expression using the ESPRESSO algorithm #
4
+ #########################################################################
5
+
6
+
7
+ # For building logic trees
8
+ require "logic_tools/logictree.rb"
9
+
10
+ # For parsing the inputs
11
+ require "logic_tools/logicparse.rb"
12
+
13
+ # For simplifying with the ESPRESSO method.
14
+ require "logic_tools/logicsimplify_es.rb"
15
+
16
+ # For the command line interface
17
+ require "logic_tools/logicinput.rb"
18
+
19
+ include LogicTools
20
+
21
+
22
+
23
+
24
+
25
+ ############################
26
+ # The main program
27
+
28
+ # Iterrate on each expression
29
+ each_input do |expr|
30
+ # Parse the expression
31
+ parsed = string2logic(expr)
32
+
33
+ # Simplify it
34
+ simple = parsed.simplify
35
+ # print "Computation done\n"
36
+
37
+ # Display the result
38
+ print simple.to_s, "\n"
39
+ end
@@ -10,11 +10,8 @@ require "logic_tools/logictree.rb"
10
10
  # For parsing the inputs
11
11
  require "logic_tools/logicparse.rb"
12
12
 
13
- # For simplifying
14
- require "logic_tools/logicsimplify.rb"
15
-
16
- # For the command line interface
17
- require "logic_tools/logicinput.rb"
13
+ # For simplifying with the Quine Mc Cluskey method.
14
+ require "logic_tools/logicsimplify_qm.rb"
18
15
 
19
16
  # For the command line interface
20
17
  require "logic_tools/logicinput.rb"
@@ -28,19 +25,6 @@ include LogicTools
28
25
  ############################
29
26
  # The main program
30
27
 
31
- ## Now use the common command line interface
32
- # # First gets the expression to treat
33
- # $expr = nil
34
- # # Is it in the arguments?
35
- # unless $*.empty? then
36
- # # Yes, get the expression from them
37
- # $expr = $*.join
38
- # else
39
- # # Get the expression from standard input
40
- # print "Please enter your expression and end with ^D:\n"
41
- # $expr = ARGF.read
42
- # end
43
- #
44
28
 
45
29
  # Iterrate on each expression
46
30
  each_input do |expr|
@@ -0,0 +1,161 @@
1
+ ######################################################################
2
+ # The test program for logic tools #
3
+ # #
4
+ # NOTE: This still a very imcomplete work! #
5
+ ######################################################################
6
+
7
+ # require 'minitest/autorun'
8
+ require "logic_tools/logicsimplify_es.rb"
9
+ require "logic_tools/logicgenerator.rb"
10
+
11
+ include LogicTools
12
+
13
+ ## Class for testing the implementation of the ESPRESSO algorithm.
14
+ class TestEspresso # < MiniTest::Unit::TestCase
15
+
16
+ ## Creates the tester with a +seed+ for random generation, a
17
+ # +deadline+ for the simplify steps and a +volume+ before splitting
18
+ # the cover.
19
+ def initialize(seed = 0, deadline = Float::INFINITY,
20
+ volume = Float::INFINITY)
21
+ @seed = seed
22
+ @deadline = deadline
23
+ @volume = volume
24
+ end
25
+
26
+ ## Checks if a +cover+ is a tautology by generating its truth table.
27
+ def truth_tautology(cover)
28
+ ## Generate each possible input and test it on the cover.
29
+ (2**(cover.width)).times do |i|
30
+ return false unless cover.eval(i)
31
+ end
32
+ return true
33
+ end
34
+
35
+ ## Tests the tautology check on covers generated by a random +generator+.
36
+ #
37
+ # NOTE: ends when a tautology is actually found.
38
+ def test_tautology_random(generator)
39
+ # Create the cover.
40
+ cover = Cover.new(*generator.each_variable)
41
+ # Tautology results.
42
+ taut0, taut1 = false, false
43
+ # Add random cubes to the cover until a tautology is met while.
44
+ begin
45
+ # Add a random cube.
46
+ cover << generator.random_cube
47
+ print "Tautology check on cover=[#{cover.to_s}]...\n"
48
+ # Check if the cover is a tautology using the standard approach.
49
+ taut0 = cover.is_tautology?
50
+ print "Through is_tautology?: #{taut0}; "
51
+ # Check it again with a truth table.
52
+ taut1 = truth_tautology(cover)
53
+ print "through truth table: #{taut1}\n"
54
+ raise "Test failure" unless taut0 == taut1
55
+ end while (!taut0)
56
+ return true
57
+ end
58
+
59
+ ## Tests randomly +number+ tautology cases on a +dimensions+ boolean
60
+ # space.
61
+ def test_tautologies_random(number = 1024, dimensions = 4)
62
+ # Create the variables.
63
+ base = "`"
64
+ variables = dimensions.times.map { |i| base.next!.clone }
65
+ # Create the generator.
66
+ generator = Generator.new(*variables)
67
+ generator.seed = @seed
68
+ # Performs the tests.
69
+ number.times do |i|
70
+ print "Test #{i}: "
71
+ return false unless test_tautology_random(generator)
72
+ end
73
+ return true
74
+ end
75
+
76
+
77
+ ## Checks if covers have the same truth table.
78
+ def same_truth_table?(cover0,cover1)
79
+ return false unless cover0.width == cover1.width
80
+ # Check for each entry.
81
+ (2**cover0.width).times do |i|
82
+ return false unless cover0.eval(i) == cover1.eval(i)
83
+ end
84
+ return true
85
+ end
86
+
87
+
88
+ ## Tests espresso on a given +cover+.
89
+ def test_espresso(cover)
90
+ print "ESPRESSO on cover=[#{cover.to_s}]...\n"
91
+ simple = cover.simplify(@deadline,@volume)
92
+ print "result: [#{simple}]\n"
93
+ check0 = (cover + simple.complement).is_tautology?
94
+ # check0 = same_truth_table?(cover,simple)
95
+ # assert_equal(true,check0)
96
+ print "check 0 = #{check0}\n"
97
+ raise "Test failure" unless check0
98
+ check1 = (cover.complement + simple).is_tautology?
99
+ # assert_equal(true,check1)
100
+ print "check 1 = #{check1}\n"
101
+ raise "Test failure" unless check1
102
+ return true
103
+ end
104
+
105
+ ## Tests the implementation of the espresso algorithm on each
106
+ # possible 1-cube cover of 4 variables.
107
+ #
108
+ # Test only on cover if a +test+ number is given.
109
+ def test_espresso_all(test = nil)
110
+ generator = Generator.new("a","b","c","d")
111
+ generator.seed = @seed
112
+ if test then
113
+ test = test.to_i
114
+ print "Test #{test}: "
115
+ return test_espresso(generator.make_1cover(test))
116
+ else
117
+ generator.each_1cover.with_index do |cover,i|
118
+ print "Test #{i}: "
119
+ return false unless test_espresso(cover)
120
+ end
121
+ return true
122
+ end
123
+ end
124
+
125
+ ## Tests ESPRESSO on a cover generated by a random +generator+.
126
+ def test_espresso_random(generator)
127
+ # Genrate a random cover.
128
+ cover = generator.random_cover
129
+ # Test it.
130
+ return false unless test_espresso(cover)
131
+ return true
132
+ end
133
+
134
+ ## Tests ESPRESSO on randomly +number+ cover cases on a +dimensions+ boolean
135
+ # space, including at most +max+ cubes.
136
+ def test_espressos_random(number = 1024, dimensions = 4, max = nil)
137
+ # Create the variables.
138
+ base = "`"
139
+ variables = dimensions.times.map { |i| base.next!.clone }
140
+ # Create the generator.
141
+ generator = Generator.new(*variables)
142
+ generator.seed = @seed
143
+ generator.max = max if max
144
+ # Ensures a rate of "-" large enough to have a high probability of
145
+ # an interesting cover (i.e., which is actually simplifiable).
146
+ # This rate +r+ is obainted as the solution of the followings:
147
+ # max/2 * 2**(r*dimensions) >= 2**dimensions
148
+ # NOTE: max/2 is the average size of the cover.
149
+ generator.rate = Math::log2(2**(dimensions+1)/max.to_f)/dimensions
150
+ # Ensures the rate is not too small though.
151
+ generator.rate = 0.3 unless generator.rate >= 0.3
152
+ print "rate=#{generator.rate}\n"
153
+ # Performs the tests.
154
+ number.times do |i|
155
+ print "Test #{i}: "
156
+ return false unless test_espresso_random(generator)
157
+ end
158
+ return true
159
+ end
160
+
161
+ end
@@ -0,0 +1,116 @@
1
+ require 'logger.rb'
2
+
3
+
4
+ module LogicTools
5
+
6
+ ## Small class for indenting
7
+ class Indenter
8
+ ## Creates a new indenter.
9
+ def initialize
10
+ @indent = 0
11
+ end
12
+
13
+ ## Increase the indent level by +value+.
14
+ #
15
+ # NOTE:
16
+ # * the indent level cannot be bellow 0.
17
+ # * the value can be negative.
18
+ def inc(value = 1)
19
+ @indent += value.to_i
20
+ @indent = 0 if @indent < 0
21
+ end
22
+
23
+ ## Decreases the indent level by +value+.
24
+ #
25
+ # NOTE:
26
+ # * the indent level cannot be bellow 0.
27
+ # * the value can be negative.
28
+ def dec(value = 1)
29
+ @indent -= value.to_i
30
+ @indent = 0 if @indent < 0
31
+ end
32
+
33
+ ## Converts to a string (generates the indent.)
34
+ def to_s
35
+ return " " * @indent
36
+ end
37
+ end
38
+
39
+
40
+ module Traces
41
+
42
+ # Add traces support to the logic tools.
43
+
44
+
45
+ ## The logger used for displaying the traces.
46
+ TRACES = Logger.new(STDOUT)
47
+
48
+ ## The indent for the traces.
49
+ TRACES_INDENT = Indenter.new
50
+
51
+ # Format the traces
52
+ TRACES.formatter = proc do |severity, datetime, progname, msg|
53
+ "[#{severity}] #{datetime}: #{TRACES_INDENT.to_s}#{msg}\n"
54
+ end
55
+ TRACES.datetime_format = '%H:%M:%S'
56
+
57
+ # By default the trace level is set warn.
58
+ TRACES.level = Logger::WARN
59
+
60
+
61
+ ## Sets the trace level to error.
62
+ def traces_error
63
+ TRACES.level = Logger::ERROR
64
+ end
65
+
66
+ ## Sets the trace level to warn.
67
+ def traces_warn
68
+ TRACES.level = Logger::WARN
69
+ end
70
+
71
+ ## Sets the trace level to info.
72
+ def traces_info
73
+ TRACES.level = Logger::INFO
74
+ end
75
+
76
+ ## Sets the trace level to debug
77
+ def traces_debug
78
+ TRACES.level = Logger::DEBUG
79
+ end
80
+
81
+
82
+ ## Sends an error-level trace.
83
+ def error(&blk)
84
+ TRACES.error(&blk)
85
+ end
86
+
87
+ ## Sends a warn-level trace.
88
+ def warn(&blk)
89
+ TRACES.warn(&blk)
90
+ end
91
+
92
+ ## Sends an info-level trace.
93
+ def info(&blk)
94
+ TRACES.info(&blk)
95
+ end
96
+
97
+ ## Sends a debug-level trace.
98
+ def debug(&blk)
99
+ TRACES.debug(&blk)
100
+ end
101
+
102
+
103
+ ## Increases the indent level by +value+.
104
+ def inc_indent(value = 1)
105
+ TRACES_INDENT.inc(value)
106
+ end
107
+
108
+ ## Deacreases the indent level by +value+.
109
+ def dec_indent(value = 1)
110
+ TRACES_INDENT.dec(value)
111
+ end
112
+
113
+
114
+ end
115
+
116
+ end
@@ -39,7 +39,7 @@ include LogicTools
39
39
  # $parsed = string2logic($expr)
40
40
  #
41
41
  # # Display the variables
42
- # $vars = $parsed.getVariables
42
+ # $vars = $parsed.get_variables
43
43
  # $vars.each { |var| print "#{var} " }
44
44
  # print "\n"
45
45
  #
@@ -55,7 +55,7 @@ each_input do |expr|
55
55
  parsed = string2logic(expr)
56
56
 
57
57
  # Display the variables
58
- vars = parsed.getVariables
58
+ vars = parsed.get_variables
59
59
  vars.each { |var| print "#{var} " }
60
60
  print "\n"
61
61
 
@@ -1,3 +1,3 @@
1
1
  module LogicTools
2
- VERSION = "0.2.4"
2
+ VERSION = "0.3.0"
3
3
  end
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.2.4
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lovic Gauthier
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-12-23 00:00:00.000000000 Z
11
+ date: 2017-01-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -74,6 +74,8 @@ description: "LogicTools is a set of command-line tools for processing logic exp
74
74
  email:
75
75
  - lovic@ariake-nct.ac.jp
76
76
  executables:
77
+ - is_tautology
78
+ - simplify_es
77
79
  - simplify_qm
78
80
  - std_conj
79
81
  - std_dij
@@ -89,19 +91,30 @@ files:
89
91
  - Rakefile
90
92
  - bin/console
91
93
  - bin/setup
94
+ - exe/is_tautology
95
+ - exe/simplify_es
92
96
  - exe/simplify_qm
93
97
  - exe/std_conj
94
98
  - exe/std_dij
95
99
  - exe/truth_tbl
96
100
  - lib/logic_tools.rb
101
+ - lib/logic_tools/is_tautology.rb
102
+ - lib/logic_tools/logicconvert.rb
103
+ - lib/logic_tools/logiccover.rb
104
+ - lib/logic_tools/logicgenerator.rb
97
105
  - lib/logic_tools/logicinput.rb
98
106
  - lib/logic_tools/logicparse.rb
99
- - lib/logic_tools/logicsimplify.rb
107
+ - lib/logic_tools/logicsimplify_es.rb
108
+ - lib/logic_tools/logicsimplify_qm.rb
100
109
  - lib/logic_tools/logictree.rb
110
+ - lib/logic_tools/minimal_column_covers.rb
101
111
  - lib/logic_tools/simplify_bug.txt
112
+ - lib/logic_tools/simplify_es.rb
102
113
  - lib/logic_tools/simplify_qm.rb
103
114
  - lib/logic_tools/std_conj.rb
104
115
  - lib/logic_tools/std_dij.rb
116
+ - lib/logic_tools/test_logic_tools.rb
117
+ - lib/logic_tools/traces.rb
105
118
  - lib/logic_tools/truth_tbl.rb
106
119
  - lib/logic_tools/version.rb
107
120
  - logic_tools.gemspec