Laboratório de Sistemas e Sinais
Máquinas de Estados
Luı́s Caldas de Oliveira
Março 2009
As máquinas de estados são sequenciais: começam num estado inicial, e reagem aos valores de entrada transitando sequencialmente entre estados. A realização de máquinas de estados em software é razoavelmente simples.
Neste laboratório, exploraremos a sua construção e progrediremos até à realização de uma implementação que faça
a composição de duas máquinas de estados.
1 Introdução
1.1
Cadeias de caracteres em Matlab
As máquinas de estados operam sobre sequências de sı́mbolos de um alfabeto. Por vezes esse alfabeto é
numérico mas, no caso mais geral, é um conjunto de elementos com nomes arbitrários. Por exemplo, a entrada
para uma máquina que funcione como um gravador de chamadas será:
Entradas = {toca, atende, fimdasaudacão, fimdamensagem, nulo}
Cada elemento do conjunto anterior pode ser representado em Matlab como uma cadeia de caracteres (help
strings). As cadeias de caracteres são delimitadas por plicas. Por exemplo:
>> x = ’toca’;
A própria cadeia de caracteres é uma matriz de caracteres, sendo assim é possı́vel indexar os caracteres individuais
>> x (1:3)
ans =
toc
Podem-se juntar cadeias de caracteres tal como matrizes normais,
>> y = ’o’;
>> z = ’sino’;
>> [x, y, z]
ans =
tocaosino
Isto pode não ser necessariamente o que é pretendido. Pode-se querer construir uma matriz de cadeias de
caracteres em que cada elemento é ele próprio uma cadeia de caracteres (em vez de um só caracter). Esse objecto
pode ser representado em Matlab como um cell array,
>> c = {’toca’, ’atende’, ’fim da saudação’, ’fim da mensagem’, ’nulo’}
Notar as chavetas em vez dos parenteses rectos habituais. Um cell array em Matlab é uma matriz em que os
seus elementos são objectos Matlab arbitrários (tais como cadeias de caracteres e matrizes). Os cell arrays podem
ser indexados tal como os vectores normais
1
>> c(1)
ans =
’toca’
Pretende-se muitas vezes testar uma cadeia de caracteres para saber se é igual a outra cadeia. O operador ==
não pode ser usado na comparação de cadeias de caracteres ou em células de um cell array,
>> c = ’toca’;
>> if (c == ’atende’) result = 1; end
??? Error using ==> ==
Array dimensions must match for binary array op.
>> c = {’toca’, ’atende’, ’fim da saudação’, ’fim da mensagem’, ’nulo’}
??? Error using ==> ==
Function ’==’ not defined for cariables of class ’cell’
As cadeias de caracteres devem ser comparadas usando strcmp ou switch (ver a ajuda on-line destes
comandos).
>> c = {’toca’, ’atende’, ’fim da saudação’, ’fim da mensagem’, ’nulo’}
1.2
Ficheiros de comandos
Em Matlab podem-se guardar programas em ficheiros que se mandam executar a partir da linha de comandos.
A um ficheiro de comandos deste tipo dá-se o nome de m-file, e tem um nome na forma comando.m em que
comando é o nome do comando a introduzir na linha de comandos para executar o programa.
Pode-se usar um qualquer editor de texto para criar e editar uma m-file mas o Matlab inclui ele próprio um
editor. Para chamar esse editor selecciona-se New e M-file do menu File do Matlab.
Para executar o programa, o Matlab precisa de saber onde encontrar o novo ficheiro de comandos. O modo
mais simples de resolver isto é guardar o ficheiro na directoria corrente do Matlab. Por exemplo, se os ficheiros de
comandos estão na directoria
D:\home\lco
poderá utilizá-los fazendo
>> cd D:\home\lco
>> pwd
ans =
D:\home\lco
O comando cd faz com que o Matlab altere a directoria de trabalho. O comando pwd retorna a directoria de
trabalho actual (a mnemónica é present working directory).
O Matlab pode procurar a presença de m-files numa sequência de directorias usando o comando path. Por
exemplo, em vez de mudar a directoria corrente, poderı́amos ter usado o seguinte,
>> path(path, ’D:\home\lco’);
Este comando indica ao Matlab que deverá procurar os ficheiros de comandos onde já procurava anteriormente
(o primeiro argumento path) e na nova directoria.
Supondo que se cria um ficheiro ola.m contendo,
% OLA - diz olá.
disp(’Olá’)
2
A primeira linha é um comentário. O comando disp imprime o seu argumento no ecrã sem mostrar o nome
da variável. Se se escrever o seguinte na linha de comandos,
>> ola
Olá
Nos nomes dos comandos podem-se trocar as letras minúsculas por maiúsculas, ou seja, OLA e ola são a
mesma coisa. O comentário no inı́cio do ficheiro é usado pelo comando help do Matlab.
>> help ola
OLA - diz olá.
O comando ola anterior corresponde a um programa e não a uma função, pois não existe valor de retorno.
Para definir uma função é necessário incluir o comando function no ficheiro. Por exemplo, se o ficheiro
reverse.m contiver:
function result = reverse(argument)
% REVERSE - retorna o array passado como argumento invertido
result = argument (length(argument):-1:1);
podemos fazer
>> reverse(’olá’)
ans =
álo
O valor retornado são os caracteres da cadeia passada como argumento em ordem inversa.
Uma função pode ter qualquer número de argumentos e valores de retorno. Para definir uma função com dois
argumentos e dois valores de retorno pode-se usar
function [res1, res2] = fun(arg1, arg2)
os valores de res1 e res2 são atribuı́do dentro do ficheiro. Para usar esta função podemos atribuir os valores
de retorno a duas variáveis diferentes,
[r1, r2] = fun(a1, a2)
Os nomes dos argumentos e das variáveis de retorno são arbitrários
2 Trabalho para os alunos
1. Considere o seguinte cell array
cellarray = {’a’, ’b’, ’a’, ’a’, ’b’}
(a) Execute a seguinte sequência de comandos:
n = 0
for e = cellarray
if strcmp(e,’a’) n = n + 1;
end
end
(b) Em seguida, defina uma função conta que conte as ocorrências do caracter a em qualquer argumento.
(c) Quantas ocorrências do caracter a existem em x e em y? Por que são diferentes?
>> x = [’a’, ’b’, ’c’, ’a’, ’aa’]
>> y = {’a’, ’b’, ’c’, ’a’, ’aa’}
(d) Modifique o comando anterior para que receba dois argumentos em que o primeiro é o caracter cujo
número de ocorrências se pretende contar no segundo argumento.
3
{0}/0
{1}/1
{1}/0
{0}/1
0
1
Entradas = {0, 1, nulo}
Saı́das = {0, 1, nulo}
Figura 1: Máquina de estados.
2. A função input pode ser usada para pedir interactivamente dados ao utilizador.
(a) Crie e execute um ficheiro de comandos Matlab com o seguinte conteúdo:
% Cumprimenta o utilizador
while 1
resp = input(’Como te chamas? ’, ’s’);
if (strcmp(resp, ’sair’)|strcmp(resp, ’’))
break;
end
disp([’Olá ’ resp])
end
(b) Escreva um programa que pede ao utilizador uma cadeia de caracteres e que usa a função conta para
devolver o número de ocorrências de a nessa cadeia.
3. Considere a máquina de estados da figura 1.
(a) Construa uma m-file contendo uma definição da sua função de actualizacão. Verifique se corresponde
ao diagrama apresentado.
% The next result is 0 or 1.
function [proximo, saida] = actualiza(estado, entrada)
%
switch estado
case ’0’
switch entrada
case ’0’
proximo = ’0’;
saida = ’0’;
case ’1’
proximo = ’1’;
saida = ’0’;
otherwise
proximo = estado;
saida = ’nulo’;
end
case ’1’
switch entrada
case ’0’
proximo = ’0’;
saida = ’1’;
case ’1’
proximo = ’1’;
saida = ’1’;
4
otherwise
proximo = estado;
saida = ’nulo’;
end
end
(b) Em seguida, crie um programa que solicite ao utilizador uma entrada e, se esta estiver no alfabeto da
máquina, que reaja ao seu valor, voltando a solicitar uma nova entrada. Se a entrada não pertencer ao
alfabeto da máquina, o programa deverá assumir que a entrada é nulo e não deverá mudar de estado
(stutter). Verifique que a sua função de actualização tem em consideração a entrada nulo.
4. Projecte um animal de estimação virtual1 , neste caso um gato, construindo uma máquina de estados, escrevendo uma função actualizacão, e escrevendo um programa para executar repetidamente essa função. O
gato virtual deverá ter o seguinte comportamento:
O gato começa por estar feliz. Se lhe fizerem festas ele ronrona. Se lhe derem comida ele
vomita. Com o passar do tempo, ele fica com fome e roça-se nas pernas das pessoas. Se lhe derem
comida quando está com fome ele ronrona e fica feliz. Se lhe fizerem festas quando tem fome, ele
morde. Se o tempo passar enquanto ele está com fome, ele morre.
(a) Crie uma função de actualização para o seu gato virtual em que as palavras em itálico na descrição
anterior devem ser elementos ou do espaço de estados ou dos alfabetos de entrada ou de saı́da. Apresente os alfabetos de entrada e de saı́da e bem como o diagrama da transição de estados. Escreva um
programa para executar a máquina de estados até que o utilizador escreva sair.
(b) Construa uma máquina de estados que produza entradas para o seu gato virtual de modo que o gato
nunca morra. Essa máquina de estados deverá gerar saı́das tempo e comida de tal maneira que o gato
nunca alcança o estado de morre.
Repare que esta máquina de estados não tem entradas particularmente significativas. O alfabeto de
entrada poderá ser
Entradas = {1, nulo}
onde uma entrada de 1 significa que a máquina deverá produzir uma saı́da não-nula, e uma entrada
nulo deverá produzir uma saı́da nula.
(c) Escreva um programa onde sua máquina de estados alimentadora seja composta em cascata com sua
máquina de estados do gato virtual, e verifique que o gato não morre. A máquina de estados deve
permitir a passagem do tempo (produzindo um número infinito de saı́das tempo) mas deve ser tão
simples quanto possı́vel.
Um dos objectivos principais deste exercı́cio é o de mostrar que as máquinas de estado sistematicamente construı́das podem ser compostas com facilidade.
A máquina de estados alimentadora pode ser considerada um controlador em cadeia aberta porque
controla o animal de estimação virtual sem observar a sua saı́da. No entanto, na maioria dos sistemas
práticos, não é possı́vel projectar um controlador em cadeia aberta. O laboratório seguinte explorará os
controladores em cadeia fechada.
1 Este
problema inspirou-se no jogo Tamagotchi feito por Bandai em Japão. Tamagotchi pode ser traduzido por “pequeno ovo” foi extremamente popular no final dos anos 90 e tinha um comportamento consideravelmente mais complexo do que o descrito neste exercı́cio.
5
Download

Laborat´orio de Sistemas e Sinais Máquinas de Estados