initial commit
This commit is contained in:
commit
fbfe4dd82c
26
graphUtils.js
Normal file
26
graphUtils.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
function edgelistToDot(name, inp){
|
||||||
|
var output = "strict graph \"" + name + "\" {\n";
|
||||||
|
for(e in inp){
|
||||||
|
e = inp[e];
|
||||||
|
output += e[0] + " -- " + e[1] + ";\n";
|
||||||
|
}
|
||||||
|
output += "}";
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
function dotToEdgelist(graph){
|
||||||
|
var outList = [];
|
||||||
|
graph = graph.split("\n");
|
||||||
|
//var name = graph[0].split(" ")[2];
|
||||||
|
//name = name.slice(1, name.length - 1);
|
||||||
|
for (var i = 0; i < graph.length - 1; i++){
|
||||||
|
if(i == 0){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var nodes = graph[i].split("--");
|
||||||
|
var node1 = Number(nodes[0]);
|
||||||
|
var node2 = Number(nodes[1].slice(0, nodes[1].length - 1));
|
||||||
|
outList.push([node1, node2]);
|
||||||
|
}
|
||||||
|
return outList;
|
||||||
|
}
|
||||||
12
main.vue
Normal file
12
main.vue
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
const Counter = {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
counter: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted(){
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Vue.createApp(Counter).mount('#counter')
|
||||||
20
simulation.html
Normal file
20
simulation.html
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Simulation</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="counter">
|
||||||
|
Counter: {{ counter }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--Simulation libraries-->
|
||||||
|
<script src="graphUtils.js"></script>
|
||||||
|
<script src="simulation.js"></script>
|
||||||
|
<!--Vue.js libraries-->
|
||||||
|
<script src="https://unpkg.com/vue@next"></script>
|
||||||
|
<!--logic-->
|
||||||
|
<script src="main.vue"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
203
simulation.js
Normal file
203
simulation.js
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
states = ["S", "I", "R"];
|
||||||
|
|
||||||
|
rules = [[ "I", "R", 1 ], // spontaneous rule I -> R with rate 1.0
|
||||||
|
[ "R", "S", 0.7 ], // spontaneous rule R -> S with rate 0.7
|
||||||
|
[ [ "I","S","I" ],[ "I","I","I" ], 0.8 ]]; // contact rule I+S -> I+I with rate 0.8
|
||||||
|
|
||||||
|
|
||||||
|
simulation = []
|
||||||
|
|
||||||
|
|
||||||
|
graph_as_edgelist = [[ 0, 4 ], [ 0, 1 ], [ 1, 5 ], [ 1, 2 ], [ 2, 6 ], [ 2, 3 ], [ 3, 7 ], [ 4, 8 ], [ 4, 5 ], [ 5, 9 ], [ 5, 6 ], [ 6, 10 ], [ 6, 7 ], [ 7, 11 ], [ 8, 12 ], [ 8, 9 ], [ 9, 13 ], [ 9, 10 ], [ 10, 14 ], [ 10, 11 ], [ 11, 15 ], [ 12, 13 ], [ 13, 14 ], [ 14, 15 ]];
|
||||||
|
|
||||||
|
horizon = 20.0; // wie lange wird simuliert
|
||||||
|
initial_distribution = [0.5, 0.5, 0.0]; // gleiche Reihenfolge wie states, musss zu rules passen und normalisiert werden
|
||||||
|
timepoint_num = 101;
|
||||||
|
|
||||||
|
function get_next_state(current_labels){
|
||||||
|
fastes_firing_time = 10000000.0; //dummy
|
||||||
|
firing_rule = null;
|
||||||
|
firing_node = null;
|
||||||
|
firing_edge = null;
|
||||||
|
|
||||||
|
//if(current_labels == null)
|
||||||
|
//iterate over nodes
|
||||||
|
for(node in nodes){
|
||||||
|
node = nodes[node];
|
||||||
|
current_state = current_labels[node];
|
||||||
|
for(rule in rules){
|
||||||
|
rule = rules[rule];
|
||||||
|
if(rule[0] instanceof Array){
|
||||||
|
//is contact rule
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(current_state == rule[0]){
|
||||||
|
current_fireing_time = randomExponential(rule[2]);
|
||||||
|
//addFiringTime(current_fireing_time);
|
||||||
|
if(current_fireing_time < fastes_firing_time){
|
||||||
|
fastes_firing_time = current_fireing_time;
|
||||||
|
firing_rule = rule;
|
||||||
|
firing_node = node;
|
||||||
|
firing_edge = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//iterate over edges
|
||||||
|
for(edge in graph_as_edgelist){
|
||||||
|
edge = graph_as_edgelist[edge];
|
||||||
|
node1 = node2 = edge;
|
||||||
|
current_state1 = current_labels[node1];
|
||||||
|
current_state2 = current_labels[node2];
|
||||||
|
for(rule in rules){
|
||||||
|
rule = rules[rule];
|
||||||
|
if(typeof rule[0] == typeof ""){
|
||||||
|
//is spont. rule
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if(current_state1 == rule[0][0] && current_state2 == rule[0][1] || current_state2 == rule[0][0] && current_state1 == rule[0][1]){
|
||||||
|
current_fireing_time = randomExponential(rule[2]);
|
||||||
|
if(current_fireing_time < fastes_firing_time){
|
||||||
|
fastes_firing_time = current_fireing_time;
|
||||||
|
firing_rule = rule;
|
||||||
|
firing_node = null;
|
||||||
|
firing_edge = edge;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(firing_rule == null){
|
||||||
|
//no rule could fire
|
||||||
|
return [null, fastes_firing_time]; //would happen anyway but still
|
||||||
|
}
|
||||||
|
//apply rule
|
||||||
|
new_labels = Array.from(current_labels);
|
||||||
|
|
||||||
|
if(firing_node != null){
|
||||||
|
new_labels[firing_node] = firing_rule[1];
|
||||||
|
return [new_labels, fastes_firing_time];
|
||||||
|
}
|
||||||
|
console.assert(firing_edge != null);
|
||||||
|
change_node1 = firing_edge[0];
|
||||||
|
change_node2 = firing_edge[1];
|
||||||
|
//we have to check which node changes in which direction
|
||||||
|
if(new_labels[change_node1] == firing_rule[0][0] && new_labels[change_node2] == firing_rule[0][1]){
|
||||||
|
new_labels[change_node1] = firing_rule[1][0];
|
||||||
|
new_labels[change_node2] = firing_rule[1][1];
|
||||||
|
}else{
|
||||||
|
new_labels[change_node1] = firing_rule[1][1];
|
||||||
|
new_labels[change_node2] = firing_rule[1][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [new_labels, fastes_firing_time];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function count_states(current_labels){
|
||||||
|
counter = [states.length];
|
||||||
|
simulation.push(current_labels);
|
||||||
|
for(label in current_labels){
|
||||||
|
label = current_labels[label];
|
||||||
|
index = states[ label ];
|
||||||
|
counter[index] += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateNodes(edgelist){
|
||||||
|
allNodes = [];
|
||||||
|
for(e in edgelist){
|
||||||
|
e = edgelist[e];
|
||||||
|
allNodes.push(e[0]);
|
||||||
|
allNodes.push(e[1]);
|
||||||
|
}
|
||||||
|
//sort
|
||||||
|
allNodes = allNodes.sort((a, b) => (a > b));
|
||||||
|
//remove duplicates
|
||||||
|
finalArray = [];
|
||||||
|
var last = -1;
|
||||||
|
for(var i = 0; i < allNodes.length; i ++){
|
||||||
|
if(last == allNodes[i]){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
finalArray.push(allNodes[i])
|
||||||
|
last = allNodes[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return finalArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
nodes = generateNodes(graph_as_edgelist);
|
||||||
|
|
||||||
|
//setup
|
||||||
|
timepoints_samples = linspace(0, horizon, timepoint_num);
|
||||||
|
timepoints_samples_static = linspace(0, horizon, timepoint_num);
|
||||||
|
current_labels = randomChoice(states, nodes.length, initial_distribution);
|
||||||
|
global_clock = 0;
|
||||||
|
labels = [];
|
||||||
|
timepoints = [];
|
||||||
|
state_counts = [];
|
||||||
|
|
||||||
|
simulate(rules, states, initial_distribution);
|
||||||
|
function simulate(newRules, newStates, newDistr){
|
||||||
|
rules = newRules;
|
||||||
|
states = newStates;
|
||||||
|
initial_distribution = newDistr;
|
||||||
|
while(timepoints_samples.length > 0){
|
||||||
|
[new_labels, time_passed] = get_next_state(current_labels);
|
||||||
|
global_clock += time_passed;
|
||||||
|
while(timepoints_samples.length > 0 && global_clock > timepoints_samples[0]){
|
||||||
|
labels.push(Array.from(current_labels));
|
||||||
|
state_counts.push(count_states(current_labels));
|
||||||
|
timepoints_samples = timepoints_samples.slice(1, timepoints_samples.length);
|
||||||
|
}
|
||||||
|
current_labels = new_labels;
|
||||||
|
}
|
||||||
|
console.log(simulation);
|
||||||
|
}
|
||||||
|
|
||||||
|
// np helper functions
|
||||||
|
|
||||||
|
function randomExponential(rate){
|
||||||
|
if(rate == 0){ return 10000000 }
|
||||||
|
return -Math.log(Math.random()) / rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
function linspace(start, end, num){
|
||||||
|
console.assert(start < end);
|
||||||
|
console.assert(num > 0);
|
||||||
|
distance = (end - start) / (num - 1);
|
||||||
|
current = start;
|
||||||
|
out = [];
|
||||||
|
while(current <= end){
|
||||||
|
out.push(Math.round(current * 100) / 100);
|
||||||
|
current += distance;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
function randomChoice(states, num, distr){
|
||||||
|
out = [];
|
||||||
|
let s = distr.reduce((a,e) => a + e);
|
||||||
|
for(var i = 0; i < num; i++){
|
||||||
|
let r = Math.random() * s;
|
||||||
|
out.push(states.find((_,i) => (r -= distr[i]) < 0));
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
//times = [];
|
||||||
|
//function addFiringTime(time){
|
||||||
|
//times.push(time);
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//function getAv(){
|
||||||
|
//var sum = 0;
|
||||||
|
//for(t in times){
|
||||||
|
//t = times[t];
|
||||||
|
//sum += t;
|
||||||
|
//}
|
||||||
|
//return sum / times.length;
|
||||||
|
//}
|
||||||
|
//simulate();
|
||||||
11
tsconfig.json
Normal file
11
tsconfig.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
// tsconfig.json
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "esnext",
|
||||||
|
"module": "esnext",
|
||||||
|
// this enables stricter inference for data properties on `this`
|
||||||
|
"strict": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"moduleResolution": "node"
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user