catlogic 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +36 -0
  9. data/Rakefile +7 -0
  10. data/bin2/.idea/.name +1 -0
  11. data/bin2/.idea/bin.iml +9 -0
  12. data/bin2/.idea/encodings.xml +5 -0
  13. data/bin2/.idea/misc.xml +5 -0
  14. data/bin2/.idea/modules.xml +9 -0
  15. data/bin2/.idea/scopes/scope_settings.xml +5 -0
  16. data/bin2/.idea/vcs.xml +7 -0
  17. data/bin2/.idea/workspace.xml +129 -0
  18. data/bin2/displayInferredTruths.rb +43 -0
  19. data/bin2/getAllValidPropositions.rb +24 -0
  20. data/bin2/testCombineSets.rb +27 -0
  21. data/bin2/testIfUnique.rb +14 -0
  22. data/bin2/testPremisePair.rb +10 -0
  23. data/bin2/testProposition.rb +47 -0
  24. data/bin2/testPropositionType.rb +40 -0
  25. data/bin2/testQuantity.rb +12 -0
  26. data/bin2/testReduceToUniqueSet.rb +18 -0
  27. data/bin2/testSyllogism.rb +45 -0
  28. data/bin2/testSyllogismForm.rb +51 -0
  29. data/catlogic.gemspec +25 -0
  30. data/lib/catlogic/distribution.rb +16 -0
  31. data/lib/catlogic/figure.rb +45 -0
  32. data/lib/catlogic/form.rb +22 -0
  33. data/lib/catlogic/mood.rb +14 -0
  34. data/lib/catlogic/premise_collection.rb +211 -0
  35. data/lib/catlogic/premise_pair.rb +61 -0
  36. data/lib/catlogic/proposition.rb +181 -0
  37. data/lib/catlogic/proposition_type.rb +47 -0
  38. data/lib/catlogic/quality.rb +16 -0
  39. data/lib/catlogic/quantity.rb +16 -0
  40. data/lib/catlogic/syllogism.rb +171 -0
  41. data/lib/catlogic/term.rb +32 -0
  42. data/lib/catlogic/version.rb +3 -0
  43. data/lib/catlogic.rb +17 -0
  44. data/spec/distribution_spec.rb +26 -0
  45. data/spec/figure_spec.rb +27 -0
  46. data/spec/form_spec.rb +22 -0
  47. data/spec/mood_spec.rb +17 -0
  48. data/spec/premise_pair_spec.rb +51 -0
  49. data/spec/proposition_spec.rb +215 -0
  50. data/spec/proposition_type_spec.rb +37 -0
  51. data/spec/quality_spec.rb +17 -0
  52. data/spec/quantity_spec.rb +19 -0
  53. data/spec/spec_helper.rb +89 -0
  54. data/spec/syllogism_spec.rb +121 -0
  55. data/spec/term_spec.rb +35 -0
  56. metadata +166 -0
