Моделирование Виртуальной Вычислительной Системы.
 
Выпуск №8
home URL
автор рассылки: noonv (noonv@narod.ru)

"Он повернулся, пнул дверь и вышел на крыльцо. Дождь словно только и ждал этого.
Только что он лениво моросил, а тут вдруг хлынул настоящим ливнем."
Аркадий и Борис Стругацкие. Гадкие лебеди.

Здравствуйте, уважаемые читатели!
Вот оно какое- лето! Жарко, зной словно выбелил небо...стоит только выглянуть на солнце и просто чувствуешь, как на тебя обрушиваются потоки оглушающей и вязкой теплоты, вот оно всемирное потепление :)
Но "вернёмся к нашим баранам", сегодня рассмотрим одно из применений клеточных автоматов: модель просачивания жидкости через слой какого-то материала.
Просачивания - ага, сейчас только об этом и разговаривать :)
Сразу оговорюсь: модель эта достаточно грубая. Нус приступим:
модель я построил просто подредактировав исходный код игры Жизнь, который был приведён в прошлом выпуске. Главная(и единственная) характеристика вещества в данной задаче - коеффициент просачивания:
const double p_LeakCoef=0.013;
изменяя это число вы можете посмотреть как будет меняться картина просачивания.
Размер поля я оставил прежний: 20x60, одна клетка может находиться в двух состояниях - она либо мокрая(wet), либо сухая(dry), причём если клетка мокрая, то она в этом состоянии и остаётся, то есть обратных процессов нет. Таким образом происходит обработка только сухих клеток. Переход ячейки из сухого состояния в противоположное, происходит так:
подсчитывается число влажных соседей данной клетки в окрестности Мура,
генерируется псевдослучайное число функцией rand(), оно делится на RAND_MAX для того, чтобы получить число в пределах от 0 до 1.
и, наконец, происходит сравнение псевдослучайного числа с произведением коеффициента просачивания на число мокрых соседних клеток. Если произведение окажется больше псевдослучайного числа, то мочим клетку :)

Note: Генерация псевдослучайных чисел.
#include<stdlib.h>
int rand(void);
void srand(unsigned seed);

rand() возвращает последовательность псевдослучайных чисел в диапазоне от 0 до RAND_MAX.
srand(seed) позволяет задать посредством аргумента seed новое начало для последовательности псевдослучайных чисел, которые будут генерироваться последующими вызовами rand(). Если srand потом будет вызвана с тем же аргументом, последовательнось генерирумых чисел поворится. Отсутствие вызова srand перед вызовами rand эквивалентна начальному вызову srand с аргументом 1.
// М.И.Беляков Мобильная операционная система М.:Радио и связь,1991

То есть картинка просачивания при одном и том ж коеффициенте просачивания будет одинаковой от запуска к запуску. Но надеюсь вы догадались, как этого избежать.

А вот и исходник.

//////////////////////////////////////////////////////////////////////
//
// 8.cpp
// for model of leakage 
//                       aka pampers =)
// issue N8
// Started: 16.07.03 9:10:12
//
//                                                    XIII
//////////////////////////////////////////////////////////////////////
// * - is wet cell 
// a - will wet
#ifndef _8_CPP_
#define _8_CPP_ 1

#include<fstream.h>
#include<stdio.h> // for getchar()
#include<stdlib.h> // for rand()
char *prog_name="pampers v0.02";
// size of massive
#define P_SIZE 20
#define P_SIZEY 60
const double p_LeakCoef=0.013; // coefficient of leakage 
							   // try to change it
