Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitcb8399a

Browse files
Add main model API and documentation
1 parent24345a2 commitcb8399a

File tree

3 files changed

+257
-0
lines changed

3 files changed

+257
-0
lines changed

‎R/api.r‎

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
#' Simulate the run of a PCS model
2+
#'
3+
#' \code{PCS_run} simulates a PCS network given a pre-specified interconnection
4+
#' matrix and model parameters, according to the mechanism outlines by
5+
#' McClelland and Rumelhart (1981).
6+
#'
7+
#' @param interconnection_matrix A square, matrix representing the link weights
8+
#' between nodes, such that each entry w_ij represents the link strength
9+
#' between nodes i and j. Accordingly, for a network of n nodes, the matrix
10+
#' must be of six n*n. In most applications, the matrix will be symmetric,
11+
#' meaning that links are bidirectional.
12+
#'
13+
#' @param initial_state Initial node activations before the first iteration is
14+
#' run. In most cases, this will be a vector of zeros, with the length
15+
#' corresponding to the number of nodes in the network.
16+
#'
17+
#' @param resting_levels Resting activation level for each node. In most cases,
18+
#' this will be a vector of zeros, with its length corresponding to the number
19+
#' of nodes in the network.
20+
#'
21+
#' @param reset Vector denoting nodes with stable activation values. The vector
22+
#' contains a value for each node; if it is unequal to zero, the node
23+
#' activation will be reset to this value after each iteration.
24+
#'
25+
#' @param node_names Vector specifying human-readable labels for every node, or
26+
#' \code{'default'}, in which case nodes are automatically named.
27+
#'
28+
#' @param stability_criterion Stability theshold for convergence criteria. If
29+
#' energy changes across iterations fall below this threshold, the model is
30+
#' considered to have converged.
31+
#'
32+
#' @param max_iterations Maximum number of iterations to run before terminating
33+
#' the simulation.
34+
#'
35+
#' @param convergence_criteria Array of convergence criteria to apply. This PCS
36+
#' implementation allows users to define and observe multiple convergence
37+
#' criteria in one model. Each entry in this array is a convergence criterion,
38+
#' which is representated as a function that receives the current iteration,
39+
#' energy, model state history and the \code{stability_criterion} defined
40+
#' above and returns a boolean value representing whether the particular
41+
#' criterion is met given the model's current state.
42+
#'
43+
#' @param convergence_names Human-readable labels for the convergence criteria,
44+
#' or \code{'default'}, in which case the criteria are numbered automatically,
45+
#' in which case the criteria are numbered automatically.
46+
#'
47+
#' @return A list representing the model state after all convergence criteria
48+
#' have been fullfilled. The key \code{iterations} contains the model state
49+
#' over its entire run, while the key \code{convergence} defines which
50+
#' convergence criteria have been met at which iteration. Together, these
51+
#' provide an exhaustive summary of the model's behavior.
52+
#'
53+
#' @export
54+
PCS_run<-function(interconnection_matrix,initial_state,resting_levels,reset,
55+
node_names=NULL,stability_criterion=10^-6,max_iterations=Inf,
56+
convergence_criteria=c(PCS_convergence_McCandR),convergence_names=NULL) {
57+
# A note on the iteration counter:
58+
# The counter reflects the current line of the
59+
# model output, but the iterations start at zero.
60+
# Therefore, whenever iterations are output,
61+
# one is subtracted from this counter.
62+
#
63+
# This may seem silly, but it makes sense because
64+
# a) It is equivalent to the python output
65+
# b) The first output is not actually from the
66+
# first iteration, rather nothing has happened
67+
# at that point.
68+
iteration<-1
69+
70+
# How many convergence criteria are going to be
71+
# applied?
72+
n_criteria<- length(convergence_criteria)
73+
74+
# Name the criteria, if that has not already happened
75+
if (is.null(convergence_names)) {
76+
convergence_names<- paste("criterion_",1:n_criteria,sep="")
77+
}
78+
79+
# Initialize the model state
80+
state<-initial_state
81+
state<- PCS_reset(state,reset)
82+
nodes<- length(state)
83+
energy<- PCS_energy(interconnection_matrix,state)
84+
85+
# Create the matrix in which we will save
86+
# the data from the model iterations
87+
memory.ma<- PCS_memory_create(nodes,node_names)
88+
memory.ma[iteration,]<- c(iteration-1,energy,state)
89+
90+
# Create the matrix in which we will save
91+
# convergence data
92+
convergence.ma<-matrix(ncol=n_criteria,nrow=nrow(memory.ma))
93+
colnames(convergence.ma)<-convergence_names
94+
convergence.ma[1, ]<-TRUE
95+
96+
# This is the main model evaluation loop
97+
continue=TRUE
98+
while (continue==TRUE&iteration<=max_iterations) {
99+
# Increment the counter
100+
iteration=iteration+1
101+
102+
# Compute the new model state and energy
103+
state<- PCS_iterate(interconnection_matrix,state,resting_levels)[1:nodes]
104+
state<- PCS_reset(state,reset)
105+
energy<- PCS_energy(interconnection_matrix,state)
106+
107+
# Write the current state into the matrix
108+
memory.ma[iteration, ]<- c(iteration-1,energy,state)
109+
110+
# Expand the output matrix if necessary
111+
if (PCS_memory_needs_expansion(memory.ma,iteration)) {
112+
memory.ma<- PCS_matrix_expand(memory.ma,iteration)
113+
convergence.ma<- PCS_matrix_expand(convergence.ma,iteration)
114+
}
115+
116+
# Check if the model has converged yet, using
117+
# the given criterion functions
118+
for (fin1:n_criteria) {
119+
convergence.ma[iteration,f]<-convergence_criteria[[f]](
120+
iteration=iteration,
121+
current_energy=energy,
122+
memory.matrix=memory.ma,
123+
stability_criterion=stability_criterion,
124+
)
125+
}
126+
127+
# Continue until all criteria are converged
128+
continue<- (sum(convergence.ma[iteration,]*1)>0)
129+
}
130+
131+
# Prepare and pass along the model output
132+
memory.ma<- PCS_matrix_trunc(memory.ma)
133+
memory.df<- as.data.frame(memory.ma)
134+
135+
convergence.ma<- PCS_matrix_trunc(convergence.ma)
136+
137+
output<-list()
138+
output$iterations<-memory.df
139+
140+
# Note that the MPI Coll implementation will always assume
141+
# one more iteration. To match their simulations,
142+
# add "+ 1" in the next line
143+
output$convergence<- colSums(convergence.ma)
144+
145+
return(output)
146+
}
147+
148+
#' Simulate the run of a PCS model based on only the interconnection matrix
149+
#'
150+
#' \code{PCS_run_from_interconnections} simulates a PCS network given \emph{only}
151+
#' the pre-specified interconnection matrix and convergence criteria, substituting
152+
#' default values from the literature for all other parameters. Thereby, it
153+
#' provides a convenient shorthand for the \link{PCS_run} function that covers
154+
#' the vast majority of applications.
155+
#'
156+
#' @inheritParams PCS_run
157+
#'
158+
#' @export
159+
PCS_run_from_interconnections<-function(interconnection_matrix,
160+
convergence_criteria=c(PCS_convergence_McCandR),convergence_names="default") {
161+
# This function is just a simplification to speed up my work
162+
163+
# Infer the number of nodes from the matrix size
164+
nodes<- nrow(interconnection_matrix)
165+
166+
# This function assumes that the initial state,
167+
# as well as the resting levels, are all set to zero
168+
resting_levels<- rep(0,nodes)
169+
state<- rep(0,nodes)
170+
171+
# We assume that the first node (and only that)
172+
# has a constant activation
173+
reset<- c(1, rep(0,nodes-1))
174+
175+
# Good to go! :-)
176+
return(PCS_run(interconnection_matrix,state,resting_levels,reset,
177+
convergence_criteria=convergence_criteria,convergence_names=convergence_names))
178+
}

