Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Красавин Компютерныы практикум в среде МатЛаб 2015

.pdf
Скачиваний:
121
Добавлен:
12.11.2022
Размер:
9.22 Mб
Скачать

разреженных матриц, т.е., например, операция A+B, где A и B – разреженные матрицы, даст в результате также разреженную матрицу. Если одна из матриц – полная, то в результате может получиться как разреженная, так и полная матрица в зависимости от типа выполняемой операции. В табл. 20.1 показаны типы результирующей матрицы при различных операциях с разреженными матрицами; R означает разреженную матрицу, F – полную.

Таблица 20.1

Тип результата при выполнении операций с разреженными матрицами

R+R

R

R+F

F

R–R

R

R–F

F

R*R

R

R*F

F

R.*R

R

R.*F

R

R./R

R

R./F

R

Функция spdiags является аналогом функции diag для разреженных матриц и позволяет формировать разреженные матрицы с заданными диагоналями или выделять диагонали из разреженных матриц. Например, для матрицы A

A = [0 1 0 2 0 0; 0 0 3 0 4 0; 5 0 0 6 0 7;...

8 9 0 0 10 0; 0 11 12 0 0 13];

A =

0

1

0

2

0

0

0

0

3

0

4

0

5

0

0

6

0

7

8

9

0

0

10

0

0

11

12

0

0

13

команда

[B, d] = spdiags(A)

231

сформирует матрицу B, состояющую из столбцов, содержащих диагонали матрицы А, и вектор d, содержащий позиции этих диагоналей в матрице:

B =

0

0

1

2

0

0

3

4

0

5

6

7

8

9

10

0

11

12

13

0

d =

-3 -2 1 3

Позиции диагоналей в матрице показаны на рис. 20.3. Для диагоналей, лежащих под главной диагональю, значения элементов добавляются в конец соответствующего столбца матрицы B, а для диагоналей, лежащих над главной диагональю, – в начало соответствующего столбца.

Рис. 20.3. Позиции диагоналей в матрице

232

Функция speye(m,n) создает единичную матрицу размера в разреженном виде.

Функция full выполняет преобразование разреженной матрицы в полную.

Функция find выполняет поиск ненулевых элементов в матрице:

[i,j,x] = find(A); % такое обращение к функции find с тремя выходными параметрами приводит к созданию двух векторов индексов и вектора, содержащего значения ненулевых элементов

i =

4

1

4

5

2

5

1

3

 

2

4

3

5

 

3

 

 

j =

1

2

2

2

3

3

4

4

 

5

5

6

6

 

1

 

 

x =

8

1

9

11

 

3

12

2

6

4

 

10

7

13

5

 

 

Функция spconvert выполняет преобразование полной матрицы в разреженную на основе матрицы, содержащей три столбца: два столбца индексов и столбец значений. Следующие две команды эквивалентны:

A = spconvert(x);

A = sparse(x(:,1),x(:,2),x(:,3)); % эта команда аналогична предыдущей

Если матрица x содержит четыре столбца, то два последних столбца используются как массивы значений, а матрица A получается комплексной; значения реальной части элементов берутся из третьего столбца x, мнимой части – из четвертого столбца.

Функция nnz возвращает число ненулевых элементов матрицы:

233

nnz(A)

ans = 13

Функция spfun используется для вычисления функций от ненулевых элементов матрицы. Функция имеет следующий формат: С = spfun(@f,A), где f – функция. Значения функции будут вычислены только от ненулевых элементов матрицы А:

C(i,j)=f(A(i,j)). Например,

CN = spfun(@cos,A)

CN =

0.2837

(3,1)

(4,1)

-0.1455

(1,2)

0.5403

(4,2)

-0.9111

(5,2)

0.0044

(2,3)

-0.9900

(5,3)

0.8439

(1,4)

-0.4161

(3,4)

0.9602

(2,5)

-0.6536

(4,5)

-0.8391

(3,6)

0.7539

(5,6)

0.9074

Функция eigs вычисляет собственные значения матрицы и оптимизирована для работы с разреженными матрицами. Она уже использовалась при вычислении энергии частицы в потенциальной яме (см. гл. 14).

Задание

20.1. Переписать алгоритмы из главы о частице в потенциальной яме, использовав трехдиагональные разреженные матрицы.

234

21

Фракталы. Рекурсия

21.1. Рекурсивные функции

Термин «рекурсия» означает «что-то, определяемое в терминах самого себя». В программировании рекурсивной называется функция, вызывающая саму себя.

Классическим примером рекурсии является рекурсивное определение факториала целого числа:

!

·

1 ! –общийслучай;

Такое определение

1!

1 –частный случай.

 

факториала является рекурсивным, потому что

факториал определяется в терминах другого факториала. В рекурсивном определении любого объекта всегда присутствуют общий и частный случаи. В общем случае факториал числа равен

числу , умноженному на факториал числа

 

. В частном

случае факториал числа

 

равен

. Достижение

частного случая

 

1

 

останавливает рекурсию.

Например,

 

 

1

 

1

 

 

3! 3·2!

2! 2·1!

1! 1

Вычисление 3! невозможно без вычисления 2!; вычисление 2! невозможно без вычисления 1!; вычисление 1! – частный случай, результат равен 1. После достижения частного случая вычисления разворачиваются в обратном порядке: зная 1!, можно найти 2!, а зная 2!, можно найти 3!.

235

При организации рекурсии необходимо обеспечить, чтобы частный случай рано или поздно был реализован, иначе рекурсия будет бесконечной. В примере 21.1 приведен код программы, вычисляющей факториал методом рекурсии.

Пример 21.1.

function facn = fact(n)

