Changes

Jump to navigation Jump to search
9,105 bytes added ,  00:40, 27 May 2016
<math>2^{2^{3}}</math>
 
Nesta seção, vamos olhar para Problemas 2 e 6 da seção de computações e explorações do texto, e ver como podemos usar Maple para resolver alguns deles.
 
Construa a tabela da função booleana de grau 3.
'''Solução'''
 
Primeiro, nós devemos notar que existem <math>2^{2^{3}}</math> funções booleana de grau 3, então a saída da nossa computação será longa. Podemos usar a função '''SumOfProductExpansion''' que desenvolvemos anteriormente para nos ajudar com esse cálculo. Lembre que a expansão da soma dos produtos, ou forma normal disjuntiva, da função booleana dará uma correspondência bijetiva entre funções booleanas e certas expressões booleanas.
 
Embora haja um número infinito de expressões booleanas, há precisamente <math>2^{2^{n}}</math> formas normais disjuntivas com n variáveis, e elas estão em bijetiva correspondência com o conjunto de todas as funções boolenas de n variáveis, portanto essa é a conveniente representação de uso.
Para gerar a lista inteira nós precisamos especificar todas as possibilidades distintas de listas de argumentos de '''SumOfProductsExpansion'''. Isso significa que nós devemos gerar o subconjunto do domínio de todas as funções boolenas de três variáveis. Agora, a função booleana f de três variáveis tem domínio igual a
<pre>Dom3 := [false,false,false],
[false,false,true],
[false,true,false],
[true,false,false],
[true,false,true],
[true,true,false],
[false,true,true],
[true,true,true];</pre>
Podemos gerar esse subconjunto usando o procedimento '''powerset''' no pacote '''combinat'''. Portanto, devemos primeiro carregar o pacote '''combinat'''.
<pre>with(combinat):</pre>
Note o formulário de saída. Nós obtemos o conjunto dos conjuntos, enquanto nosso procedimento '''SumOfProductsExpansion''' requer uma expressão sequência de listas booleanas. Isso significa que precisamos usar a função '''op''' do Maple também. Agora podemos gerar a lista de funções booleanas em três variáveis usando um loop de '''for''' simples: Você pode querer escrever a saída para um arquivo para ter melhores condições de examiná-lo. Você pode fazer isso usando a função '''printf''' no lugar de '''print'''. Alternativamente, você pode usar as funções '''writeto''' ou '''appendto''' para redirecionar a saída Maple para um arquivo. Assim que estiver pronto, você pode restaurar a saída do terminal, emitindo a chamada
<pre>writeto(terminal);</pre>
Use a facilidade help do Maple para saber mais sobre essas funções, se necessário.
 
Randomicamente, gere dez expressões de grau 4 e determine a média do número de passos para minimizá-los.
 
'''Solução'''
 
