Class: Porolog::Arguments
Overview
A Porolog::Arguments specifies arguments of a Predicate. A predicate is not like a subroutine, although there are many similarities. An Arguments represents an instance of a predicate with a specific set of arguments. This forms the basis for implementing a goal to solve the predicate with those specific arguments.
Instance Attribute Summary collapse
-
#arguments ⇒ Object
readonly
The actual arguments.
-
#block ⇒ Object
readonly
Returns the value of attribute block.
-
#predicate ⇒ Object
readonly
The Predicate for which these are the arguments.
Class Method Summary collapse
-
.arguments ⇒ Array<Porolog::Arguments>
Convenience method for testing/debugging.
-
.reset ⇒ true
Unregisters all Arguments.
Instance Method Summary collapse
-
#<<(*definition) ⇒ Porolog::Arguments
Adds a Rule to the Predicate for these Arguments.
-
#==(other) ⇒ Boolean
Whether the Arguments match.
-
#cut_fact! ⇒ Porolog::Arguments
Creates a fact rule that states that these arguments satisfy the Predicate and terminates solving the predicate.
-
#cut_fallacy! ⇒ Porolog::Arguments
Creates a fact rule that states that these arguments do not satisfy the Predicate and terminates solving the predicate.
-
#dup(goal) ⇒ Porolog::Arguments
Duplicates the Arguments in the context of the given goal.
-
#evaluates(&block) ⇒ Porolog::Arguments
Adds an evaluation Rule to the Predicate.
-
#fact! ⇒ Porolog::Arguments
Creates a fact rule that states that these arguments satisfy the Predicate.
-
#fallacy! ⇒ Porolog::Arguments
Creates a fact rule that states that these arguments do not satisfy the Predicate.
-
#goal(calling_goal = nil) ⇒ Porolog::Goal
Creates a Goal for solving this Arguments for the Predicate.
-
#initialize(predicate, arguments, &block) ⇒ Arguments
constructor
Creates a new Arguments for a Predicate.
-
#inspect ⇒ String
Pretty representation.
-
#myid ⇒ String
Convenience method for testing/debugging.
-
#solutions(max_solutions = nil) ⇒ Array<Hash{Symbol => Object}>
Returns memoized solutions.
-
#solve(max_solutions = nil) ⇒ Array<Hash{Symbol => Object}>
Solves the Arguments.
-
#solve_for(*variables, max_solutions: nil) ⇒ Array<Object>
Extracts solution values.
-
#valid? ⇒ Boolean
Whether any solutions were found.
-
#variables ⇒ Array<Symbol>
The variables contained in the arguments.
Constructor Details
#initialize(predicate, arguments, &block) ⇒ Arguments
Creates a new Arguments for a Predicate
37 38 39 40 41 42 |
# File 'lib/porolog/arguments.rb', line 37 def initialize(predicate, arguments, &block) @predicate = predicate @arguments = arguments @block = block @@arguments << self end |
Instance Attribute Details
#arguments ⇒ Object (readonly)
The actual arguments.
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 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/porolog/arguments.rb', line 21 class Arguments attr_reader :predicate, :arguments, :block # Unregisters all Arguments # @return [true] def self.reset @@arguments = [] true end reset # Creates a new Arguments for a Predicate # @param predicate [Porolog::Predicate] the Predicate for which these are the arguments # @param arguments [Array<Object>] the actual arguments def initialize(predicate, arguments, &block) @predicate = predicate @arguments = arguments @block = block @@arguments << self end # Convenience method for testing/debugging # @return [Array<Porolog::Arguments>] all registered Arguments def self.arguments @@arguments end # Convenience method for testing/debugging # @return [String] pretty identification def myid "Arguments#{(@@arguments.index(self) || -1000) + 1}" end # @return [String] pretty representation def inspect block_inspect = block.nil? ? '' : "{#{block.inspect}}" "#{@predicate&.name}(#{@arguments&.map(&:inspect).join(',')})#{block_inspect}" end # Creates a fact rule that states that these arguments satisfy the Predicate. # @return [Porolog::Arguments] the Arguments def fact! @predicate << Rule.new(self, true) self end # Creates a fact rule that states that these arguments do not satisfy the Predicate. # @return [Porolog::Arguments] the Arguments def fallacy! @predicate << Rule.new(self, false) self end # Creates a fact rule that states that these arguments satisfy the Predicate and terminates solving the predicate. # @return [Porolog::Arguments] the Arguments def cut_fact! @predicate << Rule.new(self, [:CUT, true]) self end # Creates a fact rule that states that these arguments do not satisfy the Predicate and terminates solving the predicate. # @return [Porolog::Arguments] the Arguments def cut_fallacy! @predicate << Rule.new(self, [:CUT, false]) self end # Adds a Rule to the Predicate for these Arguments # @param definition [Array<Object>, Object] the Rule definition for these Arguments # @return [Porolog::Arguments] the Arguments def <<(*definition) @predicate << Rule.new(self, *definition) self end # Adds an evaluation Rule to the Predicate # @param block the block to evaluate # @return [Porolog::Arguments] the Arguments def evaluates(&block) @predicate << Rule.new(self, block) self end # @return [Array<Symbol>] the variables contained in the arguments def variables @arguments.map(&:variables).flatten.uniq end # Creates a Goal for solving this Arguments for the Predicate # @param calling_goal [Porolog::Goal] the parent Goal (if this is a subgoal) # @return [Porolog::Goal] the Goal to solve def goal(calling_goal = nil) Goal.new(self, calling_goal) end # Returns memoized solutions # @param max_solutions [Integer] the maximum number of solutions to find (nil means find all) # @return [Array<Hash{Symbol => Object}>] the solutions found (memoized) def solutions(max_solutions = nil) @solutions ||= solve(max_solutions) max_solutions && @solutions[0...max_solutions] || @solutions end # Solves the Arguments # @param max_solutions [Integer] the maximum number of solutions to find (nil means find all) # @return [Array<Hash{Symbol => Object}>] the solutions found def solve(max_solutions = nil) @solutions = goal.solve(max_solutions) end # Extracts solution values. # @param variables [Symbol, Array<Symbol>] variable or variables # @param max_solutions [Integer] the maximum number of solutions to find (nil means find all) # @return [Array<Object>] all the values for the variables given # @example # predicate :treasure_at # treasure_at(:X,:Y) << [...] # arguments = treasure_at(:X,:Y) # xs = arguments.solve_for(:X) # ys = arguments.solve_for(:Y) # coords = xs.zip(ys) def solve_for(*variables, max_solutions: nil) variables = [*variables] solutions(max_solutions).map{|solution| values = variables.map{|variable| solution[variable] } if values.size == 1 values.first else values end } end # @return [Boolean] whether any solutions were found def valid? !solutions(1).empty? end # Duplicates the Arguments in the context of the given goal # @param goal [Porolog::Goal] the destination goal # @return [Porolog::Arguments] the duplicated Arguments def dup(goal) self.class.new @predicate, goal.variablise(arguments), &@block end # @param other [Porolog::Arguments] arguments for comparison # @return [Boolean] whether the Arguments match def ==(other) @predicate == other.predicate && @arguments == other.arguments end end |
#block ⇒ Object (readonly)
Returns the value of attribute block.
23 24 25 |
# File 'lib/porolog/arguments.rb', line 23 def block @block end |
#predicate ⇒ Object (readonly)
The Predicate for which these are the arguments.
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 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/porolog/arguments.rb', line 21 class Arguments attr_reader :predicate, :arguments, :block # Unregisters all Arguments # @return [true] def self.reset @@arguments = [] true end reset # Creates a new Arguments for a Predicate # @param predicate [Porolog::Predicate] the Predicate for which these are the arguments # @param arguments [Array<Object>] the actual arguments def initialize(predicate, arguments, &block) @predicate = predicate @arguments = arguments @block = block @@arguments << self end # Convenience method for testing/debugging # @return [Array<Porolog::Arguments>] all registered Arguments def self.arguments @@arguments end # Convenience method for testing/debugging # @return [String] pretty identification def myid "Arguments#{(@@arguments.index(self) || -1000) + 1}" end # @return [String] pretty representation def inspect block_inspect = block.nil? ? '' : "{#{block.inspect}}" "#{@predicate&.name}(#{@arguments&.map(&:inspect).join(',')})#{block_inspect}" end # Creates a fact rule that states that these arguments satisfy the Predicate. # @return [Porolog::Arguments] the Arguments def fact! @predicate << Rule.new(self, true) self end # Creates a fact rule that states that these arguments do not satisfy the Predicate. # @return [Porolog::Arguments] the Arguments def fallacy! @predicate << Rule.new(self, false) self end # Creates a fact rule that states that these arguments satisfy the Predicate and terminates solving the predicate. # @return [Porolog::Arguments] the Arguments def cut_fact! @predicate << Rule.new(self, [:CUT, true]) self end # Creates a fact rule that states that these arguments do not satisfy the Predicate and terminates solving the predicate. # @return [Porolog::Arguments] the Arguments def cut_fallacy! @predicate << Rule.new(self, [:CUT, false]) self end # Adds a Rule to the Predicate for these Arguments # @param definition [Array<Object>, Object] the Rule definition for these Arguments # @return [Porolog::Arguments] the Arguments def <<(*definition) @predicate << Rule.new(self, *definition) self end # Adds an evaluation Rule to the Predicate # @param block the block to evaluate # @return [Porolog::Arguments] the Arguments def evaluates(&block) @predicate << Rule.new(self, block) self end # @return [Array<Symbol>] the variables contained in the arguments def variables @arguments.map(&:variables).flatten.uniq end # Creates a Goal for solving this Arguments for the Predicate # @param calling_goal [Porolog::Goal] the parent Goal (if this is a subgoal) # @return [Porolog::Goal] the Goal to solve def goal(calling_goal = nil) Goal.new(self, calling_goal) end # Returns memoized solutions # @param max_solutions [Integer] the maximum number of solutions to find (nil means find all) # @return [Array<Hash{Symbol => Object}>] the solutions found (memoized) def solutions(max_solutions = nil) @solutions ||= solve(max_solutions) max_solutions && @solutions[0...max_solutions] || @solutions end # Solves the Arguments # @param max_solutions [Integer] the maximum number of solutions to find (nil means find all) # @return [Array<Hash{Symbol => Object}>] the solutions found def solve(max_solutions = nil) @solutions = goal.solve(max_solutions) end # Extracts solution values. # @param variables [Symbol, Array<Symbol>] variable or variables # @param max_solutions [Integer] the maximum number of solutions to find (nil means find all) # @return [Array<Object>] all the values for the variables given # @example # predicate :treasure_at # treasure_at(:X,:Y) << [...] # arguments = treasure_at(:X,:Y) # xs = arguments.solve_for(:X) # ys = arguments.solve_for(:Y) # coords = xs.zip(ys) def solve_for(*variables, max_solutions: nil) variables = [*variables] solutions(max_solutions).map{|solution| values = variables.map{|variable| solution[variable] } if values.size == 1 values.first else values end } end # @return [Boolean] whether any solutions were found def valid? !solutions(1).empty? end # Duplicates the Arguments in the context of the given goal # @param goal [Porolog::Goal] the destination goal # @return [Porolog::Arguments] the duplicated Arguments def dup(goal) self.class.new @predicate, goal.variablise(arguments), &@block end # @param other [Porolog::Arguments] arguments for comparison # @return [Boolean] whether the Arguments match def ==(other) @predicate == other.predicate && @arguments == other.arguments end end |
Class Method Details
.arguments ⇒ Array<Porolog::Arguments>
Convenience method for testing/debugging
46 47 48 |
# File 'lib/porolog/arguments.rb', line 46 def self.arguments @@arguments end |
.reset ⇒ true
Unregisters all Arguments
27 28 29 30 |
# File 'lib/porolog/arguments.rb', line 27 def self.reset @@arguments = [] true end |
Instance Method Details
#<<(*definition) ⇒ Porolog::Arguments
Adds a Rule to the Predicate for these Arguments
93 94 95 96 |
# File 'lib/porolog/arguments.rb', line 93 def <<(*definition) @predicate << Rule.new(self, *definition) self end |
#==(other) ⇒ Boolean
170 171 172 173 |
# File 'lib/porolog/arguments.rb', line 170 def ==(other) @predicate == other.predicate && @arguments == other.arguments end |
#cut_fact! ⇒ Porolog::Arguments
Creates a fact rule that states that these arguments satisfy the Predicate and terminates solving the predicate.
78 79 80 81 |
# File 'lib/porolog/arguments.rb', line 78 def cut_fact! @predicate << Rule.new(self, [:CUT, true]) self end |
#cut_fallacy! ⇒ Porolog::Arguments
Creates a fact rule that states that these arguments do not satisfy the Predicate and terminates solving the predicate.
85 86 87 88 |
# File 'lib/porolog/arguments.rb', line 85 def cut_fallacy! @predicate << Rule.new(self, [:CUT, false]) self end |
#dup(goal) ⇒ Porolog::Arguments
Duplicates the Arguments in the context of the given goal
164 165 166 |
# File 'lib/porolog/arguments.rb', line 164 def dup(goal) self.class.new @predicate, goal.variablise(arguments), &@block end |
#evaluates(&block) ⇒ Porolog::Arguments
Adds an evaluation Rule to the Predicate
101 102 103 104 |
# File 'lib/porolog/arguments.rb', line 101 def evaluates(&block) @predicate << Rule.new(self, block) self end |
#fact! ⇒ Porolog::Arguments
Creates a fact rule that states that these arguments satisfy the Predicate.
64 65 66 67 |
# File 'lib/porolog/arguments.rb', line 64 def fact! @predicate << Rule.new(self, true) self end |
#fallacy! ⇒ Porolog::Arguments
Creates a fact rule that states that these arguments do not satisfy the Predicate.
71 72 73 74 |
# File 'lib/porolog/arguments.rb', line 71 def fallacy! @predicate << Rule.new(self, false) self end |
#goal(calling_goal = nil) ⇒ Porolog::Goal
Creates a Goal for solving this Arguments for the Predicate
114 115 116 |
# File 'lib/porolog/arguments.rb', line 114 def goal(calling_goal = nil) Goal.new(self, calling_goal) end |
#inspect ⇒ String
57 58 59 60 |
# File 'lib/porolog/arguments.rb', line 57 def inspect block_inspect = block.nil? ? '' : "{#{block.inspect}}" "#{@predicate&.name}(#{@arguments&.map(&:inspect).join(',')})#{block_inspect}" end |
#myid ⇒ String
Convenience method for testing/debugging
52 53 54 |
# File 'lib/porolog/arguments.rb', line 52 def myid "Arguments#{(@@arguments.index(self) || -1000) + 1}" end |
#solutions(max_solutions = nil) ⇒ Array<Hash{Symbol => Object}>
Returns memoized solutions
121 122 123 124 |
# File 'lib/porolog/arguments.rb', line 121 def solutions(max_solutions = nil) @solutions ||= solve(max_solutions) max_solutions && @solutions[0...max_solutions] || @solutions end |
#solve(max_solutions = nil) ⇒ Array<Hash{Symbol => Object}>
Solves the Arguments
129 130 131 |
# File 'lib/porolog/arguments.rb', line 129 def solve(max_solutions = nil) @solutions = goal.solve(max_solutions) end |
#solve_for(*variables, max_solutions: nil) ⇒ Array<Object>
Extracts solution values.
144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/porolog/arguments.rb', line 144 def solve_for(*variables, max_solutions: nil) variables = [*variables] solutions(max_solutions).map{|solution| values = variables.map{|variable| solution[variable] } if values.size == 1 values.first else values end } end |
#valid? ⇒ Boolean
157 158 159 |
# File 'lib/porolog/arguments.rb', line 157 def valid? !solutions(1).empty? end |