Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
**Fastnet is a Julia package that allows very fast (linear-time) simulation of discrete-state dynamical processes on networks, such as commonly studied models of epidemics**

Fastnet achieves linear-time performance by using an innovative data structure. The underlying network is a potentially directed and potentially non-simple graph.
The package provides a convenient syntax that allows to implement common models in a few simple lines of code. The simulations are done using an event-driven (Gillespie) algortithm offering fast performance and excellent agreement with real world continuous-time processes. Using Fastnet models with millions of nodes can be run within minutes on a standard laptop.
The package provides a convenient syntax that allows to implement common models in a few simple lines of code. The simulations are done using an event-driven (Gillespie) algorithm offering fast performance and excellent agreement with real world continuous-time processes. Using Fastnet models with millions of nodes can be run within minutes on a standard laptop.

## Example

Expand Down Expand Up @@ -35,7 +35,7 @@ for i=1:20 # Infect 20 susceptible nodes at random
nodestate!(net,node,I)
end

function rates!(rates,t) # This functins computes the rates of processes
function rates!(rates,t) # This function computes the rates of processes
infected=countnodes_f(net,I) # count the infected nodes
activelinks=countlinks_f(net,SI) # count the SI links
rates[1]=p*activelinks # compute total infection rate
Expand Down
6 changes: 3 additions & 3 deletions docs/src/about.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# About Fastnet

The Fastnet package was developed by Thilo Gross at the Helmholtz Institute for Functional Mariene Diversity (HIFMB) in Oldenburg Germnany.
The Fastnet package was developed by Thilo Gross at the Helmholtz Institute for Functional Mariene Diversity (HIFMB) in Oldenburg Germany.

## Funding
Thilo's work is funded by the Ministry for Science and Culture of Lower Saxony (MWK) and the Volkswagen Foundation through the “Niedersächsisches Vorab” grant program (grant number ZN3285).


## Publication
The package is also decribed in the following publication:
The package is also described in the following publication:

```
TBA
Expand All @@ -25,5 +25,5 @@ Germany
```

## About the name
This package is called Fastnet because it can simulate networks fast. However the name also reminds of Fastnet rock. A small rocky island off the Irish coast that boasts a distinctive lighthouse. Before the lighthouse was built, many sailors died in wrecks on this lonely rock. This image serves as a reminder of our solidarity that blooms in harsh environments and our ability to make the world a better, safer place by making contributions toward a common good. One way to make such a contribution today is to advance humanity's knowledge and capabilites through freely accessible research and free software. If you use Fastnet, consider making also the results of your work freely available. Please build a lighthouse on the foundations I laid by providing this package.
This package is called Fastnet because it can simulate networks fast. However the name also reminds of Fastnet rock. A small rocky island off the Irish coast that boasts a distinctive lighthouse. Before the lighthouse was built, many sailors died in wrecks on this lonely rock. This image serves as a reminder of our solidarity that blooms in harsh environments and our ability to make the world a better, safer place by making contributions toward a common good. One way to make such a contribution today is to advance humanity's knowledge and capabilities through freely accessible research and free software. If you use Fastnet, consider making also the results of your work freely available. Please build a lighthouse on the foundations I laid by providing this package.

8 changes: 4 additions & 4 deletions docs/src/background.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ This section contains some background information about the way in which fastnet
## How to simulate processes on networks
If we think about simulating processes on networks, the first idea that usually comes to mind are to update all nodes simultaneously in small time steps. This idea is attractive because it makes thinking about the simulation seemingly easier, however it entails a number of problems.

1. Update order -- How do we actually implement our timesteps? Do we update every node in every timestep? And if so in which order do we update them. If the order is always the same we will create artifacts (unrealistic artifical behavior), so we need to randomize. But such randomization can lead to further problems, for instance do we keep track of who has already been updated etc.
1. Update order -- How do we actually implement our timesteps? Do we update every node in every timestep? And if so in which order do we update them. If the order is always the same we will create artifacts (unrealistic artificial behavior), so we need to randomize. But such randomization can lead to further problems, for instance do we keep track of who has already been updated etc.

