gecoder 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/CHANGES +6 -0
  2. data/README +1 -1
  3. data/THANKS +18 -0
  4. data/example/equation_system.rb +3 -1
  5. data/example/magic_sequence.rb +3 -1
  6. data/example/queens.rb +3 -1
  7. data/example/send_more_money.rb +24 -30
  8. data/example/send_most_money.rb +15 -26
  9. data/example/square_tiling.rb +3 -1
  10. data/example/sudoku-set.rb +3 -1
  11. data/lib/gecoder/bindings.rb +7 -5
  12. data/lib/gecoder/bindings/bindings.rb +8 -8
  13. data/lib/gecoder/interface.rb +4 -2
  14. data/lib/gecoder/interface/binding_changes.rb +1 -1
  15. data/lib/gecoder/interface/branch.rb +1 -1
  16. data/lib/gecoder/interface/constraints/bool_enum_constraints.rb +4 -4
  17. data/lib/gecoder/interface/constraints/bool_var_constraints.rb +2 -2
  18. data/lib/gecoder/interface/constraints/extensional_regexp.rb +1 -1
  19. data/lib/gecoder/interface/constraints/fixnum_enum_constraints.rb +2 -2
  20. data/lib/gecoder/interface/constraints/int_enum/extensional.rb +5 -5
  21. data/lib/gecoder/interface/constraints/int_enum_constraints.rb +4 -4
  22. data/lib/gecoder/interface/constraints/int_var_constraints.rb +2 -2
  23. data/lib/gecoder/interface/constraints/selected_set/select.rb +8 -8
  24. data/lib/gecoder/interface/constraints/set_enum/{select.rb → element.rb} +10 -10
  25. data/lib/gecoder/interface/constraints/set_enum_constraints.rb +5 -5
  26. data/lib/gecoder/interface/constraints/set_var_constraints.rb +2 -2
  27. data/lib/gecoder/interface/{model_sugar.rb → convenience.rb} +19 -4
  28. data/lib/gecoder/interface/enum_wrapper.rb +1 -1
  29. data/lib/gecoder/interface/{model.rb → mixin.rb} +93 -60
  30. data/lib/gecoder/interface/search.rb +23 -22
  31. data/lib/gecoder/version.rb +1 -1
  32. data/specs/branch.rb +5 -3
  33. data/specs/constraints/bool/boolean.rb +3 -1
  34. data/specs/constraints/bool/linear.rb +3 -1
  35. data/specs/constraints/bool_enum/bool_enum_relation.rb +3 -1
  36. data/specs/constraints/bool_enum/channel.rb +3 -1
  37. data/specs/constraints/fixnum_enum/element.rb +3 -1
  38. data/specs/constraints/int/arithmetic.rb +3 -1
  39. data/specs/constraints/int/channel.rb +3 -1
  40. data/specs/constraints/int/linear.rb +3 -1
  41. data/specs/constraints/int/linear_properties.rb +3 -1
  42. data/specs/constraints/int_enum/arithmetic.rb +3 -1
  43. data/specs/constraints/int_enum/channel.rb +3 -1
  44. data/specs/constraints/int_enum/count.rb +3 -1
  45. data/specs/constraints/int_enum/distinct.rb +3 -1
  46. data/specs/constraints/int_enum/element.rb +3 -1
  47. data/specs/constraints/int_enum/sort.rb +3 -1
  48. data/specs/constraints/property_helper.rb +10 -10
  49. data/specs/constraints/reification_sugar.rb +3 -1
  50. data/specs/constraints/selected_set/select.rb +6 -5
  51. data/specs/constraints/selected_set/select_properties.rb +12 -10
  52. data/specs/constraints/set/channel.rb +3 -1
  53. data/specs/constraints/set/domain.rb +4 -4
  54. data/specs/constraints/set/relation.rb +4 -4
  55. data/specs/constraints/set_enum/channel.rb +3 -1
  56. data/specs/constraints/set_enum/distinct.rb +3 -1
  57. data/specs/constraints/set_enum/{select.rb → element.rb} +13 -9
  58. data/specs/enum_wrapper.rb +1 -1
  59. data/specs/mixin.rb +78 -0
  60. data/specs/model.rb +5 -5
  61. data/specs/search.rb +20 -14
  62. data/specs/selected_set.rb +3 -3
  63. data/specs/set_elements.rb +2 -2
  64. data/tasks/distribution.rake +25 -4
  65. metadata +15 -12
  66. data/example/money.rb +0 -36
