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

&(*others)
Alias for: and
-@()
Alias for: not
>>(other)
Alias for: then
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
Also aliased as: ~, -@
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
|(*others)
Alias for: or
~()
Alias for: not

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