Há realmente duas partes para este problema: Primeiro, precisamos encontrar uma maneira de gerar expressões booleanas aleatórias. Em segundo lugar, temos de encontrar algum método de examinar o processo de minimização para que possamos contar os passos.
Maple oferece uma solução fácil para a primeira parte do problema. No pacote '''logic''', existe um procedimento chamado '''randbool''' que gera uma expressão booleana aleatória. Uma vez que é parte do pacote de lógica, ele poderá ser definido antes de ser utilizado.
<pre>with(logic):</pre>
Para usar '''randbool''', você precisa especificar um alfabeto sobre o qual construir expressões booleanas. Por exemplo, para gerar uma expressão booleana aleatória no símbolos '''a''' e '''b''', você pode digitar
<pre>randbool(a,b);</pre>
ou
<pre>randbool([a,b]);</pre>
Ou seja, o alfabeto pode ser especificado como um conjunto ou como uma lista. Note que os resultados das duas chamadas acima são diferentes - as expressões são geradas randomicamente. (Isso é verdade mesmo após o '''restart'''. Você pode tentar isso também, mas não se esqueça de carregar o pacote '''logic''' novamente). Agora, para gerar dez expressões booleanas aleatórias, podemos simplesmente usar um “loop” '''for''':
<pre>for i from 1 to 10 do
randbool(a,b);
od;</pre>
Note também que as expressões são gerados na forma normal disjuntiva, isto é, uma soma de produtos de expansão. Também é possível especificar um segundo argumento '''randbool''' de que afeta a forma das expressões geradas. O segundo argumento pode ser qualquer um entre os valores '''DNF''', '''CNF''' ou '''MOD2''', assim como o procedimento '''canon''' que nos conhecemos antes.
<pre>randbool(x,y,z, CNF);
randbool(u,v, MOD2);</pre>
Tendo resolvido a primeira parte do problema, precisamos encontrar uma maneira de contar o número de passos dados durante o processo de minimização. Existem três abordagens que podemos tomar para esta parte do problema.
A primeira é a de medir o tempo necessário para executar um procedimento. Você já viu isso antes em capítulos anteriores.
O segundo é a facilidade de rastreamento para monitorar o número de passos dados para executar uma minimização. Você pode rastrear um procedimento de bordo emitindo a chamada
<pre>readlib(trace);</pre>
Agora, se gerarmos um expressão aleatória booleana com quatro variáveis
<pre>e := randbool(a,b,c,d);</pre>
poderemos observar o número de passos necessários para simplificá-lo simplesmente chamando '''bsimp''' depois de rastreá-lo
<pre>bsimp(e);</pre>
O traçado de '''bsimp''' irá imprimir uma série de declarações do formulário B: = < algo >, que você pode contar. Nós não os temos mostrado aqui.
O procedimento '''trace''' na verdade faz com que a execução de '''bsimp''' para imprimir mais informações do que precisamos. Algumas dessas informações podem ser ignorados para este problema. Cada instrução executada é impressa, como são os argumentos e valores de retorno de qualquer sub-rotinas chamadas. Nós queremos apenas contar o número de instruções executadas, de modo que a outra informação pode ser simplesmente ignorada.
Para anular o efeito do procedimento '''trace''', você pode desfazer a função '''trace''' simplesmente com o procedimento '''untrace''':
<pre>untrace(bsimp); # 'bsimp' deixará de ser rastreada</pre>
Finalmente, para obter o máximo de informações, podemos definir a variável '''printlevel'''. A variável '''printlevel''' é um pouco confusa, ou seja, não se sabe se ela é global ou local. Como qualquer variável global, é visível no nível superior do Maple. No entanto, o seu valor é alterado cada vez que entra em uma estrutura de controle, como um loop, ou no corpo do procedimento e, em seguida, reseta para seu valor original depois de sair da estrutura. Normalmente, '''printlevel''' é definido como 1.
<pre>Printlevel;</pre>
Mas é possível atribuir um valor a '''printlevel''' que afetará o quanto é impresso dentro das estruturas de controle.
<pre>for i from 1 to 5 do
sqrt(i);
od;</pre>
Experimente o ciclo anterior depois de definir o valor de '''printlevel''' para algo como 16. Cada nível aninhado de invocação do procedimento '''printlevel''' é decrementado por 5. Assim, a criação '''printlevel''' a 6 no nível superior é muito parecido com o rastreamento (usando '''trace''') de todos os procedimentos do Maple.
Para fazer Maple mostrar o que se está fazendo a ainda maiores níveis de chamadas de função, simplesmente defina '''printlevel''' para um valor alto.
<pre>for i from 1 to 5 do
sqrt(sin(abs(i)));
od;</pre>
Por razões tipográficas, a volumosa produção foi suprimida neste manual impresso, mas você pode ver os resultados espetaculares na tela do computador. Tente fazer esse último exemplo com '''printlevel''' definindo um valor muito grande como 100000.
Agora, para realmente ver o que está acontecendo quando você invocar '''bsimp''' para minimizar a expressão booleana, você pode definir '''printlevel''' a um enorme valor, e observar os resultados.
<pre>with(logic): # esteja certo que 'bsimp' está definida
e := x &and y &or &not z;
bsimp(e);</pre>
Para interpretar os resultados de saída, é aconselhável ser capaz de olhar para o código-fonte do procedimento '''bsimp''' e as sub-rotinas da biblioteca que ele chama. Você pode fazer isso emitindo o seguinte
<pre>interface(verboseproc = 2);
eval(bsimp); # assuma 'bsimp' carregada</pre>
Isso mostra o código fonte real para a função '''bsimp''', embora comentários estão faltando. (Não pode haver comentários porque Maple desmonta o código objeto na biblioteca do Maple, a partir do qual a compilação foi despojado de todos os comentários, para produzir o código de Maple que você vê aqui).
Para entender a saída, você deve perceber que o Maple não fornece acesso a operações de nível de bits, de modo que o algoritmo usado em '''bsimp''' é um pouco diferente do que a descrita em seu livro. Em vez de cadeias de bits, Maple usa conjuntos para representar expressões booleanas.
Com essas ferramentas em mãos, agora você pode escrever um procedimento para gerar, aleatoriamente, dez expressões booleanas em quatro variáveis​​, e contar o número de passos necessários para minimizar cada um, finalmente a tomar uma média.
== '''Exercícios e Projetos''' ==
109

edits

Navigation menu