Ludwig Krippahl, 2007 Programação para as Ciências Experimentais 2006/7 Teórica 9
Ludwig Krippahl, Na aula de hoje... Minimização multidimensional Leitura e escrita formatada de ficheiros. Introdução à folha de cálculo (Excel) Exemplo: estimativa do efeito de um antibiótico no crescimento bacteriano.
Ludwig Krippahl, Crescimento bacteriano Equação de Verhulst: dB/dt = cB – mB 2
Ludwig Krippahl, Crescimento bacteriano Equação de Verhulst: dB/dt = cB – mB 2 Variação do número de organismos
Ludwig Krippahl, Crescimento bacteriano Equação de Verhulst: dB/dt = cB – mB 2 É o ritmo de crescimento vezes o número de organismos
Ludwig Krippahl, Crescimento bacteriano Equação de Verhulst: dB/dt = cB – mB 2 Menos a taxa de mortalidade vezes o quadrado desse número. A mortalidade resulta da competição por recursos.
Ludwig Krippahl, Crescimento bacteriano
Ludwig Krippahl, Crescimento bacteriano Problema: Dado um conjunto de medições, ajustar os parâmetros da equação
Ludwig Krippahl, Crescimento bacteriano Problema: Dado um conjunto de medições, ajustar os parâmetros da equação Mas são dois parâmetros: crescimento e mortalidade. Precisamos de uma minimização a duas dimensões.
Ludwig Krippahl, Minimização multidimensional Método mais simples: Minimizar uma variável de cada vez até chegar a um ponto fixo, a menos da precisão desejada Análogo ao método usado no trabalho 1
Ludwig Krippahl, Minimização multidimensional Método mais simples: Partir de um ponto inicial, um valor para cada variável. Encontrar o mínimo de uma variável. Alterar o vector das variáveis Encontrar o mínimo da próxima. Repetir para todas, as vezes que for necessário.
Ludwig Krippahl, Minimização multidimensional Ponto inicial
Ludwig Krippahl, Minimização multidimensional Ponto inicial Mínimo de X
Ludwig Krippahl, Minimização multidimensional Ponto inicial Mínimo de X Mínimo de Y
Ludwig Krippahl, Minimização multidimensional Ponto inicial Mínimo de X Mínimo de Y Novo mínimo de X
Ludwig Krippahl, Minimização multidimensional Vamos modificar a minfn Para partir do ponto dado e não ser preciso especificar os três pontos iniciais (é mais eficiente começar com 3 pontos juntos quando próximo do mínimo) Para procurar o mínimo de uma de várias variáveis.
Ludwig Krippahl, Os 3 pontos iniciais X 1 é o ponto dado
Ludwig Krippahl, Os 3 pontos iniciais X1X1 X m próximo de X 1
Ludwig Krippahl, Os 3 pontos iniciais X1X1 X m próximo de X 1 Desce? Se não, troca
Ludwig Krippahl, Os 3 pontos iniciais X1X1 XmXm X 2 a 1.618*(X m -X 1 )
Ludwig Krippahl, Os 3 pontos iniciais X1X1 XmXm X2X2 Y 2 >Y m ? Não, continua: X 1 =X m X m =X 2
Ludwig Krippahl, Os 3 pontos iniciais X1X1 XmXm Y 2 >Y m ? Não, continua: X 1 =X m X m =X 2
Ludwig Krippahl, Os 3 pontos iniciais X1X1 XmXm Y 2 >Y m ? Não, continua: X 1 =X m X m =X 2 X2X2
Ludwig Krippahl, Os 3 pontos iniciais X1X1 XmXm Y 2 >Y m ? Sim.Devolve: X 1 X m X 2 Y m (Y m para começar a minimização) X2X2
Ludwig Krippahl, Os 3 pontos iniciais function [x1,xm,x2,ym]= mininicial(funcao,params,vars,indice,delta)
Ludwig Krippahl, Os 3 pontos iniciais function [x1,xm,x2,ym]= mininicial(funcao,params,vars,indice,delta) Os valores a devolver, os 3 pontos de x e o y do meio que precisamos para começar a minimização.
Ludwig Krippahl, Os 3 pontos iniciais function [x1,xm,x2,ym]= mininicial(funcao,params,vars,indice,delta) Nome da função a minimizar e os parâmetros constantes que precisamos para a avaliar. E.g.: os coeficientes do polinómio, os dados experimentais, etc
Ludwig Krippahl, Os 3 pontos iniciais function [x1,xm,x2,ym]= mininicial(funcao,params,vars,indice,delta) Um vector com os valores das N variáveis da função (a função tem várias dimensões)
Ludwig Krippahl, Os 3 pontos iniciais function [x1,xm,x2,ym]= mininicial(funcao,params,vars,indice,delta) O índice no vector da variável que estamos a minimizar agora (a função tem várias, mas só conseguimos lidar com uma de cada vez)
Ludwig Krippahl, Os 3 pontos iniciais function [x1,xm,x2,ym]= mininicial(funcao,params,vars,indice,delta) Tamanho do passo inicial para calcular o primeiro X m a partir do X inicial, que será o valor que vem em vars(indice).
Ludwig Krippahl, Os 3 pontos iniciais razaod=1.618; x1=vars(indice); vars(indice)=x1; y1=feval(funcao,params,vars); xm=x1+delta; vars(indice)=xm; ym=feval(funcao,params,vars); Razão dourada
Ludwig Krippahl, Os 3 pontos iniciais razaod=1.618; x1=vars(indice); vars(indice)=x1; y1=feval(funcao,params,vars); xm=x1+delta; vars(indice)=xm; ym=feval(funcao,params,vars); Calcular x1 e y1. Nota: a função cujo nome foi dado em funcao precisa de todo o vars, mas só alteramos o elemento indice
Ludwig Krippahl, Os 3 pontos iniciais razaod=1.618; x1=vars(indice); vars(indice)=x1; y1=feval(funcao,params,vars); xm=x1+delta; vars(indice)=xm; ym=feval(funcao,params,vars); Mesma coisa para xm e ym
Ludwig Krippahl, Os 3 pontos iniciais if ym>y1 t=ym; ym=y1; y1=t; t=xm; xm=x1; x1=t; endif x2=xm+razaod*(xm-x1); vars(indice)=x2; y2=feval(funcao,params,vars); Se for a subir troca o x1 com o xm, e o y1 com o ym.
Ludwig Krippahl, Os 3 pontos iniciais if ym>y1 t=ym; ym=y1; y1=t; t=xm; xm=x1; x1=t; endif x2=xm+razaod*(xm-x1); vars(indice)=x2; y2=feval(funcao,params,vars); Calcula o x2 a uma distância de xm igual a vezes o intervalo (xm-x1).
Ludwig Krippahl, Os 3 pontos iniciais if ym>y1 t=ym; ym=y1; y1=t; t=xm; xm=x1; x1=t; endif x2=xm+razaod*(xm-x1); vars(indice)=x2; y2=feval(funcao,params,vars); Se x1>xm, continua para valores maiores. Se foi trocado, x1-xm é negativo e sege para valores menores.
Ludwig Krippahl, Os 3 pontos iniciais while y2<ym x1=xm; xm=x2; ym=y2; x2=xm+razaod*(xm-x1); vars(indice)=x2; y2=feval(funcao,params,vars); endwhile Enquanto continua a descer, avança com os pontos,
Ludwig Krippahl, Minimização Antes era: function xm=minfn(func,params,x1,xm,x2,prec) Agora é: function xm=minfnvec(func,params,vars,indice,prec)
Ludwig Krippahl, Minimização multidimensional function xm=minfnvec(func,params,vars,indice,prec) Valor da variável que está a minimizar no mínimo da função considerando apenas esta variável.
Ludwig Krippahl, Minimização multidimensional function xm=minfnvec(func,params,vars,indice,prec) Função (o nome, em string) e parâmetros constantes, como de costume.
Ludwig Krippahl, Minimização multidimensional function xm=minfnvec(func,params,vars,indice,prec) Vector com os valores das várias variáveis no ponto inicial, de onde parte à procura do mínimo.
Ludwig Krippahl, Minimização multidimensional function xm=minfnvec(func,params,vars,indice,prec) Índice da variável onde procurar o mínimo.
Ludwig Krippahl, Minimização multidimensional function xm=minfnvec(func,params,vars,indice,prec) Precisão (tamanho do intervalo abaixo do qual consideramos ter encontrado o mínimo)
Ludwig Krippahl, Minimização multidimensional Esta função é igual à minfn, excepto: Usa o mininicial para determinar os 3 pontos e o valor de ym [x1,xm,x2,ym]=mininicial(func,params,vars,indice,prec); Nota: um bom valor para o delta é a precisão: começamos do intervalo mais pequeno.
Ludwig Krippahl, Minimização multidimensional Esta função é igual à minfn, excepto: Usa o mininicial para determinar os 3 pontos e o valor de ym Tem que atribuir o valor correcto a vars(indice) antes de chamar a função fornecida em func xn=c1*xm+c2*x1; vars(indice)=xn; yn=feval(func,params,vars);
Ludwig Krippahl, Minimização multidimensional Esta função é igual à minfn, excepto: Usa o mininicial para determinar os 3 pontos e o valor de ym Tem que atribuir o valor correcto a vars(indice) antes de chamar a função fornecida em func Mas minfnvec ainda só minimiza numa dimensão (a dimensão indicada em indice).
Ludwig Krippahl, Minimização multidimensional Precisamos de: function xs=multimin(funcao,params,xs,prec)
Ludwig Krippahl, Minimização multidimensional function xs=multimin(funcao,params,xs,prec) Vector com os valores de todas as variáveis no mínimo da função
Ludwig Krippahl, Minimização multidimensional function xs=multimin(funcao,params,xs,prec) Nome da função a minimizar.
Ludwig Krippahl, Minimização multidimensional function xs=multimin(funcao,params,xs,prec) Parâmetros constantes...
Ludwig Krippahl, Minimização multidimensional function xs=multimin(funcao,params,xs,prec) Ponto inicial (valores de todas as variáveis da função de onde partir à procura do mínimo)
Ludwig Krippahl, Minimização multidimensional function xs=multimin(funcao,params,xs,prec) Precisão
Ludwig Krippahl, Minimização multidimensional while true xvs=xs; for f=1:length(xs) xs(f)=minfnvec(funcao,params,xs,f,prec); endfor disp("Valores até agora:") disp(xs); if sum(abs(xs-xvs))<prec break endif endwhile Ciclo infinito que só termina no break.
Ludwig Krippahl, Minimização multidimensional while true xvs=xs; for f=1:length(xs) xs(f)=minfnvec(funcao,params,xs,f,prec); endfor disp("Valores até agora:") disp(xs); if sum(abs(xs-xvs))<prec break endif endwhile Guarda os valores antigos dos xs
Ludwig Krippahl, Minimização multidimensional while true xvs=xs; for f=1:length(xs) xs(f)=minfnvec(funcao,params,xs,f,prec); endfor disp("Valores até agora:") disp(xs); if sum(abs(xs-xvs))<prec break endif endwhile Minimiza em cada dimensão, actualizando o valor nos xs
Ludwig Krippahl, Minimização multidimensional while true xvs=xs; for f=1:length(xs) xs(f)=minfnvec(funcao,params,xs,f,prec); endfor disp("Valores até agora:") disp(xs); if sum(abs(xs-xvs))<prec break endif endwhile Mostra o progresso do cálculo indicando os valores correntes (ver função disp)
Ludwig Krippahl, Minimização multidimensional while true xvs=xs; for f=1:length(xs) xs(f)=minfnvec(funcao,params,xs,f,prec); endfor disp("Valores até agora:") disp(xs); if sum(abs(xs-xvs))<prec break endif endwhile Se o total da variação absoluta das variáveis é inferior à precisão, acabou.
Ludwig Krippahl, Crescimento bacteriano De volta ao problema: dB/dt = cB – mB 2 Integramos pelo método de Euler, com a função: function mat=crescimento(cresc,mort,dt,qini,tfinal)
Ludwig Krippahl, Crescimento bacteriano function mat=crescimento(cresc,mort,dt,qini,tfinal) Matriz com os valores de tempo e número de bactérias em duas colunas
Ludwig Krippahl, Crescimento bacteriano function mat=crescimento(cresc,mort,dt,qini,tfinal) Taxa de crescimento
Ludwig Krippahl, Crescimento bacteriano function mat=crescimento(cresc,mort,dt,qini,tfinal) Taxa de mortalidade
Ludwig Krippahl, Crescimento bacteriano function mat=crescimento(cresc,mort,dt,qini,tfinal) Passo de integração
Ludwig Krippahl, Crescimento bacteriano function mat=crescimento(cresc,mort,dt,qini,tfinal) Quantidade inicial de organismos.
Ludwig Krippahl, Crescimento bacteriano function mat=crescimento(cresc,mort,dt,qini,tfinal) Tempo final.
Ludwig Krippahl, Crescimento bacteriano mat=[0,qini]; B=qini; for t=dt:dt:tfinal dB=B*cresc-B^2*mort; B=B+dB*dt; mat=[mat;t,B]; endfor
Ludwig Krippahl, Crescimento bacteriano Agora precisamos de calcular o erro do modelo aos dados experimentais. Análogo ao que fizemos para as reacções químicas, mas desta vez com várias variáveis (duas).
Ludwig Krippahl, Crescimento bacteriano function err=errocres(dados,vars) mat=crescimento(vars(1),vars(2),10,0.1,400); y=interpol(mat,dados(:,1)); err=sum((y-dados(:,2)).^2); endfunction Matriz com a simulação, 400 minutos, passo de 10 minutos.
Ludwig Krippahl, Crescimento bacteriano function err=errocres(dados,vars) mat=crescimento(vars(1),vars(2),10,0.1,400); y=interpol(mat,dados(:,1)); err=sum((y-dados(:,2)).^2); endfunction Nota: Quantidade em kilobactérias. Explicação adiante...
Ludwig Krippahl, Crescimento bacteriano function err=errocres(dados,vars) mat=crescimento(vars(1),vars(2),10,0.1,400); y=interpol(mat,dados(:,1)); err=sum((y-dados(:,2)).^2); endfunction Interpolar os valores simulados para os pontos dos dados experimentais.
Ludwig Krippahl, Crescimento bacteriano function err=errocres(dados,vars) mat=crescimento(vars(1),vars(2),10,0.1,400); y=interpol(mat,dados(:,1)); err=sum((y-dados(:,2)).^2); endfunction Erro quadrático....
Ludwig Krippahl, Crescimento bacteriano Para testar, simulamos dados com estes parâmetros: 10 pontos de 30 em 30 minutos. Nota: cada linha da matriz são 10 minutos. vals=[ , ]; mat=crescimento(vals(1),vals(2),10,0.1,400); dados=mat(3:3:30,:)
Ludwig Krippahl, Crescimento bacteriano Escolhemos um ponto inicial diferente, e minimizamos: xs=multimin("errocres",dados,[0.05,0.005],1e-4)
Ludwig Krippahl, Crescimento bacteriano Simulamos com os parâmetros calculados e comparamos: mat2=crescimento(xs(1),xs(2),10,0.1,400); hold off plot(dados(:,1),dados(:,2),"or"); hold on plot(mat2(:,1),mat2(:,2));
Ludwig Krippahl, Crescimento bacteriano
Ludwig Krippahl, Crescimento bacteriano Nota sobre as kilobactérias: Com esta equação, se contarmos em unidades de uma bactéria o parâmetro da mortalidade tem que ser mil vezes mais pequeno. Em geral, é melhor escolher as unidades de forma a que a função tenha uma escala semelhante nas várias dimensões. Desta forma a taxa de crescimento e de mortalidade têm apenas uma ordem de grandeza de diferença em vez de quatro.
Ludwig Krippahl, Processar dados experimentais Queremos estudar o efeito da meticilina no crescimento de uma bactéria. Duas pessoas, Ana e Carlos, cresceram lotes da bactéria em meios com e sem meticilina, e contaram as colónias de amostras retiradas de 30 em 30 minutos. A concentração inicial era de 100 bactérias por ml.
Ludwig Krippahl, Processar dados experimentais Os dados estão em 20 ficheiros 1.txt a 20.txt Dados de crescimento Meio:Normal Preparador:Ana 25;0 59; ;40
Ludwig Krippahl, Processar dados experimentais Objectivo: ajustar o modelo de crescimento às 2 condições e comparar os parâmetros Ler os ficheiros para uma lista de estruturas Separar as medições por meio e/ou preparador, em matriz Calcular parâmetros.
Ludwig Krippahl, Processar dados experimentais Ler os ficheiros para uma lista de estruturas function dados=leficheiros(num)
Ludwig Krippahl, Ler os ficheiros dados=list; for f=1:num fid=fopen([num2str(f),".txt"],"r"); reg.valores=[]; while !feof(fid)... endwhile dados=append(dados,reg); fclose(fid); endfor Percorre o número indicado de ficheiros numero.txt
Ludwig Krippahl, Ler os ficheiros dados=list; for f=1:num fid=fopen([num2str(f),".txt"],"r"); reg.valores=[]; while !feof(fid)... endwhile dados=append(dados,reg); fclose(fid); endfor Matriz para os valores neste ficheiro
Ludwig Krippahl, Ler os ficheiros dados=list; for f=1:num fid=fopen([num2str(f),".txt"],"r"); reg.valores=[]; while !feof(fid)... endwhile dados=append(dados,reg); fclose(fid); endfor Ler o ficheiro
Ludwig Krippahl, Ler os ficheiros dados=list; for f=1:num fid=fopen([num2str(f),".txt"],"r"); reg.valores=[]; while !feof(fid)... endwhile dados=append(dados,reg); fclose(fid); endfor Acrescenta registo à lista e fecha o ficheiro
Ludwig Krippahl, Ler os ficheiros s=fgetl(fid); if !isstr(s) break endif if findstr(s,"Meio:")!=[] reg.meio=s(6:length(s)); elseif findstr(s,"Preparador:")!=[] reg.prep=s(12:length(s)); elseif findstr(s,";")!=[] m=split(s,";"); reg.valores=[reg.valores;str2num(m(1,:)),str2num(m(2,:))]; endif; endwhile Lê uma linha e testa se o resultado é string. Se não for é por ser -1, o que indica que não há linha para ler. Nesse caso termina o ciclo (pode haver linhas vazias no final do texto).
Ludwig Krippahl, Ler os ficheiros s=fgetl(fid); if !isstr(s) break endif if findstr(s,"Meio:")!=[] reg.meio=s(6:length(s)); elseif findstr(s,"Preparador:")!=[] reg.prep=s(12:length(s)); elseif findstr(s,";")!=[] m=split(s,";"); reg.valores=[reg.valores;str2num(m(1,:)),str2num(m(2,:))]; endif; endwhile Meio: indica que se segue o meio (Normal ou Meticilina)
Ludwig Krippahl, Ler os ficheiros s=fgetl(fid); if !isstr(s) break endif if findstr(s,"Meio:")!=[] reg.meio=s(6:length(s)); elseif findstr(s,"Preparador:")!=[] reg.prep=s(12:length(s)); elseif findstr(s,";")!=[] m=split(s,";"); reg.valores=[reg.valores;str2num(m(1,:)),str2num(m(2,:))]; endif; endwhile O preparador (Ana ou Carlos)
Ludwig Krippahl, Ler os ficheiros s=fgetl(fid); if !isstr(s) break endif if findstr(s,"Meio:")!=[] reg.meio=s(6:length(s)); elseif findstr(s,"Preparador:")!=[] reg.prep=s(12:length(s)); elseif findstr(s,";")!=[] m=split(s,";"); reg.valores=[reg.valores;str2num(m(1,:)),str2num(m(2,:))]; endif; endwhile Um ; indica que é uma linha com os valores. Split, depois acrescenta à matriz.
Ludwig Krippahl, Ler os ficheiros Exemplo: octave:25> l=leficheiros(20); octave:26> l l = ( [1] = { meio = Normal prep = Ana valores = } [2] =...
Ludwig Krippahl, Organizar os dados Queremos receber uma matriz tempo, contagens para cada meio e/ou preparador: function mat=compiladados(lista,prep,meio) Recebe a lista e dois strings com o preparador e meio ( para qualquer um)
Ludwig Krippahl, Organizar os dados function mat=compiladados(lista,prep,meio) mat=[]; for f=1:length(lista) reg=nth(lista,f); if (meio=="" || strcmp(meio,reg.meio)) && (prep=="" || strcmp(prep,reg.prep)) mat=[mat;reg.valores]; endif endfor Percorre a lista elemento a elemento.
Ludwig Krippahl, Organizar os dados function mat=compiladados(lista,prep,meio) mat=[]; for f=1:length(lista) reg=nth(lista,f); if (meio=="" || strcmp(meio,reg.meio)) && (prep=="" || strcmp(prep,reg.prep)) mat=[mat;reg.valores]; endif endfor Se é este o meio ou preparador, ou se, acrescenta.
Ludwig Krippahl, Organizar os dados Exemplo: todos os dados l=leficheiros(20); dados=compiladados(l,"",""); clearplot; plot(dados(:,1),dados(:,2),"o");
Ludwig Krippahl, Organizar os dados Exemplo: todos os dados
Ludwig Krippahl, Organizar os dados Exemplos: separados por meio dmet=compiladados(l,"","Meticilina"); dsem=compiladados(l,"","Normal"); clearplot hold on plot(dmet(:,1),dmet(:,2),"or;Meticilina;"); plot(dsem(:,1),dsem(:,2),"xg;Normal;");
Ludwig Krippahl, Organizar os dados
Ludwig Krippahl, Organizar os dados Exemplos: separados por preparador ana=compiladados(l,"Ana",""); carlos=compiladados(l,"Carlos",""); clearplot hold on plot(ana(:,1),ana(:,2),"or;Ana;"); plot(carlos(:,1),carlos(:,2),"xg;Carlos;");
Ludwig Krippahl, Organizar os dados Exemplos: separados por preparador
Ludwig Krippahl, Ajustar o modelo Separamos por meio: dmet=compiladados(l,"","Meticilina"); dsem=compiladados(l,"","Normal"); E minimizamos, a partir de uma estimativa inicial: xs=multimin("errocres",dsem,[0.05,0.002],1e-4); xm=multimin("errocres",dmet,[0.05,0.002],1e-4);
Ludwig Krippahl, Ajustar o modelo Simulamos com os parâmetros calculados: sims=crescimento(xs(1),xs(2),10,0.1,400); simm=crescimento(xm(1),xm(2),10,0.1,400);
Ludwig Krippahl, Ajustar o modelo E comparamos os dados com a simulação: clearplot hold on plot(dmet(:,1),dmet(:,2),"or"); plot(dsem(:,1),dsem(:,2),"xg"); plot(simm(:,1),simm(:,2),"-r;Meticilina;"); plot(sims(:,1),sims(:,2),"-g;Normal;");
Ludwig Krippahl, Ajustar o modelo Compara-se no gráfico:
Ludwig Krippahl, Exportar o resultado Escrita formatada: fprintf fprintf(id, formato, dados) Exemplo: escrever tabela em duas colunas separadas por tab. fid=fopen("relatorio.txt","w"); mat=compiladados(l,"",""); fprintf(fid,"%i\t%i\n",mat) fclose(fid)
Ludwig Krippahl, Exportar o resultado fprintf(fid,"%i\t%i\n",mat) %i indica que é um número inteiro.
Ludwig Krippahl, Exportar o resultado fprintf(fid,"%i\t%i\n",mat) \t é o caracter tab.
Ludwig Krippahl, Exportar o resultado fprintf(fid,"%i\t%i\n",mat) \n indica uma nova linha.
Ludwig Krippahl, Exportar o resultado % é um caracter especial na string de formatação, indica que o que se segue especifica o formato (ver fprint no manual) \ é um caracter especial em qualquer string, usado para caracteres que não são visíveis (mudar de linha, tab, etc.) Para mostrar escrever dois: \\, %
Ludwig Krippahl, Exportar o resultado Quando o fprintf ou o printf (para escrever no ecrã) recebem uma matriz percorrem todos os elementos da matriz aplicando a formatação na ordem indicada; Atenção: percorre a primeira coluna toda, depois a segunda, etc.. Como temos dados em colunas, usar transposta.
Ludwig Krippahl, Importar no Excel Para importar dados estáticos no Excel (importar uma vez), file open, escolher o tipo de ficheiro (txt, neste caso), e especificar o caracter que separa os dados (tab)
Ludwig Krippahl, Importar no Excel Delimitado
Ludwig Krippahl, Importar no Excel Delimitado por tab
Ludwig Krippahl, Usar o Excel Ordenar Calcular somas e médias Usar o if O Excel é fácil de aprender pelo help. Ou pesquisando excel tutorial na internet. Exemplo:
Ludwig Krippahl, Dúvidas