data/CHANGES CHANGED
@@ -1,3 +1,9 @@
1
+ == Version 0.9.1
2
+ This release changes the preferred way of defining a model to including Gecode::Mixin (a mixin) rather than inheriting from Gecode::Model. The backend has also been updated to fix some rare bugs.
3
+
4
+ * Added Gecode::Mixin which can be mixed in rather than inheriting from Gecode::Model. Thanks to Adam Rose for the suggestion.
5
+ * Updated the backend to Gecode 2.2.0. See http://www.gecode.org/gecode-doc-latest/PageChanges_2_2_0.html for a list of changes.
6
+
1
7
  == Version 0.9.0
2
8
  This release adds a generous amount of sugar designed to cut down on often
3
9
  repeated code. It also adds the ability to freely combine constraints
data/README CHANGED
@@ -17,7 +17,7 @@ people to play with it and give feedback.
17
17
 
18
18
  == Installation
19
19
 
20
- Gecode/R requires Gecode 2.1.1, which can be downloaded from
20
+ Gecode/R requires Gecode 2.2.0, which can be downloaded from
21
21
  http://www.gecode.org/download.html . See
22
22
  http://www.gecode.org/gecode-doc-latest/PageComp.html for the installation
23
23
  instructions.
data/THANKS ADDED
@@ -0,0 +1,18 @@
1
+ A list of people who have contributed to making Gecode/R what it is
2
+ today. Sorted in alphabetical order by last name.
3
+
4
+ * David Cuadrado - For the initial raw bindings from Gecode to Ruby.
5
+ * Eivind Eklund - For the idea that led to the syntax used to specify
6
+ the regular expressions used in regexp constraints.
7
+ * Google and Ruby Central - For the funding through Google Summer of
8
+ Code 2007 that got the project started.
9
+ * James Edward Gray II - For the superb mentoring during Google Summer
10
+ of Code 2007, influencing many decisions made.
11
+ * Mikael Lagerkvist - For the support from the Gecode side.
12
+ * Andreas Launila - For the interface on top of the raw bindings and
13
+ the website.
14
+ * Adam Rose - For suggesting that Gecode/R should use a mixin rather
15
+ than inheritance.
16
+
17
+ If you think that you should be on this list then please contact the
18
+ gecoder-devel mailing list.
@@ -1,6 +1,8 @@
1
1
  require File.dirname(__FILE__) + '/example_helper'
2
2
 
3
- class EquationProblem < Gecode::Model
3
+ class EquationProblem
4
+ include Gecode::Mixin
5
+
4
6
  def initialize
5
7
  x, y, z = vars_is_an int_var_array(3, 0..9)
6
8
 
@@ -1,7 +1,9 @@
1
1
  require File.dirname(__FILE__) + '/example_helper'
2
2
 
3
3
  # Solves the magic sequence problem.
4
- class MagicSequence < Gecode::Model
4
+ class MagicSequence
5
+ include Gecode::Mixin
6
+
5
7
  # n is the length of the sequence.
6
8
  def initialize(n)
7
9
  # The i:th variable represents the value of the i:th element in the
@@ -2,7 +2,9 @@ require File.dirname(__FILE__) + '/example_helper'
2
2
 
3
3
  # Solves the n-queens problem: http://en.wikipedia.org/wiki/Nqueens . No attempt
4
4
  # to break the involved symmetries is made.
5
- class NQueens < Gecode::Model
5
+ class NQueens
6
+ include Gecode::Mixin
7
+
6
8
  def initialize(n)
7
9
  @size = n
8
10
 
@@ -2,35 +2,7 @@ require File.dirname(__FILE__) + '/example_helper'
2
2
 
3
3
  # Solves the send+more=money problem:
4
4
  # http://en.wikipedia.org/wiki/Send%2Bmore%3Dmoney
