Skip to content

Releases: scottpdo/flocc

0.5.20

02 Apr 15:03
e07ea02
Compare
Choose a tag to compare

CanvasRenderer drawing update

A minor visual improvement for CanvasRenderers drawing toroidal Environments — an Agent close to one of the borders (top, bottom, left, right), whose shape extends beyond the border will now also be drawn on the opposite side of the canvas.

Example:

  • The Agent located at (0, 0) would previously only be drawn in the upper-left. Now, with the Environment wrapping around from left to right and top to bottom, it gets drawn in all four corners. Non-toroidal Environments will still draw the image on the left.

Screenshot from 2021-04-02 11-02-19

0.5.19

01 Mar 18:51
66d0a45
Compare
Choose a tag to compare

Agent Activation

The significance of this feature is arguably enough for it to be its own major release, but there's bigger things in store for v0.6.0... Today, however, we're proud to announce different agent activation regimes!

Currently, if you call environment.tick(), that calls the tick function of every Agent in the Environment (by default sequentially, although since v0.3.1 you can randomize the order by passing { randomizeOrder: true }). This release allows for random activation order — that is, only activating 1 or more randomly chosen Agents with each time step, as opposed to all of them.

To run a model with random activation, you need to pass some additional configuration parameters:

environment.tick({
  activation: "random",
  activationCount: 10
});

With the above code, every time step 10 Agents will be randomly selected and will run their tick functions. If activationCount is equal to or greater than the number of Agents in the Environment, this is identical to calling environment.tick({ randomizeOrder: true }) (although slower in real time). If it is omitted, activationCount defaults to 1 (only activating a single Agent per time step).

The default activation regime (uniform) can also be opted into explicitly by calling environment.tick({ activation: "uniform" }). If you include an activationCount parameter with uniform activation, it will always be ignored.

Since random activation by definition activates fewer agents per time step than uniform activation, you can also tell an Environment to progress multiple time steps with each tick by including a count option:

environment.tick({
  activation: "random",
  activationCount: 10,
  count: 5
});

This will activate 10 Agents every time step, but will do this 5 times every time the above code is run. So any renderers associated with the Environment will only update every 5 time steps.

0.5.18

27 Feb 02:14
Compare
Choose a tag to compare

No substantive changes in this release, but a few very minor notes:

  • Automatic formatting hadn't been working, so added prettier as a dev dependency
  • Converted existing console.warn statements to only be called once
  • Added warning about environment.tick defaulting to randomizeOrder: true in v0.6.0

0.5.17

06 Feb 14:38
Compare
Choose a tag to compare

Network Improvements

Adds a few new features to Networks to power network analysis. (Thanks, Complex Networks Winter Workshop!)

  • Network.clusteringCoefficient(agent): Calculates the clustering coefficient for an agent in the network. The clustering coefficient is a measure of how connected this agent's neighbors are (i.e. how much of a 'cluster' it is a part of). If all of the agent's neighbors are also connected to each other, this will be 1, and if none of them are connected to each other, it will be 0.
  • Network.clusteringCoefficient(): Calling this method with no parameters returns the global clustering coefficient, a value between 0 and 1
  • Network.averageClusteringCoefficient(): The average clustering coefficient is another global measure, although it differs from the global clustering coefficient.

This also adds a new helper class Array2D, which is a thin wrapper around NumArray to handle 2-dimensional arrays. Under the hood, Networks now include both adjacency list and adjacency matrix representations, the latter being an Array2D of 0s and 1s.

0.5.16

12 Jan 16:58
e2e7370
Compare
Choose a tag to compare

Sampling with samplers

Currently it's difficult to retrieve multiple random values from an array, if you want the values to be guaranteed unique. For example, when taking 2 random values from the array [1, 2, 3, 4, 5], calling utils.sample[1, 2, 3, 4, 5]) twice is not guaranteed to return unique values; it may return 4 twice in a row.

This version adds a new function, utils.sampler, which is a factory function (a function that returns a function). Calling utils.sampler(n) returns a function that will act like utils.sample, but will return a random subset of the array on which it's called, returning either n values or all of the values in array (if fewer than n). See a few examples below:

const sample2 = utils.sampler(2);
const arr = [1, 2, 3, 4, 5];
const sampled = sample2(arr); // may return [4, 2]

