cellula 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: de9f62a45eba74c614a88bc2d734061d3003678f
4
+ data.tar.gz: d75b7307f6fd8e33831b31eb5a0a5d754f40316c
5
+ SHA512:
6
+ metadata.gz: c3aa5d7269e076dcb6ce23f4a5b72632258791152d432bd629b03e60bfece1b2239f3956736195bcf874c7ac8ac6821b96112f48221ef0a2f41db17e65b9b5e9
7
+ data.tar.gz: 39d31eed7ea97587959afaf8265fa9b9e59de9fba7b733be2f4fb2dcc85458624b1bbc7320f967584cc41b14ae87cc292603a7ea80061dfd4683309abbb863a9
@@ -0,0 +1,27 @@
1
+ This changelog is auto-generated using git-changelog.
2
+ See https://github.com/lkdjiin/git-changelog for more information.
3
+
4
+ * 2013-08-06 Generate dev's documentation
5
+ * 2013-08-06 Improve readme
6
+ * 2013-08-06 Improve documentation
7
+ * 2013-08-06 Fix bug in single 1 histories method
8
+ * 2013-08-06 Apache License v2
9
+ * 2013-08-06 Add tests for single 1 histories study method
10
+ Those tests fail for now.
11
+ * 2013-08-04 Add a test for :single study's method
12
+ * 2013-08-04 Add single 1 study method for elementary CA
13
+ This seems to be buggy. It works well with certain wolfram codes and
14
+ not so well with other ones. Problem is I don't really understand
15
+ how «single 1 histories» method of study works. I have to read more
16
+ on the subject.
17
+ * 2013-08-03 Refactoring
18
+ * 2013-08-03 Add reek to gemspec
19
+ * 2013-08-03 Extract WolframCodeRule from Rule
20
+ * 2013-08-03 Use Study instance
21
+ * 2013-08-03 Replace student by study in doc
22
+ * 2013-08-03 Rename Student to Study
23
+ * 2013-08-02 Print message and exit when bad cellula file
24
+ * 2013-08-02 Add basic Rule class
25
+ * 2013-08-02 Basic Automaton and Student objects
26
+ * 2013-08-01 Not anymore a library
27
+ * 2013-08-01 First commit
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+ ruby '2.0.0'
3
+
4
+ gemspec
5
+
6
+ gem 'rake'
7
+ gem 'rspec'
@@ -0,0 +1,48 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ cellula (0.1.0)
5
+ docile (= 1.1.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ coco (0.7.1)
11
+ diff-lcs (1.2.4)
12
+ docile (1.1.0)
13
+ rake (10.1.0)
14
+ reek (1.3.1)
15
+ ruby2ruby (~> 2.0.2)
16
+ ruby_parser (~> 3.1.1)
17
+ sexp_processor
18
+ rspec (2.14.1)
19
+ rspec-core (~> 2.14.0)
20
+ rspec-expectations (~> 2.14.0)
21
+ rspec-mocks (~> 2.14.0)
22
+ rspec-core (2.14.4)
23
+ rspec-expectations (2.14.0)
24
+ diff-lcs (>= 1.1.3, < 2.0)
25
+ rspec-mocks (2.14.2)
26
+ ruby2ruby (2.0.6)
27
+ ruby_parser (~> 3.1)
28
+ sexp_processor (~> 4.0)
29
+ ruby_parser (3.1.3)
30
+ sexp_processor (~> 4.1)
31
+ sexp_processor (4.2.1)
32
+ tomparse (0.4.2)
33
+ yard (0.8.7)
34
+ yard-tomdoc (0.7.1)
35
+ tomparse (>= 0.4.0)
36
+ yard
37
+
38
+ PLATFORMS
39
+ ruby
40
+
41
+ DEPENDENCIES
42
+ cellula!
43
+ coco (>= 0.7.1)
44
+ rake
45
+ reek
46
+ rspec
47
+ yard
48
+ yard-tomdoc
data/LICENSE ADDED
@@ -0,0 +1,167 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction, and
10
+ distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by the copyright
13
+ owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all other entities
16
+ that control, are controlled by, or are under common control with that entity.
17
+ For the purposes of this definition, "control" means (i) the power, direct or
18
+ indirect, to cause the direction or management of such entity, whether by
19
+ contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
20
+ outstanding shares, or (iii) beneficial ownership of such entity.
21
+
22
+ "You" (or "Your") shall mean an individual or Legal Entity exercising
23
+ permissions granted by this License.
24
+
25
+ "Source" form shall mean the preferred form for making modifications, including
26
+ but not limited to software source code, documentation source, and configuration
27
+ files.
28
+
29
+ "Object" form shall mean any form resulting from mechanical transformation or
30
+ translation of a Source form, including but not limited to compiled object code,
31
+ generated documentation, and conversions to other media types.
32
+
33
+ "Work" shall mean the work of authorship, whether in Source or Object form, made
34
+ available under the License, as indicated by a copyright notice that is included
35
+ in or attached to the work (an example is provided in the Appendix below).
36
+
37
+ "Derivative Works" shall mean any work, whether in Source or Object form, that
38
+ is based on (or derived from) the Work and for which the editorial revisions,
39
+ annotations, elaborations, or other modifications represent, as a whole, an
40
+ original work of authorship. For the purposes of this License, Derivative Works
41
+ shall not include works that remain separable from, or merely link (or bind by
42
+ name) to the interfaces of, the Work and Derivative Works thereof.
43
+
44
+ "Contribution" shall mean any work of authorship, including the original version
45
+ of the Work and any modifications or additions to that Work or Derivative Works
46
+ thereof, that is intentionally submitted to Licensor for inclusion in the Work
47
+ by the copyright owner or by an individual or Legal Entity authorized to submit
48
+ on behalf of the copyright owner. For the purposes of this definition,
49
+ "submitted" means any form of electronic, verbal, or written communication sent
50
+ to the Licensor or its representatives, including but not limited to
51
+ communication on electronic mailing lists, source code control systems, and
52
+ issue tracking systems that are managed by, or on behalf of, the Licensor for
53
+ the purpose of discussing and improving the Work, but excluding communication
54
+ that is conspicuously marked or otherwise designated in writing by the copyright
55
+ owner as "Not a Contribution."
56
+
57
+ "Contributor" shall mean Licensor and any individual or Legal Entity on behalf
58
+ of whom a Contribution has been received by Licensor and subsequently
59
+ incorporated within the Work.
60
+
61
+ 2. Grant of Copyright License.
62
+
63
+ Subject to the terms and conditions of this License, each Contributor hereby
64
+ grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
65
+ irrevocable copyright license to reproduce, prepare Derivative Works of,
66
+ publicly display, publicly perform, sublicense, and distribute the Work and such
67
+ Derivative Works in Source or Object form.
68
+
69
+ 3. Grant of Patent License.
70
+
71
+ Subject to the terms and conditions of this License, each Contributor hereby
72
+ grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
73
+ irrevocable (except as stated in this section) patent license to make, have
74
+ made, use, offer to sell, sell, import, and otherwise transfer the Work, where
75
+ such license applies only to those patent claims licensable by such Contributor
76
+ that are necessarily infringed by their Contribution(s) alone or by combination
77
+ of their Contribution(s) with the Work to which such Contribution(s) was
78
+ submitted. If You institute patent litigation against any entity (including a
79
+ cross-claim or counterclaim in a lawsuit) alleging that the Work or a
80
+ Contribution incorporated within the Work constitutes direct or contributory
81
+ patent infringement, then any patent licenses granted to You under this License
82
+ for that Work shall terminate as of the date such litigation is filed.
83
+
84
+ 4. Redistribution.
85
+
86
+ You may reproduce and distribute copies of the Work or Derivative Works thereof
87
+ in any medium, with or without modifications, and in Source or Object form,
88
+ provided that You meet the following conditions:
89
+
90
+ You must give any other recipients of the Work or Derivative Works a copy of
91
+ this License; and
92
+ You must cause any modified files to carry prominent notices stating that You
93
+ changed the files; and
94
+ You must retain, in the Source form of any Derivative Works that You distribute,
95
+ all copyright, patent, trademark, and attribution notices from the Source form
96
+ of the Work, excluding those notices that do not pertain to any part of the
97
+ Derivative Works; and
98
+ If the Work includes a "NOTICE" text file as part of its distribution, then any
99
+ Derivative Works that You distribute must include a readable copy of the
100
+ attribution notices contained within such NOTICE file, excluding those notices
101
+ that do not pertain to any part of the Derivative Works, in at least one of the
102
+ following places: within a NOTICE text file distributed as part of the
103
+ Derivative Works; within the Source form or documentation, if provided along
104
+ with the Derivative Works; or, within a display generated by the Derivative
105
+ Works, if and wherever such third-party notices normally appear. The contents of
106
+ the NOTICE file are for informational purposes only and do not modify the
107
+ License. You may add Your own attribution notices within Derivative Works that
108
+ You distribute, alongside or as an addendum to the NOTICE text from the Work,
109
+ provided that such additional attribution notices cannot be construed as
110
+ modifying the License.
111
+ You may add Your own copyright statement to Your modifications and may provide
112
+ additional or different license terms and conditions for use, reproduction, or
113
+ distribution of Your modifications, or for any such Derivative Works as a whole,
114
+ provided Your use, reproduction, and distribution of the Work otherwise complies
115
+ with the conditions stated in this License.
116
+
117
+ 5. Submission of Contributions.
118
+
119
+ Unless You explicitly state otherwise, any Contribution intentionally submitted
120
+ for inclusion in the Work by You to the Licensor shall be under the terms and
121
+ conditions of this License, without any additional terms or conditions.
122
+ Notwithstanding the above, nothing herein shall supersede or modify the terms of
123
+ any separate license agreement you may have executed with Licensor regarding
124
+ such Contributions.
125
+
126
+ 6. Trademarks.
127
+
128
+ This License does not grant permission to use the trade names, trademarks,
129
+ service marks, or product names of the Licensor, except as required for
130
+ reasonable and customary use in describing the origin of the Work and
131
+ reproducing the content of the NOTICE file.
132
+
133
+ 7. Disclaimer of Warranty.
134
+
135
+ Unless required by applicable law or agreed to in writing, Licensor provides the
136
+ Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
137
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
138
+ including, without limitation, any warranties or conditions of TITLE,
139
+ NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
140
+ solely responsible for determining the appropriateness of using or
141
+ redistributing the Work and assume any risks associated with Your exercise of
142
+ permissions under this License.
143
+
144
+ 8. Limitation of Liability.
145
+
146
+ In no event and under no legal theory, whether in tort (including negligence),
147
+ contract, or otherwise, unless required by applicable law (such as deliberate
148
+ and grossly negligent acts) or agreed to in writing, shall any Contributor be
149
+ liable to You for damages, including any direct, indirect, special, incidental,
150
+ or consequential damages of any character arising as a result of this License or
151
+ out of the use or inability to use the Work (including but not limited to
152
+ damages for loss of goodwill, work stoppage, computer failure or malfunction, or
153
+ any and all other commercial damages or losses), even if such Contributor has
154
+ been advised of the possibility of such damages.
155
+
156
+ 9. Accepting Warranty or Additional Liability.
157
+
158
+ While redistributing the Work or Derivative Works thereof, You may choose to
159
+ offer, and charge a fee for, acceptance of support, warranty, indemnity, or
160
+ other liability obligations and/or rights consistent with this License. However,
161
+ in accepting such obligations, You may act only on Your own behalf and on Your
162
+ sole responsibility, not on behalf of any other Contributor, and only if You
163
+ agree to indemnify, defend, and hold each Contributor harmless for any liability
164
+ incurred by, or claims asserted against, such Contributor by reason of your
165
+ accepting any such warranty or additional liability.
166
+
167
+ END OF TERMS AND CONDITIONS
@@ -0,0 +1,97 @@
1
+ Cellula
2
+ ================
3
+
4
+ Description
5
+ -----------
6
+
7
+ Cellula aims to be a framework for building, running and studying
8
+ cellular automata.
9
+
10
+ My main goal with Cellula is to *study* cellular automata, not only to *run*
11
+ them, so don't expect fancy graphics.
12
+
13
+ Another goal is to provide a simple DSL, allowing non-programmers to use
14
+ Cellula. Following is an example of Cellula DSL:
15
+
16
+ ``` ruby
17
+ automaton "Test CA" do
18
+ dimensions 1
19
+ type :elementary
20
+ width 20
21
+ rule :wolfram_code_110
22
+ end
23
+
24
+ study "Test CA" do
25
+ method :random
26
+ generations 4
27
+ end
28
+ ```
29
+
30
+ Save the previous example in a file named `my_automaton.rb` and
31
+ launch it with:
32
+
33
+ cellula path/to/my_automaton.rb
34
+
35
+
36
+ Install
37
+ -------------------------
38
+
39
+ gem install cellula
40
+
41
+ Usage
42
+ --------------------------
43
+ *This is a work in progress. More documentation is coming…*
44
+
45
+ ### automaton specifications
46
+
47
+ * dimensions
48
+ Number of dimensions of the grid. Currently Cellula supports only
49
+ 1D grids.
50
+ * type
51
+ Type of the automaton. Currently only :elementary (one-dimensional, 2
52
+ possible states per cell, neighbors are the immediate neighbors' cells.
53
+ * width
54
+ Width of the grid.
55
+ * rule
56
+ Currently only Wolfram code.
57
+
58
+ ### study specifications
59
+
60
+ * method
61
+ The study's method. Could be :random or :single. (View doc/study.rb
62
+ for more details)
63
+ * generations
64
+ Number of generations to process.
65
+
66
+ Dependencies
67
+ --------------------------
68
+
69
+ * ruby >= 2.0.0
70
+
71
+ Contributing
72
+ -------------------------
73
+
74
+ 1. Fork it
75
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
76
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
77
+ 4. Push to the branch (`git push origin my-new-feature`)
78
+ 5. Create new Pull Request
79
+
80
+ ### There is many other ways to contibute to Cellula
81
+
82
+ 1. Report any bugs
83
+ 2. Give me ideas
84
+ 3. Correct my poor english syntax
85
+ 4. Blog about Cellula
86
+ 5. Tell Cellula to your friends and colleagues
87
+
88
+ License
89
+ --------------------------
90
+ Apache v2 License (See LICENSE file).
91
+
92
+
93
+ Questions and/or Comments
94
+ --------------------------
95
+
96
+ Feel free to email [Xavier Nayrac](mailto:xavier.nayrac@gmail.com)
97
+ with any questions, or contact me on [twitter](https://twitter.com/lkdjiin).
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'rake'
4
+ require 'rspec/core/rake_task'
5
+
6
+ desc 'Test CellulaCore'
7
+ task :default => :spec
8
+
9
+ desc 'Test CellulaCore with rspec'
10
+ RSpec::Core::RakeTask.new(:spec) do |t|
11
+ t.rspec_opts = ['--color']
12
+ end
13
+
14
+ desc 'Check for code smells'
15
+ task :reek do
16
+ puts 'Checking for code smells...'
17
+ files = Dir.glob 'lib/**/*.rb'
18
+ args = files.join(' ')
19
+ sh "reek --quiet #{args} | ./reek.sed"
20
+ end
21
+
22
+ desc 'Generate documentation'
23
+ task :doc do
24
+ sh "yard --plugin tomdoc"
25
+ end
26
+
27
+ desc "Generate the changelog"
28
+ task :changelog do
29
+ system "git changelog > Changelog.markdown"
30
+ end
data/TODO ADDED
@@ -0,0 +1,9 @@
1
+ les noms ne sont pas obligatoires, et pour l'instant ils ne servent à rien.
2
+
3
+ life like
4
+
5
+ Séparer Cellula et CellulaCore ?
6
+
7
+ Option --backtrace pour exception ?
8
+
9
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
4
+ $CELLULA_PATH = File.expand_path(File.dirname(__FILE__)) + '/..'
5
+
6
+ require 'cellula'
7
+ include Cellula
8
+
9
+ banner
10
+
11
+ if ARGV[0].nil?
12
+ usage
13
+ exit
14
+ end
15
+
16
+ load ARGV[0].dup
17
+ puts @study.say_hello
18
+ puts
19
+
20
+ def to_single_1_histories(gen)
21
+ right_remove = (gen[1].size - (gen[0] * 2 + 1)) / 2
22
+ gen[1].pop(right_remove)
23
+ gen[1].join
24
+ end
25
+
26
+ generations = []
27
+
28
+ @auto.generate(@study) do |num, generation|
29
+ generations << [num, generation]
30
+ end
31
+
32
+ generations.each do |gen|
33
+ printf "%4s: %s\n", gen[0], gen[1].join()
34
+ end
35
+
36
+ if @study.method == :single
37
+ puts "Serie: " +
38
+ generations.map{|e| to_single_1_histories(e).to_i(2)}.join(', ')
39
+ end
40
+
@@ -0,0 +1,77 @@
1
+ require 'docile'
2
+ require 'cellula/automaton'
3
+ require 'cellula/study'
4
+ require 'cellula/automaton_builder'
5
+ require 'cellula/study_builder'
6
+ require 'cellula/rule'
7
+
8
+ # Public: Cellula is a framework for building, running and studying
9
+ # cellular automata. For this, Cellula provides a simple DSL.
10
+ #
11
+ # Following is an example of Cellula DSL:
12
+ #
13
+ # automaton "his name" do
14
+ # dimension 1
15
+ # type :elementary
16
+ # width 20
17
+ # rule :wolfram_code_110
18
+ # end
19
+ #
20
+ # Save the previous example in a file named `my_automaton.rb` and
21
+ # launch it with:
22
+ #
23
+ # cellula path/to/my_automaton.rb
24
+ module Cellula
25
+
26
+ # Internal: Part of the DSL API, this method builds a new Automaton
27
+ # object via AutomatonBuilder.
28
+ #
29
+ # name - String name of the automaton.
30
+ # block - A Ruby block to build the automaton.
31
+ #
32
+ # Returns nothing.
33
+ def automaton(name, &block)
34
+ @auto = Docile.dsl_eval(AutomatonBuilder.new(name), &block).build
35
+ end
36
+
37
+ # Internal: Part of the DSL API, this method builds a new Study
38
+ # object via StudyBuilder.
39
+ #
40
+ # name - String name of the automaton to study.
41
+ # block - A Ruby block to build the automaton.
42
+ #
43
+ # Returns nothing.
44
+ def study(name, &block)
45
+ @study = Docile.dsl_eval(StudyBuilder.new(name), &block).build
46
+ end
47
+
48
+ # Public: Display a banner on stdout.
49
+ #
50
+ # Returns nothing.
51
+ def banner
52
+ puts "Cellula version " + File.read('VERSION').strip
53
+ puts ""
54
+ end
55
+
56
+ # Public: Display application's usage on stdout.
57
+ #
58
+ # Returns nothing.
59
+ def usage
60
+ puts "
61
+ usage:
62
+
63
+ cellula path/to/automaton_file.rb
64
+ "
65
+ end
66
+
67
+ # Public: Print an error message and exit with code 1.
68
+ #
69
+ # message - The String message to display to user before exiting.
70
+ #
71
+ # Returns nothing.
72
+ def panic(message = "Unknown error")
73
+ puts "** Panic **"
74
+ puts message
75
+ exit(1)
76
+ end
77
+ end
@@ -0,0 +1,125 @@
1
+ module Cellula
2
+
3
+ # Public: This class provides all it's needed to run a cellular
4
+ # automaton.
5
+ #
6
+ # You rarely wants to initialize an Automaton directly. This is
7
+ # because Automaton's creation needs a lots of parameters. It is
8
+ # much more simpler to create Automata using AutomatonBuilder class.
9
+ #
10
+ # Dimensions
11
+ # ----------
12
+ # Currently only support 1D cellular automata.
13
+ #
14
+ # Type of automaton
15
+ # -----------------
16
+ # Currently only support elementary cellular automaton. Quoted from
17
+ # Wikipedia:
18
+ #
19
+ # an elementary cellular automaton is a one-dimensional cellular
20
+ # automaton where there are two possible states (labeled 0 and 1)
21
+ # and the rule to determine the state of a cell in the next generation
22
+ # depends only on the current state of the cell and its two immediate
23
+ # neighbors.
24
+ #
25
+ # See http://en.wikipedia.org/wiki/Elementary_cellular_automaton
26
+ # for more details.
27
+ #
28
+ # Rule
29
+ # ----
30
+ # Currently support only wolfram code rules.
31
+ #
32
+ # I hope to support custom rules and types soon.
33
+ class Automaton
34
+
35
+ # Public: Initialize a new Automaton.
36
+ #
37
+ # name - String name of the automaton.
38
+ # dimensions - Integer number of dimensions for the automaton's
39
+ # grid. Default is 1.
40
+ # type - Currently only :elementary.
41
+ # width - The Integer width of the automaton's grid.
42
+ # rule - Rule of the automaton. Currently rule is a Symbol
43
+ # following this pattern: :wolfram_code_X, where X is
44
+ # the rule number, from 0 to 255.
45
+ def initialize(name, dimensions, type, width, rule)
46
+ panic "Bad dimensions: #{dimensions}" if dimensions != 1
47
+ panic "Bad type: #{type}" if type != :elementary
48
+ panic "Bad width: #{width}" if width < 1
49
+ @name = name
50
+ @dimensions = dimensions
51
+ @type = type
52
+ @width = width
53
+ @rule = Rule.new(rule)
54
+ @grid = Array.new(@width)
55
+ @grid.map! {|item| rand(2) }
56
+ end
57
+
58
+ # Public: Get the String name of the automaton.
59
+ attr_reader :name
60
+
61
+ # Public: Set/get the Integer dimensions of the automaton's grid.
62
+ attr_accessor :dimensions
63
+
64
+ # Public: Set/get the Symbol type of the automaton.
65
+ attr_accessor :type
66
+
67
+ # Public: Set/get the Integer width of the automaton's grid.
68
+ attr_accessor :width
69
+
70
+ # Public: Get the rule of the automaton.
71
+ attr_reader :rule
72
+
73
+ # Public: Generate successive generations of this automaton.
74
+ # If, for example, `student.generations == 4` then #generate will
75
+ # produce 5 generations: The original generation plus the four you
76
+ # want.
77
+ #
78
+ # study - Study instance.
79
+ # block - What to do with a generation.
80
+ #
81
+ # Example
82
+ #
83
+ # automaton.generate(study) do |num, generation|
84
+ # printf "Gen %4s: %s\n", num, generation.join()
85
+ # end
86
+ # # => will result in something like that:
87
+ # # => Gen 0: 0101001010001011000001000100000100101011
88
+ # # => Gen 1: 0000010000010000000010001000001001000000
89
+ # # => Gen 2: 0000100000100000000100010000010010000000
90
+ # # => Gen 3: 0001000001000000001000100000100100000000
91
+ # # => Gen 4: 0010000010000000010001000001001000000000
92
+ #
93
+ # Returns successive generations as Array.
94
+ def generate(study, &block)
95
+ adapt_for_single_method if study.method == :single
96
+ block.call(0, @grid)
97
+ 1.upto(study.generations) do |cell_index|
98
+ apply_rule(study)
99
+ block.call(cell_index, @grid)
100
+ end
101
+ end
102
+
103
+ private
104
+
105
+ # Returns nothing.
106
+ def adapt_for_single_method
107
+ @width += 1 if @width % 2 == 0
108
+ @grid = Array.new(@width, 0)
109
+ @grid[@width / 2] = 1
110
+ end
111
+
112
+ # Apply rule to the entire grid. @grid becomes the next generation.
113
+ #
114
+ # study - Study instance.
115
+ #
116
+ # Returns nothing.
117
+ def apply_rule(study)
118
+ next_grid = @grid.map.with_index do |cell, index|
119
+ @rule.apply_rule(index, @grid, study)
120
+ end
121
+ @grid = next_grid
122
+ end
123
+
124
+ end
125
+ end
@@ -0,0 +1,55 @@
1
+ module Cellula
2
+
3
+ # Public: Provides an interface to build Automaton objects.
4
+ #
5
+ # Examples
6
+ #
7
+ # ca = AutomatonBuilder.new("my name").build
8
+ # ca = AutomatonBuilder.new("my name").dimensions(2).build
9
+ class AutomatonBuilder
10
+
11
+ # Public: Initialize an new AutomatonBuilder.
12
+ #
13
+ # name - String name of the futur Automaton.
14
+ def initialize(name)
15
+ @name = name
16
+ @dimensions = 1
17
+ @type = :elementary
18
+ @width = 20
19
+ @rule = :wolfram_code_110
20
+ end
21
+
22
+ # Public: Set the Integer dimensions of the automaton's grid.
23
+ # Default is 1.
24
+ #
25
+ # Returns self.
26
+ def dimensions(val); @dimensions = val; self; end
27
+
28
+ # Public: Set the Symbol type of the automaton. Default is
29
+ # :elementary.
30
+ #
31
+ # Returns self.
32
+ def type(val); @type = val; self; end
33
+
34
+ # Public: Set the Integer width of the automaton's grid.
35
+ # Default is 20.
36
+ #
37
+ # Returns self.
38
+ def width(val); @width = val; self; end
39
+
40
+ # Public: Set the rule of the automaton.
41
+ # Default is :wolfram_code_110.
42
+ #
43
+ # Returns self.
44
+ def rule(val); @rule = val; self; end
45
+
46
+ # Public: Builds an Automaton with characteristics given with
47
+ # the setters methods.
48
+ #
49
+ # Returns Automaton.
50
+ def build
51
+ Automaton.new(@name, @dimensions, @type, @width, @rule)
52
+ end
53
+ end
54
+ end
55
+
@@ -0,0 +1,2 @@
1
+ require 'cellula/rules/rule'
2
+ require 'cellula/rules/wolfram_code_rule'
@@ -0,0 +1,30 @@
1
+ module Cellula
2
+
3
+ # Internal: Know how to apply a rule to a single cell.
4
+ class Rule
5
+
6
+ # Public: Initialize a new Rule object.
7
+ #
8
+ # rule - Currently accept only wolfram code, in the form
9
+ # of a Symbol like :wolfram_code_110.
10
+ def initialize(rule)
11
+ if WolframCodeRule.wolfram_code?(rule)
12
+ @rule = WolframCodeRule.new WolframCodeRule.wolfram_code(rule)
13
+ else
14
+ panic "Unknown rule: #{rule.to_s}"
15
+ end
16
+ end
17
+
18
+ # Public: Apply the rule on a single cell.
19
+ #
20
+ # cell_number - Integer number of the cell to apply the rule on.
21
+ # grid - The entire grid as an Array of Integer.
22
+ # study - Study instance.
23
+ #
24
+ # Returns the Integer new state of the cell for the next generation.
25
+ def apply_rule(cell_number, grid, study)
26
+ @rule.apply_rule(cell_number, grid, study)
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,145 @@
1
+ module Cellula
2
+
3
+ # Internal: Know how to apply a Wolfram code rule on a single cell.
4
+ class WolframCodeRule
5
+
6
+ # Public: Initialize a new WolframCodeRule object.
7
+ # See http://en.wikipedia.org/wiki/Wolfram_code and
8
+ # http://en.wikipedia.org/wiki/Elementary_cellular_automaton
9
+ # for details.
10
+ #
11
+ # rule_number - Integer number of the wolfram code (a number between
12
+ # 0 and 255).
13
+ def initialize(rule_number)
14
+ @rule_number = rule_number
15
+ begin
16
+ check_rule_number
17
+ rescue Exception => ex
18
+ panic ex.message
19
+ end
20
+ @binary_string = "%08b" % @rule_number
21
+ end
22
+
23
+ # Public: Get the Integer wolfram code of the rule.
24
+ attr_reader :rule_number
25
+
26
+ # Public: Apply the rule on a single cell.
27
+ #
28
+ # cell_number - Integer number of the cell to apply the rule on.
29
+ # grid - The entire grid as an Array of Integer.
30
+ # study - Study instance.
31
+ #
32
+ # Returns the Integer new state of the cell for the next generation.
33
+ def apply_rule(cell_number, grid, study)
34
+ @cell_number = cell_number
35
+ @grid = grid
36
+ case study.method
37
+ when :random then apply_rule_with_random_method
38
+ when :single then apply_rule_with_single_method
39
+ end
40
+ end
41
+
42
+ # Get the Integer number part of a :wolfram_code_X pattern.
43
+ #
44
+ # pattern - Wolfram code pattern as a Symbol.
45
+ #
46
+ # Returns the Integer number part of the pattern.
47
+ # Exit application if the resulting number isn't between 0 and 255.
48
+ def self.wolfram_code(pattern)
49
+ pattern = pattern.to_s
50
+ num = pattern.delete("wolfram_code_").to_i
51
+ if num < 0 || num > 255
52
+ panic "Bad wolfram code: #{pattern}"
53
+ else
54
+ num
55
+ end
56
+ end
57
+
58
+ # Tells if a symbol follow the :wolfram_code_X pattern.
59
+ #
60
+ # symb - The Symbol to test.
61
+ #
62
+ # Returns Boolean true if sym is a :wolfram_code_X pattern.
63
+ def self.wolfram_code?(symb)
64
+ symb.is_a?(Symbol) && symb.to_s.start_with?("wolfram_code_")
65
+ end
66
+
67
+ private
68
+
69
+ # Returns 0 or 1.
70
+ def apply_rule_with_random_method
71
+ next_generation_cell(left_cell, @grid[@cell_number], right_cell)
72
+ end
73
+
74
+ # Get state of the cell to the left of the current one.
75
+ #
76
+ # Returns 0 or 1.
77
+ def left_cell
78
+ if @cell_number > 0
79
+ @grid[@cell_number - 1]
80
+ else
81
+ @grid[-1]
82
+ end
83
+ end
84
+
85
+ # Get state of the cell to the right of the current one.
86
+ #
87
+ # Returns 0 or 1.
88
+ def right_cell
89
+ if @cell_number == @grid.size - 1
90
+ @grid[0]
91
+ else
92
+ @grid[@cell_number + 1]
93
+ end
94
+ end
95
+
96
+ # Returns 0 or 1.
97
+ def apply_rule_with_single_method
98
+ next_generation_cell(left_cell_single, @grid[@cell_number], right_cell_single)
99
+ end
100
+
101
+ # Returns 0 or 1.
102
+ def next_generation_cell(left, middle, right)
103
+ case [left, middle, right]
104
+ when [1,1,1] then @binary_string[0].to_i
105
+ when [1,1,0] then @binary_string[1].to_i
106
+ when [1,0,1] then @binary_string[2].to_i
107
+ when [1,0,0] then @binary_string[3].to_i
108
+ when [0,1,1] then @binary_string[4].to_i
109
+ when [0,1,0] then @binary_string[5].to_i
110
+ when [0,0,1] then @binary_string[6].to_i
111
+ when [0,0,0] then @binary_string[7].to_i
112
+ end
113
+ end
114
+
115
+ # Returns 0 or 1.
116
+ def left_cell_single
117
+ if @cell_number > 0
118
+ @grid[@cell_number - 1]
119
+ else
120
+ 0
121
+ end
122
+ end
123
+
124
+ # Returns 0 or 1.
125
+ def right_cell_single
126
+ if @cell_number == @grid.size - 1
127
+ 0
128
+ else
129
+ @grid[@cell_number + 1]
130
+ end
131
+ end
132
+
133
+ # Check if rule's number (@rule_number) is in the range 0..255.
134
+ #
135
+ # Returns nothing.
136
+ # Raises ArgumentError if rule's number isn't in the range 0..255.
137
+ def check_rule_number
138
+ unless @rule_number >= 0 and @rule_number <= 255
139
+ raise ArgumentError, "Bad Wolfram Code: #{number}"
140
+ end
141
+ end
142
+
143
+ end
144
+
145
+ end
@@ -0,0 +1,76 @@
1
+ module Cellula
2
+
3
+ # Public: This class provides all it's needed to set up a study.
4
+ # Study's goal is to study cellular automaton.
5
+ #
6
+ # You rarely wants to initialize an Study object directly. This is
7
+ # because Study's creation needs a lots of parameters. It is
8
+ # much more simpler to create a Study object using StudyBuilder.
9
+ #
10
+ # Study's methods
11
+ # ---------------
12
+ # There is currently two kind of study's methods: random initial state
13
+ # (:random) and single 1 histories (:single). The following is quoted
14
+ # from Wikipedia:
15
+ #
16
+ # **Single 1 histories**
17
+ #
18
+ # One method used to study these automata is to follow its history
19
+ # with an initial state of all 0s except for a single cell with a 1.
20
+ # When the rule number is even (so that an input of 000 does not
21
+ # compute to a 1) it makes sense to interpret state at each time, t,
22
+ # as an integer expressed in binary, producing a sequence a(t) of
23
+ # integers.
24
+ #
25
+ # **Random initial state**
26
+ #
27
+ # A second way to investigate the behavior of these automata is to
28
+ # examine its history starting with a random state. Each computed
29
+ # result is placed under that results' source creating a
30
+ # two-dimensional representation of the system's evolution.
31
+ class Study
32
+
33
+ # Public: Initialize a new Study.
34
+ #
35
+ # ca_name - String name of the automaton to study.
36
+ # method - Symbol how to study the automaton.
37
+ # Default is :random.
38
+ # Could be one of:
39
+ # * :random
40
+ # * :single
41
+ # * :summed
42
+ # * :averaged
43
+ # Currently limited to :random and :single.
44
+ # generations - Integer number of generations to study.
45
+ # Default is 10.
46
+ def initialize(ca_name, method, generations)
47
+ @ca_name = ca_name
48
+ @method = method
49
+ @generations = generations
50
+ panic "Bad number of generations: #{generations}" if generations < 1
51
+ panic "Bad studying method: #{method}" if bad_studying_method
52
+ end
53
+
54
+ # Public: Get the String ca_name of the automaton to study.
55
+ attr_reader :ca_name
56
+
57
+ # Public: Set/get the Symbol studying method.
58
+ attr_accessor :method
59
+
60
+ # Public: Set/get the Integer number of generations to study.
61
+ attr_accessor :generations
62
+
63
+ def say_hello
64
+ "Studying #{@ca_name} with #{@method} method " +
65
+ "over #{@generations} generations."
66
+ end
67
+
68
+ private
69
+
70
+ def bad_studying_method
71
+ @method != :random && @method != :single
72
+ end
73
+ end
74
+ end
75
+
76
+
@@ -0,0 +1,43 @@
1
+ module Cellula
2
+
3
+ # Public: Provides an interface to build Study objects.
4
+ #
5
+ # Examples
6
+ #
7
+ # ca = StudyBuilder.new("CA name").build
8
+ # ca = StudyBuilder.new("CA name").generations(99).build
9
+ class StudyBuilder
10
+
11
+ # Public: Initialize an new StudyBuilder.
12
+ #
13
+ # ca_name - String name of the cellular automaton that the Study
14
+ # wants to study.
15
+ def initialize(ca_name)
16
+ @ca_name = ca_name
17
+ @method = :random
18
+ @generations = 10
19
+ end
20
+
21
+ # Public: Set the Symbol method of study.
22
+ # Default is :random.
23
+ #
24
+ # Returns self.
25
+ def method(val); @method = val; self; end
26
+
27
+ # Public: Set the Integer number of generations to study.
28
+ # Default is 10.
29
+ #
30
+ # Returns self.
31
+ def generations(val); @generations = val; self; end
32
+
33
+ # Public: Builds a Study with characteristics given with
34
+ # the setters methods.
35
+ #
36
+ # Returns Study.
37
+ def build
38
+ Study.new(@ca_name, @method, @generations)
39
+ end
40
+ end
41
+ end
42
+
43
+
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cellula
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Xavier Nayrac
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-08-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: docile
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.1.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 1.1.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: reek
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: coco
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.7.1
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: 0.7.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: yard
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: yard-tomdoc
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: |-
98
+ Cellula aims to be a framework for building,
99
+ running and studying cellular automata.
100
+ email: xavier.nayrac@gmail.com
101
+ executables:
102
+ - cellula
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - lib/cellula.rb
107
+ - lib/cellula/automaton.rb
108
+ - lib/cellula/automaton_builder.rb
109
+ - lib/cellula/rule.rb
110
+ - lib/cellula/rules/rule.rb
111
+ - lib/cellula/rules/wolfram_code_rule.rb
112
+ - lib/cellula/study.rb
113
+ - lib/cellula/study_builder.rb
114
+ - bin/cellula
115
+ - Changelog.markdown
116
+ - Gemfile
117
+ - Gemfile.lock
118
+ - LICENSE
119
+ - README.markdown
120
+ - Rakefile
121
+ - TODO
122
+ - VERSION
123
+ homepage: https://github.com/lkdjiin/cellula
124
+ licenses:
125
+ - ''
126
+ metadata: {}
127
+ post_install_message:
128
+ rdoc_options: []
129
+ require_paths:
130
+ - lib
131
+ required_ruby_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - '>='
134
+ - !ruby/object:Gem::Version
135
+ version: 2.0.0
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - '>='
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ requirements: []
142
+ rubyforge_project:
143
+ rubygems_version: 2.0.3
144
+ signing_key:
145
+ specification_version: 4
146
+ summary: Cellular Automata framework with a simple DSL
147
+ test_files: []
148
+ has_rdoc: