Class: Porolog::Rule
Overview
A Porolog::Rule is one clause of a Porolog::Predicate.
Defined Under Namespace
Classes: DefinitionError, Error
Instance Attribute Summary collapse
-
#arguments ⇒ Object
readonly
The Arguments of the Predicate for which this Rule applies.
-
#definition ⇒ Object
readonly
The definition of the Rule.
Class Method Summary collapse
-
.reset ⇒ Boolean
Clears all Rules.
Instance Method Summary collapse
-
#initialize(arguments, definition = nil) ⇒ Rule
constructor
Initializes the Rule.
-
#inspect ⇒ String
Pretty representation.
-
#myid ⇒ String
Convenience method for testing/debugging.
-
#satisfy(goal, &block) ⇒ Boolean
Try to satisfy the Rule for the given Goal.
-
#satisfy_conjunction(goal, subgoal, conjunction, &block) ⇒ Boolean
Try to satisfy the conjunction of the definition of the Rule for a given Goal.
-
#satisfy_definition(goal, subgoal, &block) ⇒ Boolean
Try to satisfy the definition of the Rule for a given Goal.
Constructor Details
#initialize(arguments, definition = nil) ⇒ Rule
Initializes the Rule.
40 41 42 43 44 |
# File 'lib/porolog/rule.rb', line 40 def initialize(arguments, definition = nil) @arguments = arguments @definition = definition @@rules << self end |
Instance Attribute Details
#arguments ⇒ Object (readonly)
The Arguments of the Predicate for which this Rule applies.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/porolog/rule.rb', line 19 class Rule # Error class for rescuing or detecting any Rule error. class Error < PorologError ; end # Error class indicating that there is an error in the definition of the Rule. class DefinitionError < Error ; end attr_reader :arguments, :definition # Clears all Rules. # @return [Boolean] success def self.reset @@rules = [] true end reset # Initializes the Rule. # @param arguments [Porolog::Arguments] the Arguments of the Predicate for which this Rule applies. # @param definition [Object] the definition of the Rule. def initialize(arguments, definition = nil) @arguments = arguments @definition = definition @@rules << self end # Convenience method for testing/debugging # @return [String] pretty identification def myid "Rule#{(@@rules.index(self) || -1000) + 1}" end # @return [String] pretty representation. def inspect " #{@arguments.inspect}:- #{@definition.inspect}" end # Try to satisfy the Rule for the given Goal. # @param goal [Porolog::Goal] the Goal in which to satisfy this Rule. # @param block [Proc] code to perform when the Rule is satisfied. # @return [Boolean] the success of deleting the subgoal. def satisfy(goal, &block) subgoal = Goal.new self.arguments, goal unified_goals = unify_goals(goal, subgoal) if unified_goals satisfy_definition(goal, subgoal) do |solution_goal| block.call(solution_goal) end else subgoal.log << "Dead-end: Cannot unify with #{goal.inspect}" end subgoal.delete! end # Try to satisfy the definition of the Rule for a given Goal. # @param goal [Porolog::Goal] the given Goal for the Rule. # @param subgoal [Porolog::Goal] the subgoal for the Rule's definition. # @param block [Proc] code to perform when the definition is satisfied. # @return [Boolean] whether the definition was satisfied. def satisfy_definition(goal, subgoal, &block) case @definition when TrueClass block.call(subgoal) true when FalseClass false when Array satisfy_conjunction(goal, subgoal, @definition) do |solution_goal| block.call(solution_goal) end else raise DefinitionError, "UNEXPECTED TYPE OF DEFINITION: #{@definition.inspect} (#{@definition.class})" end end # Try to satisfy the conjunction of the definition of the Rule for a given Goal. # A conjunction is a sequence of expressions where the sequence is true # if all the expressions are true. # # @param goal [Porolog::Goal] the given Goal for the Rule. # @param subgoal [Porolog::Goal] the subgoal for the Rule's definition. # @param conjunction [Array] the conjunction to satisfy. # @param block [Proc] code to perform when the definition is satisfied. # @return [Boolean] whether the definition was satisfied. def satisfy_conjunction(goal, subgoal, conjunction, &block) arguments = conjunction.first conjunction = conjunction[1..-1] # -- Handle non-Arguments -- case arguments when :CUT, true subgoal.log << "CUTTING #{goal.inspect}..." result = true if conjunction.empty? !goal.terminated? && block.call(subgoal) else result = satisfy_conjunction(goal, subgoal, conjunction, &block) end if arguments == :CUT goal.terminate! goal.log << "TERMINATED after #{subgoal.inspect}" end return result when false return false when nil !goal.terminated? && block.call(subgoal) return true end # -- Unify Subsubgoal -- subsubgoal = arguments.goal(subgoal) unified = subsubgoal.inherit_variables(subgoal) # -- Satisfy Subgoal -- result = false unified && subsubgoal.satisfy() do result = true if conjunction.empty? !goal.terminated? && block.call(goal) else result = !goal.terminated? && satisfy_conjunction(goal, subsubgoal, conjunction, &block) end end # -- Uninstantiate -- subsubgoal.delete! result && !goal.terminated? end end |
#definition ⇒ Object (readonly)
The definition of the Rule.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/porolog/rule.rb', line 19 class Rule # Error class for rescuing or detecting any Rule error. class Error < PorologError ; end # Error class indicating that there is an error in the definition of the Rule. class DefinitionError < Error ; end attr_reader :arguments, :definition # Clears all Rules. # @return [Boolean] success def self.reset @@rules = [] true end reset # Initializes the Rule. # @param arguments [Porolog::Arguments] the Arguments of the Predicate for which this Rule applies. # @param definition [Object] the definition of the Rule. def initialize(arguments, definition = nil) @arguments = arguments @definition = definition @@rules << self end # Convenience method for testing/debugging # @return [String] pretty identification def myid "Rule#{(@@rules.index(self) || -1000) + 1}" end # @return [String] pretty representation. def inspect " #{@arguments.inspect}:- #{@definition.inspect}" end # Try to satisfy the Rule for the given Goal. # @param goal [Porolog::Goal] the Goal in which to satisfy this Rule. # @param block [Proc] code to perform when the Rule is satisfied. # @return [Boolean] the success of deleting the subgoal. def satisfy(goal, &block) subgoal = Goal.new self.arguments, goal unified_goals = unify_goals(goal, subgoal) if unified_goals satisfy_definition(goal, subgoal) do |solution_goal| block.call(solution_goal) end else subgoal.log << "Dead-end: Cannot unify with #{goal.inspect}" end subgoal.delete! end # Try to satisfy the definition of the Rule for a given Goal. # @param goal [Porolog::Goal] the given Goal for the Rule. # @param subgoal [Porolog::Goal] the subgoal for the Rule's definition. # @param block [Proc] code to perform when the definition is satisfied. # @return [Boolean] whether the definition was satisfied. def satisfy_definition(goal, subgoal, &block) case @definition when TrueClass block.call(subgoal) true when FalseClass false when Array satisfy_conjunction(goal, subgoal, @definition) do |solution_goal| block.call(solution_goal) end else raise DefinitionError, "UNEXPECTED TYPE OF DEFINITION: #{@definition.inspect} (#{@definition.class})" end end # Try to satisfy the conjunction of the definition of the Rule for a given Goal. # A conjunction is a sequence of expressions where the sequence is true # if all the expressions are true. # # @param goal [Porolog::Goal] the given Goal for the Rule. # @param subgoal [Porolog::Goal] the subgoal for the Rule's definition. # @param conjunction [Array] the conjunction to satisfy. # @param block [Proc] code to perform when the definition is satisfied. # @return [Boolean] whether the definition was satisfied. def satisfy_conjunction(goal, subgoal, conjunction, &block) arguments = conjunction.first conjunction = conjunction[1..-1] # -- Handle non-Arguments -- case arguments when :CUT, true subgoal.log << "CUTTING #{goal.inspect}..." result = true if conjunction.empty? !goal.terminated? && block.call(subgoal) else result = satisfy_conjunction(goal, subgoal, conjunction, &block) end if arguments == :CUT goal.terminate! goal.log << "TERMINATED after #{subgoal.inspect}" end return result when false return false when nil !goal.terminated? && block.call(subgoal) return true end # -- Unify Subsubgoal -- subsubgoal = arguments.goal(subgoal) unified = subsubgoal.inherit_variables(subgoal) # -- Satisfy Subgoal -- result = false unified && subsubgoal.satisfy() do result = true if conjunction.empty? !goal.terminated? && block.call(goal) else result = !goal.terminated? && satisfy_conjunction(goal, subsubgoal, conjunction, &block) end end # -- Uninstantiate -- subsubgoal.delete! result && !goal.terminated? end end |
Class Method Details
.reset ⇒ Boolean
Clears all Rules.
30 31 32 33 |
# File 'lib/porolog/rule.rb', line 30 def self.reset @@rules = [] true end |
Instance Method Details
#inspect ⇒ String
Returns pretty representation.
53 54 55 |
# File 'lib/porolog/rule.rb', line 53 def inspect " #{@arguments.inspect}:- #{@definition.inspect}" end |
#myid ⇒ String
Convenience method for testing/debugging
48 49 50 |
# File 'lib/porolog/rule.rb', line 48 def myid "Rule#{(@@rules.index(self) || -1000) + 1}" end |
#satisfy(goal, &block) ⇒ Boolean
Try to satisfy the Rule for the given Goal.
61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/porolog/rule.rb', line 61 def satisfy(goal, &block) subgoal = Goal.new self.arguments, goal unified_goals = unify_goals(goal, subgoal) if unified_goals satisfy_definition(goal, subgoal) do |solution_goal| block.call(solution_goal) end else subgoal.log << "Dead-end: Cannot unify with #{goal.inspect}" end subgoal.delete! end |
#satisfy_conjunction(goal, subgoal, conjunction, &block) ⇒ Boolean
Try to satisfy the conjunction of the definition of the Rule for a given Goal. A conjunction is a sequence of expressions where the sequence is true if all the expressions are true.
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/porolog/rule.rb', line 109 def satisfy_conjunction(goal, subgoal, conjunction, &block) arguments = conjunction.first conjunction = conjunction[1..-1] # -- Handle non-Arguments -- case arguments when :CUT, true subgoal.log << "CUTTING #{goal.inspect}..." result = true if conjunction.empty? !goal.terminated? && block.call(subgoal) else result = satisfy_conjunction(goal, subgoal, conjunction, &block) end if arguments == :CUT goal.terminate! goal.log << "TERMINATED after #{subgoal.inspect}" end return result when false return false when nil !goal.terminated? && block.call(subgoal) return true end # -- Unify Subsubgoal -- subsubgoal = arguments.goal(subgoal) unified = subsubgoal.inherit_variables(subgoal) # -- Satisfy Subgoal -- result = false unified && subsubgoal.satisfy() do result = true if conjunction.empty? !goal.terminated? && block.call(goal) else result = !goal.terminated? && satisfy_conjunction(goal, subsubgoal, conjunction, &block) end end # -- Uninstantiate -- subsubgoal.delete! result && !goal.terminated? end |
#satisfy_definition(goal, subgoal, &block) ⇒ Boolean
Try to satisfy the definition of the Rule for a given Goal.
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/porolog/rule.rb', line 81 def satisfy_definition(goal, subgoal, &block) case @definition when TrueClass block.call(subgoal) true when FalseClass false when Array satisfy_conjunction(goal, subgoal, @definition) do |solution_goal| block.call(solution_goal) end else raise DefinitionError, "UNEXPECTED TYPE OF DEFINITION: #{@definition.inspect} (#{@definition.class})" end end |