Skip to content

Commit

Permalink
Merge pull request #49 from cesaraustralia/cleanup
Browse files Browse the repository at this point in the history
Cleanup
  • Loading branch information
rafaqz authored Jul 24, 2020
2 parents 9392ae4 + 6324249 commit c113e52
Show file tree
Hide file tree
Showing 29 changed files with 1,014 additions and 769 deletions.
8 changes: 4 additions & 4 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "DynamicGrids"
uuid = "a5dba43e-3abc-5203-bfc5-584ca68d3f5b"
authors = ["Rafael Schouten <[email protected]>"]
version = "0.9.0"
version = "0.10.0"

[deps]
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
Expand All @@ -26,11 +26,11 @@ UnicodeGraphics = "ebadf6b4-db70-5817-83da-4a19ad584e34"
Colors = "0.9, 0.10, 0.11, 0.12"
ConstructionBase = "1"
Crayons = "4"
DimensionalData = "^0.10.7, 0.11"
DimensionalData = "0.11"
DocStringExtensions = "0.8"
FieldDefaults = "0.3"
FieldDefaults = "0.3.1"
FieldDocTables = "0.1"
FieldMetadata = "0.2, 0.3"
FieldMetadata = "0.3"
FileIO = "1"
FreeTypeAbstraction = "^0.6.5, 0.8"
Mixers = "0.1"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ using DynamicGrids, DynamicGridsGtk, ColorSchemes, Colors
const DEAD, ALIVE, BURNING = 1, 2, 3

