123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348 |
- <?xml version="1.0" ?>
- <diagram author="Simon Van Mierlo" name="NetLogo debugging-enhanced simulator">
- <description>
- A NetLogo simulator (enhanced with debugging support).
- </description>
- <top>
- import pyNetLogo
- import pprint, time
- class Breakpoint(object):
- def __init__(self, breakpoint_id, function, enabled, disable_on_trigger):
- self.id = breakpoint_id
- self.function = function
- self.enabled = enabled
- self.disable_on_trigger = disable_on_trigger
- </top>
- <inport name="request"/>
- <outport name="reply"/>
- <class name="NetLogoSimulator" default="true">
- <constructor>
- <parameter name="model"/>
- <body>
- <![CDATA[
- self.link = pyNetLogo.NetLogoLink(gui=True,
- netlogo_home="C:\\Program Files\\NetLogo 6.0.3",
- netlogo_version="6")
- self.link.load_model(model)
- self.attr_names = self.link.report('last last reflection:breeds')
- self.link.command("setup")
- self.ignored_attributes = set(["WHO", "HEADING", "SHAPE", "LABEL", "LABEL-COLOR", "BREED", "HIDDEN?", "PEN-SIZE", "PEN-MODE"])
- self.breakpoints = []
- self.realtime_scale = 1.0
- self.simulation_time = 0
- self.time_next = 1
- self.turtles = {}
- # Values to be set during simulation
- self.realtime_starttime = None
- ]]>
- </body>
- </constructor>
- <method name="turtles_created">
- <parameter name="new_turtles" />
- <body>
- return set(new_turtles.keys()) - set(self.turtles.keys())
- </body>
- </method>
- <method name="turtles_deleted">
- <parameter name="new_turtles" />
- <body>
- return set(self.turtles.keys()) - set(new_turtles.keys())
- </body>
- </method>
- <method name="get_all_turtles">
- <body>
- try:
- all_turtle_attributes = self.link.report("reflection:turtles")
- except:
- all_turtle_attributes = {}
- turtles = {}
- for turtle_attributes in all_turtle_attributes:
- the_turtle = dict(zip(self.attr_names, turtle_attributes.getResultAsObject()))
- turtles[int(float(the_turtle["WHO"]))] = the_turtle
- turtles = {k: {ak: av for ak, av in turtles[k].iteritems() if ak not in self.ignored_attributes} for k in turtles.keys()}
- return turtles
- </body>
- </method>
- <method name="breakpoint_triggers">
- <body>
- <![CDATA[
- breakpoint_id = -1
- for bp in self.breakpoints:
- if not bp.enabled:
- continue
- # Include the function in the scope
- exec(bp.function)
- # And execute it, note that the breakpoint thus has to start with "def breakpoint("
- if breakpoint(self.link.report("ticks"), self.turtles):
- # Triggered!
- breakpoint_id = bp.id
- else:
- # Not triggered, so continue
- continue
- return breakpoint_id
- ]]>
- </body>
- </method>
- <method name="process_breakpoints">
- <body>
- <![CDATA[
- breakpoint_id = self.breakpoint_triggers()
- if (breakpoint_id != -1):
- for breakpoint in self.breakpoints:
- if breakpoint.id == breakpoint_id:
- if breakpoint.disable_on_trigger:
- breakpoint.enabled = False
- return breakpoint_id
- ]]>
- </body>
- </method>
- <!-- Calculate the time to wait before triggering the next transition.
- This method is also called in non-realtime simulation, so make sure that it returns infinity in that case. -->
- <method name="calculate_after">
- <body>
- <![CDATA[
- try:
- # Process in parts of 100 milliseconds to repeatedly check the termination condition
- nexttime = (self.time_next - (time.time() - self.realtime_starttime) / self.realtime_scale) * self.realtime_scale
- x = min(0.1, nexttime)
- return x
- except (TypeError, AttributeError) as e:
- # We are probably not simulating in realtime...
- return float('inf')
- ]]>
- </body>
- </method>
- <!-- Parse a list of options that can be passed together with the request -->
- <method name="parse_options">
- <parameter name="configuration"/>
- <body>
- <![CDATA[
- self.realtime_scale = 1.0 if "realtime_scale" not in configuration else 1.0/configuration["realtime_scale"]
- # Subtract the current simulation time to allow for pausing
- self.realtime_starttime = (time.time() - self.simulation_time * self.realtime_scale)
- # Reset the time used in the waiting, as it might not get recomputed
- self.the_time = 0.00001
- ]]>
- </body>
- </method>
- <scxml initial="main">
- <parallel id="main">
- <state id="simulation_flow" initial="initialize">
- <state id="initialize">
- <transition target="../check_termination">
- <script>
- self.new_turtles = self.get_all_turtles()
- </script>
- <raise scope="output" port="reply" event="all_states">
- <parameter expr="self.simulation_time" />
- <parameter expr="self.new_turtles" />
- <parameter expr="{'CREATED_TURTLES': self.turtles_created(self.new_turtles),
- 'DELETED_TURTLES': self.turtles_deleted(self.new_turtles)}" />
- </raise>
- <script>
- self.turtles = self.new_turtles
- </script>
- </transition>
- </state>
- <state id="check_termination" initial="workaround">
- <onexit>
- <script>
- self.simulation_time = self.time_next
- </script>
- </onexit>
- <state id="workaround">
- <transition after="self.sccd_yield()" target="../check_termination"/>
- </state>
- <state id="wait">
- <onexit>
- <script>
- diff = time.time() - self.realtime_starttime
- self.simulation_time = diff / self.realtime_scale
- </script>
- </onexit>
- <transition after="self.calculate_after()" target="../check_termination"/>
- <transition cond="INSTATE('../../../simulation_state/paused')" target="../check_termination"/>
- </state>
- <state id="check_termination">
- <onentry>
- <script>
- self.the_time = self.calculate_after()
- </script>
- </onentry>
- <transition cond="(not INSTATE('../../../simulation_state/paused')) and (self.breakpoint_triggers() > -1)" target="../workaround">
- <script>
- breakpoint_id = self.process_breakpoints()
- </script>
- <raise scope="output" port="reply" event="breakpoint_triggered">
- <parameter expr="breakpoint_id"/>
- </raise>
- <raise event="termination_condition"/>
- </transition>
- <transition target="../../execute_step" cond="INSTATE('../../../simulation_state/continuous')" />
- <transition target="../../execute_step" event="step" port="request" />
- <transition target="../wait" cond="INSTATE('../../../simulation_state/realtime') and (self.the_time > 0.0)"/>
- <transition target="../../execute_step" cond="INSTATE('../../../simulation_state/realtime') and (self.the_time <= 0.0)"/>
- <transition cond="INSTATE('../../../simulation_state/paused')" port="request" event="god_event" target="../workaround">
- <parameter name="configuration"/>
- <script>
- turtle_id = configuration["turtle"]
- state_attribute = configuration["attribute"]
- new_value = configuration["value"]
- askstring = "ask turtle %i [set %s %s]" % (int(turtle_id), state_attribute, new_value)
- self.link.command(askstring)
- self.new_turtles = self.get_all_turtles()
- </script>
- <raise scope="output" port="reply" event="god_event_ok" />
- <raise scope="output" port="reply" event="all_states">
- <parameter expr="self.simulation_time" />
- <parameter expr="self.new_turtles" />
- <parameter expr="{'CREATED_TURTLES': self.turtles_created(self.new_turtles),
- 'DELETED_TURTLES': self.turtles_deleted(self.new_turtles)}" />
- </raise>
- <script>
- self.turtles = self.new_turtles
- </script>
- </transition>
- </state>
- </state>
- <state id="execute_step" initial="executing_step">
- <onentry>
- <script>
- self.link.command("go")
- self.new_turtles = self.get_all_turtles()
- </script>
- </onentry>
- <state id="executing_step">
- <transition target="../../check_termination" cond="INSTATE('../../../simulation_state/continuous')">
- <script>
- self.time_next = self.time_next + 1
- </script>
- </transition>
- <transition target="../../check_termination" cond="ELSE">
- <raise scope="output" port="reply" event="all_states">
- <parameter expr="self.simulation_time" />
- <parameter expr="self.new_turtles" />
- <parameter expr="{'CREATED_TURTLES': self.turtles_created(self.new_turtles),
- 'DELETED_TURTLES': self.turtles_deleted(self.new_turtles)}" />
- </raise>
- <script>
- self.time_next = self.time_next + 1
- self.turtles = self.new_turtles
- </script>
- </transition>
- </state>
- </state>
- </state>
- <state id="simulation_state" initial="paused">
- <state id="paused">
- <transition target="../continuous" event="continuous" port="request" />
- <transition target="../realtime" event="realtime" port="request">
- <parameter name="configuration" />
- <script>
- self.parse_options(configuration)
- </script>
- </transition>
- </state>
- <state id="continuous">
- <transition target="../paused" event="pause">
- <raise scope="output" port="reply" event="all_states">
- <parameter expr="self.simulation_time" />
- <parameter expr="self.new_turtles" />
- <parameter expr="{'CREATED_TURTLES': self.turtles_created(self.new_turtles),
- 'DELETED_TURTLES': self.turtles_deleted(self.new_turtles)}" />
- </raise>
- <script>
- self.turtles = self.new_turtles
- </script>
- </transition>
- <transition event="termination_condition" target="../paused">
- <raise port="reply" event="terminate">
- <parameter expr="self.simulation_time"/>
- </raise>
- </transition>
- </state>
- <state id="realtime">
- <transition target="../paused" event="pause">
- <script>
- diff = time.time() - self.realtime_starttime
- self.simulation_time = diff / self.realtime_scale
- self.new_turtles = self.get_all_turtles()
- </script>
- <raise scope="output" port="reply" event="all_states">
- <parameter expr="self.simulation_time" />
- <parameter expr="self.new_turtles" />
- <parameter expr="{'CREATED_TURTLES': self.turtles_created(self.new_turtles),
- 'DELETED_TURTLES': self.turtles_deleted(self.new_turtles)}" />
- </raise>
- <script>
- self.turtles = self.new_turtles
- </script>
- </transition>
- <transition event="termination_condition" target="../paused">
- <raise port="reply" event="terminate">
- <parameter expr="self.simulation_time"/>
- </raise>
- </transition>
- </state>
- </state>
- <state id="reset_manager" initial="listening">
- <state id="listening">
- <transition port="request" event="reset" target="." cond="INSTATE('../../simulation_state/paused')">
- <script>
- self.link.command("setup")
- self.new_turtles = self.get_all_turtles()
- self.simulation_time = 0
- self.realtime_scale = 1.0
- self.realtime_starttime = None
- self.time_next = 1
- </script>
- <raise scope="output" port="reply" event="all_states">
- <parameter expr="self.simulation_time"/>
- <parameter expr="self.new_turtles"/>
- <parameter expr="{'CREATED_TURTLES': self.turtles_created(self.new_turtles),
- 'DELETED_TURTLES': self.turtles_deleted(self.new_turtles)}" />
- </raise>
- <script>
- self.turtles = self.new_turtles
- </script>
- </transition>
- </state>
- </state>
- <state id="breakpoint_manager">
- <state id="breakpoint_manage">
- <transition port="request" event="add_breakpoint" target=".">
- <parameter name="breakpoint_id"/>
- <parameter name="function"/>
- <parameter name="enabled"/>
- <parameter name="disable_on_trigger"/>
- <script>
- self.breakpoints.append(Breakpoint(breakpoint_id, function, enabled, disable_on_trigger))
- </script>
- </transition>
- <transition port="request" event="del_breakpoint" target=".">
- <parameter name="del_breakpoint_id"/>
- <script>
- self.breakpoints = [breakpoint for breakpoint in self.breakpoints if breakpoint.id != del_breakpoint_id]
- </script>
- </transition>
- <transition port="request" event="toggle_breakpoint" target=".">
- <parameter name="breakpoint_id"/>
- <parameter name="enabled"/>
- <script>
- for breakpoint in self.breakpoints:
- if breakpoint.id == breakpoint_id:
- breakpoint.enabled = enabled
- break
- </script>
- </transition>
- </state>
- </state>
- </parallel>
- </scxml>
- </class>
- </diagram>
|