5
- class SendMoreMoney < Gecode::Model
6
- def initialize
7
- # Set up the variables, 8 letters with domain 0..9.
8
- s,e,n,d,m,o,r,y = @letters = int_var_array(8, 0..9)
9
-
10
- # Set up the constraints.
11
- # The equation must hold.
12
- (equation_row(s, e, n, d) + equation_row(m, o, r, e)).must ==
13
- equation_row(m, o, n, e, y)
14
-
15
- # The initial letters may not be 0.
16
- s.must_not == 0
17
- m.must_not == 0
18
-
19
- # All letters must be assigned different digits.
20
- @letters.must_be.distinct
21
-
22
- # Set the branching.
23
- branch_on @letters, :variable => :smallest_size, :value => :min
24
- end
25
-
26
- def to_s
27
- %w{s e n d m o r y}.zip(@letters).map do |text, letter|
28
- "#{text}: #{letter.value}"
29
- end.join(', ')
30
- end
31
-
32
- private
33
-
5
+ solution = Gecode.solve do
34
6
  # A helper to make the linear equation a bit tidier. Takes a number of
35
7
  # variables and computes the linear combination as if the variable
36
8
  # were digits in a base 10 number. E.g. x,y,z becomes
@@ -38,6 +10,28 @@ class SendMoreMoney < Gecode::Model
38
10
  def equation_row(*variables)
39
11
  variables.inject{ |result, variable| variable + result*10 }
40
12
  end
13
+
14
+ # Set up the variables.
15
+ # Let "letters" be an array of 8 integer variables with domain 0..9.
16
+ # The elements represents the letters s, e, n, d, m, o, r and y.
17
+ letters_is_an int_var_array(8, 0..9)
18
+ s,e,n,d,m,o,r,y = letters
19
+
20
+ # Set up the constraints.
21
+ # The equation must hold.
22
+ (equation_row(s, e, n, d) + equation_row(m, o, r, e)).must ==
23
+ equation_row(m, o, n, e, y)
24
+
25
+ # The initial letters may not be 0.
26
+ s.must_not == 0
27
+ m.must_not == 0
28
+
29
+ # All letters must be assigned different digits.
30
+ letters.must_be.distinct
31
+
32
+ # Tell Gecode what variables we want to know the values of.
33
+ branch_on letters, :variable => :smallest_size, :value => :min
41
34
  end
42
35
 
43
- puts SendMoreMoney.new.solve!.to_s
36
+ puts 's e n d m o r y'
37
+ puts solution.letters.values.join(' ')
@@ -2,36 +2,34 @@ require File.dirname(__FILE__) + '/example_helper'
2
2
 
3
3
  # Solves the cryptarithmetic send+most=money problem while maximizing the value
4
4
  # of "money".
5
- class SendMoreMoney < Gecode::Model
5
+ class SendMostMoney
6
+ include Gecode::Mixin
7
+
6
8
  attr :money
7
9
 
8
10
  def initialize
9
11
  # Set up the variables, 9 letters with domain 0..9.
10
- s,e,n,d,m,o,s,t,y = @letters = int_var_array(9, 0..9)
11
- @money = wrap_enum([m,o,n,e,y])
12
+ s,e,n,d,m,o,s,t,y = letters_is_an int_var_array(9, 0..9)
13
+ # Express the quantity we are optimizing, in this case money.
14
+ # This utilises that any operand can be converted into a variable.
15
+ @money = equation_row(m,o,n,e,y).to_int_var
12
16
 
13
17
  # Set up the constraints.
14
18
  # The equation must hold.
15
19
  (equation_row(s, e, n, d) + equation_row(m, o, s, t)).must ==
16
- equation_row(m,o,n,e,y)
20
+ equation_row(m, o, n, e, y)
17
21
 
18
22
  # The initial letters may not be 0.
19
23
  s.must_not == 0
20
24
  m.must_not == 0
21
25
 
22
26
  # All letters must be assigned different digits.
23
- @letters.must_be.distinct
27
+ letters.must_be.distinct
24
28
 
25
29
  # Set the branching.
26
- branch_on @letters, :variable => :smallest_size, :value => :min
30
+ branch_on letters, :variable => :smallest_size, :value => :min
27
31
  end
28
32
 
29
- def to_s
30
- %w{s e n d m o s t y}.zip(@letters).map do |text, letter|
31
- "#{text}: #{letter.value}"
32
- end.join(', ')
33
- end
34
-
35
33
  private
36
34
 
37
35
  # A helper to make the linear equation a bit tidier. Takes a number of
@@ -39,20 +37,11 @@ class SendMoreMoney < Gecode::Model
39
37
  # were digits in a base 10 number. E.g. x,y,z becomes
40
38
  # 100*x + 10*y + z .
41
39
  def equation_row(*variables)