typedef unsigned int uint;
// variables
char *file_name="pampers.txt";
fstream fs; // for manipulations with file
char p_mas[P_SIZE+2][P_SIZEY+2]; //massive
int p_i,p_j; // counter's
uint p_time=0; // age of model
uint p_coef=0; // coefficient for check cell
// functions
int in_file(char*); // get data from file and set massive
void calculate(uint,uint); // calculate one cell 
int main()
{
	// print Hello :)
	cout<<"+---------------+\n";
	cout<<"|  Pampers :)   |\n";
	cout<<"|               |\n";
	cout<<"|          XIII |\n";
	cout<<"+---------------+"<<endl;
	cout<<"press Enter for next step; for Exit press q"<<endl;
	// set border
	for(p_i=0;p_i<P_SIZEY+2;p_i++)
		p_mas[0][p_i]=p_mas[P_SIZE+1][p_i]='-';
	for(p_j=0;p_j<P_SIZE+2;p_j++)
		p_mas[p_j][0]=p_mas[p_j][P_SIZEY+1]='|';
	p_mas[P_SIZE+1][0]=p_mas[0][P_SIZEY+1]='+';
	p_mas[0][0]=p_mas[P_SIZE+1][P_SIZEY+1]='+';
	// set elements of p_mas zero
	for(p_i=1;p_i<P_SIZE+1;p_i++)
	{
		for(p_j=1;p_j<P_SIZEY+1;p_j++)
			p_mas[p_i][p_j]='0';
	}
	// get data
	if(in_file(file_name))
		return 1; // error open file
	while(getchar()!='q')
	{
		cout<<"Time: "<<p_time++<<endl;
		// print massive
		for(p_i=0;p_i<P_SIZE+2;p_i++)
		{
			for(p_j=0;p_j<P_SIZEY+2;p_j++)
			{
				if(p_mas[p_i][p_j]=='a')
					p_mas[p_i][p_j]='*'; // wet
				if(p_mas[p_i][p_j]=='0')
					cout<<" ";
				else
					cout<<p_mas[p_i][p_j];
			}
			cout<<endl;
		}
		// calculate next step
		for(p_i=1;p_i<P_SIZE+1;p_i++)
		{
			for(p_j=1;p_j<P_SIZEY+1;p_j++)
				calculate(p_i,p_j);
		}
	}
	////////////
	return 0;
}
int in_file(char*file)
{// get data from file and set life-massive
	fs.open(file,ios::in);
	if(!fs)
	{// can't open file
		cout<<"Error open file!\t"<<file_name<<endl;
		return 1;
	}
	// get data
	for(p_i=1;p_i<P_SIZE+1;p_i++)
	{
		for(p_j=1;p_j<P_SIZEY+1;p_j++)
			fs>>p_mas[p_i][p_j];
	}
	fs.close();
	return 0;
}
void calculate(uint x,uint y)
{// calculate one cell with x,y
	switch(p_mas[x][y])
	{
	case 'a':
	case '+':
	case '|':
	case '-':
	case '*':
	break;
	case '0':// only for dry cell
		//-------------------------------------//
		p_coef=0;
		if(p_mas[x][y-1]=='*') // west
			p_coef++;
		if(p_mas[x-1][y-1]=='*')// north-west
			p_coef++;
		if(p_mas[x-1][y]=='*')// north
			p_coef++;
		if(p_mas[x-1][y+1]=='*')// north-east
			p_coef++;
		if(p_mas[x][y+1]=='*')// east
			p_coef++;
		if(p_mas[x+1][y+1]=='*')// south-east
			p_coef++;
		if(p_mas[x+1][y]=='*')// south
			p_coef++;
		if(p_mas[x+1][y-1]=='*')// south-west
			p_coef++;
		//
		// take pseudorandom number in the range 0 to 1.
		// yes here very simple case; in reality,  
		// here must be equation with exp() ; i think so =)
		//
		if((double)rand()/RAND_MAX<p_LeakCoef*p_coef)
				p_mas[x][y]='a';
		//-------------------------------------//
		break;
	default:
		break;
	}
}
#endif

Теперь файл с данными называется pampers.txt. Вот пример каким он может быть:
000000000000000000**********************00000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000

или можете всю первую строчку сделать влажной :) экспериментируйте.
Сразу почему-то вспоминаются эти дурацкие рекламные ролики про памперсы и прокладки ! :-)

Можно сказать, что модель у нас стохастическая, т.е. в ней присутствует элемент случайности.

Пока!

[noonv@volodia noonv]$ logout

XIII

Рейтинг@Mail.ru
Хостинг от uCoz