From ea50051b921d78769bc553611e8fd0d28f9ae03d Mon Sep 17 00:00:00 2001 From: Pedro Andrade Date: Thu, 15 Oct 2015 11:05:13 -0300 Subject: [PATCH] Updates to TerraME version 1.6. Close #14. --- description.lua | 4 +- doc/files/LogoAgent.html | 110 ++++++++++++++++++++++++--- doc/files/LogoModel.html | 14 ++-- doc/files/Utils.html | 22 +++--- doc/files/data.html | 14 ++-- doc/files/font.html | 14 ++-- doc/files/models.html | 108 ++++++++++++++++++++++++-- doc/index.html | 34 ++++----- doc/luadoc.css | 6 +- lua/GrowingSociety.lua | 11 ++- lua/Labyrinth.lua | 13 ++++ lua/LifeCycle.lua | 9 +++ lua/LogoAgent.lua | 78 ++++++++++++++++--- lua/LogoModel.lua | 9 +-- lua/Overpopulation.lua | 9 +++ lua/SingleAgent.lua | 9 +++ lua/Sugarscape.lua | 23 +++--- lua/Utils.lua | 8 +- snapshots/GrowingSociety-chart-1.bmp | Bin 900054 -> 900054 bytes tests/LogoAgent.lua | 3 + 20 files changed, 398 insertions(+), 100 deletions(-) diff --git a/description.lua b/description.lua index 20ee996..d93d768 100644 --- a/description.lua +++ b/description.lua @@ -1,8 +1,8 @@ -version = "0.1" +version = "0.2" package = "logo" license = "GPL" title = "Simple spatial ABM" -depends = "terrame (>= 1.5)" +depends = "terrame (>= 1.6)" authors = "Pedro R. Andrade" contact = "pedro.andrade@inpe.br" content = "Implements ABM paradigm for spatial models with at most one agent per cell." diff --git a/doc/files/LogoAgent.html b/doc/files/LogoAgent.html index 912f90d..6bf0657 100644 --- a/doc/files/LogoAgent.html +++ b/doc/files/LogoAgent.html @@ -88,6 +88,8 @@

Models

+ + @@ -111,6 +113,9 @@

Types