42
- variables.to_number
43
- end
44
- end
45
-
46
- class Array
47
- # Computes a number of the specified base using the array's elements as
48
- # digits.
49
- def to_number(base = 10)
50
- inject{ |result, variable| variable + result * base }
40
+ variables.inject{ |result, variable| variable + result * 10 }
51
41
  end
52
42
  end
53
43
 
54
- solution = SendMoreMoney.new.optimize! do |model, best_so_far|
55
- model.money.to_number.must > best_so_far.money.values.to_number
56
- end
57
- puts solution.to_s
58
- puts "money: #{solution.money.values.to_number}"
44
+ solution = SendMostMoney.new.maximize! :money
45
+ puts 's e n d m o s t y'
46
+ puts solution.letters.values.join(' ')
47
+ puts "money: #{solution.money.value}"
@@ -2,7 +2,9 @@ require File.dirname(__FILE__) + '/example_helper'
2
2
 
3
3
  # Solves the square tiling problem. The objective is to pack supplied squares
4
4
  # into a bigger rectangle so that there is no overlap.
5
- class SquareTiling < Gecode::Model
5
+ class SquareTiling
6
+ include Gecode::Mixin
7
+
6
8
  # Takes the width and height of the rectangle to pack the squares into. Then
7
9
  # the sizes of the squares that should be packed into the rectangle. The sizes
8
10
  # must be sorted.
@@ -4,7 +4,9 @@ require 'enumerator'
4
4
  # Solves the sudoku problem using sets. The model used is a fairly direct
5
5
  # translation of the corresponding Gecode example:
6
6
  # http://www.gecode.org/gecode-doc-latest/sudoku-set_8cc-source.html .
7
- class SudokuSet < Gecode::Model
7
+ class SudokuSet
8
+ include Gecode::Mixin
9
+
8
10
  # Takes a 9x9 matrix of values in the initial sudoku, 0 if the square is
9
11
  # empty.
10
12
  def initialize(predefined_values)
@@ -1,6 +1,6 @@
1
1
  # Problems can be formulated and solved either through defining a new
2
- # class that inherits from Gecode::Model or by using Gecode#solve et al.
3
- # Gecode::Model describes how to formulate problems.
2
+ # class that mixes in Gecode::Mixin or by using Gecode.solve et al.
3
+ # Gecode::Mixin describes how to formulate problems.
4
4
  #
5
5
  # ==== Examples
6
6
  #
@@ -12,9 +12,11 @@
12
12
  # x = y - 3
13
13
  # 0 <= x,y,z <= 9
14
14
  #
15
- # === Inheriting from Gecode::Model
15
+ # === Mixing in Gecode::Mixin
16
+ #
17
+ # class EquationProblem
18
+ # include Gecode::Mixin
16
19
  #
17
- # class EquationProblem < Gecode::Model
18
20
  # def initialize
19
21
  # variables_is_an int_var_array(3, 0..9)
20
22
  # x, y, z = variables
@@ -27,7 +29,7 @@
27
29
  # end
28
30
  # puts EquationProblem.new.solve!.variables.join(' ')
29
31
  #
30
- # === Using Gecode#solve
32
+ # === Using Gecode.solve
31
33
  #
32
34
  # solution = Gecode.solve do
33
35
  # variables_is_an int_var_array(3, 0..9)
@@ -1966,7 +1966,7 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
1966
1966
  func.add_parameter "Gecode::BoolVar", "b"
1967
1967
  end
1968
1968
 
1969
- ns.add_function "selectUnion" do |func|
1969
+ ns.add_function "elementsUnion" do |func|
1970
1970
  func.add_parameter "Gecode::MSpace*", "home"
1971
1971
  func.add_parameter "Gecode::MSetVarArray", "x" do |param|
1972
1972
  param.custom_conversion = "*ruby2Gecode_MSetVarArrayPtr(x, 2)->ptr()"
@@ -1975,35 +1975,35 @@ Rust::Bindings::create_bindings Rust::Bindings::LangCxx, "gecode" do |b|
1975
1975
  func.add_parameter "Gecode::SetVar", "z"
1976
1976
  end
1977
1977
 
1978
- ns.add_function "selectInter" do |func|
1978
+ ns.add_function "elementsInter" do |func|
1979
1979
  func.add_parameter "Gecode::MSpace*", "home"
1980
1980
  func.add_parameter "Gecode::MSetVarArray", "x" do |param|
