Skip to content

Commit

Permalink
Add human behavior module (#190)
Browse files Browse the repository at this point in the history
Signed-off-by: David P. Chassin <dchassin@slac.stanford.edu>
Signed-off-by: Alyona Teyber <Ivanova.alyona5@gmail.com>
Signed-off-by: Duncan Ragsdale <88173870+Thistleman@users.noreply.github.com>
Co-authored-by: Alyona Teyber <Ivanova.alyona5@gmail.com>
Co-authored-by: Duncan Ragsdale <88173870+Thistleman@users.noreply.github.com>
  • Loading branch information
3 people authored Apr 17, 2024
1 parent 621cac0 commit 8afa4a0
Show file tree
Hide file tree
Showing 22 changed files with 27,773 additions and 30 deletions.
35 changes: 35 additions & 0 deletions docs/Module/Behavior.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[[/Module/Behavior]] -- Human behavior module

# Synopsis

GLM:

~~~
module behavior
{
message_flags [DEBUG|QUIET|VERBOSE|WARNING];
system_resolution 1e-9;
}
~~~

# Description

The `behavior` module implements various behavioral models that can be used to
modify properties of devices as a way of representing how individual
preferences and decisions affect devices.

## Continuous behavior

The `random` class is used to apply distributions directly to properties of
objects. See [[/Module/Behavior/Random]] for details.

## Discrete behavior

The `system` class is used to apply random states to properties of objects.
See [[/Module/Behavior/System]] for details.


# See also

* [[/Module/Behavior/Random]]
* [[/Module/Behavior/System]]
72 changes: 72 additions & 0 deletions docs/Module/Behavior/Random.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
[[/Module/Behavior/Random]] - Random continuous behavior

# Synopsis

~~~
module Behavior
{
set {QUIET=65536, WARNING=131072, DEBUG=262144, VERBOSE=524288} message_flags; // module message control flags
int32 retry_limit; // limit on the number of sampling retries when RETRY limits are in effect
}
class random
{
enumeration {RT_TRIANGLE=12, RT_BETA=11, RT_GAMMA=10, RT_WEIBULL=9, RAYLEIGH=8, EXPONENTIAL=6, PARETO=5, BERNOULLI=4, LOGNORMAL=3, NORMAL=2, UNIFORM=1, DEGENERATE=0} type; // Distribution type to be used to generate values
double a; // The first distribution parameter value
double b; // The second distribution parameter value
double lower_limit; // The lower limit for generated values
double upper_limit; // The upper limit for generated values
enumeration {NONE=0, CLAMP=1, RETRY=2} limit_method; // Method to use to enforce limits
double refresh_rate[s]; // The rate at which values are generated
method point; // Point to which random value is posted as <object-name>:<property-name>
}
~~~

# Description

The `random` class is used to apply continuous distributions directly to double properties of objects. All the properties may be changes at any time. However validation is only performed during initialization.

The distribution type is specified by the `type` properties, with `a` and `b` providing the arguments to the distribution. The `lower_limit` and `upper_limit` values are used to perform clipping. There are three kind of limits.

* `NONE`: the limits are not imposed on the samples.

* `CLAMP`: the limits are imposed by clamping the output to the specified range. The result does not change the probabilities within the limits, but increases the probability of sampling the limits themselves.

* `RETRY`: the limits are imposed by resampling when a sample is outside the specified range. The result does not change the shape of the probability density function within the limits, but increases the probability of observing values within the limits.

The `refresh_rate` property determines how often the target values are updated.

The `point` method allows one or more target values to be added. Points are specified as `<object-name>.<property-name>`. Generally point are specified at initialization, but in some cases they can be added during the simulation. However, points cannot be removed once they are added.

# Caveat

Using `limit_method RETRY` can affect performance when the limits constrain the range to a relatively unlikely part of the distribution. In such cases, the `retry_limit` may be easily exceeded in a non-deterministic manner.

# Example

~~~
module Behavior;
class test
{
double x;
double y;
}
object test
{
name human_1;
}
object behavior.random
{
type NORMAL;
a 0;
b 1;
refresh_rate 1h;
lower_limit -1;
upper_limit +1;
limit_method RETRY;
point "human_1.x";
}
~~~

# See also

* [[/Module/Behavior]]
111 changes: 111 additions & 0 deletions docs/Module/Behavior/System.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
[[/Module/Behavior/System]] - Random discrete behavior

# Synopsis

~~~
module behavior {
set {QUIET=65536, WARNING=131072, DEBUG=262144, VERBOSE=524288} message_flags; // module message control flags
double system_resolution; // Resolution of system properties
}
class system {
double tau; // System activity
double mu; // Asset potential
int64 N; // Number of devices
int64 N0; // Number of sites
method u; // State values
method q; // State quantities
method device; // Property of device connected to this system
double U; // (OUTPUT) Total value of all states
double sigma; // (OUTPUT) System entropy
method p; // (OUTPUT) State probabilities
double Z; // (OUTPUT) State partition function
double F; // (OUTPUT) Free value
double P; // (OUTPUT) Internal price
double Q; // (OUTPUT) Total quantity
double Nexp; // (OUTPUT) Expected number of devices
double Uexp; // (OUTPUT) Expected device value
double Qexp; // (OUTPUT) Expected quantity
double chi; // (OUTPUT) Price susceptibility (dQ/dP)
double Cp; // (OUTPUT) Value capacity (dU/dtau)
}
~~~

# Description

The `system` object implements a statistical mechanics-inspired model of the
aggregate properties of systems of devices that behave in accordance with
principles that are analogous to those in thermodynamics, i.e.,

1. If two systems are in equilibrium with a third system, then they are in
equilibrium with each other.

2. In a closed system any change in internal value is equal to the value added
to the system minus the value removed from it. When two system are connected,
the total internal value of the combined system is the sum of the internal
values of the separate systems.

3. When two separate systems at internal equilibrium are connected, then when
they come to equilibrium the sum of their separate entropies at equilibrium
is less than or equal to the total entropy of the connected systems.

4. The system's entropy approaches a constant value as the system's activity
`tau` approach zero.

The follow analogies to thermodynamics are used in the generalization of the model:

* *number of devices* `N`: This is equivalent to the number of particles.
* *value* `u`: This is equivalent to energy.
* *activity* `tau`: This is equivalent to absolute temperature.
* *asset potential* `mu`: This is equivalent to chemical potential.
* *quantity* `q` is equivalent to magnetic moment.
* *price* `P` is equivalent to magnetic field.

The values of outputs are updated anytime the system updates. The values of
the state probabilities `p` and quantities `q` is given in the same order
that values `u` are given and must be specified after `u` is specified. The
value `Z` is the normalization factor for the probabilities when `tau != 0`.
When `tau == 0`, `Z` is a count of the states with non-zero probabilities.

Two types of `device` properties can be updated by a system model based on the
state probability `p`:

* `enumeration`: The specified property is assigned the state index number in `u`.

* `double`: The specified property is assigned the value of the quantity `q`.

# Example

The following example creates two devices with two state variables `x` and
`s`. The system model is given activity `tau=1.0`, and two possible states 0
and 1 with values `0.0` and `1.0`, respectively. The first device's state
variable `x` is updated based the value of the state chosen, and the second
device's state variable `s` is chosen based on the index of the state
chosen.

~~~
class device
{
double x;
enumeration {OFF=0,ON=1} s;
}
object device
{
name "device_1";
}
object device
{
name "device_2";
}
module behavior;
object system
{
tau 1.0;
u 0.0,1.0;
device "device_1.s,device_2.s"
}
~~~

# See also

* [[/Module/Behavior]]
74 changes: 74 additions & 0 deletions docs/Module/Random.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
[[/Module/Behavior/Random]] -

# Synopsis

~~~
module Behavior
{
set {QUIET=65536, WARNING=131072, DEBUG=262144, VERBOSE=524288} message_flags; // module message control flags
int32 retry_limit; // limit on the number of sampling retries when RETRY limits are in effect
}
class random
{
enumeration {RT_TRIANGLE=12, RT_BETA=11, RT_GAMMA=10, RT_WEIBULL=9, RAYLEIGH=8, EXPONENTIAL=6, PARETO=5, BERNOULLI=4, LOGNORMAL=3, NORMAL=2, UNIFORM=1, DEGENERATE=0} type; // Distribution type to be used to generate values
double a; // The first distribution parameter value
double b; // The second distribution parameter value
double lower_limit; // The lower limit for generated values
double upper_limit; // The upper limit for generated values
enumeration {NONE=0, CLAMP=1, RETRY=2} limit_method; // Method to use to enforce limits
double refresh_rate[s]; // The rate at which values are generated
method point; // Point to which random value is posted as <object-name>:<property-name>
}
~~~

# Description

The `random` class is used to apply continuous distributions directly to double properties of objects. All the properties may be changes at any time. However validation is only performed during initialization.

The distribution type is specified by the `type` properties, with `a` and `b` providing the arguments to the distribution. The `lower_limit` and `upper_limit` values are used to perform clipping. There are three kind of limits.

* `NONE`: the limits are not imposed on the samples.

* `CLAMP`: the limits are imposed by clamping the output to the specified range. The result does not change the probabilities within the limits, but increases the probability of sampling the limits themselves.

* `RETRY`: the limits are imposed by resampling when a sample is outside the specified range. The result does not change the shape of the probability density function within the limits, but increases the probability of observing values within the limits.

The `refresh_rate` property determines how often the target values are updated.

The `point` method allows one or more target values to be added. Points are specified as `<object-name>.<property-name>`. Generally point are specified at initialization, but in some cases they can be added during the simulation. However, points cannot be removed once they are added.

# Caveat

Using `limit_method RETRY` can affect performance when the limits constrain the range to a relatively unlikely part of the distribution. In such cases, the `retry_limit` may be easily exceeded in a non-deterministic manner.

# Example

~~~
module Behavior;
class test
{
double x;
double y;
}
object test
{
name human_1;
}
object behavior.random
{
type NORMAL;
a 0;
b 1;
refresh_rate 1h;
lower_limit -1;
upper_limit +1;
limit_method RETRY;
point "human_1.x";
}
~~~

# See also

* [[/Module/Behavior]]
* [[/Module/Behavior/Inclusive]]
* [[/Module/Behavior/Random]]
1 change: 1 addition & 0 deletions module/Makefile.mk
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ include module/assert/Makefile.mk
include module/climate/Makefile.mk
include module/commercial/Makefile.mk
include module/generators/Makefile.mk
include module/behavior/Makefile.mk
include module/industrial/Makefile.mk
include module/influxdb/Makefile.mk
include module/market/Makefile.mk
Expand Down
18 changes: 18 additions & 0 deletions module/behavior/Makefile.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# module/behavior/Makefile.mk
# Copyright (C) 2024 Regents of the Leland Stanford Junior University

pkglib_LTLIBRARIES += module/behavior/behavior.la

module_behavior_behavior_la_CPPFLAGS =
module_behavior_behavior_la_CPPFLAGS += $(AM_CPPFLAGS)

module_behavior_behavior_la_LDFLAGS =
module_behavior_behavior_la_LDFLAGS += $(AM_LDFLAGS)

module_behavior_behavior_la_LIBADD =

module_behavior_behavior_la_SOURCES =
module_behavior_behavior_la_SOURCES += module/behavior/behavior.cpp module/behavior/behavior.h

module_behavior_behavior_la_SOURCES += module/behavior/random.cpp module/behavior/random.h
module_behavior_behavior_la_SOURCES += module/behavior/system.cpp module/behavior/system.h
25 changes: 25 additions & 0 deletions module/behavior/autotest/test_connection.glm
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module behavior;

object system
{
name "system_0";
tau 0.1;
N 20;
mu 1.0;
u 0,1;
q -1,1;
}

object system
{
name "system_1";
tau 0.05;
N 10;
mu 0.1;
u 0,1;
q -1,1;
connection "system_0";
connection_type VALUE;
}

#set savefile=test_connection.json
34 changes: 34 additions & 0 deletions module/behavior/autotest/test_device.glm
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module behavior;

object system
{
name "system_0";
tau 0.1;
N 20;
mu 1.0;
u 0,1;
q -1,1;
}
class device
{
double x;
enumeration {OFF=0,ON=1} s;
}

#for DEV in ${RANGE 0,10}
object device
{
name "device_${DEV}";
}
modify system_0.device "device_${DEV}.x";
#done

#for DEV in ${RANGE 11,20}
object device
{
name "device_${DEV}";
}
modify system_0.device "device_${DEV}.s";
#done

#set savefile=test_device.json
Loading

0 comments on commit 8afa4a0

Please sign in to comment.