+
  • LogoAgent
  • + +
  • LogoModel @@ -136,8 +141,6 @@

    Types

    - - @@ -161,9 +164,6 @@

    Functions

    -
  • LogoAgent
  • - - @@ -210,6 +210,51 @@

    LogoAgent + + + + +Basic Agent for Logo models. + + + + + +

    Arguments

    + + + + + + + + +

    Usage

    +
    import("logo")
    +
    +LogoAgent{}
    + + + + + + + + +

    Functions

    @@ -291,7 +336,19 @@

    Arguments

    Usage

    -
    agent:breed()
    +
    import("logo")
    +
    +Breed = LogoModel{
    +   quantity = 10,
    +   dim = 10,
    +   finalTime = 10,
    +   changes = function(agent)
    +       agent:breed()
    +       agent:relocate()
    +   end
    +}
    +
    +Breed:execute()
    @@ -336,7 +393,18 @@

    Arguments

    Usage

    -
    quantity = countNeighbors(agent)
    +
    import("logo")
    +
    +Count = LogoModel{
    +   quantity = 3,
    +   dim = 3,
    +   finalTime = 2,
    +   changes = function(agent)
    +       print(agent:countNeighbors())
    +   end
    +}
    +
    +Count:execute()
    @@ -381,7 +449,20 @@

    Arguments

    Usage

    -
    neigh = emptyNeighbor(agent)
    +
    import("logo")
    +
    +Empty = LogoModel{
    +   quantity = 6,
    +   dim = 3,
    +   finalTime = 10,
    +   changes = function(agent)
    +       if not agent:emptyNeighbor() then
    +           print("not empty")
    +       end
    +   end
    +}
    +
    +Empty:execute()
    @@ -426,7 +507,18 @@

    Arguments

    Usage

    -
    agent:relocate()
    +
    import("logo")
    +
    +Relocate = LogoModel{
    +   quantity = 10,
    +   dim = 10,
    +   finalTime = 10,
    +   changes = function(agent)
    +       agent:relocate()
    +   end
    +}
    +
    +Relocate:execute()
    diff --git a/doc/files/LogoModel.html b/doc/files/LogoModel.html index 8117544..a9a2981 100644 --- a/doc/files/LogoModel.html +++ b/doc/files/LogoModel.html @@ -88,6 +88,8 @@

    Models

    + + @@ -111,6 +113,11 @@

    Types

    +
  • + LogoAgent +
  • + +
  • LogoModel
  • @@ -134,8 +141,6 @@

    Types

    - - @@ -159,11 +164,6 @@

    Functions

    -
  • - LogoAgent -
  • - - diff --git a/doc/files/Utils.html b/doc/files/Utils.html index e7bbf03..76fe667 100644 --- a/doc/files/Utils.html +++ b/doc/files/Utils.html @@ -88,6 +88,8 @@

    Models

    + + @@ -111,6 +113,11 @@

    Types

    +
  • + LogoAgent +
  • + +
  • LogoModel @@ -136,8 +143,6 @@

    Types

    - - @@ -161,11 +166,6 @@

    Functions

    -
  • - LogoAgent -
  • - - @@ -277,7 +277,9 @@

    Arguments

    Usage

    -
    cs = getLabyrinth("room")
    +
    import("logo")
    +
    +room = getLabyrinth("room")
    @@ -322,7 +324,9 @@

    Arguments

    Usage

    -
    cs = getSugar("room")
    +
    import("logo")
    +
    +room = getSugar("default")
    diff --git a/doc/files/data.html b/doc/files/data.html index 00ae6f6..0860227 100644 --- a/doc/files/data.html +++ b/doc/files/data.html @@ -88,6 +88,8 @@

    Models

    + + @@ -111,6 +113,11 @@

    Types

    +
  • + LogoAgent +
  • + +
  • LogoModel @@ -136,8 +143,6 @@

    Types

    - - @@ -161,11 +166,6 @@

    Functions

    -
  • - LogoAgent -
  • - - diff --git a/doc/files/font.html b/doc/files/font.html index 3b85f2a..f2a9366 100644 --- a/doc/files/font.html +++ b/doc/files/font.html @@ -91,6 +91,8 @@

    Models

    + + @@ -114,6 +116,11 @@

    Types

    +
  • + LogoAgent +
  • + +
  • LogoModel @@ -139,8 +146,6 @@

    Types

    - - @@ -164,11 +169,6 @@

    Functions

    -
  • - LogoAgent -
  • - - diff --git a/doc/files/models.html b/doc/files/models.html index 773bf50..7c7bab3 100644 --- a/doc/files/models.html +++ b/doc/files/models.html @@ -88,6 +88,8 @@

    Models

    + + @@ -111,6 +113,11 @@

    Types

    +
  • + LogoAgent +
  • + +
  • LogoModel @@ -136,8 +143,6 @@

    Types

    - - @@ -161,11 +166,6 @@

    Functions

    -
  • - LogoAgent -
  • - - @@ -262,6 +262,21 @@

    Models

    Model where a given Society grows, filling the whole space. Agents reproduce with 20% of probability if there is an empty neighbor. +

    Arguments

    + + @@ -273,6 +288,23 @@

    Models

    A labyrynth, where agents move randomly from a given entrance until an exit point. There are some available labyrynths available. See the documentation of data. +

    Arguments

    + + @@ -284,6 +316,21 @@

    Models

    A model where agents reproduce and die by age. Each Agent starts with age zero. From age 15 until 30 they have 30% of chance of reproducing if there is an empty neighbor cell. Agents have 5% of probability of dying each time step after age 20. +

    Arguments

    + + @@ -299,6 +346,21 @@

    Models

    Model where Agents die by overpopulation. Each Agent beeds with a probability of 30% and die if there are more than three Agents in the neighborhood. +

    Arguments

    + + @@ -310,6 +372,21 @@

    Models

    A single agent moving around randomly. +

    Arguments

    + + @@ -321,6 +398,23 @@

    Models

    Model where a given Society grows, filling the whole space. Agents reproduce with 20% of probability if there is an empty neighbor. +

    Arguments

    + + diff --git a/doc/index.html b/doc/index.html index 27f499d..5adda9a 100644 --- a/doc/index.html +++ b/doc/index.html @@ -90,6 +90,8 @@

    Models

    + + @@ -113,6 +115,11 @@

    Types

    +
  • + LogoAgent +
  • + +
  • LogoModel @@ -138,8 +145,6 @@

    Types

    - - @@ -163,11 +168,6 @@

    Functions

    -
  • - LogoAgent -
  • - - @@ -205,19 +205,19 @@

    Data


    - Version: 0.1
    + Version: 0.2
    License: GPL
    - Release: 22 September 2015
    + Release: 15 October 2015
    Authors: Pedro R. Andrade
    - Depends: terrame (>= 1.5)
    + Depends: terrame (>= 1.6)

    @@ -336,6 +336,8 @@

    Models

    + + @@ -363,6 +365,11 @@

    Types

    + + LogoAgent + Basic Agent for Logo models. + + @@ -392,8 +399,6 @@

    Types

    - - @@ -422,11 +427,6 @@

    Functions

    - - LogoAgent - - - diff --git a/doc/luadoc.css b/doc/luadoc.css index 63259d3..4f33d45 100644 --- a/doc/luadoc.css +++ b/doc/luadoc.css @@ -56,10 +56,8 @@ a:link { font-weight:bold; color: #004080; text-decoration: none; } a:visited { font-weight:bold; color: #006699; text-decoration: none; } a:link:hover { text-decoration:underline; } hr { color:#cccccc } -.imgBorder { - border-width: 1px; - border-color: Black; -} +img { border-width: 0px; } + h3 { padding-top: 1em; } diff --git a/lua/GrowingSociety.lua b/lua/GrowingSociety.lua index 0aa3bd1..f8c7e7d 100644 --- a/lua/GrowingSociety.lua +++ b/lua/GrowingSociety.lua @@ -2,13 +2,22 @@ --- Model where a given Society grows, filling -- the whole space. Agents reproduce with 20% of -- probability if there is an empty neighbor. +-- @arg data.dim The x and y dimensions of space. +-- @arg data.chart A boolean value indicating whether a Chart +-- with the number of Agents along the simulation should +-- be drawn. +-- @arg data.quantity The initial number of Agents in the model. +-- @arg data.finalTime The final simulation time. +-- @arg data.map A boolean value indicating whether a Map +-- with the spatial distribution r of Agents along the +-- simulation should be drawn. -- @image growing-society.bmp GrowingSociety = LogoModel{ quantity = 1, dim = 20, chart = true, background = "green", - finalTime = 100, + finalTime = 60, changes = function(agent) if Random():number() < 0.2 then agent:breed() diff --git a/lua/Labyrinth.lua b/lua/Labyrinth.lua index 86016d2..3058331 100644 --- a/lua/Labyrinth.lua +++ b/lua/Labyrinth.lua @@ -6,6 +6,19 @@ labyrinths.default = "room" -- a given entrance until an exit point. -- There are some available labyrynths available. -- See the documentation of data. +-- @arg data.dim The x and y dimensions of space. +-- @arg data.chart A boolean value indicating whether a Chart +-- with the number of Agents along the simulation should +-- be drawn. +-- @arg data.finalTime The final simulation time. +-- @arg data.quantity The initial number of Agents in the model. +-- @arg data.map A boolean value indicating whether a Map +-- with the spatial distribution r of Agents along the +-- simulation should be drawn. +-- @arg data.labyrinth The spatial representation of the model. +-- The available labyrinths are described in the data available in the package. +-- They should be used without ".labyrinth" extension. The default pattern is +-- "room". -- @image labyrinth.bmp Labyrinth = LogoModel{ labyrinth = Choice(labyrinths), diff --git a/lua/LifeCycle.lua b/lua/LifeCycle.lua index 5ff7663..a9e4392 100644 --- a/lua/LifeCycle.lua +++ b/lua/LifeCycle.lua @@ -4,6 +4,15 @@ -- 30 they have 30% of chance of reproducing if there -- is an empty neighbor cell. Agents have 5% of -- probability of dying each time step after age 20. +-- @arg data.dim The x and y dimensions of space. +-- @arg data.chart A boolean value indicating whether a Chart +-- with the number of Agents along the simulation should +-- be drawn. +-- @arg data.quantity The initial number of Agents in the model. +-- @arg data.finalTime The final simulation time. +-- @arg data.map A boolean value indicating whether a Map +-- with the spatial distribution r of Agents along the +-- simulation should be drawn. -- @image life-cycle.bmp LifeCycle = LogoModel{ quantity = 10, diff --git a/lua/LogoAgent.lua b/lua/LogoAgent.lua index 90429d1..ccba299 100644 --- a/lua/LogoAgent.lua +++ b/lua/LogoAgent.lua @@ -1,9 +1,22 @@ ---LogoAgent_ = { --- type_ = "Agent", +LogoAgent_ = { + type_ = "Agent", --- Return an empty neighbor Cell. If there is no empty neighbor -- then it returns false. -- @arg agent An Agent. - -- @usage neigh = emptyNeighbor(agent) + -- @usage import("logo") + -- + -- Empty = LogoModel{ + -- quantity = 6, + -- dim = 3, + -- finalTime = 10, + -- changes = function(agent) + -- if not agent:emptyNeighbor() then + -- print("not empty") + -- end + -- end + -- } + -- + -- Empty:execute() emptyNeighbor = function(agent) local empty = {} forEachNeighbor(agent:getCell(), function(_, neigh) @@ -17,10 +30,21 @@ end return Random():sample(empty) - end + end, --- Count the number of Agents in the neighbor cells. -- @arg agent An Agent. - -- @usage quantity = countNeighbors(agent) + -- @usage import("logo") + -- + -- Count = LogoModel{ + -- quantity = 3, + -- dim = 3, + -- finalTime = 2, + -- changes = function(agent) + -- print(agent:countNeighbors()) + -- end + -- } + -- + -- Count:execute() countNeighbors = function(agent) local count = 0 forEachNeighbor(agent:getCell(), function(_, neigh) @@ -30,11 +54,22 @@ end) return count - end + end, --- Walk to a random neighbor Cell. If there is no -- empty neighbor then this function returns false. -- @arg agent An Agent. - -- @usage agent:relocate() + -- @usage import("logo") + -- + -- Relocate = LogoModel{ + -- quantity = 10, + -- dim = 10, + -- finalTime = 10, + -- changes = function(agent) + -- agent:relocate() + -- end + -- } + -- + -- Relocate:execute() relocate = function(agent) local empty = agent:emptyNeighbor() @@ -44,12 +79,24 @@ agent:move(empty) return true - end + end, --- Reproduce the Agent to a random neighbor Cell. -- If there is no empty neighbor cell then this -- function returns nil. -- @arg agent An Agent. - -- @usage agent:breed() + -- @usage import("logo") + -- + -- Breed = LogoModel{ + -- quantity = 10, + -- dim = 10, + -- finalTime = 10, + -- changes = function(agent) + -- agent:breed() + -- agent:relocate() + -- end + -- } + -- + -- Breed:execute() breed = function(agent) local empty = agent:emptyNeighbor() @@ -61,17 +108,24 @@ newborn:move(empty) return newborn end ---} +} ---[[ setmetatable(LogoAgent_, metaTableAgent_) metaTableLogoAgent_ = { __index = LogoAgent_ } +--- Basic Agent for Logo models. +-- @arg data.init A function that gets the agent itself as argument and +-- will be executed when the agent is initialized. +-- @arg data.execute A function that gets the agent itself as argument and +-- is called every time step. +-- @usage import("logo") +-- +-- LogoAgent{} function LogoAgent(data) setmetatable(data, metaTableLogoAgent_) return data end ---]] + diff --git a/lua/LogoModel.lua b/lua/LogoModel.lua index eeca62a..32b8214 100644 --- a/lua/LogoModel.lua +++ b/lua/LogoModel.lua @@ -81,14 +81,9 @@ function LogoModel(data) } end - --instance.agent = LogoAgent{ - instance.agent = Agent{ + instance.agent = LogoAgent{ init = init, - execute = changes, - emptyNeighbor = emptyNeighbor, - breed = breed, - countNeighbors = countNeighbors, - relocate = relocate + execute = changes } instance.soc = Society{ diff --git a/lua/Overpopulation.lua b/lua/Overpopulation.lua index 7b9830d..3fe0256 100644 --- a/lua/Overpopulation.lua +++ b/lua/Overpopulation.lua @@ -3,6 +3,15 @@ -- Each Agent beeds with a probability of 30% -- and die if there are more than three Agents -- in the neighborhood. +-- @arg data.dim The x and y dimensions of space. +-- @arg data.quantity The initial number of Agents in the model. +-- @arg data.chart A boolean value indicating whether a Chart +-- with the number of Agents along the simulation should +-- be drawn. +-- @arg data.finalTime The final simulation time. +-- @arg data.map A boolean value indicating whether a Map +-- with the spatial distribution r of Agents along the +-- simulation should be drawn. -- @image overpopulation.bmp Overpopulation = LogoModel{ quantity = 10, diff --git a/lua/SingleAgent.lua b/lua/SingleAgent.lua index efde136..bd42a77 100644 --- a/lua/SingleAgent.lua +++ b/lua/SingleAgent.lua @@ -1,5 +1,14 @@ --- A single agent moving around randomly. +-- @arg data.dim The x and y dimensions of space. +-- @arg data.chart A boolean value indicating whether a Chart +-- with the number of Agents along the simulation should +-- be drawn. +-- @arg data.quantity The initial number of Agents in the model. +-- @arg data.finalTime The final simulation time. +-- @arg data.map A boolean value indicating whether a Map +-- with the spatial distribution r of Agents along the +-- simulation should be drawn. -- @image single-agent.bmp SingleAgent = LogoModel{ quantity = 1, diff --git a/lua/Sugarscape.lua b/lua/Sugarscape.lua index d767baf..6ad7355 100644 --- a/lua/Sugarscape.lua +++ b/lua/Sugarscape.lua @@ -1,17 +1,22 @@ -local sugar = {} - -forEachFile(packageInfo("logo").data, function(file) - if string.sub(file, -6) == ".sugar" then - table.insert(sugar, string.sub(file, 1, -7)) - end -end) - --- Model where a given Society grows, filling -- the whole space. Agents reproduce with 20% of -- probability if there is an empty neighbor. +-- @arg data.dim The x and y dimensions of space. +-- @arg data.quantity The initial number of Agents in the model. +-- @arg data.chart A boolean value indicating whether a Chart +-- with the number of Agents along the simulation should +-- be drawn. +-- @arg data.finalTime The final simulation time. +-- @arg data.map A boolean value indicating whether a Map +-- with the spatial distribution r of Agents along the +-- simulation should be drawn. +-- @arg data.sugarMap The spatial representation of the model. +-- The available sugarscapes are described in the data available in the package. +-- They should be used without ".sugar" extension. The default pattern is +-- "room". -- @image sugarscape.bmp Sugarscape = LogoModel{ - sugarMap = Choice(sugar), + sugarMap = Choice(filesByExtension("logo", ".sugar")), quantity = 10, finalTime = 200, space = function(instance) diff --git a/lua/Utils.lua b/lua/Utils.lua index 753953f..08cbb49 100644 --- a/lua/Utils.lua +++ b/lua/Utils.lua @@ -4,7 +4,9 @@ local base = getPackage("base") -- this table will be unnecessary when TerraME 1 --- Return a CellularSpace with the representation of a given labyrinth -- data available in the package. -- @arg pattern A string with the name of a labyrinth. --- @usage cs = getLabyrinth("room") +-- @usage import("logo") +-- +-- room = getLabyrinth("room") function getLabyrinth(pattern) mandatoryArgument(1, "string", pattern) local mfile = base.file(pattern..".labyrinth", "logo") @@ -53,7 +55,9 @@ end --- Return a CellularSpace with the representation of a given sugarscape -- data available in the package. -- @arg pattern A string with the name of a sugarscape. --- @usage cs = getSugar("room") +-- @usage import("logo") +-- +-- room = getSugar("default") function getSugar(pattern) mandatoryArgument(1, "string", pattern) diff --git a/snapshots/GrowingSociety-chart-1.bmp b/snapshots/GrowingSociety-chart-1.bmp index 58b7872b0a569f73d2f440eabf45a60a54a651ea..0f788496b6bf8bd3a851fac9f3eaeb489bcdb80e 100644 GIT binary patch delta 12482 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 diff --git a/tests/LogoAgent.lua b/tests/LogoAgent.lua index 07f4024..518e238 100644 --- a/tests/LogoAgent.lua +++ b/tests/LogoAgent.lua @@ -14,5 +14,8 @@ return{ relocate = function(unitTest) unitTest:assert(true) end, + LogoAgent = function(unitTest) + unitTest:assert(true) + end }