const sample6 = utils.sampler(6);
const shuffled = sample6(arr); // this will only have 5 elements, and be a shuffled version of `arr`

const sample1 = utils.sampler(1);
const singleValue = sample1(arr); // when called with 1, this acts exactly the same as `utils.sample`

const sample0 = utils.sampler(0);
const result = sample0(arr); // for 0 or negative values, always returns `null`

Like utils.sample, multiple-value sample functions returned from utils.sampler will also accept as a second parameter an array of numbers representing weighted values.

const sample2 = utils.sampler(2);
const arr = [1, 2, 3, 4, 5];

const weightsA = [100, 10, 1, 1, 1]; // weights do not have to be normalized (sum to 1)
sample2(arr, weightsA); // will probably but not always be [1, 2]

const weightsB = [100, 100, 1, 1, 1];
sample2(arr, weightsB); // will probably be either [1, 2] or [2, 1] (with equal likelihood)

0.5.15

06 Jan 14:05
2fcec5a
Compare
Choose a tag to compare

Setting defaults for stats functions given empty arrays

Previously, the behavior of utility functions — utils.max, utils.min, and others, was unspecified if passed an empty array. It turns out that utils.max actually returned -Infinity (this is native JS behavior for Math.max() when no arguments are passed!)

Now, most stats functions return null if passed an empty array. This includes:

  • utils.max
  • utils.min
  • utils.mean
  • utils.median
  • utils.stdDev

The one exception is utils.sum, which returns 0. While this does differ from the behavior of the others, I would argue that summing 'starts' from 0, while the other functions have no clear 'starting point.' In any case, one should be aware of this behavior whenever passing an empty array to one of these functions.

0.5.14

05 Jan 16:55
dae8b14
Compare
Choose a tag to compare

Updates to how Agent tick rules are assigned

(Deprecated: Agent.addRule and Agent.enqueue)

To date, it's been a cumbersome extra step to 1. instantiate an Agent with data, 2. add a tick rule, and then 3. add it to the environment. However, with this release, these three steps can now be performed simultaneously!

Before:

const agent = new Agent({
  x: 12
});
agent.addRule(a => a.increment('x')); // with each tick, increment `x` value
environment.addAgent(agent);

Now:

environment.addAgent(new Agent({
  x: 12,
  tick(a) { a.increment('x'); }
}));

By setting a function (or Rule) value for tick, this will be called with every Environment.tick that the Agent belongs to. This is identical behavior to calling agent.addRule(...), except that only one function can be set at any time.

Agents can also enqueue a rule to be called once at the end of the current tick, by calling agent.enqueue(...). Similarly, this is deprecated in favor of setting a queue value:

Before:

agent.addRule(a => {
  a.increment('x');
  a.enqueue(a => a.decrement('y'));
});

Now:

a.set('tick', a => {
  a.increment('x');
  a.set('queue', a => a.decrement('y'));
});

In this case, the lines of code remains the same, but instead of calling the addRule and enqueue methods, you should set tick and queue values.

The Agent.addRule and Agent.enqueue methods are now deprecated, and will be removed in version 0.7.0. Please migrate your existing code to the new API!

0.5.12

20 Nov 19:46
Compare
Choose a tag to compare

CanvasRenderer updates

Some miscellaneous updates and improvements to CanvasRenderers:

  • New shape option: "triangle" (e.g. agent.set("shape", "triangle");). Listens to the Agent's size and color values as well.
  • Agents with shape "rectangle" now center at the Agent's xy location rather than using that as the top-left of the rectangle.
  • Agents can now be labeled with text. Set the following parameters:

0.5.11

18 Nov 16:04
6783ef3
Compare
Choose a tag to compare

KDTree Bugfix

Fixed a bug where having 0 agents in either the left or right subtrees of a KDTree would sometimes lead to an infinite loop when calling KDTree.rebalance. Also updated Environment.addAgent and .removeAgent to take an optional 2nd parameter to decide whether to rebalance the KDTree (defaults to true).

0.5.10

10 Nov 16:16
Compare
Choose a tag to compare

Heatmap bugfix

One more fix: When using position: "fixed" and a max value lower than the automatically detected maximum number of agents in a single cell, colors were not correctly rendering. This fix clamps the alpha value to the range 0...1, so that values above the maximum render correctly.