‎R/convergence.r‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#' Check a PCS network for convergence
2+
#'
3+
#' This function applies the convergence criterion defined by McClelland and
4+
#' Rumelhart to a given network, and returns either a (qualitative) boolean
5+
#' value that represents the convergence state, or a (quantitative) value that
6+
#' represents the number of iterations (of the last 10) that have met the
7+
#' convergence threshold.
8+
#'
9+
#' The check requires the following parameters:
10+
#'
11+
#' @param iteration The iteration to consider -- in most cases, this will be the
12+
#' current iteration during a simulation run, however, the check can also be
13+
#' applied to a model output retroactively, and the iteration specified
14+
#' manually.
15+
#'
16+
#' @param current_energy The current energy level within the network
17+
#'
18+
#' @param memory.matrix A matrix of iteration, energy and node states (in
19+
#' columns, in that order), across all previous iterations (in rows).
20+
#'
21+
#' @param stability_criterion Criterion for stability. Changes below this value
22+
#' are no longer considered significant, and ten iterations without significant changes
23+
#' to the energy level in succession will trigger the convergence check.
24+
#'
25+
#' @param output Either \code{'qualitative'} (default), in which case the check
26+
#' returns a boolean value representing whether it has passed or not, or
27+
#' \code{'quantitative'}, in which case the number of checked trials for which
28+
#' the convergence criterion was met is returned. This last option is of most
29+
#' value for debugging convergence.
30+
#'
31+
#' @export
32+
PCS_convergence_McCandR<-function(iteration,current_energy,memory.matrix,
33+
stability_criterion=10^-6,output="qualitative") {
34+
# Felix' interpretation of the McClelland & Rumelhart criterion
35+
if (iteration<=10) {
36+
return(TRUE)
37+
}else {
38+
# Convergence stops if the change in energy between iterations
39+
# is below a certain threshold for > 10 trials
40+
energy_changes<-memory.matrix[(iteration-10):(iteration-1),2]-
41+
memory.matrix[(iteration-9):(iteration),2]
42+
changes_below_threshold<- sum(energy_changes<stability_criterion)
43+
44+
if (output=="quantitative") {
45+
return(changes_below_threshold)
46+
}else {
47+
return(changes_below_threshold<10)
48+
}
49+
}
50+
}

‎R/helpers.r‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Helper functions, largely for model state management
2+
# ----------------------------------------------------
3+
4+
PCS_memory_create<-function(nodes,node_names=NULL) {
5+
if (is.null(node_names)) {
6+
node_names= paste("node_",1:nodes,sep="")
7+
}
8+
memory<-matrix(ncol=2+nodes,nrow=100)
9+
colnames(memory)<- c("iteration","energy",node_names)
10+
return(memory)
11+
}
12+
13+
PCS_memory_needs_expansion<-function(memory,iteration) {
14+
return(iteration+1== nrow(memory))
15+
}
16+
17+
PCS_matrix_expand<-function(ma,iteration) {
18+
if (PCS_memory_needs_expansion(ma,iteration)) {
19+
return(
20+
rbind(ma,matrix(ncol=ncol(ma),nrow=100))
21+
)
22+
}else {
23+
return(ma)
24+
}
25+
}
26+
27+
PCS_matrix_trunc<-function(x) {
28+
return(x[!is.na(x[,1]), ,drop=F])
29+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp