Class: YNelson::Agent

Inherits:
Object
  • Object
show all
Includes:
YPetri::Agent::PetriNetRelated, YPetri::Agent::SimulationRelated
Defined in:
lib/y_nelson/agent.rb

Overview

YNelson’s user inteface. As the name suggests, represents an agent that manipulates the YNelson world. In his introduction to zz structures, Ted Nelson has remarks regarding the desired UI, such as:

Selection is a pointer to a collection of cells. View consists of selection and a coordinate system. Field<em> is a connected (contiguous) selection. <em>Coordinate system is a collection of oriented dimensions.

Apart from these author’s suggestions, the interface should offer similar functionality as YPetri::Agent – that is, should allow constructing a Petri net with the same commands as YPetri does.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeAgent

Initialization of a YNelson::Agent instance. For YNelson manipulators, the world is always YNelson itself.



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/y_nelson/agent.rb', line 25

def initialize
  @world = ::YNelson
  super
  # A hash of sheets. (For the moment being, YNelson acts like a spreadsheet.)
  @sheets = {}
  # Default dimension of this manipulator.
  @default_dimension = YNelson.Dimension( :row )
  # Zz object pointers of this manipulator.
  @primary_point = YNelson::ZzPoint.new
  @secondary_point = YNelson::ZzPoint.new
  # Zz dimension pointers of this manipulator.
  @primary_dimension_point =
    YNelson::DimensionPoint.new YNelson.Dimension( :row )
  @secondary_dimension_point =
    YNelson::DimensionPoint.new YNelson.Dimension( :column )
end

Instance Attribute Details

#sheetsObject (readonly)

Now the part related to the zz structure itself, like in module YNelson::Manipulator::ZzRelatedMethods

blah blah

end include YNelson::Manipulator::ZzRelatedMethods



48
49
50
# File 'lib/y_nelson/agent.rb', line 48

def sheets
  @sheets
end

#worldObject (readonly)

Returns the value of attribute world.



17
18
19
# File 'lib/y_nelson/agent.rb', line 17

def world
  @world
end

Instance Method Details

#default_dimensionObject

Now let’s look into the graph visualization.



67
68
69
# File 'lib/y_nelson/agent.rb', line 67

def default_dimension
  @default_dimension
end

#graphviz(dim1 = primary_dimension_point, dim2 = secondary_dimension_point) ⇒ Object

Define graphviz places.



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/y_nelson/agent.rb', line 99

def graphviz dim1=primary_dimension_point, dim2=secondary_dimension_point
  γ = GraphViz.new :G, type: :digraph  # Create a new graph

  # main        = γ.add_nodes( "main", shape: "box" )
  # parse       = γ.add_nodes( "parse", fillcolor: "yellow", style: "rounded,filled", shape: "diamond" )
  # execute     = γ.add_nodes( "execute", shape: "record", label: "{ a | b | c }", style: "rounded" )
  # init        = γ.add_nodes( "init", fillcolor: "yellow", style: "filled" )

  # set global node options
  γ.node[:color] = "#ddaa66"
  γ.node[:style] = "filled"
  γ.node[:shape] = "box"
  γ.node[:penwidth] = "1"
  γ.node[:fontname] = "Trebuchet MS"
  γ.node[:fontsize] = "8"
  γ.node[:fillcolor] = "#ffeecc"
  γ.node[:fontcolor] = "#775500"
  γ.node[:margin] = "0.0"

  # set global edge options
  γ.edge[:color] = "#999999"
  γ.edge[:weight] = "1"
  γ.edge[:fontsize] = "6"
  γ.edge[:fontcolor] = "#444444"
  γ.edge[:fontname] = "Verdana"
  γ.edge[:dir] = "forward"
  γ.edge[:arrowsize] = "0.5"

  # add zz objects
  place_nodes = places.map.with_object Hash.new do |place, |
    [place] = γ.add_nodes place.name.to_s
  end
  transition_nodes = transitions.map.with_object Hash.new do |transition, |
    [transition] = γ.add_nodes transition.name.to_s
  end
  nodes = place_nodes.merge transition_nodes
  # add edges for selected dimensions
  nodes.each { |instance, node|
    negward_neighbor = instance.( dim1 ).negward.neighbor
    nodes[ negward_neighbor ] << node if negward_neighbor # color 1
    negward_neighbor = instance.( dim2 ).negward.neighbor
    nodes[ negward_neighbor ] << node if negward_neighbor # color 2
  }

  γ.output png: "zz.png"        # Generate output image
  YSupport::KDE.show_file_with_kioclient File.expand_path( '.', "zz.png" )

  # main        = γ.add_nodes( "main", shape: "box" )
  # parse       = γ.add_nodes( "parse", fillcolor: "yellow", style: "rounded,filled", shape: "diamond" )
  # execute     = γ.add_nodes( "execute", shape: "record", label: "{ a | b | c }", style: "rounded" )
  # init        = γ.add_nodes( "init", fillcolor: "yellow", style: "filled" )
end

#make_transitionsObject



277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
# File 'lib/y_nelson/agent.rb', line 277

def make_transitions
  # require 'debug'
  # LATER: When walking around the sheets, currently, there is no
  # protection against references to empty cells
  @transitions_to_make.map { |prescription|
    sheet = prescription[:sheet]
    type = prescription[:type]
    place = prescription[:place]
    block = prescription[:assignment_closure]

    case type
    when :unary_codomain_w_magic_block
      # PARAMETER MAGIC:
      # Blocks with specially named input arguments
      domain = block.parameters.map{ |e| e[1].to_s }.map{ |param|
        point = ZzPoint.new( place )
        if SHEETS.keys.include? sheet_name = param.split('_')[0] then
          # if the name consists of a sheet and parameter name, then ok
          rest = param[sheet_name.size + 1..-1]
          point = ZzPoint.new( SHEETS[sheet_name][0][0] )
          col = [*('a'..'z')].index rest[0]
          point.rewind_negward! :x
          if rest.size > 1 then # also change row, asssuming "a0" style
            point.rewind_negward! :y
            row = rest[1..-1].to_i
            row.times { point.step_posward :y }
          end
          col.times { point.step_posward :x }
          point.cell
        elsif [*('a'..'z')].include? param[0] then
          # if the name consists of an alphabetic letter...
          col = [*('a'..'z')].index param[0]
          point.rewind_negward! :x
          if param.size > 1 then # also change row, assuming "a0" style
            point.rewind_negward! :y
            row = param[1..-1].to_i
            row.times { point.step_posward :y }
          end
          col.times { point.step_posward :x }
          point.cell
        elsif param[0] = '_' then
          # Params named '_1', '_2', ... refer to different rows, same :col,
          # param named '__' refers to same cell
          if param == '__' then cell else
            i = param[1..-1].to_i
            point.rewind_negward! :y
            i.times { point.step_posward :x }
            point.cell
          end
        else
          raise TypeError, "unrecognized magic block parameter: #{param}"
        end
      } # block.parameters.map
      
      # Instantiate the new transition (do not fire it yet):
      Transition( domain: domain,
                  codomain: [ place ],
                  action_closure: block,
                  assignment_action: true )
    when :downstream_copy
      # DOWNSTREAM COPY
      # A single transition assigning upstream value to the downstream cell
      Transition( domain: prescription[:domain],
                                codomain: [ place ],
                                action_closure: λ {|v| v },
                                assignment_action: true )
    else raise "Unknown transition prescription type: #{prescription[:type]}"
    end
  } # @transitions_to_make.map
end

#new_downstream_cell(&block) ⇒ Object Also known as: ϝ

Places an order for a spreadsheet-like assignment transition. The order will be fullfilled later when #make_transitions method is called.



351
352
353
354
355
356
357
358
359
360
361
362
# File 'lib/y_nelson/agent.rb', line 351

def new_downstream_cell &block
  # The place can be instatiated right away
  place = ZzCell( nil )

  # Transition making requests get remembered in @transitions_to_make:
  ( @transitions_to_make ||= [] ) <<
    { place: place,
      sheet: @current_sheet_name,
      assignment_closure: block,
      type: :unary_codomain_w_magic_block }
  return place
end

#new_downstream_copy(cell) ⇒ Object Also known as:

Places an order for a spreadsheet-lie pure reference to another cell.



367
368
369
370
371
372
373
374
375
376
# File 'lib/y_nelson/agent.rb', line 367

def new_downstream_copy( cell )
  # Again, the place can be instantiated immediately
  p = ZzCell( nil )

  # And put the transition making request to @transitions_to_make:
  ( @transitions_to_make ||= [] ) <<
    { place: p, sheet: @current_sheet_name, domain: cell,
      type: :downstream_copy }
  return p
end

#new_zz_row(*args) ⇒ Object Also known as:

Creates a new row (rank along :row dimension) zipped to current row along ξ.dim, using the supplied arguments as new row’s cell values.



253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/y_nelson/agent.rb', line 253

