Prof. MsC. Carlos de Castro
Bem vindos ao minicurso de Octave/Matlab.
GNU Octave é uma linguagem de alto nível, construída inicialmente para computação numérica. Ela provê uma interface de linha de comando para resolver problemas lineares e não lineares numericamente e executa outros experimentos numéricos que são compatíveis com MATLAB.
A imagem a seguir é a interface do MATLAB e OCTAVE.
Acessar Site (lá tem tudo o que precisa saber, para todos os sistemas operacionais).
É o local onde estarão os scripts e funções que você irá desenvolver para o Octave. Você pode alterar a localização da pasta, navegando no gerenciador.
É o local onde onde podemos escrever e executar os programas, funções e fórmulas matemáticas.
No editor é onde você escreve seus scripts e funções, e salva-os na pasta. Esse arquivo salvo terá extensão .m e aparecerá no gerenciador de arquivos (caso você salve lá). Você poderá executar suas funções chamando-as pelo nome na Janela de comandos ou clicando com o botão direito no arquivo, em gerenciador de arquivos, e clicar em Executar.
Para criar um script novo, clique no botão que fica no canto superior esquerdo, com o nome de Novo script |
Essa janela irá aparecer todas as variáveis que estão ativas. Nele você pode ver o nome da variável, a classe (se é char - caractere, double - ponto flutuante real com dupla precisão, int - inteiro, etc), a dimensão ($1\times 3$ - vetor 'deitadinho' de 1 linha e 3 colunas) e o valor.
Nesse ambiente, você poderá ver o histórico de comandos feitos, desde o momento da primeira abertura do programa.
Essa janelinha fica logo abaixo do editor ou da Janela de Comandos. Nela, você consegue trocar entre esses ambientes.
Aqui no Notebook, tanto os scripts, quanto a janela de comando são representadas na mesma célula, como a que vemos abaixo:
x = 3;
sqrt(3)
for i=1:5
x = x**i
end
ans = 1.7321 x = 3 x = 9 x = 729 x = 2.8243e+11 x = 1.7970e+57
Na janela do octave:
Aqui no Jupyter, posso fazer tudo em uma mesma célula:
3+2
x=3;
y=2;
x+y
x+10
10+y
x=3+2;
x
ans = 5 ans = 5 ans = 13 ans = 12 x = 5
Ou podemos fazer separadamente, pra ficar igual à janela de comando.
3+2
ans = 5
x=3;
y=2;
x+y
ans = 5
x+10
ans = 13
10+y
ans = 12
x=3+2;
x
x = 5
Como as células aqui do Jupyter são a mistura do editor de funções com a janela de comando, vamos utilizar apenas uma célula, quando conveniente, a partir de agora. :)
Caso queira rodar o kernel do Octave no Jupyter Notebook, acesse o git: https://github.com/Calysto/octave_kernel e veja como instalar no seu computador. Caso ainda não tenha jupyter, instala o Anaconda por aqui https://anaconda.org/anaconda/jupyter e volta lá no Git do Octave_kernel para instalar.
Perceberam uma coisa interessante? O caractere ;
faz com que você controle o que aparece ou o que não aparece na janela de comando. Vamos fazer um teste.
Na célula a seguir, vou fazer uma soma em looping, ou seja, vou pedir pro octave fazer uma soma de números naturais, de 1 até um n determinado. Para isso, usarei um loop for
, que veremos mais pra frente.
% Aqui eu vou esquecer o ;. O que vai acontecer?
n=15
soma = 0
for i = 1:n
soma = soma + i
end
print = ['A soma de 1 até ' int2str(n) ' é ' int2str(soma) '.']
disp(print)
n = 15 soma = 0 soma = 1 soma = 3 soma = 6 soma = 10 soma = 15 soma = 21 soma = 28 soma = 36 soma = 45 soma = 55 soma = 66 soma = 78 soma = 91 soma = 105 soma = 120 print = A soma de 1 até 15 é 120. A soma de 1 até 15 é 120.
Apareceu um monte de coisa que eu não queria. Como fazer para não aparecer?
n=100;
soma = 0;
for i = 1:n
soma = soma + i;
end
print = ['A soma de 1 até ' int2str(n) ' é ' int2str(soma) '.'];
disp(print)
A soma de 1 até 100 é 5050.
Operação | Símbolo | Exemplo |
---|---|---|
Adição | $+$ | $3$ $+$ $2$ $=$ $5$ |
Subtração | $-$ | $3$ $-$ $2$ $=$ $1$ |
Multiplicação | $\ast$ | $3$ $\ast$ $2$ $=$ $6$ |
Divisão usual | $/$ | $3$ $/$ $2$ $=$ $1.5$ |
Divisão ivertida* | $\setminus$ | $3$ $\setminus$ $2$ $=$ $0.\overline{6}$ |
Potênciação | ^ ou $\ast\ast$ | $3$ ^ $2$ $=$ $9$ |
Módulo (ou resto sob divisão Euclidiana) | mod( $a$,$b$) | mod($3$ ,$2$) $=$ $1$ |
*jajá veremos para que isso serve.
Ao trabalhar com ponto flutuante (double ou float), é possível obter diversas visualizações desses números com o Octave. A seguir, vemos uma lista de alguns formatos possíveis:
Sintaxe | formato | Exemplo($\pi$) |
---|---|---|
format short | precisão simples | 3.1416 |
format long | precisão dupla | 3.14159265358979 |
format short $e$ | precisão simples $e$ | 3.1416e+00 |
format long $e$ | precisão dupla $e$ | 3.14159265358979e+00 |
format hex | Hexadecimal | 400921fb54442d18 |
format bank | 2 casas decimais | 3.14 |
Sintaxe | formato | Exemplo($\approx \pi$) |
---|---|---|
format rat | Quociente | $355/113$ |
Erro relativo | 8.4914$\times 10^{-8}$ |
help sin
'sin' is a built-in function from the file libinterp/corefcn/mappers.cc -- sin (X) Compute the sine for each element of X in radians. See also: asin, sind, sinh. Additional help for built-in functions and operators is available in the online version of the manual. Use the command 'doc <topic>' to search the manual index. Help and information about Octave is also available on the WWW at http://www.octave.org and via the help@octave.org mailing list.
lookfor eigenvalue
eig Compute the eigenvalues (LAMBDA) and optionally the right e igenvectors (V) and the left eigenvectors (W) of a matrix o or a pair of matrices. ordschur Reorders the real Schur factorization (U,S) obtained with t he 'schur' function, so that selected eigenvalues appear in n the upper left diagonal blocks of the quasi triangular Sc chur matrix. qz QZ decomposition of the generalized eigenvalue problem condeig Compute condition numbers of a matrix with respect to eigen values. polyeig Solve the polynomial eigenvalue problem of degree L. eigs Calculate a limited number of eigenvalues and eigenvectors of A, based on a selection criteria.
Clc
e Clear
apagam as informações da Janela de comando e da lista de variáveis no "Ambiente de trabalho", respectivamente.¶comando | resulta em |
---|---|
pi | $\pi$ |
$i$ ou $j$ | se não foi usado como outra variável, $i$ $=$ $j$ $=$ $\sqrt{-1}$ |
eps | Menor número tal que $1+eps>1$. Aqui na minha máquina: $eps=2.2204e-16$ |
realmin | Menor representação em ponto flutuante: $realmin=2^{-1022}$ |
realmax | Maior representação em ponto flutuante: $realmax=2^{1024}$ |
inf | Infinito |
NaN | Not-a-number. Por ex.: $\frac{0}{0}$ |
A construção de matrizes e vetores no Octave já está inclusa na instalação padrão do programa. Na sintaxe, o vetor é representado como um conjunto de números, separados em linhas e colunas, organizados entre []
, de modo que:
` ou vírgula
,` representa números em uma mesma linha da matriz;;
, nesse caso, representa números em diferentes linhas.1) Para construir um vetor linha $x$, basta criar a lista com seus elementos separados por ,
ou por espaço :
x=[1 2 3 4]
x=[1,2,3,4]
x = 1 2 3 4 x = 1 2 3 4
2) Para construir um vetor coluna $y$, basta criar a lista com seus elementos separados por ;
: (não se preocupe, o ponto e vírgula no final do vetor continua existindo).
y=[1;2;3;4]
z=[1;3;2;4];
y = 1 2 3 4
3) Para construir uma matriz $M$ de 3 linhas e 4 colunas, teremos que usar todos os separadores vistos anteriormente:
M = [1 2 3;4,5,6;7,8 9]
%Para deixar mais bonito, sugiro sempre fazer da seguinte forma
M = [1 2 3;
4 5 6;
7 8 9];
M = 1 2 3 4 5 6 7 8 9
Obs: O Octave/Matlab aceita variáveis como entrada das matrizes.
format bank
k=10;
x=sqrt(3)^5;
M = [k k^2 sqrt(k);
x sqrt(x) x/k;
pi 2*pi sin(pi)]
M = 10.00 100.00 3.16 15.59 3.95 1.56 3.14 6.28 0.00
Na Álgebra Linear, Processamento de Sinais, Análise Numérica, etc, é comum utilizar de vetores com uma padronização entre os seus elementos. Essa padronização pode ser obtida de algumas maneiras, especialmente
A sintaxe para criar esses vetores é simples: Se quisermos um vetor $x$, indo de $n\in\mathbb{R}$ até no máximo $m\in\mathbb{R}$, com a distância entre seus elementos $q\in\mathbb{R}$, basta fazermos $$x=[n:q:m].$$
format short
n=0.2
m=0.5
q=1/sqrt(1127.5)
x1=[n:q:m]
n = 0.20000 m = 0.50000 q = 0.029781 x1 = Columns 1 through 8: 0.20000 0.22978 0.25956 0.28934 0.31912 0.34891 0.37869 0.40847 Columns 9 through 11: 0.43825 0.46803 0.49781
Aqui, usaremos a função >>linspace(n, m, N)
, em que $n\in\mathbb{R}$ é o primeiro elemento do vetor, $m\in\mathbb{R}$ é o último elemento do vetor e $N\in \mathbb{N}$ é o número de elementos do vetor.
n=0.2
m=0.5
N=11
x2=linspace(n,m,N)
n = 0.20000 m = 0.50000 N = 11 x2 = Columns 1 through 8: 0.20000 0.23000 0.26000 0.29000 0.32000 0.35000 0.38000 0.41000 Columns 9 through 11: 0.44000 0.47000 0.50000
OBS: Veja que os dois métodos construíram vetores diferentes, com o mesmo número de elementos e determinados o mesmo $n$ e $m$.
format short
erro=norm(x1-x2)
ERRO=x1-x2
erro = 0.0042938 ERRO = Columns 1 through 6: 0.0000000 -0.0002188 -0.0004377 -0.0006565 -0.0008753 -0.0010942 Columns 7 through 11: -0.0013130 -0.0015318 -0.0017507 -0.0019695 -0.0021883
Dada uma matriz $$A=\left(\begin{array}{ccc} m_{11} & m_{12} & m_{13} \\ m_{21} & m_{22} & m_{23} \\ m_{31} & m_{32} & m_{33} \end{array}\right)$$ como podemos acessar os elementos da matriz? Isto é, caso precisamos obter o elemento que se encontra na linha 3
, coluna 2
da matriz, acessamos a partir do Octave.
As sintaxes
para acesso dos elementos de matrizes $(M\in\mathbb{C}^{n\times n})$ e vetores $(v\in\mathbb{C}^n)$, para algum $n\in \mathbb{N}$, no Octave/Matlab é $$M/v(\ell,c),$$ em que $\ell,c\in\mathbb{N}$ são os índices da(o) matriz/vetor. No caso de vetores, a sintaxe pode ser tanto $$v(\ell,1)\text{ ou }v(\ell) \text{ (para o caso de vetor coluna)}$$ ou $$v(1,c)\text{ ou }v(c) \text{ (para o caso de vetor linha)}.$$
Para acessar linhas ou colunas inteiras, ou até partes da matriz, é possível utilizar as sintaxes
:
Voltando à matriz $A$, podemos criar o seguinte esquema:
$$A=\left(\begin{array}{ccc} m_{11} & m_{12} & m_{13} \\ m_{21} & m_{22} & m_{23} \\ m_{31} & m_{32} & m_{33} \end{array}\right)=\left(\begin{array}{ccc} A(1,1) & A(1,2) & A(1,3) \\ A(2,1) & A(2,2) & A(2,3) \\ A(3,1) & A(3,2) & A(3,3) \\ \end{array}\right) = \left(\begin{array}{ccc} \rule{12pt}{.6pt} & A(1,:) & \rule{12pt}{.6pt} \\ \rule{12pt}{.6pt} & A(2,:) & \rule{12pt}{.6pt} \\ \rule{12pt}{.6pt} & A(3,:) & \rule{12pt}{.6pt} \\ \end{array}\right)=\left(\begin{array}{ccc} \rule{.6pt}{12pt} & \rule{.6pt}{12pt} & \rule{.6pt}{12pt} \\ A(:,1) & A(:,2) & A(:,3) \\ \rule{.6pt}{12pt} & \rule{.6pt}{12pt} & \rule{.6pt}{12pt} \\ \end{array}\right).$$Antes de passarmos para operações entre matrizes e vetores, vamos fazer uns exercícios.
Obs: Para excluir uma linha ou coluna de uma matriz, basta fazer $M(:,p) = []$ (para excluir a $p$-ésima coluna da matriz, ou $M(q,:)=[]$ para excluir a $q$-ésima linha.
1) Escolha $m,n\in \mathbb{N}$, $3 \leq m,n \leq 10$ para criar uma matriz aleatória $M\in\mathbb{R}^{m\times n}$.
m = 5; % Mude esse número, se quiser.
n = 5; % Mude esse número, se quiser.
M = rand(m,n); % A função ones é nativa do Octave/Matlab que cria uma matriz em que todos os elementos são iguais a 1
2) Altere a primeira coluna e a primeira linha da matriz por um vetor com números aleatórios de $0$ a $1$ (utilize a função $rand()$).
3) Escolha uma submatriz $M'\in \mathbb{R}^{2\times 2}$ da sua matriz $M$ e substitua por uma matriz de identidade $I_{2\times 2}$ (Use a função eye$(\cdot)$).
% Faça a parte 2 e 3 aqui
4) Altere o elemento da linha $m-2$ e coluna $2$ para o número $NUM=randi(m*n)$ (randi é uma função que devolve um número inteiro aleatório de $0$ a $m\cdot n$).
% Faça a parte 4 aqui
5) Separe sua matriz $M$ em vetores coluna e vetores linha. (por exemplo, se $$M=\left(\begin{array}{ccc} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{array}\right),$$ então teremos os vetores coluna $$c1=\left(\begin{array}{c} 1 \\ 4 \\ 7 \end{array}\right),c2=\left(\begin{array}{c} 2 \\ 5 \\ 8 \end{array}\right)\text{ e } c3=\left(\begin{array}{c} 3 \\ 6 \\ 9 \end{array}\right)$$ e os vetores linha $$\ell1=\left(\begin{array}{ccc} 1 & 2 & 3 \end{array}\right),$$ $$\ell2=\left(\begin{array}{ccc} 4 & 5 & 6 \end{array}\right)\text{ e } $$ $$\ell3=\left(\begin{array}{ccc} 7 & 8 & 9 \end{array}\right).\left. \right)$$
% Faça a parte 5 aqui
Para efetuar operações com matrizes e vetores, é preciso ter um pouco de cuidado. Devemos, aqui, lembrar da álgebra linear antes de sair fazendo produto de vetores e matrizes.
Lembrando que em um espaço vetorial $V$ qualquer definido sobre um corpo $\mathbb{K}$, definimos a soma e o produto por escalar entre os elementos desse espaço, isto é, se $v,w \in V$ e $V$ é um espaço vetorial, então $v+w \in V$ e $\lambda v \in V$, qualquer que seja $\lambda \in \mathbb{K}$. Da mesma forma, o Octave/Matlab não vai saber o que fazer se eu pegar $v \in V$ e $w \in W$, com $V$ e $W$ espaços vetoriais tais que $W\cap V = \emptyset$ e fizer $v+w$ ou $w \cdot v$.
Podemos definir, aqui, algumas operações possíveis entre vetores, matrizes e escalares.
Se $v=(v_1 \ v_2 \ \cdots \ v_n)^T$ e $w=(w_1 \ w_2 \ \cdots \ w_n)^T$ e $\lambda \in \mathbb{C}$:
Produto de Hadamard
e, no Octave, utiliza-se $v.\ast w$).'
, isto é, $v'$.produto interno
pode ser calculado, no matlab, utilizando a função $dot(v,w)$ ou, $v'\ast w$.obs: Se $v\in \mathbb{C}^n$ e $w \in \mathbb{C}^m$ e a operação $\langle v, w \rangle = v^Tw$ resulta em um número real, o que acontece se fizermos $vw^T$? Ainda é possível fazer essa operação, mas o resultará em uma matriz que mora em $\mathbb{C}^{n \times w}.$ Por exemplo: se $v=(1 \ 2 \ 3)^T$ e $w=(4 \ 3 \ 2 \ 1)^T$, então $$vw^T=\left(\begin{array}{cccc} 4 & 3 & 2 & 1 \\ 8 & 6 & 4 & 2 \\ 12 & 9 & 6 & 3 \end{array}\right).$$ Ou seja, se $v=(v_1 \ v_2 \ \cdots \ v_n)^T$ e $w=(w_1 \ w_ 2 \ \cdots \ w_m)^T$, então $$ vw^T=\left(\begin{array}{ccc} \rule{12pt}{.6pt} & v_1w & \rule{12pt}{.6pt} \\ \rule{12pt}{.6pt} & v_2w & \rule{12pt}{.6pt} \\ & \vdots & \\ \rule{12pt}{.6pt} & v_nw & \rule{12pt}{.6pt} \end{array}\right).$$
Vejamos:
v=[1;2;3]; w=[3;2;1];
disp("O produto v'*w = ")
disp(v'*w)
disp("O produto v*w' = ")
disp(v*w')
O produto v'*w = 10 O produto v*w' = 3 2 1 6 4 2 9 6 3
As operações válidas para matrizes são:
Importante: no Octave/Matlab, utiliza-se $\ast$ para o produto entre matrizes e produto matriz-vetor. Percebam que esse produto só está definido se o número de colunas da matriz à esquerda no produto é o mesmo número de linhas da matriz à direita no produto. A comutatividade não é sempre válida
.
1) Considere as matrizes $A \in \mathbb{C}^{3 \times 2}, B \in \mathbb{C}^{2 \times 3}, C \in \mathbb{C}^{3 \times 3}, x \in \mathbb{C}^{2}, y \in \mathbb{C}^{3}\text{ e }z \in \mathbb{C}^{5}.$ Faça:
$ \ \ \ \ \ \ $ a) $AB$. $ \ \ \ $ b) $CA$. $ \ \ \ $ c) $A^TC$. $ \ \ \ $ d) $BC$. $ \ \ \ $ e) $3A^T+\frac{1}{2}B$. $ \ \ \ $ f) $B\odot A^T$. $ \ \ \ $ g) $Ax$. $ \ \ \ \ $ h) $By$. $ \ \ \ \ $ i) $[x^T \ y^T]z$
A=[rand() 2*rand(); sqrt(rand()) sqrt(2*rand()); 1/sin(sqrt(2)) rand/cos(sqrt(2))];
B=inv(A'*A)*A';
C=rand(3);
x=A(:,randi(2));
y=A(randi(3),:)';
z=[B(randi(2),:)';B(:,randi(3))];
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %%
% % % % % % % % % % % % % % % % % % Responda aqui aos exercícios
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %%
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %%
String são caracteres organizados na forma de um vetor. Para criá-la, digitamos os caracteres entre aspas simples (’) ou duplas ("):
O fato de string ser um vetor nos permite o mesmo tratamento que temos feito até o momento. Assim podemos referenciar, adicionar e eliminar elementos da string e criar matrizes de strings.
Vejamos os exemplos a seguir:
nome = "Carlos"
sobrenome='Castro'
idade = '33'
nome = Carlos sobrenome = Castro idade = 33
dados = [nome;sobrenome;idade]
size(dados)
dados = Carlos Castro 33 ans = 3 6
dados = [nome sobrenome idade]
size(dados)
dados = CarlosCastro33 ans = 1 14
% Teste aqui as funçoes, se quiser :)
O sistema linear é uma coleção de equações com uma ou mais variáveis. Um sistema linear, geral, com $m$ equações e $n$ incógnitas é como dado a seguir:
$$\left\{\begin{array}{cll} a_{11}x_1 + a_{12}x_2 + a_{13}x_3 + \cdots + a_{1(n-1)}x_{n-1} & = & b_1 \\ a_{21}x_1 + a_{22}x_2 + a_{23}x_3 + \cdots + a_{2(n-1)}x_{n-1} & = & b_2 \\ a_{31}x_1 + a_{32}x_2 + a_{33}x_3 + \cdots + a_{3(n-1)}x_{n-1} & = & b_3 \\ \vdots & \vdots & \vdots \\ a_{m1}x_1 + a_{m2}x_2 + a_{m3}x_3 + \cdots + a_{m(n-1)}x_{n-1} & = & b_m \end{array}\right.$$Pela definição de produto matriz-vetor, é fácil perceber que o sistema linear acima pode ser representado pelo produto matriz-vetor $Ax=b$, em que
$$A=\left(\begin{array}{cccc} a_{11} & a_{12} & \cdots & a_{1(n-1)} \\ a_{21} & a_{22} & \cdots & a_{2(n-1)} \\ a_{31} & a_{32} & \cdots & a_{3(n-1)} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m1} & a_{m2} & \cdots & a_{m(n-1)} \end{array}\right), x =\left(\begin{array}{c} x_1 \\ x_2 \\ x_3 \\ \vdots \\ x_m \end{array}\right)\text{ e } A=\left(\begin{array}{c} b_1 \\ b_2 \\ b_3 \\ \vdots \\ b_m \end{array}\right)$$Portanto, a solução do sistema linear, quando existe, pode ser obtida isolando o vetor $x$ de um lado da igualdade $Ax=b$. Se $A$ é uma matriz quadrada e inversível, a solução do sistema é dada por $$x=A^{-1}b.$$ No Octave/Matlab, para resolver um sistema linar que tenha solução, basta representa-lo no formato matricial e, utilizar o operador $\setminus$, que vimos anteriormente. Esse operador escolhe a forma mais eficiente de resolver esse sistema.
obs: podíamos, aqui, dizer que para resolver um sistema, bastava encontrar a matriz inversa de $A$, $A^{-1}$ e fazer $x=A^{-1}b$. O Matlab até tem uma função que encontra essa inversa ($inv(A)$, ou simplesmente $A^{-1}$). Mas como encontrar essa inversa é muito caro computacionalmente, e pode levar a erros numéricos de ponto flutuante, existem métodos mais eficientes de se obter a solução de sistemas lineares (como fatoração $QR$, $SVD$ ...). Vejamos...
t=[];
for n=500:200:5000
A=rand(n);
b=rand(n,1);
tic;
x1=A\b;
t1=toc;
tic;
x2=inv(A)*b;
t2=toc;
t=[t;t1 t2];
end
plot([500:200:5000],log(t(:,1)),
[500:200:5000],log(t(:,2)));
legend(['Operador \';'Inversa']);
xlabel('Size'); ylabel('log Time (s)');
Considere o sistema
$$\left\{\begin{array}{cll} x -y + 2z & = & 5 \\ -x + y + -z & = & -3 \\ 3x + 5y + 7z &= & -1 \\ \end{array}\right.$$Observe que é possível representar o sistema de equações acima como uma igualdade entre dois vetore, $$Ax=b,$$ em que $$A= \left(\begin{array}{ccc}1 & -1 & 2 \\ -1 & 1 & -1 \\ 3 & 5 & 7 \end{array}\right), x=\left(\begin{array}{c} x \\ y \\ z\end{array}\right)\text{ e }b= \left(\begin{array}{c}5 \\ -3 \\ -1\end{array}\right).$$
Colocando em variáveis no Octave/Matlab, podemos encontrar a solução $x=\left(\begin{array}{r}-\frac{5}{4} \\ -\frac{9}{4} \\ 2\end{array}\right)$ como segue:
format rat
A = [1 -1 2;
-1 1 -1;
3 5 7];
b=[5;-3;-1];
x = A\b
x = -5/4 -9/4 2
Suponha que queiramos imprimir o gráfico da função $f(x)=\sin{(x)}$. Em nosso primeiro teste, vamos aplicar a função seno no conjunto $\left\{0, \frac{\pi}{2}, \pi, \frac{3\pi}{2}, 2\pi\right\}$. Ao aplicar a função seno em cada um dos pontos desse domínio, obtemos o vetor $ \left\{\sin (0), \sin \left( \frac{\pi}{2}\right), \sin(\pi), \sin\left( \frac{3\pi}{2}\right), \sin(2\pi)\right\}=\{0, 1, -1, 0\}$.
Para imprimirmos esse resultado, utilizaremos a função plot
em sua sintaxe mais simples:
plot(D,f(D))
em que $D$ é o domínio do gráfico e f(D) é a imagem da função, no domínio especificado. Na próxima célula definiremos os conjuntos $D$, o conjunto $FD=\sin(D)$ e plotaremos esse resultado.
D=[0;pi/2;pi;3*pi/2;2*pi];
FD=sin(D);
plot(D,FD)
Note que esse não é exatamente o gráfico do seno que conhecemos, mas sim uma aproximação. O comando plot
liga cada ponto $(x, f (x))$, e como nesse caso só temos 5 pontos, o gráfico terá apenas 5 pontos.
Vamos usar o comando linspace
para criar um vetor com uma quantidade grande o suficientede elementos. Por exemplo, se quisermos um vetor de 50 elementos:
x = linspace(0, 2*pi, 50);
Isso fará com que $x$ seja o vetor que tem $0$ como primeiro, elemento, $2\pi$ como último elemento, e $48$ elementos entre eles. Por fim, criamos o vetor com o seno aplicado a cada elemento de x e o plotamos
y = sin(x);
plot(x, y);
O Octave/Matlab te dá algumas possibilidades de plot 2D. Com a função plot, você poderá plotar mais de um gráfico em uma única janela, ou plotar em subjanelas, adicionar título, legenda, alterar o formato do domínio e imagem, etc. Aqui vamos explorar algumas possibilidades. Fique livre em explorar outras possibilidades.
Caso necessite plotar dois gráficos de um mesmo domínio em uma só janela, com a função plot
é possível. Para isso, basta adicionar mais elementos na função, a ver
plot(D,I1,D,I2,...,D,In)
x=linspace(0,6*pi,100);
plot(x,sin(x),x,cos(x),x,1./(1+x))
Você pode, ainda, utilizar a sintaxe
plot(D,F(D))
hold on
plot(D,G(D))
hold on
plot(D,H(D))
hold off
para plotar diversos gráficos em uma mesma janela.
A sintaxe para criar subplots, ou seja, multiplos plots em diferentes janelas, é
subplot(m,n,p)
em que $m$ é o número de linhas, $n$ é o número de colunas e $p$ é a posição em que o gráfico irá ocupar. Para ilustrar melhor, vamos observar a seguinte imagem (Fonte: http://matlab.izmiran.ru/help/techdoc/ref/subplot.html):
Observe que, o plot nomeado como subplot 221
é o gráfico na posição $p=1$, de um conjunto de gráficos 4 gráficos, em uma "matriz de gráficos" $m\times n$, com $m=n=2$. Confuso? SIM :( Vamos para a prática.
x = [0:0.1:2*pi];
subplot(221); plot(x,sin(x));
subplot(222); plot(x,cos(x));
subplot(223); plot(x,x);
subplot(224); plot(x,x.^2);
x = [0:0.1:2*pi]';
subplot(223); plot(x,sin(x));
subplot(224); plot(x,cos(x));
subplot(2,2,[1 2]); plot(x,sin(x) + cos(x) + cos(x).*sin(x));
Você pode armazenar todos os gráficos que queira imprimir em uma mesma janela em uma matriz e aplicar a função plot
nela:
x=[0:0.1:2*pi]';
A=[sin(x) sin(x+pi/2)];
plot(x,A)
É possível mudar o design dos gráficos. Você poderá alterar as cores das linhas e até o formato da linha (pontilhado, tracejado, etc). A sintaxe pode ser:
plot(D,F(D),'opcao 1','opcao 2', ... , 'opcao n',D, G(D), 'opcao n+1','opcao n+2',...)
em que $D$ é o domínio do seu gráfico, $F(D)/G(D)$ são as imagens, e $'opcao \ k'$ são as opções de design que você escolher.
Algumas das opções podem ser vistas nas tabelas a seguir:
Nome | código | cor |
---|---|---|
Vermelho | 'r' | |
Verde | 'g' | |
Azul | 'b' | |
Ciano | 'c' | |
Magenta | 'm' | |
Amarelo | 'y' | |
Preto | 'k' | |
Branco | 'w' |
É possível, ainda, utilizar a sintaxe
plot(D,FD,'Color',RGB_code)
para utilizar a cor que desejar. Por exemplo:
plot(x,sin(x),'Color',[0.4940 0.1840 0.5560])
Descrição | Código | Resultado |
---|---|---|
Linha sólida (padrão) | '$-$' | |
Tracejado | '$- -$' | |
Pontilhado | ':' | |
Traço e ponto | '$- .$' |
Código | Descrição |
---|---|
'o' | Círculo |
'+' | Sinal de + |
'*' | Asterisco |
'.' | Ponto |
'x' | X |
'_' | Linha horizontal |
'|' | Linha Vertical |
'square' or 's' | Quadrado |
'diamond' or 'd' | Losango |
'^' | Acento circunflexo |
'v' | Letra V |
'>' | Símbolo de maior |
'<' | Símbolo de menor |
'pentagram' or 'p' | Pentagrama |
'hexagram' or 'h' | Hexagrama |
Vamos ver alguns exemplos:
plot(x,sin(x),'g');
hold on;
plot(x,sin(x+pi/8),'.');
hold on;
plot(x,sin(x+2*pi/8),'-');
hold on;
plot(x,sin(x+3*pi/8),'p');
hold on;
plot(x,sin(x+4*pi/8),'-.');
hold on;
plot(x,sin(x+5*pi/8),':','Color','r');
hold on;
plot(x,sin(x+6*pi/8),'<','Color',[214, 85, 135]./255);
hold off;
A função plot tem alguns outros parâmetros que podem ser adicionados à janela do gráfico, como legenda, título, rótulo dos eixos, tamanho, etc. Vejamos alguns desses parâmetros:
plot(D,F(D),D,G(D), ... , D, Z(D));
title('...'); % Título do gráfico
legend(['...',...,'...']); % Legenda dos gráficos que compõe a janela do plot.
xlabel('...'); % Define o rótulo do eixo x
ylabel('...'); % Define o rótulo do eixo y
xlim([a b]); % Define o subdomínio do eixo x a ser exibido no gráfico
ylim([a b]); % Define o subdomínio do eixo y a ser exibido no gráfico
t=[0:1/44100:1]';
y=sin(2*pi*20*t);
z=sin(2*pi*200*t);
subplot(211);
plot(t,y);
hold on;
plot(t,z);
hold off;
title('Osciladores com taxa de amostragem a 44100 Hz');
legend(['20Hz';'200Hz']);
xlim([0 0.05]);
xlabel('t');
% ----------------------------------------------------------------------
y=sin(2*pi*5*t);
z=sin(2*pi*20*t);
subplot(212);
plot(t,y);
hold on;
plot(t,z,':');
hold off;
title('Oscilador com taxa de amostragem a 44100 Hz');
legend(['5 Hz';'20Hz']);
xlim([0 1.2]);
xlabel('t');
Neste módulo, vamos precisar de um pacote para Octave chamado "Symbolic". Nele, poderemos fazer cálculos simbólicos, isto é, utilizar x
como variável. É possível que no Matlab já venha instalado. Caso esteja usando Octave, será necessário fazer algumas instalações antes.
UBUNTU/macOS
Verifique q versão do seu python instalado fazendo
python --version
Caso não tenha o Python3.9 instalado no seu computador faça
sudo apt update
sudo apt install python3.9
Instale o PIP:
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
python3.9 get-pip.py
Instale o Sympy (v. 1.5.1)
pip3.9 install sympy==1.5.1
pkg install -forge symbolic
pkg load symbolic
WINDOWS
Download symbolic-win-py-bundle-2.7.0.zip em https://github.com/cbm755/octsympy/releases
Abra o octave e execute
pkg install symbolic-win-py-bundle-2.7.0.zip
pkg load symbolic
pkg install -forge symbolic
pkg load symbolic
For information about changes from previous versions of the symbolic package, run 'news symbolic'.
O objetivo da matemática simbólica, aqui, é para simularmos a continuidade de funções. Lembre-se que no computador, trabalhamos com matemática discreta. Assim, a definição de limite, derivada e integral, como conhecemos, não se aplica aqui. Por isso é necessário utilizar da simulação de continuidade para efetuarmos os cálculos dessas funções.
Ao instalar com sucesso o pacote de matemática simbólica em seu computador, utilizaremos uma função deste pacote chamada syms
, para declarar a variável que iremos referenciar.
No seu Octave, digite:
syms x;
Symbolic pkg v2.9.0: Python communication link active, SymPy v1.5.1.
Após definirmos nossa função simbólica, podemos definir nossas funções. Para definir a função $f(x)=\sqrt{\frac{1}{x^2+1}}$, fazemos
fx = sqrt(1/(x^2+1))
fx = (sym) ________ ╱ 1 ╱ ────── ╱ 2 ╲╱ x + 1
Para calcularmos o Limite
na função $f(x)$ acima, utilizaremos a função limit
, cuja sintaxe é
limit(fx,x,a)
em que fx
é a função que queremos calcular o limite, x
é a variável a se aplicar esse limite e a
é o escalar tal que $x\to a$. Por exemplo:
limit(fx,x,1)
ans = (sym) √2 ── 2
Para o cálculo da $n$-ésima derivada da função $f(x)$ utilizaremos a função diff
cuja sintaxe é
diff(fx,n)
em que fx
é a função que queremos calcular e n
é o grau da derivada que queremos calcular. No octave, obtemos:
disp('Primeira derivada de f(x)')
disp(diff(fx))
disp('Segunda derivada de f(x)')
disp(diff(fx,2))
disp('7-ésima derivada de f(x)')
disp(diff(fx,7))
Primeira derivada de f(x) ________ ╱ 1 -x⋅ ╱ ────── ╱ 2 ╲╱ x + 1 ───────────────── 2 x + 1 Segunda derivada de f(x) ⎛ 2 ⎞ ________ ⎜ 3⋅x ⎟ ╱ 1 ⎜────── - 1⎟⋅ ╱ ────── ⎜ 2 ⎟ ╱ 2 ⎝x + 1 ⎠ ╲╱ x + 1 ────────────────────────── 2 x + 1 7-ésima derivada de f(x) ⎛ 6 4 2 ⎞ ________ ⎜ 429⋅x 693⋅x 315⋅x ⎟ ╱ 1 315⋅x⋅⎜- ───────── + ───────── - ────── + 35⎟⋅ ╱ ────── ⎜ 3 2 2 ⎟ ╱ 2 ⎜ ⎛ 2 ⎞ ⎛ 2 ⎞ x + 1 ⎟ ╲╱ x + 1 ⎝ ⎝x + 1⎠ ⎝x + 1⎠ ⎠ ─────────────────────────────────────────────────────────── 4 ⎛ 2 ⎞ ⎝x + 1⎠
É possível avaliar o valor das derivadas (e das funções) nos pontos desejados. Para isso, utilizaremos a função subs
, cuja sintaxe é
x=k;
subs(fx)
em que x
é a variável que queremos avaliar, k
é o valor em que substituiremos o $x$ e fx
é a função. Por exemplo:
disp('------------'); disp('');
x=2;
disp('f(2)='); disp(subs(fx)); disp(''); disp('------------'); disp('');
disp('f`(2)='); disp(subs(diff(fx))); disp(''); disp('------------'); disp('');
disp('f```(2)='); disp(subs(diff(fx,3))); disp(''); disp('------------'); disp('');
------------ f(2)= √5 ── 5 ------------ f`(2)= -2⋅√5 ────── 25 ------------ f```(2)= -6⋅√5 ────── 125 ------------
Para calcularmos integrais indefinidas
, devemos usar a função int
, cuja sintaxe é
int(fx)
em que fx
é a função que queremos avaliar. No octave, a integral indefinida da função $$g(x)=\int \ln{x}-x^3 dx$$ fica
syms x;
g=log(x)-x^3;
int(g)
ans = (sym) 4 x - ── + x⋅log(x) - x 4
Para calcularmos integrais definidas
, utilizaremos a mesma função anterior, adicionando os limites de integração na sintaxe. Ou seja, para calcular $$\int\limits_{a}^{b}f(x)dx,$$ utiliza-se a sintaxe
int(fx,a,b)
onde fx
é a função que queremos avaliar, a
é o limite inferior e b
é o limite superior. No octave:
int(g,1,2)
ans = (sym) -19/4 + 2⋅log(2)
Muitas vezes, tem-se a necessidade de visualizarmos as funções que estamos trabalhando. Assim, para plotarmos os gráficos de funções simbólicas, utilizaremos a função ezplot
, cuja sintaxe é
ezplot(fx,DOM)
em que fx
é a função que queremos visualizar e DOM é um vetor linha de 2 variáveis $DOM=[xmin xmax]$, que definirá o domínio da função. No octave:
ezplot(fx,[-2*pi 2*pi])
Um algoritmo é uma sequência finita de ações executáveis, precisos e não ambíguos a fim de obter uma solução para um determinado problema. Já a linguagem de programação traduz um algoritmo (sequência de instruções/ações) da linguagem humana para a linguagem de máquina.
Uma maneira eficiente de projetar um algorítmo é por meio de um pseudo código. Por exemplo, se eu quero escrever um algoritmo que devolve o módulo de um número, em qualquer linguagem de programação, seu pseudo código pode ser escrito da seguinte forma:
Dado um número a
Se a >= 0, então
modulo = a
Senão
modulo=-a
retorna modulo
Em C++, por exemplo, o algorítmo acima poderia ser escrita como uma função, e ficaria assim:
double modulo(double x){
double m;
if (x >= 0){
m = x;
} else {
m = -x;
}
return m;
}
Em Python, por exemplo, esse mesma função ficaria
def modulo(x):
if x>=0:
m = x
else:
m = -x
return m
Cada linguagem de programação tem suas características. No Matlab/Octave, por exemplo, a mesma função acima ficaria:
function m = modulo(x)
if x >= 0
m = x;
else
m = -x;
end
end
m1 = modulo(-2)
m2 = modulo(-2332)
m1 = 2 m2 = 2332
Algumas observações importantes na hora de criarmos nossos algoritmos aqui no Octave/Matlab:
%
é considerado um comentário;...
indica que o comando continua na próxima linha. Tal recurso permite deixar o texto mais organizado;;
(lembra dele?) no final de uma linha de comando. Ele omite na janela de comandos as iterações que serão realizadas (mantém a janela de comando mais limpa e organizada);input
;disp
.tic;
% algoritmo
toc;
Operações lógicas | Descrição |
---|---|
$\sim$ | Negação |
$\vert$ | ... ou ... |
& | ... e ... |
OBS: Operações curto-circuito
expr1 && expr2
representa a operação lógica ... e ...
e aplica um comportamento de curto circuito no código. Isto é, $expr2$ não é avaliada se $expr1$ é falso
.
expr1 || expr2
representa a operação lógica ... ou ...
e aplica um comportamento de curto circuito no código. Isto é, $expr2$ não é avaliada se $expr1$ for verdadeira.
Operações relacionais | Descrição |
---|---|
$==$ | Igual a |
$\sim =$ | Diferente |
$<$ | menor do que |
$>$ | maior do que |
$<=$ | menor ou igual a ($\leq$) |
$>=$ | maior ou igual a ($\geq$) |
O Octave/Matlab possui estruturas que permitem o controle do fluxo de execução de comandos e da ordem em que a computação é feita.
A estrutura FOR
possibilita que um bloco de código seja repetido por um número de vezes fixo e predefinido. Sua sintaxe é:
for variável = início:passo:fim
% comandos
end
1) Faça um algoritmo usando laço FOR que retorne a soma dos números de $1$ a $N$, em que $N$ é dado pelo usuário.
N = input('Digite um número natural: ');
disp(' ')
disp('Método 1 - Laço FOR')
disp(' ')
soma = 0;
tic;
for n = 1:N
soma = soma + n;
end
disp(['A soma de 1 até ' num2str(N) ' é ' num2str(soma)]);
toc;
Digite um número natural:2343 Método 1 - Laço FOR A soma de 1 até 2343 é 2745996 Elapsed time is 0.015285 seconds.
OBS: Laços for nem sempre são a melhor forma de construir um algoritmo, em Matlab/Octave. Vou escrever o mesmo algorimo acima usando vetores e funções nativas. Vamos comparar os tempos.
disp(' ')
disp('Método 2 - vetores e funções nativas')
disp(' ')
tic;
t = [1:N];
soma2 = sum(t);
disp(['A soma de 1 até ' num2str(N) ' é ' num2str(soma)]);
toc;
Método 2 - vetores e funções nativas A soma de 1 até 2343 é 2745996 Elapsed time is 0.0112772 seconds.
A estrutura while é utilizada quando é necessário repetir certo comando de código várias vezes, enquanto uma determinada condição é satisfeita. Geralmente, usa-se while quando não se sabe ao certo a quantidade de passos a serem dados pelo algoritmo. Sintaxe:
while expressão
comandos
end
1) Encontre o menor número $n\in\mathbb{N}\cup\{0\}$ tal que $\frac{1}{2^n} < 10^{-12}$ .
x=1;
n=0;
while x>1e-12
n = n+1;
x = x/2;
end
disp(['Quando n = ' num2str(n) ', a sequência 1/(2^n) chegou a ' num2str(x)]);
Quando n = 40, a sequência 1/(2^n) chegou a 9.0949e-13
2) Encontre o menor número natural tal que $\sqrt[n]{n} < 1 + 10^{-5}$.
format long
n=2;
while n^(1/n) > 1 + 1e-5
n = n + 1;
end
disp(['A sequência n^(1/n) vale ' num2str(n^(1/n)) ' quando n = ' num2str(n)])
A sequência n^(1/n) vale 1 quando n = 1416368
3) Encontre o menor número, maior ou igual a um $N$ fornecido pelo usuário que é múltiplo de $7$.
N = input('Digite um número natural: ');
while rem(N,7) ~= 0
N = N+1;
end
disp([num2str(N) ' é múltiplo de 7.'])
Digite um número natural:2343 2345 é múltiplo de 7.
A estrutura if
é usada para executar um bloco de comandos apenas se uma determinada condição for satisfeita. Sintaxe:
if expressão1
% comandos 1
elseif expressão2
% comandos 2
elseif expressão3
% comandos 3
else
% comandos 4
end
1) Faça um programa que diga se a pessoa é adulta, adolescente, criança ou idosa, com base na idade fornecida. Use o comando While para fazer o usuário digitar uma idade maior do que zero.
idade_correta = false;
while ~idade_correta
idade = input('Informe sua idade: ');
if idade > 0
idade_correta = true;
end
end
if idade < 12
disp('Você é uma criança.')
elseif idade >= 12 & idade < 18
disp('Você é um adolescente.')
elseif idade >= 18 & idade < 65
disp('Você é um adulto.')
else
disp('Você é um idoso')
end
if idade > 150
disp(' ')
disp(' ')
disp(' ')
disp('... Chico Xavier, é você?')
end
Informe sua idade:231 Você é um idoso ... Chico Xavier, é você?
O switch executa uma ação dentre várias opções, dependendo de um parâmetro passado inicialmente, onde cada escolha é um caso. Sintaxe:
switch variável_de_teste
case{caso1}
% comandos1
case{caso2}
% comandos2
case{caso3}
% comandos3
otherwise
% comandos
end
1) Construa um programa onde o usuário digita dois números e indica se irá somá-los, multiplicá-los ou subtraí-los.
n = input('Digite um número: '); m = input('Digite um número: ');
operacao = input('Digite: 1 para somá-los; 2 para subtraí-los; 3 para multiplicá-los. Opção: ');
switch operacao
case{1}
oper='+';
x=n+m;
case{2}
oper='-';
x=n-m;
case{3}
oper='*';
x=m*n;
otherwise
x=NaN;
disp('Essa não é uma operação válida')
end
if x ~= NaN
disp([num2str(n) oper num2str(m) '=' num2str(x)])
end
Digite um número:12 Digite um número:12 Digite: 1 para somá-los; 2 para subtraí-los; 3 para multiplicá-los. Opção:1 12+12=24
Muitas vezes não será necessário criarmos uma nova função, pois o Octave/MATLAB já nos traz uma grande biblioteca de funções pré-definidas. Por exemplo: se quisermos calcular o fatorial de um número $n$, não é necessário criar uma nova função para isso, basta usarmos a função
factorial(n).
Algumas funções pré-definidas no Octave/MATLAB:
Função | Descrição |
---|---|
factorial($n$) | Retorna o fatorial de $n$ |
$\sin(n)$ | Retorna o seno de $n$ |
$sqrt(n)$ | Retorna a raíz quadrada de um número $n$ |
gcd($n$,$m$) | Retorna o maior divisor comum entre $n$ e $m$ |
rem($n$,$m$) | Retorna o resto de divisao de $n$ por $m$ |
Muitas vezes queremos criar funções que ainda não estão na biblioteca virtual do Octave/MATLAB. Para isso temos o comando $function$, que obedece a seguinte sintaxe:
function[saida] = nomedafuncao(entrada)
% Comentário da função, que aparecerá quando fizer '>>> help nomedafuncao'
<comandos>
end
Dados dois números, queremos uma função que nos retorne a soma e o produto dos dois. Vamos utilizar o function:
function [s,p] = somaprod(a,b)
% Função que retorna a soma e o produto de dois números dados.
s = a + b;
p = a*b;
end
Agora basta salvar o arquivo como somaprod.m
. Para executar a função, basta digitarmos no Octave/MatLab que o propgrama irá retornar os vaores de soma e produto. Vale lembrar que, quando uma função retorna 2 ou mais valores, é possível solicitar apenas um deles, como veremos na célula abaixo.
disp('Imprimindo os dois valores:')
[a,b]=somaprod(11,12)
disp(' ')
disp('Imprimindo o primeiro valor')
c = somaprod(11,12)
disp(' ')
disp('Imprimindo o segundo valor')
[~,d]=somaprod(11,12)
disp(' ')
disp('Pedindo help da função')
help somaprod
Imprimindo os dois valores: a = 23 b = 132 Imprimindo o primeiro valor c = 23 Imprimindo o segundo valor d = 132 Pedindo help da função 'somaprod' is a command-line function Função que retorna a soma e o produto de dois números dados. Additional help for built-in functions and operators is available in the online version of the manual. Use the command 'doc <topic>' to search the manual index. Help and information about Octave is also available on the WWW at http://www.octave.org and via the help@octave.org mailing list.