2. Collisions -- What do we do if different events that occur in one timestep are contradictory? For example what if a node in an epidemic situation infects another node and recovers from the disease at the same time. Does the infection always go first? Or can the recovery occur first making the infection event impossible?

3. Timing artifacts -- Even if we find elegant solutions for event collisions and update order, we are still approximating a real-word system in which time flows continously by a model in which time proceeds in discrete steps. This in itself can cause some artifacts. For example it can lead to the formation of certain patterns which won't occur in the continuous time system.
3. Timing artifacts -- Even if we find elegant solutions for event collisions and update order, we are still approximating a real-word system in which time flows continuously by a model in which time proceeds in discrete steps. This in itself can cause some artifacts. For example it can lead to the formation of certain patterns which won't occur in the continuous time system.

4. Efficiency -- The most common solution to the problems above is to make timesteps tiny. While this lessens the impact of the artifacts it does not prevent them altogether. Moreover, it comes at a high cost in terms of efficiency. We will need to simulate many timesteps to cover the desired stretch of time, and in each of these steps we will be checking a large number of nodes for possible updates. However, since our timesteps are now tiny the probability that a given node is affected by an event in a given timestep is tiny, often in below 1 in a million. This means we spent a lot of computation time to do updates on nodes in which nothing changes at all.

Simulations that work with discrete timesteps can still be a good idea if the underlying system fundamentally works in discrete timesteps. However, in the vast majority of cases we can simulate systems better, faster, and more elgantly by not using timesteps at all...
Simulations that work with discrete timesteps can still be a good idea if the underlying system fundamentally works in discrete timesteps. However, in the vast majority of cases we can simulate systems better, faster, and more elegantly by not using timesteps at all...

