Симуляция агрессивный, пассивный, альтруист — различия между версиями

Материал из Department of Theoretical and Applied Mechanics
Перейти к: навигация, поиск
(Инструкция по использованию)
 
(не показаны 2 промежуточные версии этого же участника)
Строка 3: Строка 3:
 
# Вся система состоит из неограниченного числа итераций длинной несколько секунд.
 
# Вся система состоит из неограниченного числа итераций длинной несколько секунд.
 
# В начале итерации на квадратном поле случайным образом расположено одинаковое число пищи.
 
# В начале итерации на квадратном поле случайным образом расположено одинаковое число пищи.
# Черепахе любой модели поведения необходимо употребить 1 пищу, чтобы выжить и продолжить существовать в следующей итерации, 2 пищи, чтобы выжить и дать потомство в количестве одной черепахи, чья модель поведения совпадает с моделью родителя, но может измениться с какой-то вероятностью(вероятность мутации) на одну из двух других моделей, больше употребить невозможно. Если же не было употреблено пищи совсем, то на следующей итерации черепаха исчезает.
+
# Черепахе любой модели поведения необходимо употребить 1 пищу, чтобы выжить и продолжить существовать в следующей итерации, 2 пищи, чтобы выжить и дать потомство в количестве одной черепахи, чья модель поведения совпадает с моделью родителя, но может измениться с какой-то вероятностью(вероятность мутации) на одну из двух других моделей, больше 2 употребить невозможно. Если же не было употреблено пищи совсем, то на следующей итерации черепаха исчезает.
 
# Модель поведения "пассивный" заключается в случайном блуждании по полю в поиске пищи.
 
# Модель поведения "пассивный" заключается в случайном блуждании по полю в поиске пищи.
 
# Модель поведения "агрессивный" заключается в преимущественном случайном блуждании по полю в поиске пищи, однако при недостатке пищи для выживания черепаха будет пытаться отобрать еду у ближайшей сытой черепахи любой модели поведения.
 
# Модель поведения "агрессивный" заключается в преимущественном случайном блуждании по полю в поиске пищи, однако при недостатке пищи для выживания черепаха будет пытаться отобрать еду у ближайшей сытой черепахи любой модели поведения.
# Модель поведения "альтруист" заключается в преимущественном случайном блуждании по полю в поиске пищи, однако если будет употреблено 2 пищи то черепаха будет стремится отдать 1 пищу ближайшей голодной черепахе любой модели поведения.
+
# Модель поведения "альтруист" заключается в преимущественном случайном блуждании по полю в поиске пищи, однако если будет употреблено 2 пищи то черепаха будет стремиться отдать 1 пищу ближайшей голодной черепахе любой модели поведения.
  
 
== Основные допущения и ограничения ==
 
== Основные допущения и ограничения ==
Строка 17: Строка 17:
 
* Чтобы ускорить симуляцию изменяйте значение параметра "simulation speed".
 
* Чтобы ускорить симуляцию изменяйте значение параметра "simulation speed".
 
* Чтобы начать симуляцию нажмите кнопку "start simulation", а чтобы закончить - "end simulation".
 
* Чтобы начать симуляцию нажмите кнопку "start simulation", а чтобы закончить - "end simulation".
* Симуляцию можно приостановить нажав кнопку "stop".
+
* Симуляцию можно приостановить, нажав кнопку "stop".
 
* Можно разрешить черепахам мутировать только в определённые модели поведения, поставив возле соответствующего поля галочку.
 
* Можно разрешить черепахам мутировать только в определённые модели поведения, поставив возле соответствующего поля галочку.
 
В симуляции агрессивные черепахи раскрашены рыжим цветом, пассивные - болотным, альтруисты - зелёным. На графиках это отображается красным, жёлтым и зелёным соответственно.
 
В симуляции агрессивные черепахи раскрашены рыжим цветом, пассивные - болотным, альтруисты - зелёным. На графиках это отображается красным, жёлтым и зелёным соответственно.
 +
 
== Симуляция ==
 
== Симуляция ==
 