rule = let prob_combustion=0.0001, prob_regrowth=0.01
Neighbors(RadialNeighborhood{1}()) do neighborhood, cell
Neighbors(RadialNeighborhood(1)) do neighborhood, cell
if cell == ALIVE
if BURNING in neighborhood
BURNING
Expand Down
69 changes: 16 additions & 53 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,55 +4,6 @@
DynamicGrids
```

## More Examples

While this package isn't designed or optimised specifically to run the game of
life, it's a simple demonstration of what it can do. This example runs a
game of life and displays it in a REPLOutput.


```@example
using DynamicGrids
# Build a random starting grid
init = round.(Int8, max.(0.0, rand(-2.0:0.1:1.0, 70,70)))
# Use the default game of life model
model = Ruleset(Life())
# Use an output that shows the cellular automata as blocks in the REPL
output = REPLOutput(init; tspan=1:50, fps=5)
sim!(output, model)
```

More life-like examples:

```julia
# Morley
sim!(output, Ruleset(Life(b=[3,6,8], s=[2,4,5]))

# 2x2
sim!(output, Ruleset(Life(b=[3,6], s=[1,2,5])))

# Dimoeba
init1 = round.(Int8, max.(0.0, rand(70,70)))
sim!(output, Ruleset(Life(b=[3,5,6,7,8], s=[5,6,7,8]); init=init1))

## No death
sim!(output, Ruleset(Life(b=[3], s=[0,1,2,3,4,5,6,7,8])))

## 34 life
sim!(output, Ruleset(Life(b=[3,4], s=[3,4])); init=init, fps=10)

# Replicator
init2 = round.(Int8, max.(0.0, rand(70,70)))
init2[:, 1:30] .= 0
init2[21:50, :] .= 0
sim!(output, Ruleset(Life(b=[1,3,5,7], s=[1,3,5,7])); init=init2)
```
## Rules

Rules define simulation behaviour. They hold data relevant to the simulation,
Expand Down Expand Up @@ -87,10 +38,11 @@ and how they are combined to update the value of the current cell.
```@docs
Neighborhood
AbstractRadialNeighborhood
RadialNeighborhood
AbstractCustomNeighborhood
CustomNeighborhood
LayeredCustomNeighborhood
Moore
VonNeumann
AbstractPositional
Positional
LayeredPositional
```

```@docs
Expand All @@ -111,19 +63,22 @@ ArrayOutput
GraphicOutput
REPLOutput
ImageOutput
GifOutput
```

### Grid processors

```@docs
GridProcessor
SingleGridProcessor
SparseOptInspector
ColorProcessor
MultiGridProcessor
ThreeColorProcessor
LayoutProcessor
Greyscale
Grayscale
TextConfig
```

### Gifs
Expand All @@ -132,6 +87,14 @@ Grayscale
savegif
```

### Internal components for outputs

```@docs
DynamicGrids.Extent
DynamicGrids.GraphicConfig
DynamicGrids.ImageConfig
```

## Ruleset config

### Overflow
Expand Down
16 changes: 10 additions & 6 deletions src/DynamicGrids.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module DynamicGrids
replace(text, "```julia" => "```@example")
end DynamicGrids


using Colors,
ConstructionBase,
Crayons,
Expand All @@ -26,6 +27,8 @@ using Colors,
Test,
UnicodeGraphics

const DG = DynamicGrids

using Base: tail

import Base: show, getindex, setindex!, lastindex, size, length, push!, append!,
Expand All @@ -37,24 +40,25 @@ import FieldMetadata: @description, description,
@default, default


export sim!, resume!, replay, savegif, isinferred, method, methodtype

export sim!, resume!, replay, savegif, isinferred, neighbors, rules, method, methodtype
export rules, neighbors, inbounds, isinbounds, radius, gridsize,
currenttime, currenttimestep, timestep, tspan

export Rule, NeighborhoodRule, CellRule, ManualRule, ManualNeighborhoodRule

export Chain, Cell, Neighbors, Manual, Map, Life

export AbstractRuleset, Ruleset

export Neighborhood, AbstractRadialNeighborhood, RadialNeighborhood,
AbstractCustomNeighborhood, CustomNeighborhood, LayeredCustomNeighborhood,
VonNeumannNeighborhood
export Neighborhood, AbstractRadialNeighborhood, Moore,
AbstractPositional, Positional, VonNeumann, LayeredPositional

export PerformanceOpt, NoOpt, SparseOpt

export Overflow, RemoveOverflow, WrapOverflow

export Output, GraphicOutput, ImageOutput, ArrayOutput, REPLOutput
export Output, GraphicOutput, ImageOutput, ArrayOutput, REPLOutput, GifOutput

export GridProcessor, SingleGridProcessor, ColorProcessor, SparseOptInspector,
MultiGridProcessor, ThreeColorProcessor, LayoutProcessor
Expand Down Expand Up @@ -88,13 +92,13 @@ include("outputs/graphic.jl")
include("outputs/image.jl")
include("outputs/array.jl")
include("outputs/repl.jl")
include("outputs/gif.jl")
include("interface.jl")
include("framework.jl")
include("sequencerules.jl")
include("maprules.jl")
include("overflow.jl")
include("utils.jl")
include("map.jl")
include("life.jl")
include("show.jl")

Expand Down
32 changes: 18 additions & 14 deletions src/chain.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
without intermediate reads or writes from grids. They are potentially compiled
together into a single function call, especially if you use `@inline` on all
`applyrule`. methods. `Chain` can hold either all [`CellRule`](@ref) or
[`NeighborhoodRule`](@ref) followed by [CellRule`](@ref).
[`NeighborhoodRule`](@ref) followed by [`CellRule`](@ref).
"""
struct Chain{R,W,T<:Union{Tuple{},Tuple{Union{<:NeighborhoodRule,<:CellRule},Vararg{<:CellRule}}}} <: Rule{R,W}
rules::T
Expand Down Expand Up @@ -31,36 +31,39 @@ Base.firstindex(chain::Chain) = firstindex(rules(chain))
Base.lastindex(chain::Chain) = lastindex(rules(chain))

"""
applyrule(rules::Chain, data, state, (i, j))
applyrule(data, rules::Chain, state, (i, j))
Chained rules. If a [`Chain`](@ref) of rules is passed to `applyrule`, run them
sequentially for each cell. This can have much beter performance as no writes
occur between rules, and they are essentially compiled together into compound
rules. This gives correct results only for [`CellRule`](@ref), or for a single
[`NeighborhoodRule`](@ref) followed by [`CellRule`](@ref).
"""
@inline applyrule(chain::Chain, data::SimData, state, index, args...) = begin
newstate = applyrule(chain::Chain, chain[1], data, state, index, args...)
end
@inline applyrule(chain::Chain{R,W,Tuple{}}, data::SimData, state, index, args...
) where {R,W} =
@inline applyrule(data::SimData, chain::Chain, state, index) =
chainrule(data, chain::Chain, chain[1], state, index)
@inline applyrule(data::SimData, chain::Chain{R,W,Tuple{}}, state, index) where {R,W} =
chainstate(chain, map(Val, writekeys(chain)), state)

@inline applyrule(chain::Chain, rule::Rule{RR,RW}, data::SimData, state, index, args...
@inline chainrule(data::SimData, chain::Chain, rule::Rule{RR,RW}, state, index
) where {RR,RW} = begin
# Get the state needed by this rule
read = chainstate(chain, Val{RR}, state)
write = applyrule(rule, data, read, index, args...)
# Run the rule
write = applyrule(data, rule, read, index)
# Create new state with the result and state from other rules
newstate = update_chainstate(chain, rule, state, write)
applyrule(tail(chain), data, newstate, index)
# Run applyrule on the rest of the chain
applyrule(data, tail(chain), newstate, index)
end
@inline applyrule(chain::Chain, rule::Rule{RR,RW}, data::SimData, state, index, args...
@inline chainrule(data::SimData, chain::Chain, rule::Rule{RR,RW}, state, index, args...
) where {RR<:Tuple,RW} = begin
read = chainstate(chain, (map(Val, readkeys(rule))...,), state)
write = applyrule(rule, data, read, index, args...)
write = applyrule(data, rule, read, index)
newstate = update_chainstate(chain, rule, state, write)
applyrule(tail(chain), data, newstate, index)
applyrule(data, tail(chain), newstate, index)
end

# Get state as a NamedTuple or single value
@inline chainstate(chain::Chain, keys::Tuple, state) = begin
keys = map(unwrap, keys)
vals = map(k -> state[k], keys)
Expand All @@ -69,6 +72,8 @@ end
@inline chainstate(chain::Chain, key::Type{<:Val}, state) =
state[unwrap(key)]

# Merge new state with previous state
# Returning a new NamedTuple with all keys having the most recent state
@generated update_chainstate(chain::Chain{CR,CW}, rule::Rule{RR,RW}, state::NamedTuple{K,V}, writestate::Tuple
) where {CR,CW,RR,RW,K,V} = begin
expr = Expr(:tuple)
Expand All @@ -90,7 +95,6 @@ end
NamedTuple{$keys}(newstate)
end
end

@generated update_chainstate(chain::Chain{CR,CW}, rule::Rule{RR,RW}, state::NamedTuple{K,V}, writestate
) where {CR,CW,RR,RW,K,V} = begin
expr = Expr(:tuple)
Expand Down
4 changes: 4 additions & 0 deletions src/extent.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,7 @@ setstarttime!(e::Extent, start) =
e.tspan = start:step(tspan(e)):last(tspan(e))
setstoptime!(e::Extent, stop) =
e.tspan = first(tspan(e)):step(tspan(e)):stop

gridsize(extent::Extent) = gridsize(init(extent))
gridsize(A::AbstractArray) = size(A)
gridsize(nt::NamedTuple) = size(first(nt))
10 changes: 5 additions & 5 deletions src/framework.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ sim!(output::Output, ruleset=ruleset(output);
aux=aux(output),
fps=fps(output),
nreplicates=nothing,
simdata=nothing) = begin
simdata=nothing, kwargs...) = begin

gridsize(init) == gridsize(DG.init(output)) || throw(ArgumentError("init size does not match output init"))
# Some rules are only valid for a set time-step size.
step(ruleset) !== nothing && step(ruleset) != step(tspan) &&
throw(ArgumentError("tspan step $(step(tspan)) must equal rule step $(step(ruleset))"))
Expand All @@ -57,7 +58,7 @@ sim!(output::Output, ruleset=ruleset(output);
# Set run speed for GraphicOutputs
setfps!(output, fps)
# Show the first grid
showgrid(output, simdata, 1, tspan)
showframe(output, simdata, 1, tspan)
# Let the init grid be displayed as long as a normal grid
delay(output, 1)
# Run the simulation over simdata and a unitrange
Expand All @@ -71,7 +72,6 @@ Shorthand for running a rule without defining a `Ruleset`.
"""
sim!(output::Output, rules::Rule...;
tspan=tspan(output),
overflow=RemoveOverflow(),
kwargs...) = begin
ruleset = Ruleset(rules...; timestep=step(tspan), kwargs...)
sim!(output::Output, ruleset; tspan=tspan, kwargs...)
Expand Down Expand Up @@ -156,14 +156,14 @@ simloop!(output::Output, simdata, fspan) = begin
# Run the ruleset and setup data for the next iteration
simdata = sequencerules!(simdata)
# Save/do something with the the current grid
storegrid!(output, simdata)
storeframe!(output, simdata)
# Let interface things happen
isasync(output) && yield()
# Stick to the FPS
delay(output, f)
# Exit gracefully
if !isrunning(output) || f == last(fspan)
showgrid(output, simdata, f, currenttime(simdata))
showframe(output, simdata, f, currenttime(simdata))
setstoptime!(output, currenttime(simdata))
finalise(output)
break
Expand Down
Loading

2 comments on commit c113e52

@rafaqz
Copy link
Member Author

@rafaqz rafaqz commented on c113e52 Jul 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/18369

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.10.0 -m "<description of version>" c113e52e866f85fb756194b37fb5041e024d9645
git push origin v0.10.0

Please sign in to comment.