class PropLogic::Term
monkey-patching cache generation
Abstract base class for terms of PropLogic
. Actual terms are subclasses of Term
.
Attributes
terms[R]
Public Class Methods
get(klass, *terms)
click to toggle source
# File lib/prop_logic/term.rb, line 124 def self.get(klass, *terms) terms = validate_terms(*terms) if klass == AndTerm || klass == OrTerm terms = terms.map { |t| t.is_a?(klass) ? t.terms : t }.flatten return terms[0] if terms.length == 1 end cached klass, *terms end
Protected Class Methods
new()
click to toggle source
@raise NotImplementedError Term
is abstract class.
# File lib/prop_logic/term.rb, line 13 def initialize raise NotImplementedError, 'Term cannot be initialized' end
Private Class Methods
cached(klass, *terms)
click to toggle source
# File lib/prop_logic/term.rb, line 111 def self.cached(klass, *terms) @table ||= generate_cache key = klass.name + terms.map(&:object_id).join(',') return @table[key] if @table[key] ret = klass.__send__ :new, *terms @table[key] = ret # kick caching mechanism ret.variables ret.freeze end
generate_cache()
click to toggle source
# File lib/prop_logic/hash_cache.rb, line 5 def self.generate_cache {} end
validate_terms(*terms)
click to toggle source
# File lib/prop_logic/term.rb, line 87 def self.validate_terms(*terms) raise ArgumentError, 'no terms given' if terms.empty? terms.map do |term| case term when TrueClass True when FalseClass False when Term term else raise TypeError, "#{term.class} cannot be treated as term" end end end
Public Instance Methods
and(*others)
click to toggle source
# File lib/prop_logic/term.rb, line 28 def and(*others) others.unshift self Term.get AndTerm, *others end
Also aliased as: &
assign(trues, falses, variables = nil)
click to toggle source
# File lib/prop_logic/term.rb, line 144 def assign(trues, falses, variables = nil) # contradicted assignment raise ArgumentError, 'Contradicted assignment' unless (trues & falses).empty? variables ||= trues | falses assigned_terms = terms.map do |term| if (term.variables & variables).empty? term else term.assign(trues, falses, variables) end end Term.get self.class, *assigned_terms end
assign_false(*variables)
click to toggle source
# File lib/prop_logic/term.rb, line 162 def assign_false(*variables) assign [], variables end
assign_true(*variables)
click to toggle source
# File lib/prop_logic/term.rb, line 158 def assign_true(*variables) assign variables, [] end
cnf?()
click to toggle source
check if this term is a cnf term. @return [Boolean] false unless overridden.
# File lib/prop_logic/term.rb, line 135 def cnf? false end
each_sat() { |sat| ... }
click to toggle source
loop with each satisfied terms. @return [Enumerator] if block is not given. @return [nil] if block is given.
# File lib/prop_logic/term.rb, line 173 def each_sat return to_enum(:each_sat) unless block_given? sat_loop(self) do |sat, solver| yield sat negated_vars = sat.terms.map do |t| t.is_a?(NotTerm) ? t.terms[0] : ~t end solver << PropLogic.all_or(*negated_vars) end end
equiv?(other)
click to toggle source
# File lib/prop_logic/term.rb, line 188 def equiv?(other) ((self | other) & (~self | ~other)).unsat? end
initialize_copy(*)
click to toggle source
disallow duplication
# File lib/prop_logic/term.rb, line 18 def initialize_copy(*) raise TypeError, 'Term cannot be duplicated (immutable, not necessary)' end
nnf?()
click to toggle source
# File lib/prop_logic/term.rb, line 67 def nnf? false end
not()
click to toggle source
# File lib/prop_logic/term.rb, line 42 def not Term.get NotTerm, self end
or(*others)
click to toggle source
# File lib/prop_logic/term.rb, line 35 def or(*others) others.unshift self Term.get OrTerm, *others end
Also aliased as: |
reduce()
click to toggle source
# File lib/prop_logic/term.rb, line 71 def reduce if reduced? self else Term.get self.class, *@terms.map(&:reduce) end end
reduced?()
click to toggle source
# File lib/prop_logic/term.rb, line 79 def reduced? false end
sat?()
click to toggle source
# File lib/prop_logic/term.rb, line 166 def sat? PropLogic.sat_solver.call(self) end
then(other)
click to toggle source
# File lib/prop_logic/term.rb, line 49 def then(other) Term.get ThenTerm, self, other end
Also aliased as: >>
to_cnf()
click to toggle source
# File lib/prop_logic/term.rb, line 83 def to_cnf reduce.to_cnf end
to_nnf()
click to toggle source
# File lib/prop_logic/term.rb, line 59 def to_nnf if nnf? self else Term.get self.class, *@terms.map(&:to_nnf) end end
to_s_in_term()
click to toggle source
# File lib/prop_logic/term.rb, line 55 def to_s_in_term to_s true end
unsat?()
click to toggle source
# File lib/prop_logic/term.rb, line 184 def unsat? sat? == false end
variables()
click to toggle source
@return [Array] variables used by this term.
# File lib/prop_logic/term.rb, line 140 def variables @variables ||= @terms.map(&:variables).flatten.uniq end
Private Instance Methods
check_ambivalent_vars()
click to toggle source
# File lib/prop_logic/term.rb, line 200 def check_ambivalent_vars return unless @is_reduced term_by_class = @terms.group_by(&:class) return if term_by_class[NotTerm].nil? || term_by_class[Variable].nil? negated_variales = term_by_class[NotTerm].map { |t| t.terms[0] } @is_reduced = false unless (negated_variales & term_by_class[Variable]).empty? end
check_nnf_reduced()
click to toggle source
# File lib/prop_logic/term.rb, line 208 def check_nnf_reduced @is_reduced = true @is_nnf = @terms.all? do |term| @is_reduced &&= !term.is_a?(Constant) && term.reduced? @is_reduced &&= !term.is_a?(NotTerm) || term.terms[0].is_a?(Variable) next true if @is_reduced term.nnf? end return unless @is_reduced check_term_uniqueness check_ambivalent_vars end
check_term_uniqueness()
click to toggle source
checking methods
# File lib/prop_logic/term.rb, line 196 def check_term_uniqueness @is_reduced &&= (@terms.length == @terms.uniq.length) end