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