def new_zz_row *args
  args = args[0].first if args.size == 1 and args[0].is_a? Hash
  previous_row = ( ::YTed::SHEETS[@current_sheet_name][-1] || [] ).dup
  row = args.map{ |a| ZzCell( a ) }
  row.each_consecutive_pair{ |a, b| a.P! x: b } # connect along :x
  row.each{ |e| e.N! y: previous_row.shift } # zip to previous row
  ::YTed::SHEETS[@current_sheet_name] << row
  if row[0].value.is_a? Symbol then
    ::YTed::SHEETS[@current_sheet_name]
      .define_singleton_method args[0] { row[1].aE_kind_of ::YPetri::Place }
  end
end

#new_zz_sheet(name) ⇒ Object

#new_zz_sheet creates a new sheet with a single cell holding the sheet’s name and sets main point to it in :col dimenion sheet name as its value



269
270
271
272
273
274
275
# File 'lib/y_nelson/agent.rb', line 269

def new_zz_sheet( name )
  @current_sheet_name = name
  ::YTed::SHEETS[name] = []
  ::YTed::SHEETS
    .define_singleton_method name.to_sym do ::YTed::SHEETS[name] end
  return ::YTed::SHEETS[name]
end

#primary_dimension_pointObject Also known as: d1



81
82
83
# File 'lib/y_nelson/agent.rb', line 81

def primary_dimension_point
  @primary_dimension_point
end

#primary_pointObject Also known as: p1



71
72
73
# File 'lib/y_nelson/agent.rb', line 71

def primary_point
  @primary_point
end

#secondary_dimension_pointObject Also known as: d2



86
87
88
# File 'lib/y_nelson/agent.rb', line 86

def secondary_dimension_point
  @secondary_dimension_point
end

#secondary_pointObject Also known as: p2



76
77
78
# File 'lib/y_nelson/agent.rb', line 76

def secondary_point
  @secondary_point
end

#visualize(*args, &block) ⇒ Object

Define function to display it with kioclient.



93
94
95
# File 'lib/y_nelson/agent.rb', line 93

def visualize *args, &block
  graphviz *args, &block
end

#zz_rank(array, dimension) ⇒ Object

FIXME these methods do not work well #rank method creates a rank of connected cells along the given dimension (named arg :dimension, alias :dΞ ), from values given as array (named arg :array, alias :ᴀ). The rank is returned as a cell array.



228
229
230
231
232
# File 'lib/y_nelson/agent.rb', line 228

def zz_rank( array, dimension )
  array.map{ |e| ZzCell( e ) }.each_consecutive_pair{ |a, b|
    a.redefine_neighbors( dimension: dimension, posward: b )
  }
end

#zz_zip(cell_array, dimension) ⇒ Object

Zips an array of ZzCells (receiver) with another array of ZzCells in a given dimension. That is, each cell in the first array is made to point (have posward neighbor) to the corresponding cell in the second array.



238
239
240
241
242
243
244
# File 'lib/y_nelson/agent.rb', line 238

def zz_zip( cell_array, dimension )
  cell_array.a℈_all_∈( ::YTed::ZzCell )
  self.a℈_all_∈( ::YTed::ZzCell ).each.with_index{|cell, i|
    cell.redefine_neighbors( dimension: dimension,
                             posward: cell_array[i] )
  }
end

#ξ2_negward_neighbor(dim = nil) ⇒ Object Also known as: ξ2N



206
# File 'lib/y_nelson/agent.rb', line 206

def ξ2_negward_neighbor dim=nil; ::YTed::POINT2.negward_neighbor dim end

#ξ2_negward_side(dim = nil) ⇒ Object Also known as: ξ2n



161
# File 'lib/y_nelson/agent.rb', line 161

def ξ2_negward_side dim=nil; ::YTed::POINT2.negward_side dim end

#ξ2_posward_neighbor(dim = nil) ⇒ Object Also known as: ξ2P



204
# File 'lib/y_nelson/agent.rb', line 204

def ξ2_posward_neighbor dim=nil; ::YTed::POINT2.posward_neighbor dim end

#ξ2_posward_side(dim = nil) ⇒ Object Also known as: ξ2p



159
# File 'lib/y_nelson/agent.rb', line 159

def ξ2_posward_side dim=nil; ::YTed::POINT2.posward_side dim end

#ξ2_redefine_negward_neighbor(*args) ⇒ Object Also known as: ξ2N!



219
220
# File 'lib/y_nelson/agent.rb', line 219

def ξ2_redefine_negward_neighbor *args
::YTed::POINT2.redefine_negward_neighbor *args end

#ξ2_redefine_posward_neighbor(*args) ⇒ Object Also known as: ξ2P!



216
217
# File 'lib/y_nelson/agent.rb', line 216

def ξ2_redefine_posward_neighbor *args
::YTed::POINT2.redefine_posward_neighbor *args end

#ξ2_rewind_negward(*aa, &b) ⇒ Object



182
# File 'lib/y_nelson/agent.rb', line 182