data/catlogic.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'catlogic/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "catlogic"
8
+ spec.version = Catlogic::VERSION
9
+ spec.authors = ["Jeffrey C. Witt"]
10
+ spec.email = ["jeffreycwitt@gmail.com"]
11
+ spec.summary = %q{A gem for building categorial propositions and syllogisms}
12
+ spec.description = %q{A gem for building categorial propositions and syllogisms}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency 'rspec'
24
+ spec.add_development_dependency 'pry'
25
+ end
@@ -0,0 +1,16 @@
1
+ class Distribution
2
+ attr_reader :label
3
+
4
+ def initialize(distribution)
5
+ @label = distribution
6
+ end
7
+
8
+ def opposite
9
+ if self.label == 'distributed'
10
+ opposite = Distribution.new('undistributed')
11
+ elsif self.label == 'undistributed'
12
+ opposite = Distribution.new('distributed')
13
+ end
14
+ return opposite
15
+ end
16
+ end
@@ -0,0 +1,45 @@
1
+ class Figure
2
+ attr_reader :label
3
+
4
+ def initialize(figure)
5
+ @label = figure
6
+ end
7
+
8
+
9
+ def major_subject
10
+ if @label == 1 || @label == 3
11
+ subject = Term.new('M')
12
+
13
+ elsif @label == 2 || @label == 4
14
+ subject = Term.new('P')
15
+ end
16
+ return subject
17
+ end
18
+
19
+ def major_predicate
20
+ if @label == 1 || @label == 3
21
+ predicate = Term.new("P")
22
+ elsif @label == 2 || @label == 4
23
+ predicate = Term.new("M")
24
+ end
25
+ return predicate
26
+ end
27
+ def minor_subject
28
+ if @label == 1 || @label == 2
29
+ subject = Term.new("S")
30
+
31
+ elsif @label == 3 || @label == 4
32
+ subject = Term.new("M")
33
+
34
+ end
35
+ return subject
36
+ end
37
+ def minor_predicate
38
+ if @label == 1 || @label == 2
39
+ predicate = Term.new("M")
40
+ elsif @label == 3 || @label == 4
41
+ predicate = Term.new("S")
42
+ end
43
+ return predicate
44
+ end
45
+ end
@@ -0,0 +1,22 @@
1
+ class Form
2
+ attr_reader :mood, :figure, :label
3
+ # takes three Mood Object and Figure Object
4
+ def initialize(mood, figure)
5
+ @mood = mood
6
+ @figure = figure
7
+ @label = "#{@mood.label}#{@figure.label}"
8
+ end
9
+ def syllogism
10
+ majorproposition = Proposition.new(@mood.majortype.quantity, @figure.major_subject, @mood.majortype.quality, @figure.major_predicate, true)
11
+ minorproposition = Proposition.new(@mood.minortype.quantity, @figure.minor_subject, @mood.minortype.quality, @figure.minor_predicate, true)
12
+ conclusion = Proposition.new(@mood.conclusiontype.quantity, Term.new("S"), @mood.conclusiontype.quality, Term.new("P"), true)
13
+
14
+ syllogism = Syllogism.new(majorproposition, minorproposition, conclusion)
15
+
16
+ return syllogism
17
+ end
18
+ def validity
19
+ syllogism = self.syllogism
20
+ syllogism.validity
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ class Mood
2
+ attr_reader :majortype, :minortype, :conclusiontype
3
+
4
+ # takes three propositionType objects
5
+ def initialize(majortype, minortype, conclusiontype)
6
+ @majortype = majortype
7
+ @minortype = minortype
8
+ @conclusiontype = conclusiontype
9
+ end
10
+
11
+ def label
12
+ "#{@majortype.label}#{@minortype.label}#{@conclusiontype.label}"
13
+ end
14
+ end
@@ -0,0 +1,211 @@
1
+ class PremiseCollection
2
+ def initialize(propositionarray)
3
+ @collection = propositionarray
4
+ end
5
+
6
+ def getAllValidSyllogisms
7
+
8
+ if @collection.count < 2
9
+ puts "collection must include two or more propositions"
10
+ else
11
+ #inputconclusions = @collection
12
+ validsyllogisms = []
13
+ pairs = []
14
+
15
+ @collection.each do |proposition|
16
+
17
+ @collection.each do |secondproposition|
18
+ unless proposition.equal? secondproposition
19
+ pairs << PremisePair.new(proposition, secondproposition)
20
+ end
21
+ end
22
+ end
23
+ pairs.each do |pair|
24
+ if pair.isThreeTermPair?
25
+ conclusions = pair.getPossibleConclusions
26
+ conclusions.each do |conclusion|
27
+ syllogism = Syllogism.new(pair.getMajor, pair.getMinor, conclusion)
28
+ if syllogism.validity == "valid"
29
+ validsyllogisms << syllogism
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ return validsyllogisms
36
+ end
37
+
38
+ def getUniqueValidSyllogisms
39
+ inputconclusions = @collection
40
+ validsyllogisms = self.getAllValidSyllogisms
41
+ uniquevalidsyllogisms = []
42
+
43
+ validsyllogisms.each do |syllogism|
44
+ validconclusion = syllogism.getConclusion
45
+ if (validconclusion.isUnique?(inputconclusions))
46
+ uniquevalidsyllogisms << syllogism
47
+ end
48
+ end
49
+ return uniquevalidsyllogisms
50
+ end
51
+
52
+ =begin
53
+ def getUniqueInferredTruths
54
+
55
+ uniquevalidsyllogisms = self.getUniqueValidSyllogisms
56
+ uniqueinferredtruths = []
57
+
58
+ uniquevalidsyllogisms.each do |syllogism|
59
+ uniqueinferredtruths << syllogism.getConclusion
60
+ end
61
+
62
+ return uniqueinferredtruths
63
+ end
64
+ =end
65
+
66
+ def getAllInferredTruths
67
+ inputconclusions = @collection
68
+ inferredconclusions = []
69
+
70
+ validsyllogisms = self.getAllValidSyllogisms
71
+ validsyllogisms.each do |syllogism|
72
+ validconclusion = syllogism.getConclusion
73
+
74
+ if (validconclusion.isUnique?(inputconclusions))
75
+ inferredconclusions << validconclusion
76
+ end
77
+ end
78
+ return inferredconclusions
79
+ end
80
+
81
+
82
+ def getUniqueInferredTruths
83
+ newset = PremiseCollection.new(self.getAllInferredTruths)
84
+ unique_inferredconclusions = newset.reduceToUniqueSet
85
+ return unique_inferredconclusions
86
+ end
87
+
88
+
89
+
90
+ def displayLoopedInferredTruths
91
+
92
+ #get first set of inferences from initial collection set
93
+ inferredtruths = self.getUniqueInferredTruths
94
+ #combine with existing - on first interation will be comined with empty array
95
+ combinedset = self.combineSets(inferredtruths)
96
+
97
+ puts "======================="
98
+ puts "first set of inferences"
99
+ puts inferredtruths.count
100
+ puts "======================="
101
+
102
+
103
+ self.displayAllValidSyllogisms
104
+ self.displayUniqueSyllogisms
105
+ self.displayInferredTruths
106
+
107
+
108
+ while (inferredtruths.count != 0)
109
+
110
+ ## create new collection object
111
+ newcollection = PremiseCollection.new(combinedset)
112
+
113
+ ## get next set of inferences
114
+
115
+ #reset inferred truths
116
+ inferredtruths = newcollection.getUniqueInferredTruths
117
+ #rest combined set
118
+ combinedset = newcollection.combineSets(inferredtruths)
119
+
120
+ puts "======================="
121
+ puts "next set of inferences"
122
+ puts inferredtruths.count
123
+ puts "======================="
124
+
125
+ #display inferred set
126
+ newcollection.displayAllValidSyllogisms
127
+ newcollection.displayUniqueSyllogisms
128
+ newcollection.displayInferredTruths
129
+
130
+ end
131
+ end
132
+
133
+
134
+ def combineSets(newset)
135
+ newcollection = []
136
+
137
+ newcollection << @collection
138
+ newcollection << newset
139
+
140
+
141
+ return newcollection.flatten
142
+ end
143
+
144
+
145
+
146
+ def reduceToUniqueSet
147
+ unique_knownconclusions = []
148
+
149
+ @collection.each do |conclusion|
150
+ if unique_knownconclusions.count == 0
151
+ unique_knownconclusions << conclusion
152
+ elsif conclusion.isUnique?(unique_knownconclusions)
153
+ unique_knownconclusions << conclusion
154
+ end
155
+
156
+
157
+ end
158
+ return unique_knownconclusions
159
+ end
160
+
161
+ def displayInferredTruths
162
+ truths = self.getUniqueInferredTruths
163
+ puts
164
+ puts "==== Begin Display All Unique Inferred Truths ==="
165
+ truths.each do |truth|
166
+ truth.displayProposition
167
+ end
168
+ puts "==== End Display All Unique Inferred Truths ==="
169
+ puts
170
+
171
+ end
172
+
173
+ def displayAllValidSyllogisms
174
+ puts
175
+ puts "====== Begin Display All Valid Syllogisms==="
176
+ allvalidsyllogisms = self.getAllValidSyllogisms
177
+ allvalidsyllogisms.each do |syllogism|
178
+ syllogism.displayForm
179
+ syllogism.displaySyllogism
180
+ puts
181
+ end
182
+ puts "======End All Vallid Syllogisms==="
183
+ puts
184
+ end
185
+
186
+ def displayUniqueSyllogisms
187
+
188
+ puts
189
+ puts "======Begin Display All Syllogism Producing new truths==="
190
+ uniquevalidsyllogisms = self.getUniqueValidSyllogisms
191
+ uniquevalidsyllogisms.each do |syllogism|
192
+ syllogism.displayForm
193
+ syllogism.displaySyllogism
194
+ puts
195
+ end
196
+ puts "======End Display All Syllogism Producing new truths==="
197
+ puts
198
+
199
+ end
200
+
201
+
202
+ def getNumberOfInferredTruths
203
+ self.getUniqueInferredTruths.count
204
+ end
205
+ def getNumberOfInputTruths
206
+ @collection.count
207
+ end
208
+ def getRatioInputToInferred
209
+ self.getNumberOfInferredTruths / self.getNumberOfInputTruths
210
+ end
211
+ end
@@ -0,0 +1,61 @@
1
+ class PremisePair
2
+
3
+ attr_reader :major, :minor
4
+
5
+ def initialize(major, minor)
6
+ @major = major
7
+ @minor = minor
8
+ end
9
+
10
+ def middle
11
+ termarray = [@major.subject.label, @major.predicate.label, @minor.subject.label, @minor.predicate.label]
12
+ middle = nil
13
+ if self.three_term_pair?
14
+ termarray.detect do |term|
15
+ if termarray.count(term) == 2
16
+ middle = Term.new(term)
17
+ end
18
+ end
19
+ else
20
+ middle = "Error: this is not a three term syllogism"
21
+ end
22
+ return middle
23
+ end
24
+
25
+ def three_term_pair?
26
+ termarray = [@major.subject.label, @major.predicate.label, @minor.subject.label, @minor.predicate.label]
27
+ if termarray.uniq.size == 3
28
+ answer = true
29
+ else
30
+ answer = false
31
+ end
32
+ end
33
+
34
+ def majorterm
35
+ if @major.subject.label == self.middle.label
36
+ majorterm = @major.predicate
37
+ else
38
+ majorterm = @major.subject
39
+ end
40
+ majorterm
41
+ end
42
+ def minorterm
43
+ if @minor.subject.label == self.middle.label
44
+ minorterm = @minor.predicate
45
+ else
46
+ minorterm = @minor.subject
47
+ end
48
+ minorterm
49
+ end
50
+
51
+ # still need a test for this
52
+ def possible_conclusions
53
+ @possible_conclusions = [
54
+ Proposition.new(Quantity.new("universal"), self.minor, Quality.new("affirmative"), self.minor, true),
55
+ Proposition.new(Quantity.new("universal"), self.minor, Quality.new("negative"), self.minor, true),
56
+ Proposition.new(Quantity.new("particular"), self.minor, Quality.new("affirmative"), self.minor, true),
57
+ Proposition.new(Quantity.new("particular"), self.minor, Quality.new("negative"), self.minor, true)
58
+ ]
59
+ end
60
+
61
+ end
@@ -0,0 +1,181 @@
1
+ class Proposition
2
+
3
+ attr_reader :quantity, :subject, :quality, :predicate, :truthvalue
4
+
5
+ def initialize(quantity, subject, quality, predicate, truthvalue)
6
+ @quantity=quantity
7
+ @subject=subject
8
+ @quality=quality
9
+ @predicate=predicate
10
+ @truthvalue=truthvalue
11
+ end
12
+
13
+ def type
14
+ if @quantity.label == 'universal' && @quality.label == 'affirmative'
15
+ @type=PropositionType.new("A")
16
+ elsif @quantity.label == 'universal' && @quality.label == 'negative'
17
+ @type=PropositionType.new("E")
18
+ elsif @quantity.label == 'particular' && @quality.label == 'affirmative'
19
+ @type=PropositionType.new("I")
20
+ elsif @quantity.label == 'particular' && @quality.label == 'negative'
21
+ @type=PropositionType.new("O")
22
+ end
23
+ return @type
24
+ end
25
+
26
+ def contradictory
27
+
28
+ quantity = @quantity.opposite
29
+ quality = @quality.opposite
30
+
31
+ @contradictory = Proposition.new(quantity, @subject, quality, @predicate, !@truthvalue)
32
+ return @contradictory
33
+ end
34
+
35
+ def subaltern
36
+
37
+ quantity = @quantity.opposite
38
+
39
+ if @quantity.label == "universal"
40
+ if @truthvalue
41
+ truthvalue = @truthvalue
42
+ elsif !@truthvalue
43
+ truthvalue = "unknown"
44
+ end
45
+ elsif @quantity.label == "particular"
46
+ if !@truthvalue
47
+ truthvalue = !@truthvalue
48
+ elsif @truthvalue
49
+ truthvalue = "unknown"
50
+ end
51
+ end
52
+
53
+ @subaltern = Proposition.new(quantity, @subject, @quality, @predicate, truthvalue)
54
+ return @subaltern
55
+ end
56
+
57
+ def contrary
58
+ if @quantity.label == "particular"
59
+ abort("There is no contrary for this type of propostion. Try subcontrary")
60
+ end
61
+ quality = @quality.opposite
62
+
63
+ if @truthvalue
64
+ truthvalue = !@truthvalue
65
+ elsif !@truthvalue
66
+ truthvalue = "unknown"
67
+ end
68
+
69
+ contrary = Proposition.new(@quantity, @subject, quality, @predicate, truthvalue)
70
+ return contrary
71
+ end
72
+
73
+ def subcontrary
74
+ if @quantity.label == "universal"
75
+ abort("There is no subcontrary for this type of propostion. Try contrary.")
76
+ end
77
+
78
+ quality = @quality.opposite
79
+
80
+ if !@truthvalue
81
+ truthvalue = !@truthvalue
82
+ elsif @truthvalue
83
+ truthvalue = "unknown"
84
+ end
85
+
86
+ subcontrary = Proposition.new(@quantity, @subject, quality, @predicate, truthvalue)
87
+ return subcontrary
88
+ end
89
+
90
+ def converse
91
+ if self.type.label == "A" || self.type.label == "O"
92
+ truthvalue = "unknown"
93
+ else
94
+ truthvalue = @truthvalue
95
+ end
96
+ @converse = Proposition.new(@quantity, @predicate, @quality, @subject, truthvalue)
97
+ end
98
+
99
+ def obverse
100
+ quality = @quality.opposite
101
+
102
+ predicate = @predicate.opposite
103
+ @obverse = Proposition.new(@quantity, @subject, quality, predicate, @truthvalue)
104
+ end
105
+
106
+ def contrapolated
107
+ if self.type.label == "E" || self.type.label == "I"
108
+ truthvalue = "unknown"
109
+ else
110
+ truthvalue = @truthvalue
111
+ end
112
+ subject = @subject.opposite
113
+ predicate = @predicate.opposite
114
+
115
+ @contrapolated = Proposition.new(@quantity, predicate, @quality, subject, truthvalue)
116
+
117
+ end
118
+
119
+ def position_of_term(term)
120
+ if self.subject.label == term.label
121
+ @positionofmiddle = 'subject'
122
+ elsif self.predicate.label == term.label
123
+ @positionofmiddle = 'predicate'
124
+ end
125
+ return @positionofmiddle
126
+ end
127
+
128
+ def label
129
+ if @quantity.label == "universal"
130
+ if @quality.label == "affirmative"
131
+ display_quantity = "All"
132
+ display_quality = "are"
133
+ elsif @quality.label == "negative"
134
+ display_quantity = "No"
135
+ display_quality = "are"
136
+ end
137
+ elsif @quantity.label == "particular"
138
+ if @quality.label == "affirmative"
139
+ display_quantity = "Some"
140
+ display_quality = "are"
141
+ elsif @quality.label == "negative"
142
+ display_quantity = "Some"
143
+ display_quality = "are not"
144
+ end
145
+ end
146
+ "#{display_quantity} #{@subject.label} #{display_quality} #{@predicate.label}"
147
+ end
148
+
149
+ def distribution(position)
150
+ if position == 'subject'
151
+ distribution = @subject.distribution_subject(@quantity)
152
+ elsif position == 'predicate'
153
+ distribution = @predicate.distribution_predicate(@quality)
154
+ end
155
+ return distribution
156
+ end
157
+
158
+ def unique?(set)
159
+ numerofoccurences = self.number_of_occurences(set)
160
+ if numerofoccurences == 0
161
+ true
162
+ else
163
+ false
164
+ end
165
+ end
166
+
167
+ def number_of_occurences(set)
168
+ @occurences = 0
169
+ set.each do |proposition|
170
+ if (proposition.quantity.label == self.quantity.label &&
171
+ proposition.subject.label == self.subject.label &&
172
+ proposition.quality.label == self.quality.label &&
173
+ proposition.predicate.label == self.predicate.label &&
174
+ proposition.truthvalue == self.truthvalue)
175
+ @occurences += 1
176
+ end
177
+ end
178
+ @occurences
179
+ end
180
+
181
+ end
@@ -0,0 +1,47 @@
1
+ class PropositionType
2
+
3
+ attr_reader :label, :truthvalue
4
+
5
+ def initialize(type, truthvalue=true)
6
+ @type = type
7
+ @label = type
8
+ @truthvalue = truthvalue
9
+ end
10
+ def getType
11
+ @type
12
+ end
13
+
14
+ def quantity
15
+ if @label == "A"
16
+ quantity = Quantity.new("universal")
17
+ elsif @label == "E"
18
+ quantity = Quantity.new("universal")
19
+ elsif @label == "I"
20
+ quantity = Quantity.new("particular")
21
+ elsif @label == "O"
22
+ quantity = Quantity.new("particular")
23
+ else
24
+ quantity = "not a valid type"
25
+ end
26
+ return quantity
27
+ end
28
+ def quality
29
+ if @label == "A"
30
+ quality = Quality.new("affirmative")
31
+ elsif @label == "E"
32
+ quality = Quality.new("negative")
33
+ elsif @label == "I"
34
+ quality = Quality.new("affirmative")
35
+ elsif @label == "O"
36
+ quality = Quality.new("negative")
37
+ else
38
+ quality = "not a valid type"
39
+ end
40
+ return quality
41
+ end
42
+
43
+ def proposition
44
+ proposition = Proposition.new(Quantity.new(self.quantity.label), Term.new("S"), Quality.new(self.quality.label), Term.new("P"), @truthvalue)
45
+ return proposition
46
+ end
47
+ end
@@ -0,0 +1,16 @@
1
+ class Quality
2
+ attr_reader :label
3
+
4
+ def initialize(quality)
5
+ @label = quality
6
+ end
7
+
8
+ def opposite
9
+ if self.label == 'negative'
10
+ qualityopposite = Quality.new('affirmative')
11
+ elsif self.label == 'affirmative'
12
+ qualityopposite = Quality.new('negative')
13
+ end
14
+ return qualityopposite
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ class Quantity
2
+ attr_reader :label
3
+
4
+ def initialize(quantity)
5
+ @label = quantity
6
+ end
7
+
8
+ def opposite
9
+ if self.label == 'universal'
10
+ quantityopposite = Quantity.new('particular')
11
+ elsif self.label == 'particular'
12
+ quantityopposite = Quantity.new('universal')
13
+ end
14
+ return quantityopposite
15
+ end
16
+ end