1981
- param.custom_conversion = "*ruby2Gecode_MSetVarArrayPtr(x, 2)->ptr()"
1981
+ param.custom_conversion = "*ruby2Gecode_MSetVarArrayPtr(argv[1], 2)->ptr()"
1982
1982
  end
1983
1983
  func.add_parameter "Gecode::SetVar", "y"
1984
1984
  func.add_parameter "Gecode::SetVar", "z"
1985
1985
  end
1986
1986
 
1987
- ns.add_function "selectInterIn" do |func|
1987
+ ns.add_function "elementsInter" do |func|
1988
1988
  func.add_parameter "Gecode::MSpace*", "home"
1989
1989
  func.add_parameter "Gecode::MSetVarArray", "x" do |param|
1990
- param.custom_conversion = "*ruby2Gecode_MSetVarArrayPtr(x, 2)->ptr()"
1990
+ param.custom_conversion = "*ruby2Gecode_MSetVarArrayPtr(argv[1], 2)->ptr()"
1991
1991
  end
1992
1992
  func.add_parameter "Gecode::SetVar", "y"
1993
1993
  func.add_parameter "Gecode::SetVar", "z"
1994
1994
  func.add_parameter "Gecode::IntSet", "universe"
1995
1995
  end
1996
1996
 
1997
- ns.add_function "selectSet" do |func|
1997
+ ns.add_function "element" do |func|
1998
1998
  func.add_parameter "Gecode::MSpace*", "home"
1999
1999
  func.add_parameter "Gecode::MSetVarArray", "x" do |param|
2000
- param.custom_conversion = "*ruby2Gecode_MSetVarArrayPtr(x, 2)->ptr()"
2000
+ param.custom_conversion = "*ruby2Gecode_MSetVarArrayPtr(argv[1], 2)->ptr()"
2001
2001
  end
2002
2002
  func.add_parameter "Gecode::IntVar", "y"
2003
2003
  func.add_parameter "Gecode::SetVar", "z"
2004
2004
  end
2005
2005
 
2006
- ns.add_function "selectDisjoint" do |func|
2006
+ ns.add_function "elementsDisjoint" do |func|
2007
2007
  func.add_parameter "Gecode::MSpace*", "home"
2008
2008
  func.add_parameter "Gecode::MSetVarArray", "x" do |param|
2009
2009
  param.custom_conversion = "*ruby2Gecode_MSetVarArrayPtr(x, 2)->ptr()"
@@ -1,9 +1,11 @@
1
1
  require 'gecoder/interface/binding_changes'
2
2
  require 'gecoder/interface/enum_matrix'
3
- require 'gecoder/interface/model'
3
+ require 'gecoder/interface/mixin'
4
+ require 'gecoder/interface/mixin'
5
+ require 'gecoder/interface/mixin'
4
6
  require 'gecoder/interface/search'
5
7
  require 'gecoder/interface/constraints'
6
8
  require 'gecoder/interface/variables'
7
9
  require 'gecoder/interface/enum_wrapper'
8
10
  require 'gecoder/interface/branch'
9
- require 'gecoder/interface/model_sugar'
11
+ require 'gecoder/interface/convenience'
@@ -3,7 +3,7 @@ module GecodeRaw #:nodoc: all
3
3
  class Space
4
4
  # Used by Gecode during BAB-search.
5
5
  def constrain(best_so_far_space)
6
- Gecode::Model.constrain(self, best_so_far_space)
6
+ Gecode::Mixin.constrain(self, best_so_far_space)
7
7
  end
8
8
  end
9
9
  end
@@ -1,5 +1,5 @@
1
1
  module Gecode
2
- class Model
2
+ module Mixin
3
3
  # Specifies which variables that should be branched on (given as an
4
4
  # enum of operands or as a single operand). One can optionally
5
5
  # also select which of the variables that should be used first with
@@ -5,19 +5,19 @@ module Gecode::BoolEnum #:nodoc:
5
5
  # constraints defined in BoolEnumConstraintReceiver can be placed.
6
6
  #
7
7
  # Enumerations of boolean operands can be created either by using
8
- # Gecode::Model#bool_var_array and Gecode::Model#bool_var_matrix, or
8
+ # Gecode::Mixin#bool_var_array and Gecode::Mixin#bool_var_matrix, or
9
9
  # by wrapping an existing enumeration containing BoolOperand using
10
- # Gecode::Model#wrap_enum. The enumerations, no matter how they were
10
+ # Gecode::Mixin#wrap_enum. The enumerations, no matter how they were
11
11
  # created, all respond to the properties defined by BoolEnumOperand.