def ξ2_rewind_negward *aa, &b; ::YTed::POINT.rewind_negward *aa, &b end

#ξ2_rewind_negward!(dim = nil) ⇒ Object Also known as: ξ2rn!, ξ2nn!



195
# File 'lib/y_nelson/agent.rb', line 195

def ξ2_rewind_negward! dim=nil; ::YTed::POINT2.rewind_negward! dim end

#ξ2_rewind_posward(*aa, &b) ⇒ Object Also known as: ξ2rp, ξ2pp



180
# File 'lib/y_nelson/agent.rb', line 180

def ξ2_rewind_posward *aa, &b; ::YTed::POINT.rewind_posward *aa, &b end

#ξ2_rewind_posward!(dim = nil) ⇒ Object Also known as: ξ2rp!, ξ2pp!



192
# File 'lib/y_nelson/agent.rb', line 192

def ξ2_rewind_posward! dim=nil; ::YTed::POINT2.rewind_posward! dim end

#ξ2_step_negward(dim = nil) ⇒ Object Also known as: ξ2n!



171
# File 'lib/y_nelson/agent.rb', line 171

def ξ2_step_negward dim=nil; ::YTed::POINT2.step_negward dim end

#ξ2_step_posward(dim = nil) ⇒ Object Also known as: ξ2p!



169
# File 'lib/y_nelson/agent.rb', line 169

def ξ2_step_posward dim=nil; ::YTed::POINT2.step_posward dim end

#ξ_negward_neighbor(dim = nil) ⇒ Object Also known as: ξN



202
# File 'lib/y_nelson/agent.rb', line 202

def ξ_negward_neighbor dim=nil; ::YTed::POINT.negward_neighbor dim end

#ξ_negward_side(dim = nil) ⇒ Object Also known as: ξn



157
# File 'lib/y_nelson/agent.rb', line 157

def ξ_negward_side dim=nil; ::YTed::POINT.negward_side dim end

#ξ_posward_neighbor(dim = nil) ⇒ Object Also known as: ξP

Neighbor referencers



200
# File 'lib/y_nelson/agent.rb', line 200

def ξ_posward_neighbor dim=nil; ::YTed::POINT.posward_neighbor dim end

#ξ_posward_side(dim = nil) ⇒ Object Also known as: ξp

Cell side referencers with r. to primary and secondary point



155
# File 'lib/y_nelson/agent.rb', line 155

def ξ_posward_side dim=nil; ::YTed::POINT.posward_side dim end

#ξ_redefine_negward_neighbor(*args) ⇒ Object Also known as: ξN!



213
214
# File 'lib/y_nelson/agent.rb', line 213

def ξ_redefine_negward_neighbor *args
::YTed::POINT.redefine_negward_neighbor *args end

#ξ_redefine_posward_neighbor(*args) ⇒ Object Also known as: ξP!

Neighbor redefinition



210
211
# File 'lib/y_nelson/agent.rb', line 210

def ξ_redefine_posward_neighbor *args
::YTed::POINT.redefine_posward_neighbor *args end

#ξ_rewind_negward(*aa, &b) ⇒ Object



178
# File 'lib/y_nelson/agent.rb', line 178

def ξ_rewind_negward *aa, &b; ::YTed::POINT.rewind_negward *aa, &b end

#ξ_rewind_negward!(dim = nil) ⇒ Object Also known as: ξrn!, ξnn!



189
# File 'lib/y_nelson/agent.rb', line 189

def ξ_rewind_negward! dim=nil; ::YTed::POINT.rewind_negward! dim end

#ξ_rewind_posward(*aa, &b) ⇒ Object Also known as: ξrp, ξpp

Point rank rewinders (rewinders without exclamation mark expect block or return enumerator



176
# File 'lib/y_nelson/agent.rb', line 176

def ξ_rewind_posward *aa, &b; ::YTed::POINT.rewind_posward *aa, &b end

#ξ_rewind_posward!(dim = nil) ⇒ Object

Point rak rewinters with exclamation mark (no block or enum, just do it)



186
# File 'lib/y_nelson/agent.rb', line 186

def ξ_rewind_posward! dim=nil; ::YTed::POINT.rewind_posward! dim end

#ξ_step_negward(dim = nil) ⇒ Object Also known as: ξn!



167
# File 'lib/y_nelson/agent.rb', line 167

def ξ_step_negward dim=nil; ::YTed::POINT.step_negward dim end

#ξ_step_posward(dim = nil) ⇒ Object Also known as: ξp!

Point walkers



165
# File 'lib/y_nelson/agent.rb', line 165

def ξ_step_posward dim=nil; ::YTed::POINT.step_posward dim end