y_nelson 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0d19c1eb4d0fca009913f2c4632ea803aafee8a0
4
+ data.tar.gz: 2ae45a24959f7041a7017a0ef44ee1f5023f4b44
5
+ SHA512:
6
+ metadata.gz: e42a83132fbecca38473d47c05ef1e7ecb3d1e134e517c7eda1c18b79b10df80d1d1340eae7e1e896e0027a3dca2339c35b703fb472ea38c5cf7a1874fd29b19
7
+ data.tar.gz: 51d15c79f5210d76e936dc0777285dccf7447b2a5faa59013822429798776c06ee092771f285af058d0c302a8cff0e9912fed75b4b87238cf32ba7fc4b344f2b
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ *~
2
+ .#*
3
+ \#*#
4
+ *.gem
5
+ *.rbc
6
+ .bundle
7
+ .config
8
+ .yardoc
9
+ Gemfile.lock
10
+ InstalledFiles
11
+ _yardoc
12
+ coverage
13
+ doc/
14
+ lib/bundler/man
15
+ pkg
16
+ rdoc
17
+ spec/reports
18
+ test/tmp
19
+ test/version_tmp
20
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in y_nelson.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 boris
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # YNelson
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'y_nelson'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install y_nelson
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,43 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Zz dimension can in principle be any object, in YNelson, special class
3
+ # Dimension is used.
4
+ #
5
+ class YNelson::Dimension
6
+ class << self
7
+ alias __new__ new
8
+
9
+ # Presents class-owned instances (array).
10
+ #
11
+ def instances
12
+ return @instances ||= []
13
+ end
14
+
15
+ # The #new constructor is changed, so that same instance is returned for
16
+ # same constructor arguments.
17
+ #
18
+ def new *args
19
+ instances.find { |ɪ| ɪ.object == args } or
20
+ __new__( *args ).tap { |ɪ| instances << ɪ }
21
+ end
22
+ end
23
+
24
+ attr_reader :object
25
+
26
+ # Simply assigns array of arguments to @object atrribute.
27
+ #
28
+ def initialize *args
29
+ @object = args
30
+ end
31
+
32
+ # Short instance description string.
33
+ #
34
+ def to_s
35
+ "#<YNelson::Dimension [#{object.join ', '}]>"
36
+ end
37
+ end # class YNelson::Dimension
38
+
39
+ # Convenience constructor.
40
+ #
41
+ def YNelson.Dimension *args
42
+ YNelson::Dimension.new *args
43
+ end
@@ -0,0 +1,15 @@
1
+ #encoding: utf-8
2
+
3
+ # A pointer to a zz dimension.
4
+ #
5
+ class YNelson::DimensionPoint
6
+ attr_accessor :dimension
7
+
8
+ def initialize dimension
9
+ @dimension = dimension
10
+ end
11
+
12
+ def default_dimension
13
+ YNelson.default_dimension
14
+ end
15
+ end # class YTed::DimensionPoint
@@ -0,0 +1,360 @@
1
+ # -*- coding: utf-8 -*-
2
+ # YNelson user inteface. Ted Nelson, in his introduction of zz structures, has
3
+ # remarks regarding a desired UI, such as:
4
+ #
5
+ # <em>Selection</em> is a pointer to a collection of cells.
6
+ # <em>View</em> consists of selection and a coordinate system.
7
+ # <em>Field<em> is a connected (contiguous) selection.
8
+ # <em>Coordinate system</em> is a collection of oriented dimensions.
9
+ #
10
+ # Apart from that, this manipulator should offer similar functionality as
11
+ # YPetri::Manipulator - that is, should allow constructing a Petri net
12
+ # without much ado about zz aspect, just like YPetri does.
13
+ #
14
+ class YNelson::Manipulator
15
+ attr_reader :workspace
16
+
17
+ include YPetri::Manipulator::PetriNetRelatedMethods
18
+ include YPetri::Manipulator::SimulationRelatedMethods
19
+
20
+ def initialize
21
+ # For YNelson manipulators, the workspace is always YNelson itself.
22
+ @workspace = ::YNelson
23
+ super
24
+ # A hash of sheets. For the moment being, YNelson acts as a spreadsheet.
25
+ @sheets = {}
26
+ # Default dimension of this manipulator.
27
+ @default_dimension = YNelson.Dimension :row
28
+ # Zz object pointers of this manipulator.
29
+ @primary_point = YNelson::ZzPoint.new
30
+ @secondary_point = YNelson::ZzPoint.new
31
+ # Zz dimension pointers of this manipulator.
32
+ @primary_dimension_point =
33
+ YNelson::DimensionPoint.new YNelson.Dimension( :row )
34
+ @secondary_dimension_point =
35
+ YNelson::DimensionPoint.new YNelson.Dimension( :column )
36
+ end
37
+
38
+ # Now the part related to the zz structure itself, like in
39
+ # module YNelson::Manipulator::ZzRelatedMethods
40
+ # blah blah
41
+ # end
42
+ # include YNelson::Manipulator::ZzRelatedMethods
43
+
44
+ attr_reader :sheets
45
+
46
+ # Dimension convenience constructor from
47
+ delegate( :Dimension,
48
+ to: :workspace )
49
+
50
+ # Creation of a single-output formula known well from spreadseets. Given a
51
+ # place, it creates a new assignment transition.
52
+ #
53
+ def ϝ &block
54
+ new_place = YNelson::Place.new
55
+ new_transition = YNelson::Transition.new assignment: true,
56
+ codomain: new_place,
57
+ action: block
58
+ return new_place, new_transition
59
+ end
60
+
61
+ # Now let's look into the graph visualization.
62
+
63
+ def default_dimension; @default_dimension end
64
+
65
+ def primary_point; @primary_point end
66
+ alias p1 primary_point
67
+
68
+ def secondary_point; @secondary_point end
69
+ alias p2 secondary_point
70
+
71
+ def primary_dimension_point; @primary_dimension_point end
72
+ alias d1 primary_dimension_point
73
+
74
+ def secondary_dimension_point; @secondary_dimension_point end
75
+ alias d2 secondary_dimension_point
76
+
77
+ # Define function to display it with kioclient
78
+ def visualize *args, &block; graphviz *args, &block end
79
+
80
+ # Define graphviz places
81
+ def graphviz dim1=primary_dimension_point, dim2=secondary_dimension_point
82
+ γ = GraphViz.new :G, type: :digraph # Create a new graph
83
+
84
+ # main = γ.add_nodes( "main", shape: "box" )
85
+ # parse = γ.add_nodes( "parse", fillcolor: "yellow", style: "rounded,filled", shape: "diamond" )
86
+ # execute = γ.add_nodes( "execute", shape: "record", label: "{ a | b | c }", style: "rounded" )
87
+ # init = γ.add_nodes( "init", fillcolor: "yellow", style: "filled" )
88
+
89
+ # set global node options
90
+ γ.node[:color] = "#ddaa66"
91
+ γ.node[:style] = "filled"
92
+ γ.node[:shape] = "box"
93
+ γ.node[:penwidth] = "1"
94
+ γ.node[:fontname] = "Trebuchet MS"
95
+ γ.node[:fontsize] = "8"
96
+ γ.node[:fillcolor] = "#ffeecc"
97
+ γ.node[:fontcolor] = "#775500"
98
+ γ.node[:margin] = "0.0"
99
+
100
+ # set global edge options
101
+ γ.edge[:color] = "#999999"
102
+ γ.edge[:weight] = "1"
103
+ γ.edge[:fontsize] = "6"
104
+ γ.edge[:fontcolor] = "#444444"
105
+ γ.edge[:fontname] = "Verdana"
106
+ γ.edge[:dir] = "forward"
107
+ γ.edge[:arrowsize] = "0.5"
108
+
109
+ # add zz objects
110
+ place_nodes = places.map.with_object Hash.new do |place, ꜧ|
111
+ ꜧ[place] = γ.add_nodes place.name.to_s
112
+ end
113
+ transition_nodes = transitions.map.with_object Hash.new do |transition, ꜧ|
114
+ ꜧ[transition] = γ.add_nodes transition.name.to_s
115
+ end
116
+ nodes = place_nodes.merge transition_nodes
117
+ # add edges for selected dimensions
118
+ nodes.each { |instance, node|
119
+ negward_neighbor = instance.( dim1 ).negward.neighbor
120
+ nodes[ negward_neighbor ] << node if negward_neighbor # color 1
121
+ negward_neighbor = instance.( dim2 ).negward.neighbor
122
+ nodes[ negward_neighbor ] << node if negward_neighbor # color 2
123
+ }
124
+
125
+ γ.output png: "zz.png" # Generate output image
126
+ YSupport::KDE.show_file_with_kioclient File.expand_path( '.', "zz.png" )
127
+
128
+ # main = γ.add_nodes( "main", shape: "box" )
129
+ # parse = γ.add_nodes( "parse", fillcolor: "yellow", style: "rounded,filled", shape: "diamond" )
130
+ # execute = γ.add_nodes( "execute", shape: "record", label: "{ a | b | c }", style: "rounded" )
131
+ # init = γ.add_nodes( "init", fillcolor: "yellow", style: "filled" )
132
+ end
133
+
134
+ # graphviz [:domain, 0 ], [:codomain, 0]
135
+
136
+ # Cell side referencers with r. to primary and secondary point
137
+ def ξ_posward_side dim=nil; ::YTed::POINT.posward_side dim end
138
+ alias :ξp :ξ_posward_side
139
+ def ξ_negward_side dim=nil; ::YTed::POINT.negward_side dim end
140
+ alias :ξn :ξ_negward_side
141
+ def ξ2_posward_side dim=nil; ::YTed::POINT2.posward_side dim end
142
+ alias :ξ2p :ξ2_posward_side
143
+ def ξ2_negward_side dim=nil; ::YTed::POINT2.negward_side dim end
144
+ alias :ξ2n :ξ2_negward_side
145
+
146
+ # Point walkers
147
+ def ξ_step_posward dim=nil; ::YTed::POINT.step_posward dim end
148
+ alias :ξp! :ξ_step_posward
149
+ def ξ_step_negward dim=nil; ::YTed::POINT.step_negward dim end
150
+ alias :ξn! :ξ_step_negward
151
+ def ξ2_step_posward dim=nil; ::YTed::POINT2.step_posward dim end
152
+ alias :ξ2p! :ξ2_step_posward
153
+ def ξ2_step_negward dim=nil; ::YTed::POINT2.step_negward dim end
154
+ alias :ξ2n! :ξ2_step_negward
155
+
156
+ # Point rank rewinders
157
+ # (rewinders without exclamation mark expect block or return enumerator
158
+ def ξ_rewind_posward *aa, &b; ::YTed::POINT.rewind_posward *aa, &b end
159
+ alias :ξrp :ξ_rewind_posward
160
+ def ξ_rewind_negward *aa, &b; ::YTed::POINT.rewind_negward *aa, &b end
161
+ alias :ξpp :ξ_rewind_posward
162
+ def ξ2_rewind_posward *aa, &b; ::YTed::POINT.rewind_posward *aa, &b end
163
+ alias :ξ2rp :ξ2_rewind_posward
164
+ def ξ2_rewind_negward *aa, &b; ::YTed::POINT.rewind_negward *aa, &b end
165
+ alias :ξ2pp :ξ2_rewind_posward
166
+
167
+ # Point rak rewinters with exclamation mark (no block or enum, just do it)
168
+ def ξ_rewind_posward! dim=nil; ::YTed::POINT.rewind_posward! dim end
169
+ alias :ξrn! :ξ_rewind_posward!
170
+ alias :ξnn! :ξ_rewind_posward!
171
+ def ξ_rewind_negward! dim=nil; ::YTed::POINT.rewind_negward! dim end
172
+ alias :ξrn! :ξ_rewind_negward!
173
+ alias :ξnn! :ξ_rewind_negward!
174
+ def ξ2_rewind_posward! dim=nil; ::YTed::POINT2.rewind_posward! dim end
175
+ alias :ξ2rp! :ξ2_rewind_posward!
176
+ alias :ξ2pp! :ξ2_rewind_posward!
177
+ def ξ2_rewind_negward! dim=nil; ::YTed::POINT2.rewind_negward! dim end
178
+ alias :ξ2rn! :ξ2_rewind_negward!
179
+ alias :ξ2nn! :ξ2_rewind_negward!
180
+
181
+ # Neighbor referencers
182
+ def ξ_posward_neighbor dim=nil; ::YTed::POINT.posward_neighbor dim end
183
+ alias :ξP :ξ_posward_neighbor
184
+ def ξ_negward_neighbor dim=nil; ::YTed::POINT.negward_neighbor dim end
185
+ alias :ξN :ξ_negward_neighbor
186
+ def ξ2_posward_neighbor dim=nil; ::YTed::POINT2.posward_neighbor dim end
187
+ alias :ξ2P :ξ2_posward_neighbor
188
+ def ξ2_negward_neighbor dim=nil; ::YTed::POINT2.negward_neighbor dim end
189
+ alias :ξ2N :ξ2_negward_neighbor
190
+
191
+ # Neighbor redefinition
192
+ def ξ_redefine_posward_neighbor *args
193
+ ::YTed::POINT.redefine_posward_neighbor *args end
194
+ alias :ξP! :ξ_redefine_posward_neighbor
195
+ def ξ_redefine_negward_neighbor *args
196
+ ::YTed::POINT.redefine_negward_neighbor *args end
197
+ alias :ξN! :ξ_redefine_negward_neighbor
198
+ def ξ2_redefine_posward_neighbor *args
199
+ ::YTed::POINT2.redefine_posward_neighbor *args end
200
+ alias :ξ2P! :ξ2_redefine_posward_neighbor
201
+ def ξ2_redefine_negward_neighbor *args
202
+ ::YTed::POINT2.redefine_negward_neighbor *args end
203
+ alias :ξ2N! :ξ2_redefine_negward_neighbor
204
+
205
+
206
+ # FIXME these methods do not work well
207
+ # #rank method creates a rank of connected cells along the given
208
+ # dimension (named arg :dimension, alias :dΞ ), from values given as array
209
+ # (named arg :array, alias :ᴀ). The rank is returned as a cell array.
210
+ def zz_rank( array, dimension )
211
+ array.map{ |e| ZzCell( e ) }.each_consecutive_pair{ |a, b|
212
+ a.redefine_neighbors( dimension: dimension, posward: b )
213
+ }
214
+ end
215
+
216
+ # Zips an array of ZzCells (receiver) with another array of ZzCells
217
+ # in a given dimension. That is, each cell in the first array is made
218
+ # to point (have posward neighbor) to the corresponding cell in the
219
+ # second array.
220
+ def zz_zip( cell_array, dimension )
221
+ cell_array.a℈_all_∈( ::YTed::ZzCell )
222
+ self.a℈_all_∈( ::YTed::ZzCell ).each.with_index{|cell, i|
223
+ cell.redefine_neighbors( dimension: dimension,
224
+ posward: cell_array[i] )
225
+ }
226
+ end
227
+
228
+ # All we need right now is use Zz as a spreadsheet, writing data in rows.
229
+
230
+ # FIXME: Zz properites not used at all - classical Ruby data structures
231
+ # are used instead. ξ is just a holder for sheet name
232
+
233
+ # Creates a new row (rank along :row dimension) zipped to current row
234
+ # along ξ.dim, using the supplied arguments as new row's cell values.
235
+ def new_zz_row *args
236
+ args = args[0].first if args.size == 1 and args[0].is_a? Hash
237
+ previous_row = ( ::YTed::SHEETS[@current_sheet_name][-1] || [] ).dup
238
+ row = args.map{ |a| ZzCell( a ) }
239
+ row.each_consecutive_pair{ |a, b| a.P! x: b } # connect along :x
240
+ row.each{ |e| e.N! y: previous_row.shift } # zip to previous row
241
+ ::YTed::SHEETS[@current_sheet_name] << row
242
+ if row[0].value.is_a? Symbol then
243
+ ::YTed::SHEETS[@current_sheet_name]
244
+ .define_singleton_method args[0] { row[1].aE_kind_of ::YPetri::Place }
245
+ end
246
+ end
247
+ alias :→ :new_zz_row
248
+
249
+ # #new_zz_sheet creates a new sheet with a single cell holding the sheet's
250
+ # name and sets main point to it in :col dimenion sheet name as its value
251
+ def new_zz_sheet( name )
252
+ @current_sheet_name = name
253
+ ::YTed::SHEETS[name] = []
254
+ ::YTed::SHEETS
255
+ .define_singleton_method name.to_sym do ::YTed::SHEETS[name] end
256
+ return ::YTed::SHEETS[name]
257
+ end
258
+
259
+ def make_transitions
260
+ # require 'debug'
261
+ # LATER: When walking around the sheets, currently, there is no
262
+ # protection against references to empty cells
263
+ @transitions_to_make.map { |prescription|
264
+ sheet = prescription[:sheet]
265
+ type = prescription[:type]
266
+ place = prescription[:place]
267
+ block = prescription[:assignment_closure]
268
+
269
+ case type
270
+ when :unary_codomain_w_magic_block
271
+ # PARAMETER MAGIC:
272
+ # Blocks with specially named input arguments
273
+ domain = block.parameters.map{ |e| e[1].to_s }.map{ |param|
274
+ point = ZzPoint.new( place )
275
+ if SHEETS.keys.include? sheet_name = param.split('_')[0] then
276
+ # if the name consists of a sheet and parameter name, then ok
277
+ rest = param[sheet_name.size + 1..-1]
278
+ point = ZzPoint.new( SHEETS[sheet_name][0][0] )
279
+ col = [*('a'..'z')].index rest[0]
280
+ point.rewind_negward! :x
281
+ if rest.size > 1 then # also change row, asssuming "a0" style
282
+ point.rewind_negward! :y
283
+ row = rest[1..-1].to_i
284
+ row.times { point.step_posward :y }
285
+ end
286
+ col.times { point.step_posward :x }
287
+ point.cell
288
+ elsif [*('a'..'z')].include? param[0] then
289
+ # if the name consists of an alphabetic letter...
290
+ col = [*('a'..'z')].index param[0]
291
+ point.rewind_negward! :x
292
+ if param.size > 1 then # also change row, assuming "a0" style
293
+ point.rewind_negward! :y
294
+ row = param[1..-1].to_i
295
+ row.times { point.step_posward :y }
296
+ end
297
+ col.times { point.step_posward :x }
298
+ point.cell
299
+ elsif param[0] = '_' then
300
+ # Params named '_1', '_2', ... refer to different rows, same :col,
301
+ # param named '__' refers to same cell
302
+ if param == '__' then cell else
303
+ i = param[1..-1].to_i
304
+ point.rewind_negward! :y
305
+ i.times { point.step_posward :x }
306
+ point.cell
307
+ end
308
+ else
309
+ raise TypeError, "unrecognized magic block parameter: #{param}"
310
+ end
311
+ } # block.parameters.map
312
+
313
+ # Instantiate the new transition (do not fire it yet):
314
+ Transition( domain: domain,
315
+ codomain: [ place ],
316
+ action_closure: block,
317
+ assignment_action: true )
318
+ when :downstream_copy
319
+ # DOWNSTREAM COPY
320
+ # A single transition assigning upstream value to the downstream cell
321
+ Transition( domain: prescription[:domain],
322
+ codomain: [ place ],
323
+ action_closure: λ {|v| v },
324
+ assignment_action: true )
325
+ else raise "Unknown transition prescription type: #{prescription[:type]}"
326
+ end
327
+ } # @transitions_to_make.map
328
+ end
329
+
330
+ # Places an order for a spreadsheet-like assignment transition. The order
331
+ # will be fullfilled later when #make_transitions method is called.
332
+ #
333
+ def new_downstream_cell &block
334
+ # The place can be instatiated right away
335
+ place = ZzCell( nil )
336
+
337
+ # Transition making requests get remembered in @transitions_to_make:
338
+ ( @transitions_to_make ||= [] ) <<
339
+ { place: place,
340
+ sheet: @current_sheet_name,
341
+ assignment_closure: block,
342
+ type: :unary_codomain_w_magic_block }
343
+ return place
344
+ end
345
+ alias :ϝ :new_downstream_cell
346
+
347
+ # Places an order for a spreadsheet-lie pure reference to another cell.
348
+ #
349
+ def new_downstream_copy( cell )
350
+ # Again, the place can be instantiated immediately
351
+ p = ZzCell( nil )
352
+
353
+ # And put the transition making request to @transitions_to_make:
354
+ ( @transitions_to_make ||= [] ) <<
355
+ { place: p, sheet: @current_sheet_name, domain: cell,
356
+ type: :downstream_copy }
357
+ return p
358
+ end
359
+ alias :↱ :new_downstream_copy
360
+ end
@@ -0,0 +1,12 @@
1
+ # Represents Petri nets inside the Nelson net.
2
+ #
3
+ class YNelson::Net < YPetri::Net
4
+
5
+ private
6
+
7
+ # Place, Transition, Net class
8
+ #
9
+ def Place; ::YNelson::Place end
10
+ def Transition; ::YNelson::Transition end
11
+ def Net; ::YNelson::Net end
12
+ end # class YNelson::Net
@@ -0,0 +1,28 @@
1
+ # YNelson::Place is analogical to a spreadsheet cell. It is based on
2
+ # YPetri::Place and offers simlar interace.
3
+ #
4
+ class YNelson::Place < YPetri::Place
5
+ include YNelson::Yzz
6
+ alias call along # .( :dim ) instead of .along( :dim )
7
+
8
+ class << self
9
+ end
10
+
11
+ # Subclass of YTed::Zz::Side.
12
+ #
13
+ class Side < Side
14
+ # "Budding": creation of new cells from the cell sides
15
+ def bud( value: L!, f: nil )
16
+ # FIXME
17
+ end
18
+ alias :>> :bud
19
+ end
20
+
21
+ private
22
+
23
+ # Place, Transition, Net class
24
+ #
25
+ def Place; ::YNelson::Place end
26
+ def Transition; ::YNelson::Transition end
27
+ def Net; ::YNelson::Net end
28
+ end
@@ -0,0 +1,38 @@
1
+ # YNelson::Transition is based on YPetri::Transition and offers similar
2
+ # interface. "Functions", on which transitions of a functional Petri net
3
+ # are based, are analogical to 'formulas' of a spreadsheet.
4
+ #
5
+ class YNelson::Transition < YPetri::Transition
6
+ include YNelson::Yzz
7
+ alias call along # .( :dim ) rather than .along( :dim )
8
+
9
+ private
10
+
11
+ # YNelson extends this YPetri::Transition private method, so that a zz
12
+ # connection is automatically created along dimension [:domain, i] for
13
+ # i-th domain place of the transition.
14
+ #
15
+ def inform_upstream_places
16
+ upstream_places.each_with_index { |p, i|
17
+ along( YNelson.Dimension self, :domain, i ) >> p
18
+ }
19
+ super
20
+ end
21
+
22
+ # YNelson extends this YPetri::Transition private method, so that a zz
23
+ # connection is autimatically created along along dimension [:codomain, i]
24
+ # for i-th codomain place of the transition.
25
+ #
26
+ def inform_downstream_places
27
+ downstream_places.each_with_index { |p, i|
28
+ along( YNelson.Dimension self, :codomain, i ) >> p
29
+ }
30
+ super
31
+ end
32
+
33
+ # Place, Transition, Net class.
34
+ #
35
+ def Place; ::YNelson::Place end
36
+ def Transition; ::YNelson::Transition end
37
+ def Net; ::YNelson::Net end
38
+ end
@@ -0,0 +1,4 @@
1
+ module YNelson
2
+ DEBUG = false
3
+ VERSION = "0.1.5"
4
+ end
@@ -0,0 +1,11 @@
1
+ # Represents Petri nets inside the Nelson net.
2
+ #
3
+ module YNelson::Yzz
4
+ include Yzz
5
+
6
+ def along *args
7
+ return super( args[0] ) if
8
+ args.size == 1 && args[0].is_a?( ::YNelson::Dimension )
9
+ super( ::YNelson.Dimension *args )
10
+ end
11
+ end # module YzzPrepend
Binary file
@@ -0,0 +1,136 @@
1
+ #encoding: utf-8
2
+
3
+ # A pointer to a Zz object. A glorified variable, basically.
4
+ #
5
+ class YNelson::ZzPoint
6
+ attr_accessor :zz
7
+
8
+ # Initialization has one optional argument :zz -- zz object at which the
9
+ # point should be initialized.
10
+ #
11
+ def initialize( zz: nil )
12
+ @zz = zz
13
+ end
14
+
15
+ delegate :marking, :value, :υ,
16
+ :marking=, :value=, :υ=,
17
+ :test_arcs, :codomain, :downstream_transitions,
18
+ :action_arcs, :domain, :upstream_transitions, :ϝ, # digamma: ϝ
19
+ :arcs, # :connectivity alias not delegated to avoid confusion
20
+ :upstream_places, # :precedents, :← not delegated, same reason
21
+ :downstream_places, # :dependents, :→ aliases not delegated
22
+ to: :zz
23
+ alias :v :value
24
+
25
+ def default_dimension; YNelson.primary_dimension end
26
+
27
+ # Quasi-delegation to zz
28
+
29
+ def along dimension=default_dimension
30
+ zz.along dimension
31
+ end
32
+
33
+ def posward( along: default_dimension )
34
+ along( along ).posward
35
+ end
36
+ alias p posward
37
+
38
+ def negward( along: default_dimension )
39
+ along( along ).negward_side
40
+ end
41
+ alias n negward
42
+
43
+ def posward_neighbor( along: default_dimension )
44
+ posward( along: along ).neighbor
45
+ end
46
+ alias P posward_neighbor
47
+
48
+ def negward_neighbor( along: default_dimension )
49
+ negward( along: along ).neighbor
50
+ end
51
+ alias N negward_neighbor
52
+
53
+ def redefine_posward_neighbor( neighbor, along: default_dimension )
54
+ posward( along: along ) << neighbor
55
+ end
56
+ alias P! :redefine_posward_neighbor
57
+
58
+ def redefine_negward_neighbor( neighbor, along: default_dimension )
59
+ negward( along: along ) << neighbor
60
+ end
61
+ alias N! :redefine_negward_neighbor
62
+
63
+ def bud_posward( value=nil, along: default_dimension )
64
+ posward( along: along ).bud value
65
+ end
66
+ alias bud bud_posward
67
+
68
+ def bud_negward( value=nil, along: default_dimension )
69
+ negward( along: along ).bud value
70
+ end
71
+
72
+ def rank( along: default_dimension )
73
+ zz.get_rank along: along
74
+ end
75
+
76
+ # Walkers
77
+
78
+ def step_posward( along: default_dimension )
79
+ neighbor = posward_neighbor along: along
80
+ if neighbor.is_a_zz? then @zz = neighbor else false end
81
+ end
82
+ alias step step_posward
83
+ alias p! step_posward
84
+
85
+ def step_negward( along: default_dimension )
86
+ neighbor = negward_neighbor along: along
87
+ if neighbor.is_a_zz? then @zz = neighbor else false end
88
+ end
89
+ alias n! step_negward
90
+
91
+ # Rewinders
92
+
93
+ def rewind_posward( along: default_dimension )
94
+ origin = zz
95
+ if block_given? then
96
+ loop { yield zz
97
+ return :end unless posward_neighbor( along: along ).is_a_zz?
98
+ return :loop if posward_neighbor( along: along ) == origin
99
+ step_posward along: along }
100
+ else # no block given, returns enumerator
101
+ Enumerator.new { |y|
102
+ loop { y << zz
103
+ break :end unless posward_neighbor( along: along ).is_a_zz?
104
+ break :loop if posward_neighbor( along: along ) == origin
105
+ step_posward along: along }
106
+ }
107
+ end
108
+ end
109
+
110
+ def rewind_negward( along: default_dimension )
111
+ origin = zz
112
+ if block_given? then
113
+ loop { yield zz
114
+ return :end unless negward_neighbor( along: along ).is_a_zz?
115
+ return :loop if negward_neighbor( along: along ) == origin
116
+ step_negward along: along }
117
+ else
118
+ Enumerator.new { |y|
119
+ loop { y << zz
120
+ break :end unless negward_neighbor( along: along ).is_a_zz?
121
+ break :loop if negward_neighbor( along: along ) == origin
122
+ step_negward along: along }
123
+ }
124
+ end
125
+ end
126
+
127
+ # Simple unconditional rewind.
128
+
129
+ def rewind_posward!( along: default_dimension )
130
+ rewind_posward( along: along ) {} # implemented using empty block
131
+ end
132
+
133
+ def rewind_negward!( along: default_dimension )
134
+ rewind_negward( along: along ) {}
135
+ end
136
+ end # class YNelson::ZzPoint
data/lib/y_nelson.rb ADDED
@@ -0,0 +1,146 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'yzz'
3
+ require 'y_petri'
4
+ require 'y_support/kde'
5
+
6
+ require 'graphviz'
7
+
8
+ require_relative 'y_nelson/version'
9
+ require_relative 'y_nelson/yzz'
10
+ require_relative 'y_nelson/dimension'
11
+ require_relative 'y_nelson/place'
12
+ require_relative 'y_nelson/transition'
13
+ require_relative 'y_nelson/net'
14
+ require_relative 'y_nelson/zz_point'
15
+ require_relative 'y_nelson/dimension_point'
16
+ require_relative 'y_nelson/manipulator'
17
+
18
+ # YNelson is an implementation of a cross between Ted Nelson's Zz structure, and
19
+ # a functional Petri net (FPN). The resulting data structure, which combines
20
+ # qualities of FPNs with those of relational databases, I refer to as Nelson net
21
+ # throughout this text.
22
+ #
23
+ # One way to understand Nelson nets is as a genralization of a spreadsheet. In
24
+ # his explanations of Zz structures, Ted Nelson makes wide use of spreadsheet
25
+ # metaphors: cells, ranks, rows, columns, cursors, selections... Nelson net
26
+ # implemented here adds "formulas" to the mix, represented by FPN transitions.
27
+ #
28
+ # Nelson net disposes of the arbitrary constraints on FPNs as well as the
29
+ # orthogonal structure of "cells" seen in most practical spreadsheet
30
+ # implementations:
31
+ #
32
+ # 1. Both places and transitions of the FPN take part in zz structure.
33
+ # 2. Formula-based transitions are upgraded to standalone FPN transitions.
34
+ #
35
+ # The implications of the zz structure differences from ordinary hyperorthogonal
36
+ # structures hav been, to a degree, explained by Ted Nelson himself. There is a
37
+ # growing body of literature on zz structure applications, including in
38
+ # bioinformatics.
39
+ #
40
+ # As for functional Petri nets, their power in computing is well recognized (eg.
41
+ # Funnel, Odersky 2000). FPNs are sometimes just called functional nets, because
42
+ # Petri originally described his nets as timeless and functionless. However, in
43
+ # special-purpose applications, such as biochemical applications, to which I
44
+ # incline, it is appropriate to honor Petri, who designed his nets specifically
45
+ # with chemical modeling in mind as one of their main applications. In
46
+ # biochemistry, it is common to call functional nets Petri nets (Miyano, 200?).
47
+ #
48
+ module YNelson
49
+ # Singleton class of YNelson is partial descendant of YPetri::Workspace. More
50
+ # specifically, it mixes in most YPetri::Workspace instance methods and
51
+ # provides interface, which should be a superset of YPetri::Workspace. The
52
+ # difference is, that while YPetri::Workspace can have multiple instances,
53
+ # representing workdesks, YNelson is a singleton representing relational
54
+ # database.
55
+ #
56
+ class << self
57
+ # YNelson metaclass includes instance methods of YPetri::Workspace.
58
+ include YPetri::Workspace::PetriNetRelatedMethods
59
+ include YPetri::Workspace::SimulationRelatedMethods
60
+
61
+ # Allows summoning DSL by 'include YNelson' (like YPetri does).
62
+ #
63
+ def included receiver
64
+ # receiver.instance_variable_set :@NelsonManipulator, Manipulator.new
65
+ # puts "included in #{receiver}"
66
+ receiver.module_exec {
67
+ define_method :nelson_manipulator do
68
+ singleton_class.instance_variable_get :@NelsonManipulator or
69
+ ( puts "defining Manipulator for #{self} singleton class" if YNelson::DEBUG
70
+ singleton_class.instance_variable_set :@NelsonManipulator, Manipulator.new )
71
+ end
72
+ }
73
+ end
74
+
75
+ def dimensions; @dimensions end
76
+ end # class << self
77
+
78
+ # Instance variables @Place, @Transition, @Net are expected by
79
+ # YPetri::Workspace module.
80
+ @Place, @Transition, @Net = self::Place, self::Transition, self::Net
81
+
82
+ # Atypical call to #initialize in the course of module execution.
83
+ initialize
84
+
85
+ delegate( :workspace, to: :nelson_manipulator )
86
+
87
+ # Petri net aspect.
88
+ delegate( :Place, :Transition, :Net,
89
+ :place, :transition, :pl, :tr,
90
+ :places, :transitions, :nets,
91
+ :pp, :tt, :nn,
92
+ :net_point,
93
+ :net_selection,
94
+ :net, :ne,
95
+ :net_point_reset,
96
+ :net_point_set,
97
+ to: :nelson_manipulator )
98
+
99
+ # Simulation aspect.
100
+ delegate( :simulation_point, :ssc_point, :cc_point, :imc_point,
101
+ :simulation_selection, :ssc_selection,
102
+ :cc_selection, :imc_selection,
103
+ :simulations,
104
+ :clamp_collections,
105
+ :initial_marking_collections,
106
+ :simulation_settings_collections,
107
+ :clamp_collection_names, :cc_names,
108
+ :initial_marking_collection_names, :imc_names,
109
+ :simulation_settings_collection_names, :ssc_names,
110
+ :set_clamp_collection, :set_cc,
111
+ :set_initial_marking_collection, :set_imc,
112
+ :set_simulation_settings_collection, :set_ssc,
113
+ :new_timed_simulation,
114
+ :clamp_cc, :initial_marking_cc, :simulation_settings_cc,
115
+ :simulation_point_position,
116
+ :simulation,
117
+ :clamp_collection, :cc,
118
+ :initial_marking_collection, :imc,
119
+ :simulation_settings_collection, :ssc,
120
+ :clamp,
121
+ :initial_marking,
122
+ :set_step, :set_step_size,
123
+ :set_time, :set_target_time,
124
+ :set_sampling,
125
+ :set_simulation_method,
126
+ :new_timed_simulation,
127
+ :run!,
128
+ :print_recording,
129
+ :plot,
130
+ :plot_selected,
131
+ :plot_state,
132
+ :plot_flux,
133
+ to: :nelson_manipulator )
134
+
135
+ # Zz aspect.
136
+ delegate( :Dimension,
137
+ :ϝ,
138
+ :default_dimension,
139
+ :primary_point, :p1,
140
+ :secondary_point, :p2,
141
+ :primary_dimension_point, :d1,
142
+ :secondary_dimension_point, :d2,
143
+ :visualize,
144
+ :graphviz,
145
+ to: :nelson_manipulator )
146
+ end
@@ -0,0 +1,121 @@
1
+ #! /usr/bin/ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ require 'minitest/spec'
5
+ require 'minitest/autorun'
6
+ # tested component itself
7
+ require './../lib/y_nelson'
8
+
9
+ # **************************************************************************
10
+ # Nelson net test
11
+ # **************************************************************************
12
+ #
13
+ describe YNelson do
14
+ before do
15
+ skip
16
+ @m = YNelson::Manipulator.new
17
+ @p = @m.Place default_marking: 3.2,
18
+ marking: 1.1,
19
+ quantum: 0.1
20
+ end
21
+
22
+ describe YNelson::Dimension do
23
+ it "should give same instance for same object" do
24
+ assert_equal YNelson.Dimension( :xxx ), @m.Dimension( :xxx )
25
+ end
26
+ end
27
+
28
+ describe "new transition form correct zz connections with places" do
29
+ it "should work as expected" do
30
+ assert_equal [], @p.neighbors
31
+ assert_equal [], @p.connectivity # 'connectivity' now exclusively a zz keyword
32
+ t = @m.Transition codomain: @p, action: lambda { 0.1 }, assignment: true
33
+ assert_equal [ @p ], t.neighbors
34
+ dim = @m.Dimension( :codomain, 0 )
35
+ assert_equal @p, t.along( dim ).posward.neighbor
36
+ # And then, it would be the job of dimension reduction to determine if
37
+ # some dimensions should be visualized or otherwise used together.
38
+ end
39
+ end
40
+
41
+ it "should work" do
42
+ # TODO:
43
+ # has point
44
+ # has dimension point
45
+ # can create places
46
+ @m.Place
47
+ # can remove places
48
+ end
49
+
50
+ describe "small Nelson net" do
51
+ before do
52
+ # TODO:
53
+ # Create a net of several places and transition
54
+ end
55
+
56
+ it "should work" do
57
+ # TODO:
58
+ # exercise the created Nelson net to make sure it works
59
+ # #set_posward_neighbor
60
+ # #set_negward_neighbor
61
+ # #along, #posward, #negward, etc...
62
+ end
63
+ end
64
+ end
65
+
66
+ describe YNelson::ZzPoint do
67
+ it "should work" do
68
+ # TODO
69
+ end
70
+ end
71
+
72
+ describe YNelson::DimensionPoint do
73
+ it "should work" do
74
+ # TODO
75
+ end
76
+ end
77
+
78
+ describe "visualization" do
79
+ before do
80
+ @m = YNelson::Manipulator.new
81
+ @m.Place name: :A, m!: 3.2
82
+ @m.Place name: :B, m!: 5
83
+ @m.Transition name: :T1, s: { A: -1, B: 1 }, rate: 1
84
+ @m.Place name: :C, m!: 7.0
85
+ @m.Transition name: :T2, s: { B: -1, C: 1 }, rate: 1
86
+ end
87
+
88
+ it "should work" do
89
+ dim1 = YNelson::Dimension( :domain, 0 )
90
+ dim2 = YNelson::Dimension( :codomain, 1 )
91
+ @m.visualize dim1, dim2
92
+ end
93
+ end
94
+
95
+ # describe "zz structure with a transition or two" do
96
+ # before do
97
+ # new_zz_sheet "koko"
98
+ # @c1, @c2, @c3 = ZzCell( 1 ), ZzCell( 2 ), ZzCell( 3 )
99
+ # new_zz_row @c1, @c2, @c3
100
+ # @c4 = ϝ { |a0, b0, c0| a0 + b0 + c0 }
101
+ # new_zz_row @c4
102
+ # end
103
+
104
+ # it "should have #make_transitions" do
105
+ # tt = make_transitions
106
+ # assert_equal 1, tt.size
107
+ # t = tt[0]
108
+ # assert_kind_of ::YPetri::Transition, t
109
+ # assert t.domain.include? @c1
110
+ # assert t.domain.include? @c2
111
+ # assert t.domain.include? @c3
112
+ # assert_equal nil, @c4.marking
113
+ # t.fire!
114
+ # assert_equal 6, @c4.marking
115
+ # new_zz_sheet "pipi"
116
+ # @c5 = ϝ { |koko_a0, koko_b0| koko_a0 + koko_b0 }
117
+ # tt = make_transitions
118
+ # tt.each &:fire!
119
+ # assert_equal 3, @c5.value
120
+ # end
121
+ # end
data/test/zz.png ADDED
Binary file
data/y_nelson.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'y_nelson/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "y_nelson"
8
+ spec.version = YNelson::VERSION
9
+ spec.authors = ["boris"]
10
+ spec.email = ["\"boris@iis.sinica.edu.tw\""]
11
+ spec.description = %q{Formalization and generalization of a spreadsheet.}
12
+ spec.summary = %q{A fusion of functional Petri net with a zz structure.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'yzz'
22
+ spec.add_dependency 'y_petri'
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.3"
25
+ spec.add_development_dependency "rake"
26
+ end
metadata ADDED
@@ -0,0 +1,121 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: y_nelson
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.5
5
+ platform: ruby
6
+ authors:
7
+ - boris
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-05-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: yzz
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: y_petri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
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: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Formalization and generalization of a spreadsheet.
70
+ email:
71
+ - '"boris@iis.sinica.edu.tw"'
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - Gemfile
78
+ - LICENSE.txt
79
+ - README.md
80
+ - Rakefile
81
+ - lib/y_nelson.rb
82
+ - lib/y_nelson/dimension.rb
83
+ - lib/y_nelson/dimension_point.rb
84
+ - lib/y_nelson/manipulator.rb
85
+ - lib/y_nelson/net.rb
86
+ - lib/y_nelson/place.rb
87
+ - lib/y_nelson/transition.rb
88
+ - lib/y_nelson/version.rb
89
+ - lib/y_nelson/yzz.rb
90
+ - lib/y_nelson/zz.png
91
+ - lib/y_nelson/zz_point.rb
92
+ - test/y_nelson_test.rb
93
+ - test/zz.png
94
+ - y_nelson.gemspec
95
+ homepage: ''
96
+ licenses:
97
+ - MIT
98
+ metadata: {}
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - '>='
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - '>='
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ requirements: []
114
+ rubyforge_project:
115
+ rubygems_version: 2.0.3
116
+ signing_key:
117
+ specification_version: 4
118
+ summary: A fusion of functional Petri net with a zz structure.
119
+ test_files:
120
+ - test/y_nelson_test.rb
121
+ - test/zz.png