if n == 1 facn = 1;

else

facn = n * facn(n-1);

end end

Программа в примере 21.1 работает следующим образом. Пусть снова требуется вычислить 3!. При первом обращении к функции происходит попытка присвоить переменной facn результат вычисления 3 * facn(2). Однако значение facn(2) в этот момент не определено, и вычисление прерывается рекурсивным обращением к функции facn для вычисления facn(2). При этом обращении делается попытка вычисления значения 2 * facn(1). Но значение facn(1) в этот момент также не определено, и вычисление прерывается рекурсивным обращением к функции facn для вычисления facn(1). При этом обращении реализуется ветвь if конструкции if-else, и рекурсия достигает частного случая. Вычисляется значение facn(1), далее оно передается в процесс, ожидающий вычисления facn(2), которое, в свою очередь, передается в процесс, ожидающий вычисления facn(3).

В примере 21.2 рассматривается применение рекурсивной функции для перестановки слов в предложении в обратном порядке.

Пример 21.2.

function reverse_words(sent)

% sent – исходное предложение

236

[word, rest] = strtok(sent); % функция strtok разбивает входной аргумент на две части: первое слово записывается в переменную word, а оставшийся текст – в переменную rest

if ~isempty(rest) % если переменная rest не является пустым

массивом,

происходит

рекурсивное

обращение

к

функции;

когда

в

переменной rest не остается слов,

наступает частный случай, и рекурсия

останавливается

 

 

 

reverse_words(rest);

 

 

 

 

end

 

 

 

 

disp(word) % вывод на экран слова,

содержащегося в

переменной

word; первым будет выведено последнее слово в предложении, так как именно на нем останавливается рекурсия

end

% Пример работы функции

reverse_words('Маша любит кашу')

кашу

любит

Маша

Рекурсивные функции часто используются при построении фрактальных объектов.

21.2. Ковер Серпинского

Ковер Серпинского является фрактальным объектом с размерностью 1.585 [5]. Метод построения ковра достаточно простой. В качестве начального множества выберем равносторонний треугольник . Удалим внутренность центральной треугольной части и обозначим оставшееся множество . Затем повторим описанный процесс для каждого из трех оставшихся треугольников и получим следующее приближение . Продолжая таким же образом, получим

237

последовательность множеств

, которая и образует ковер

Серпинского (рис. 21.1).

 

Рис. 21.1. Построение ковра Серпинского

Для построения ковра Серпинского можно использовать следующий алгоритм.

1.

Задать порядок ковра .

 

 

 

 

 

2.

Задать координаты вершин исходного треугольника

3.

Построить: ,

равносторонний, , , ,

треугольник.

и залить его

 

черным цветом.

 

 

 

 

 

4.

Вычислить координаты середин сторон треугольника

:

 

 

2

;

2

;

 

 

 

 

 

238

;

;

 

 

 

 

 

 

2

;

;

 

 

 

 

;

 

.

 

Построить треугольник2

 

5.

 

 

и залить его белым цветом.

6.

Повторить

раз действия

в пунктах 4 и 5 для

 

треугольников

,

 

 

,

соответственно.

Алгоритм можно реализовать с использованием рекурсивной процедуры, выполняющей последовательность действий, описанную в пп. 4 и 5. Полный код программы [4] приведен в примере 21.2.

Пример 21.2.

function z = Serpinsky(Lmax)

%Lmax - порядок ковра

%задание координат вершин равнобедренного треугольника x1=0;

y1=0;

x2=1;

y2=0;

x3=0.5;

y3=sin(pi/3);

h=figure(1); % инициализация графического окна hold on

fill([x1 x2 x3],[y1 y2 y3],'k'); % прорисовка равностороннего треугольника и заливка его черным цветом; функция fill закрашивает многоугольник, определяемый векторами координат x и y

set(gca,'xtick',[],'ytick',[]); % отключение режима оцифровки осей set(gca,'XColor','w','YColor','w'); % установка цвета рисования

осей

% обращение к функции, прорисовывающей равносторонние треугольники белого цвета

239

Simplex(x1,y1,x2,y2,x3,y3,0,Lmax); hold off %

function z=Simplex(x1,y1,x2,y2,x3,y3,n,Lmax)

if n < Lmax % условие достижения рекурсией частного случая

%задание координат вершин текущего равностороннего треугольника dx=(x2-x1)/2;

dy=(y3-y1)/2; x1n=x1+dx; y1n=y1; x2n=x1+dx+dx/2; y2n=y1+dy; x3n=x1+dx/2; y3n=y1+dy;

%прорисовка текущего равностороннего треугольника

n=n+1;

fill([x1n x2n x3n],[y1n y2n y3n],'w');

%применение функции Simplex к треугольнику c вершинами

%(Xa',Ya); (Xa',Ya); (Xc',Yc') Simplex(x1,y1,x1n,y1n,x3n,y3n,n,Lmax);

%применение функции Simplex к треугольнику c вершинами

%(Xa',Ya); (Xb',Yb'); (Xb',Yb') Simplex(x1n,y1n,x2,y2,x2n,y2n,n,Lmax);

%применение функции Simplex к треугольнику c вершинами

%(Xc',Yc'); (Xb',Yb'); (Xc,Yc) Simplex(x3n,y3n,x2n,y2n,x3,y3,n,Lmax);

end

21.3. Губка Менгера

Губка Менгера является объемным аналогом ковра Серпинского. Принципиально схема построения губки не отличается от схемы построения ковра, разница состоит лишь в числе итераций на каждом уровне. Пример 21.3 содержит код, реализующий построение губки и ее заливку различными цветами

(рис. 21.2).

240

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]