## The Gillespie Algorithms
In 1976 Daniel T. Gillespie published the idea for an event-driven simulation algorithm
Expand Down Expand Up @@ -40,4 +40,4 @@ The basic idea for the bookkeeping used in Fastnet was born while we were workin
```
T. Gross, C.J. Dommar D’Lima and B. Blasius (2006) "Epidemic dynamics on an adaptive network." Phys. Rev. Lett. 96, 208701.
```
The underlying datastructure that makes the bookkeeping possible is also available in Julia, on its own in the [Repos package](https://github.com/bridgewalker/Repos.jl) Fastnet does not use this package but rather reimplements the Repos structure in an opimized way for its current application.
The underlying datastructure that makes the bookkeeping possible is also available in Julia, on its own in the [Repos package](https://github.com/bridgewalker/Repos.jl) Fastnet does not use this package but rather reimplements the Repos structure in an optimized way for its current application.
4 changes: 2 additions & 2 deletions docs/src/concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ In Fastnet there are two ways to refer to a specific network node:

1. Node ID -- Every node has a unique ID number that never changes. The ID number may be recycled if a node is destroyed and later another node is created. All ID numbers are integers in the range 1:N, where N is the maximal node number that was passed to the FastNet constructor when the network was created. Node IDs are not necessarily consecutive so a network containing two nodes could contain the nodes with IDs 17 and 23 for example.

2. Node state and position -- We can also identify nodes by saying "the n'th node in state x" where n is one of the allowed node states and x is the so-called positon in this state. So in the epidemic model from the tutorial we might say we want the first infected node. A state-position pair will not always refer to the same node, but the positions are always numbered consecutively, so if there are two infected nodes these will have the positions 1 and 2 in the infected state.
2. Node state and position -- We can also identify nodes by saying "the n'th node in state x" where n is one of the allowed node states and x is the so-called position in this state. So in the epidemic model from the tutorial we might say we want the first infected node. A state-position pair will not always refer to the same node, but the positions are always numbered consecutively, so if there are two infected nodes these will have the positions 1 and 2 in the infected state.

In general the FastNet functions expect you to refer to nodes by node ID. However, class and position is useful for example if you want to iterate over all nodes in a certain state. You can obtain the ID of a node at a certain position using the function
```julia
Expand All @@ -29,7 +29,7 @@ So there can in principle be a link that connects a node to itself and a given p
The network has been implemented in this way mainly to improve the efficiency of models that should almost always remain simple graphs. Allowing the occasional multi-link or self-loop eliminates the need for constant checking if a given operation would make the graph non-simple. By contrast models that make extensive use of self-loops or multi-links are rare. As a result this feature presently remains a bit undertested, so use with caution.

In the underlying data structure of Fastnet, every link is represented as a directed link (an arc in math-speak).
This comes at no addional computational or memory cost and actually makes many nuances of the implementation easier.
This comes at no additional computational or memory cost and actually makes many nuances of the implementation easier.
Nevertheless the package has been developed with undirected networks in mind and we can often simply ignore the underlying directedness of links. What this means is that Fastnet can be used to implement models that use directed links, models that use undirected (or bidirectional) links, and even models that mix the two types.

One (mildly beneficial) effect of the directed nature of links is that there is a unique way to refer to the nodes at the end of the link. They can be determined by the functions
Expand Down
4 changes: 2 additions & 2 deletions docs/src/customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ MyReportingFunction(sim::FastSim,head::Bool)
```
The first argument that is passed is a reference to the sim that should be reported on. The second argument is a bool that tells the function whether a header needs to be printed. For example the default reporting function prints first the column heads of the output table and then the network state if true is passed. It prints only the network state if false is passed.

Once called your custom reporting function should handle all the neccessary printing, writing to disk, etc.
Once called your custom reporting function should handle all the necessary printing, writing to disk, etc.
Also your reporting function should push the node and link counts to the *sim.results* dataframe, if you want the
results to be stored there. You can do this by including
```julia
Expand All @@ -39,7 +39,7 @@ Some useful information can be read from the first argument *sim*:

The *printresults* field contains either true, if output should be printed to the terminal, false if no output should be printed to the terminal or an IOStream to which terminal output should be redirected.

Information about the network can be gained by calling the typeical functions (countnodes, etc.) on *sim.net*. In addition the FastNet object *sim.net* contains two fields that may be useful
Information about the network can be gained by calling the typical functions (countnodes, etc.) on *sim.net*. In addition the FastNet object *sim.net* contains two fields that may be useful

- *sim.net.nodealias* -- A Vector of strings containing names for the node states
- *sim.net.linkalias* -- A Vector of strings containing names for the tracked link states
Expand Down
2 changes: 1 addition & 1 deletion docs/src/faq.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Frequently Asked Questions

## How large can I make the network?
This depends mainly on how much memory you have. Fastnet can simulate networks with several million nodes with relative ease. At some point you will see performance drop on the number of hard disk accesses on your operating system will spike. That is the point where Julia runs out of memory and some of the data needs to get parked on the hard disk. By contrast if you have a lot of memory available Fastnet can conceivably simulate sparce networks with billions of nodes.
This depends mainly on how much memory you have. Fastnet can simulate networks with several million nodes with relative ease. At some point you will see performance drop on the number of hard disk accesses on your operating system will spike. That is the point where Julia runs out of memory and some of the data needs to get parked on the hard disk. By contrast if you have a lot of memory available Fastnet can conceivably simulate sparse networks with billions of nodes.

## Can I use my own seed / random number generator?
Yes, you can initialize your random number generator however you want and then pass it as an argument in the FastNet constructor.
Expand Down
2 changes: 1 addition & 1 deletion docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

**Fastnet is a Julia package that allows very fast (linear-time) simulation of discrete-state dynamical processes on networks, such as commonly studied models of epidemics**

Fastnet achieves linear-time performance by using an innovative data structure. The underlying network is a potentially directed and potentially non-simple graph. The package provides a convenient syntax that allows to implement common models in a few simple lines of code. The simulations are done using an event-driven (Gillespie) algortithm offering fast performance and excellent agreement with real world continuous-time processes. Using fastnet models with millions of nodes can be run within minutes on a standard laptop.
Fastnet achieves linear-time performance by using an innovative data structure. The underlying network is a potentially directed and potentially non-simple graph. The package provides a convenient syntax that allows to implement common models in a few simple lines of code. The simulations are done using an event-driven (Gillespie) algorithm offering fast performance and excellent agreement with real world continuous-time processes. Using fastnet models with millions of nodes can be run within minutes on a standard laptop.

## Publication
This package is described also in the following publication
Expand Down
6 changes: 3 additions & 3 deletions docs/src/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ Finally we fill the `rates` vector with the results. Here we chose to put the in

The final `nothing` tells Julia that the function does not have a return value.

(One may wonder whether it would be more efficient to squeeze the six lines of code into two lines and avoid the definition of intermediate variables. The answer is generally no. Julia is a compiled language and the compiler will take care of such small scale optimizations for us, so it won't make a difference in performance. In this case the longer form makes the code more readable and makes it easier to fnd bugs.)
(One may wonder whether it would be more efficient to squeeze the six lines of code into two lines and avoid the definition of intermediate variables. The answer is generally no. Julia is a compiled language and the compiler will take care of such small scale optimizations for us, so it won't make a difference in performance. In this case the longer form makes the code more readable and makes it easier to find bugs.)

## Implementing the processes
As the final piece of our model we need to define what happens when the processes occur we do this by defining two more functions
Expand All @@ -128,7 +128,7 @@ If a recovery event occurs a random node recovers, so in our `recovery!` functio

In an infection event the disease gets passed along a random SI-link, so we use `randomlink` to pick an SI link at random. Then we find the two endpoints of the link with `linksrc` and `linkdst`. We could then use an `if` statement to find out which one of the two endpoints is the susceptible node, but ifs create control hazards which aren't great for performance so its probably a bit quicker to set both of the endpoints to the infected state. (One of them was infected anyway and the other is the one that we need to infect.)

Again the fuctions used in our implementation of these processes run either in constant time (`randomnode`, `randomlink`, `linksrc`, `linkdst`), or they scale only with the degree of the affected node and the number of link states that we are tracking (`nodestate!`), hence the runtime required to simulate one event won't depend on the network size. Simulating a network for a finite time will still scale linearly with network size as larger networks have more nodes and links on which events can occur.
Again the functions used in our implementation of these processes run either in constant time (`randomnode`, `randomlink`, `linksrc`, `linkdst`), or they scale only with the degree of the affected node and the number of link states that we are tracking (`nodestate!`), hence the runtime required to simulate one event won't depend on the network size. Simulating a network for a finite time will still scale linearly with network size as larger networks have more nodes and links on which events can occur.

### Simulation
Now that we have all the pieces, we can set up and run the simulation
Expand All @@ -152,7 +152,7 @@ Before the `runsim` I have added Julia's `@time` macro which times the performan
But before we run really large simulations we should make one final improvement...

## Faster functions
To help with debugging, functions such as `nodestate!` carry out a number of checks and try to provide meaningful error message if their arguments look iffy. This comes at a price in terms of performance. Because your rates and process functions might be called billions of times in large simulations, you may want to avoid these extra checks. For this purpose Fastnet provides faster implementations for some of the key functions. The names of these functions are identical to the other function names with an added `_f` at the end, so in addion to `nodestate!` there is also
To help with debugging, functions such as `nodestate!` carry out a number of checks and try to provide meaningful error message if their arguments look iffy. This comes at a price in terms of performance. Because your rates and process functions might be called billions of times in large simulations, you may want to avoid these extra checks. For this purpose Fastnet provides faster implementations for some of the key functions. The names of these functions are identical to the other function names with an added `_f` at the end, so in addition to `nodestate!` there is also

```julia
nodestate_f!(net::FastNet,node,newstate)
Expand Down
Loading