{{#widget:Iframe | url=http://tm.spbstu.ru/htmlets/js2020/Simulation%20agr%20pas%20alt/Simulation.html| width=1200 | height=1400 | border=0}}
 
{{#widget:Iframe | url=http://tm.spbstu.ru/htmlets/js2020/Simulation%20agr%20pas%20alt/Simulation.html| width=1200 | height=1400 | border=0}}
Строка 25: Строка 26:
 
<div class="mw-collapsible mw-collapsed" style="width:100%" >
 
<div class="mw-collapsible mw-collapsed" style="width:100%" >
 
'''Текст программы на языке JavaScript (разработчики [http://tm.spbstu.ru/Фурманов_Натан_3630103/90003 Фурманов Натан] и [http://tm.spbstu.ru/Курмакаева_Алсу Курмакаева Алсу]):''' <div class="mw-collapsible-content">
 
'''Текст программы на языке JavaScript (разработчики [http://tm.spbstu.ru/Фурманов_Натан_3630103/90003 Фурманов Натан] и [http://tm.spbstu.ru/Курмакаева_Алсу Курмакаева Алсу]):''' <div class="mw-collapsible-content">
Файл '''"script.js"'''
+
Файл '''"Main script.js"'''
 
<syntaxhighlight lang="javascript" line start="1" enclose="div">
 
<syntaxhighlight lang="javascript" line start="1" enclose="div">
 
window.addEventListener('load', main, false);
 
window.addEventListener('load', main, false);

Текущая версия на 12:32, 1 июня 2020

Формулировка задачи[править]

Дана абстрактная система, в начальный момент состоящая из пищи и какого-то количества существ(черепах) каждой модели поведения из трёх возможных - агрессивный, пассивный, альтруист. Необходимо построить симуляцию данной системы. Её условия таковы:
  1. Вся система состоит из неограниченного числа итераций длинной несколько секунд.
  2. В начале итерации на квадратном поле случайным образом расположено одинаковое число пищи.
  3. Черепахе любой модели поведения необходимо употребить 1 пищу, чтобы выжить и продолжить существовать в следующей итерации, 2 пищи, чтобы выжить и дать потомство в количестве одной черепахи, чья модель поведения совпадает с моделью родителя, но может измениться с какой-то вероятностью(вероятность мутации) на одну из двух других моделей, больше 2 употребить невозможно. Если же не было употреблено пищи совсем, то на следующей итерации черепаха исчезает.
  4. Модель поведения "пассивный" заключается в случайном блуждании по полю в поиске пищи.
  5. Модель поведения "агрессивный" заключается в преимущественном случайном блуждании по полю в поиске пищи, однако при недостатке пищи для выживания черепаха будет пытаться отобрать еду у ближайшей сытой черепахи любой модели поведения.
  6. Модель поведения "альтруист" заключается в преимущественном случайном блуждании по полю в поиске пищи, однако если будет употреблено 2 пищи то черепаха будет стремиться отдать 1 пищу ближайшей голодной черепахе любой модели поведения.

Основные допущения и ограничения[править]

  • Начальное число черепах каждой модели поведения ограничено 20 .
  • Число пищи ограничено 60.
  • Длительность одной итерации ограничена 30 секундами.

Инструкция по использованию[править]

  • Чтобы изменить какой-то параметр введите в строку число не превышающее установленных границ. Разрешены только символы цифр 0-9.
  • Чтобы ускорить симуляцию изменяйте значение параметра "simulation speed".
  • Чтобы начать симуляцию нажмите кнопку "start simulation", а чтобы закончить - "end simulation".
  • Симуляцию можно приостановить, нажав кнопку "stop".
  • Можно разрешить черепахам мутировать только в определённые модели поведения, поставив возле соответствующего поля галочку.

В симуляции агрессивные черепахи раскрашены рыжим цветом, пассивные - болотным, альтруисты - зелёным. На графиках это отображается красным, жёлтым и зелёным соответственно.

Симуляция[править]

Текст программы на языке JavaScript (разработчики Фурманов Натан и Курмакаева Алсу):

Файл "Main script.js"

  1 window.addEventListener('load', main, false);
  2 
  3 function main() {
  4 
  5   ctx = main_canvas.getContext('2d');
  6   w = main_canvas.width;
  7   h = main_canvas.height;
  8   ctxp = population_canvas.getContext('2d');
  9   wp = population_canvas.width;
 10   hp = population_canvas.height;
 11   ctxm = mean_canvas.getContext('2d');
 12   wm = mean_canvas.width;
 13   hm = mean_canvas.height;
 14   var end = true;
 15   var image = document.getElementById('source');
 16 
 17 
 18   function food(x=0, y=0){
 19     this.x = x;
 20     this.y = y;
 21 
 22     this.info = function(){
 23       return [this.x, this.y];
 24     }
 25 
 26     this.draw= function(){
 27       ctx.drawImage(image, this.x-10, this.y-10, 20, 20);
 28     }
 29   }
 30 
 31 
 32   Run_button.onclick = function(){
 33 
 34   	if (!end) {
 35       end = true;
 36       Stop_button.value = 'stop';
 37       return
 38     }
 39     
 40     console.log('|___________________NEW SIMULATION___________________|')
 41     ctxp.clearRect(0,0,wp,hp);
 42     ctxm.clearRect(0,0,wp,hp);
 43 
 44     Run_button.value = 'end simulation';
 45     Stop_button.disabled = false;
 46     Population_pas_input.disabled = true;
 47     Population_agr_input.disabled = true;
 48     Population_alt_input.disabled = true;
 49     Food_supply_input.disabled = true;
 50     Durability_input.disabled = true;
 51     Mutation_input.disabled = true;
 52     passive_mutation_allowed.disabled = true;
 53     aggressive_mutation_allowed.disabled = true;
 54     altruistic_mutation_allowed.disabled = true;
 55 	end = false;
 56 
 57     fps = 100;
 58     dt = 1/fps;
 59     iteration_durability = Durability_input.value;
 60     var iteration = 0;
 61     var simulation_speed = Simulation_speed_input.value;;
 62 
 63     var Start_population = parseInt(Population_pas_input.value)+parseInt(Population_agr_input.value)+parseInt(Population_alt_input.value);
 64     var Alt_population = [parseInt(Population_alt_input.value)];
 65     var Pas_population = [parseInt(Population_pas_input.value)];
 66     var Agr_population = [parseInt(Population_agr_input.value)];
 67     var Population = [Start_population];
 68 
 69     var Turtles = [];
 70     var velocity = 100;
 71     var size = 15;
 72     var viewing_radius = 150;
 73 
 74     var Mutation_probability = Mutation_input.value/100;
 75 
 76     var Food_quantity = Food_supply_input.value;
 77     var Current_food_quantity = Food_quantity;
 78 
 79     for (var i=0; i<Population_pas_input.value; i++){
 80       Turtles.push(new Turtle((w-2*size)*Math.random()+size, h-(h-2*size)*Math.random()-size,
 81         velocity, size, viewing_radius,'passive'));
 82     }
 83     for (var i=0; i<Population_agr_input.value; i++){
 84       Turtles.push(new Turtle((w-2*size)*Math.random()+size, h-(h-2*size)*Math.random()-size,
 85         velocity, size, viewing_radius,'aggressive'));
 86     }
 87      for (var i=0; i<Population_alt_input.value; i++){
 88       Turtles.push(new Turtle((w-2*size)*Math.random()+size, h-(h-2*size)*Math.random()-size,
 89         velocity, size, viewing_radius,'altruistic'));
 90     }
 91     
 92 
 93     console.log('Population: '+Population[iteration]);
 94     console.log('Altruistic population: '+Alt_population[iteration]);
 95     console.log('Passive population: '+Pas_population[iteration]);
 96     console.log('Aggressive population: '+Agr_population[iteration]);
 97 
 98 
 99     var Food_supply = [];
100     for (var i=0; i<Current_food_quantity; i++){
101       Food_supply.push(new food(w*Math.random(), h*Math.random()));
102     }
103 
104 
105 
106 
107 
108     function move(){
109       var turn_propobility = 0.05;
110 
111       for (var i=0; i<Population[iteration]; i++){
112         var best_food_distance = viewing_radius;
113         var best_turtle_distance = viewing_radius;
114         var target_name = 'food';
115 
116         if ((Turtles[i].satiety < 2)||(Turtles[i].gender == 'altruistic')){
117           for (var j=0; j<Current_food_quantity; j++){
118             var distance = Math.sqrt(Math.pow(Food_supply[j].x-Turtles[i].x,2)+
119               Math.pow(Food_supply[j].y-Turtles[i].y,2));
120 
121             if ((distance < best_food_distance)&&(Turtles[i].satiety < 2)){
122               Turtles[i].target = j;
123               best_food_distance = distance;
124               target_name = 'food';
125             }
126           }
127           if ((Turtles[i].gender == 'aggressive')&&(Turtles[i].target == -1)&&(Turtles[i].satiety==0)){
128             for (var j=0; j<Population[iteration]; j++){
129               var distance = Math.sqrt(Math.pow(Turtles[j].x-Turtles[i].x,2)+
130                 Math.pow(Turtles[j].y-Turtles[i].y,2));
131 
132               if ((distance < best_turtle_distance)&&(i!=j)&&(Turtles[j].satiety == 2)){
133                 Turtles[i].target = j;
134                 best_turtle_distance = distance;
135                 target_name = 'turtle';
136               }
137             }
138           }
139           if ((Turtles[i].gender == 'altruistic')&&(Turtles[i].target == -1)&&(Turtles[i].satiety==2)){
140             for (var j=0; j<Population[iteration]; j++){
141               var distance = Math.sqrt(Math.pow(Turtles[j].x-Turtles[i].x,2)+
142                 Math.pow(Turtles[j].y-Turtles[i].y,2));
143 
144               if ((distance < best_turtle_distance)&&(i!=j)&&(Turtles[j].satiety == 0)){
145                 Turtles[i].target = j;
146                 best_turtle_distance = distance;
147                 target_name = 'turtle';
148               }
149             }
150           }
151 
152           if (Turtles[i].target != -1){
153             var target = Turtles[i].target;
154 
155             if (target_name == 'food'){
156             	Turtles[i].moveTo(Food_supply[target].x, Food_supply[target].y);
157               var best_food_distance = viewing_radius;
158 
159               var distance = Math.sqrt(Math.pow(Food_supply[target].x-Turtles[i].x,2)+
160                 Math.pow(Food_supply[target].y-Turtles[i].y,2));
161               if (distance <= 1.5*Turtles[i].size){
162                 Turtles[i].satiety++;
163                 Food_supply.splice(target,1);
164                 Current_food_quantity--;
165               }
166             } else if (target_name == 'turtle'){
167             	Turtles[i].moveTo(Turtles[target].x, Turtles[target].y);
168             	//if (Turtles[i].gender == 'aggressive'){
169             	  //Turtles[i].moveTo(Turtles[target].x, Turtles[target].y);
170             	//}
171 
172               var distance = Math.sqrt(Math.pow(Turtles[target].x-Turtles[i].x,2)+
173                 Math.pow(Turtles[target].y-Turtles[i].y,2));
174               if (distance <= 1.5*Turtles[i].size){
175                 if (Turtles[i].gender == 'aggressive'){
176                 	Turtles[i].satiety++;
177 					Turtles[target].satiety--;
178                 } else if (Turtles[i].gender == 'altruistic'){
179                 	Turtles[i].satiety--;
180 					Turtles[target].satiety++;
181                 }
182               }
183             }  
184 
185             Turtles[i].target = -1;
186           } else{
187             Turtles[i].wander(turn_propobility);
188           }
189 
190         } else{
191           Turtles[i].wander(turn_propobility);
192         }
193       }
194     }
195 
196     function draw(){
197       ctx.clearRect(0,0,w,h);
198       for (var i=0; i<Population[iteration]; i++){
199         Turtles[i].draw();
200       }
201       for (var i=0; i<Current_food_quantity; i++){
202         Food_supply[i].draw();
203       }
204       ctx.fillStyle = "black";
205       ctx.font = "italic 10pt Arial";
206       ctx.textAlign = "left";
207       ctx.fillText('Iteration '+iteration, 10, 20);
208       ctx.fillText('Time '+Math.round((performance.now() - time - stop_time)/100)/10, 10, 40);
209     }
210 
211     function control(){
212       if (Population[iteration] != 0){
213         if (Turtles[0].energy < 0){
214           console.log('|___________end of iteration '+iteration+'__________|');	
215           console.log('Time: '+(performance.now()-time - stop_time)/1000);
216           time = performance.now();
217           stop_time = 0;
218 
219           var N = Population[iteration];
220           var New_population = Population[iteration];
221           for (var i=0; i<N; i++){
222             if (Turtles[i].satiety == 0){
223               Turtles.splice(i,1);;
224               N--;
225               New_population--;
226               i--;
227             } else if (Turtles[i].satiety == 1){
228               Turtles[i].energy = 100;
229               Turtles[i].satiety = 0;
230             } else{
231             	var gender = Turtles[i].gender;
232             	if (Math.random() <= Mutation_probability){
233         			if (gender == 'aggressive'){
234         				if (((Math.random() <= 0.5)||(!altruistic_mutation_allowed.checked))&&(passive_mutation_allowed.checked)){
235         					gender = 'passive';
236         				} else if (altruistic_mutation_allowed.checked){
237         					gender = 'altruistic';
238         				}
239         			} else if (gender == 'altruistic'){
240         				if (((Math.random() <= 0.5)||(!aggressive_mutation_allowed.checked))&&(passive_mutation_allowed.checked)){
241         					gender = 'passive';
242         				} else if (aggressive_mutation_allowed.checked){
243         					gender = 'aggressive';
244         				}
245         			} else if (gender == 'passive'){
246         				if (((Math.random() <= 0.5)||(!altruistic_mutation_allowed.checked))&&(aggressive_mutation_allowed.checked)){
247         					gender = 'aggressive';
248         				} else if (altruistic_mutation_allowed.checked){
249         					gender = 'altruistic';
250         				}
251         			}
252             	}
253               Turtles.push(new Turtle(Turtles[i].x+5*size*(2*Math.random()-1),
254                 Turtles[i].y+5*size*(2*Math.random()-1),
255                 velocity, size, viewing_radius, gender));
256               New_population++;
257               Turtles[i].energy = 100;
258               Turtles[i].satiety = 0;
259             }
260           }
261           iteration++;
262 
263           Population.push(New_population);
264 
265           var new_passive = 0;
266           var new_aggressive = 0;
267           var new_altruistic = 0;
268           for (var i=0; i<Population[iteration]; i++){
269           	if (Turtles[i].gender == 'passive'){
270           		new_passive++;
271           	} else if (Turtles[i].gender == 'aggressive'){
272           		new_aggressive++;
273           	} else if (Turtles[i].gender == 'altruistic'){
274           		new_altruistic++;
275           	}
276           }
277           Alt_population.push(new_altruistic);
278           Agr_population.push(new_aggressive);
279           Pas_population.push(new_passive);
280 
281           console.log('Population: '+Population[iteration]);
282           console.log('Altruistic population: '+Alt_population[iteration]);
283           console.log('Passive population: '+Pas_population[iteration]);
284           console.log('Aggressive population: '+Agr_population[iteration]);
285           Population_graph(Alt_population, Pas_population, Agr_population, Population);
286 
287           Current_food_quantity = Food_quantity;
288           Food_supply = [];
289           for (var i=0; i<Food_quantity; i++){
290             Food_supply.push(new food(w*Math.random(), h*Math.random()));
291           }
292 
293         }else{
294         	draw();
295         	for (var x=0; x<simulation_speed; x++){
296         	  move();
297         	}
298         }
299       } 
300     }
301 
302 
303 
304 
305     var stop = false;
306     Stop_button.onclick = function(){
307       if (stop) {
308         stop = false;
309         stop_time = performance.now() - stop_time;
310         Stop_button.value = 'stop';
311       } else {
312         stop = true;
313         stop_time = performance.now() - stop_time;
314         Stop_button.value = 'continue';
315       }
316     }
317 
318     simulation = function(){
319       if (!stop){
320         control();
321       }
322       if ((Population[iteration] == 0)||(end)) {
323         console.log('|_____________end of simulation____________|');
324         Run_button.value = 'start simulation';
325         Stop_button.disabled = true;
326         Population_pas_input.disabled = false;
327         Population_agr_input.disabled = false;
328         Population_alt_input.disabled = false;
329         Food_supply_input.disabled = false;
330         Durability_input.disabled = false;
331         Mutation_input.disabled = false;
332         passive_mutation_allowed.disabled = false;
333   		aggressive_mutation_allowed.disabled = false;
334    		altruistic_mutation_allowed.disabled = false;
335         end = true;
336 
337         ctx.clearRect(0,0,w,h);
338         clearInterval(timerId);
339       } 
340     }
341 
342     Simulation_speed_input.oninput = function() {
343       simulation_speed = Simulation_speed_input.value;
344       Result_speed.value = Simulation_speed_input.value;
345     }
346 
347     var time = performance.now();
348     var stop_time = 0;
349     var timerId = setInterval(simulation, 1000/fps);
350 
351   }
352 }