12
12
  #
13
13
  # ==== Examples
14
14
  #
15
15
  # Produces an array of five boolean operands inside a problem formulation
16
- # using Gecode::Model#bool_var_array:
16
+ # using Gecode::Mixin#bool_var_array:
17
17
  #
18
18
  # bool_enum = bool_var_array(5)
19
19
  #
20
- # Uses Gecode::Model#wrap_enum inside a problem formulation to create
20
+ # Uses Gecode::Mixin#wrap_enum inside a problem formulation to create
21
21
  # a BoolEnumOperand from an existing enumeration containing the
22
22
  # boolean operands +bool_operand1+ and +bool_operand2+:
23
23
  #
@@ -5,14 +5,14 @@ module Gecode::Bool #:nodoc:
5
5
  # constraints defined in BoolConstraintReceiver can be placed.
6
6
  #
7
7
  # Boolean operands can be created either by using
8
- # Gecode::Model#bool_var et al, or by using properties that produce
8
+ # Gecode::Mixin#bool_var et al, or by using properties that produce
9
9
  # boolean operands. The operands, no matter how they were created,
10
10
  # all respond to the properties defined by BoolOperand.
11
11
  #
12
12
  # ==== Examples
13
13
  #
14
14
  # Produces a single boolean operand (more specifically a BoolVar)
15
- # inside a problem formulation, using Gecode::Model#bool_var:
15
+ # inside a problem formulation, using Gecode::Mixin#bool_var:
16
16
  #
17
17
  # bool_operand = bool_var
18
18
  #
@@ -1,5 +1,5 @@
1
1
  module Gecode
2
- class Model
2
+ module Mixin
3
3
  # Specifies an integer regexp that matches +regexp+ repeated between
4
4
  # +at_least+ and +at_most+ times (inclusive). If +at_most+ is
5
5
  # omitted then no upper bound is placed. If both +at_least+ and
@@ -6,12 +6,12 @@ module Gecode::FixnumEnum #:nodoc:
6
6
  # They typically service as constant arrays or constant sets.
7
7
  #
8
8
  # The fixnum enumeration operands are created by wrapping an enumeration
9
- # of fixnum Gecode::Model#wrap_enum. The enumerations created that way
9
+ # of fixnum Gecode::Mixin#wrap_enum. The enumerations created that way
10
10
  # all respond to the properties defined by FixnumEnumOperand.
11
11
  #
12
12
  # ==== Examples
13
13
  #
14
- # Uses Gecode::Model#wrap_enum inside a problem formulation to create
14
+ # Uses Gecode::Mixin#wrap_enum inside a problem formulation to create
15
15
  # a FixnumEnumOperand from an existing enumeration of Fixnum:
16
16
  #
17
17
  # fixnum_enum = wrap_enum([3, 5, 7])
@@ -44,7 +44,7 @@ module Gecode::IntEnum
44
44
  # == Regexp syntax
45
45
  #
46
46
  # The regular expressions are specified using arrays, integers and a
47
- # few methods provided by Model. Arrays are used to group the
47
+ # few methods provided by Mixin. Arrays are used to group the
48
48
  # integers in sequences that must be matched. The following array
49
49
  # describes a regular expression matching a 1 followed by a 7.
50
50
  #
@@ -55,18 +55,18 @@ module Gecode::IntEnum
55
55
  #
56
56
  # [[[1], 7]]
57
57
  #
58
- # A couple of methods provided by Model are used to express patterns
58
+ # A couple of methods provided by Mixin are used to express patterns
59
59
  # beyond mere sequences:
60
60
  #
61
- # [Model#repeat] Used for specifying patterns that include patterns
61
+ # [Mixin#repeat] Used for specifying patterns that include patterns
62
62
  # that may be repeated a given number of times. The
63
63
  # number of times to repeat a pattern can be specified
64
64
  # using a lower and upper bound, but the bounds can be
65
65
  # omitted to for instance allow an expression to be
66
66
  # repeated any number of times.
67
- # [Model#any] Used for specifying alternatives.
67
+ # [Mixin#any] Used for specifying alternatives.
68
68
  #
69
- # Additionally Model#at_least_once and Model#at_most_once are
69
+ # Additionally Mixin#at_least_once and Mixin#at_most_once are
70
70
  # provided as convenience methods.
71
71
  #
72
72
  # ==== Examples