A revolução do hardware e do software

[<] [>] [sumário]



Introdução

[topo]

Os primeiros computadores da década de 1940 possuíam somente dois níveis de linguagem de programação: o nível da linguagem de máquina, no qual toda a programação era feita, e o nível da lógica digital, onde os programas eram efetivamente executados. Com Wilkes, em 1951, surgiu a ideía de se projetar um computador a três níveis, a fim de se simplificar o hardware. Esta máquina tinha um programa denominado interpretador armazenado permanentemente, cuja função era executar os programas em linguagem de máquina. O hardware assim poderia ser simplificado: teria apenas que executar um pequeno conjunto de microinstruções armazenadas, ao invés de todo o programa em linguagem de máquina, o que exigia menos circuitos eletrônicos. A partir daí começam a evoluir as linguagens e as arquiteturas das máquinas, impulsionadas, principalmente, pelo aparecimento de um novo conceito na História da Computação: os Sistemas Operacionais.

 


Da segunda geração de computadores aos dias de hoje

[topo]

A segunda geração (1956 - 1963) foi impulsionada pela invenção do transistor (1948) e em 1956 já se produziam computadores com esta tecnologia. Apareceram também os modernos dispositivos, tais como as impressoras, as fitas magnéticas, os discos para armazenamento, etc. Os computadores passaram a ter um desenvolvimento rápido, impulsionados principalmente por dois fatores essenciais: os sistemas operacionais e as linguagens de programação.Os circuitos integrados propiciaram um novo avanço e com eles surgiram os computadores de terceira geração (1964 - 1970). As tecnologias LSI, VLSI e ULSI§1 abrigam milhões de componentes eletrônicos em um pequeno espaço ou chip, iniciando a quarta geração, que vem até os dias de hoje. Os atuais avanços em pesquisa e o projeto de novas tecnologias para os computadores estão possibilitando o surgimento da quinta geração. Dois avanços que configuram um divisor de águas são o processamento paralelo, que quebrou o paradigma de von Neumann§2, e a tecnologia dos supercondutores.

 


O desenvolvimento das linguagens

[topo]

Várias linguagens, muitas delas conceitualmente diferentes entre si, foram surgindo e sendo aprimoradas, incorporando-se umas em outras. Com algumas poucas exceções, o projeto de cada linguagem foi influenciado pela experiência em linguagens anteriores. Merecem especial atenção pelo seu pioneirismo e pelos novos paradigmas que introduziram as linguagens, chamadas de alto nível: FORTRAN e LISP.

Com relação ao FORTRAN, em 1954 ocorreu um simpósio sobre 'computação automática'§3, e seu maior evento foi a apresentação do compilador algébrico de Laning e Zierler (ver capítulo Os primeiros 'compiladores'). Foi o primeiro 'software' que permitiu como entrada de dados um código algébrico elegante, embora limitado. Nesse meio tempo John Backus já montara um grupo de pesquisa dentro da IBM para trabalhar em um projeto sobre programação automática, para responder a uma questão fundamental: "(...) pode uma máquina traduzir uma linguagem matemática abrangente em um conjunto razoável de instruções, a um baixo custo, e resolver totalmente uma questão?"77. Em novembro de 1954 a equipe de Backus tinha criado o IBM Mathematical FORmula TRANslation System, o FORTRAN. O primeiro parágrafo da apresentação desse trabalho enfatizava que os sistemas anteriores ofereciam duas escolhas: ou uma fácil codificação e uma execução lenta do programa ou uma laboriosa codificação com rápida execução, mas "o FORTRAN propiciava o melhor das duas opções"38. Com o FORTRAN apareceram as expressões simbólicas, subprogramas com parâmetros, mas principalmente ocorreu a primeira tentativa de se definir rigorosamente a sintaxe de uma linguagem de programação. Um pouco mais tarde surgiu a notação BNF para a descrição sintática de uma linguagem de programação.

A história do LISP remonta a Turing e Church. Pela análise de Turing nos anos de 1936 e 1937, após seu famoso artigo sobre o décimo problema de Hilbert, o cálculo-lambda de Church, apesar da sua sintaxe simples, era suficientemente poderoso para descrever todas as funções mecanicamente computáveis, ou seja, pode ser visto paradigmaticamente como uma linguagem de programação. No cálculo-lambda muitos problemas de programação, especificamente aqueles referentes às chamadas de procedimento, estão em sua forma mais pura, e isto influenciará diretamente linguagens como LISP e Algol3.

Em 1955 e 1956 E.K. Blum, no U.S. Naval Ordinance Laboratory desenvolveu uma linguagem completamente diferente das demais, ADES (Automatic Digital Encoding System), baseada na teoria das funções recursivas e no esquema desenvolvido para elas por Kleene. Foi a primeira linguagem "declarativa", no sentido de que o programador estabelece as relações entre as variáveis quantitativas sem explicitamente especificar a ordem de avaliação (mais à frente se falará sobre este paradigma de programação).

Aparece agora a figura de John McCarthy, matemático, um dos primeiros a trabalhar no tema de Inteligência Artificial. Juntamente com Marvin Minsky iniciou um grande projeto nessa área. Estava procurando desenvolver uma linguagem algébrica para processamento de listas, preocupado com o problema de como representar informações da realidade por meio de sentenças escritas em uma linguagem formal adequada, e de como criar um programa que executasse fazendo inferências lógicas. Surgiu então o LISP, uma linguagem que pode ser utilizada como um formalismo para descrição de algoritmos, para escrever programas e provar propriedades de algoritmos, sendo adequada à computação simbólica e à inteligência artificial. Sobretudo com LISP pode-se visualizar melhor um importante conceito na computação moderna que é o uso de estruturas de dados como objetos abstratos. É um dos aspectos centrais dessa linguagem, comparada a como a Matemática usa os números naturais como entidades abstratas.

Nos inícios da década de 1960, fruto do trabalho de americanos e europeus, surgiu uma linguagem projetada para representar algoritmos ao invés de se escrever programas simplesmente, o Algol-60. Ela implementava o conceito de estrutura de blocos, onde variáveis, procedimentos, etc., poderiam ser declarados onde quer que o programa os necessitasse. Algol-60 influenciou profundamente muitas linguagens que vieram depois e evoluiu para o Algol-68.


PL/I surgiu como uma tentativa de se projetar uma linguagem de uso geral reunindo características de linguagens para aplicações numéricas como FORTRAN e Algol e para processamento de dados comerciais. Ela inovou ao permitir a construção de código de 'baixo nível' para o controle de exceções e o conceito de processamento concorrente, entre outros. O resultado foi algo anômalo, complexo e incoerente, de difícil implementação.

Foi a linguagem Pascal entretanto que se tornou a mais popular das linguagens do estilo Algol, porque é simples, sistemática e facilmente implementável nos diferentes computadores. Junto com o Algol-68, está entre as primeiras linguagens com uma ampla gama de instruções para controle de fluxo, definição e construção de novos tipos de dados. Ada, que veio depois do Pascal, introduziu o conceito de pacotes e permite a construção de grandes programas com estrutura modular.

Podem-se discernir na história das linguagens certas tendências. A primeira foi perseguir altos níveis de abstração. Os rótulos simbólicos e mnemônicos das linguagens de montagem abstraem códigos de operação e endereços. Variáveis e atribuição abstraem acesso a um endereço de memória e atualização. Estruturas de dados abstraem formas de armazenamento. Estruturas de controle abstraem desvios. Procedimentos abstraem subrotinas. E assim por diante.

Outra tendência foi a proliferação dos paradigmas. A maioria das linguagens mencionadas até agora são imperativas, caracterizadas por comandos que atualizam variáveis. A estrutura das linguagens imperativas é induzida pelo hardware, com preocupação de que os dados trafeguem o mais rapidamente possível. Daí alguns de seus aspectos relevantes: sequência de comandos, atribuição, controles (loopings), etc. É ainda o paradigma dominante.

Já as linguagens que seguem o paradigma funcional (também conhecidas como declarativas), como o LISP, tem como características a clareza e a busca de um maior poder expressivo, procurando manter a maior independência possível do paradigma de von Neumann, que caracteriza as linguagens imperativas§4. Buscam uma transparência referencial e a não ocorrência de efeitos colaterais nas suas instruções. Em LISP não há o conceito de estado - dado por uma atribuição -, memória, sequência de instruções, etc., procurando-se tornar mais visível o uso das funções. Nas linguagens imperativas as funções dependem de estados internos, fora de seu contexto ( x := x + 'argumento'), com a produção de efeitos colaterais (alteração de valores, impressão, etc.). LISP foi a ancestral das linguagens funcionais que culminaram atualmente em linguagens como Miranda, ML e Haskell, que tratam funções como valores de primeira classe.

Smalltalk é uma linguagem baseada em classes de objetos. Um objeto é uma variável que pode ser acessada somente através de operações associadas a ele. Smalltalk é um exemplo de uma linguagem que segue o paradigma de orientação a objeto. Simula foi um ancestral de tais linguagens.

É importante reparar que a notação matemática em sua generalidade não é facilmente implementável. No entanto muitos projetistas de linguagens quiseram explorar subconjuntos da notação matemática em linguagens de programação. Surgiram então tentativas de se contruir uma 'linguagem lógica', isto é, baseada em um subconjunto da lógica matemática. O computador é programado para inferir relacionamentos entre valores, ao invés de computar valores de saída a partir de valores de entrada. Prolog popularizou a linguagem lógica. Em sua forma pura é fraca e ineficiente, tendo sido alterada para incluir características não lógicas e tonar-se mais amigável como linguagem de programação.

No início da década de 1990 ocorreu um difusão intensa do paradigma da orientação a objeto§5. Este paradigma esteve em gestação por cerca de 30 anos e as novas tecnologias como a Internet, as necessidades geradas pela novas arquiteturas, tais como a de cliente-servidor§6 e a do processamento distribuído, coincidiam com o paradigma da orientação a objeto: encapsulamento, mensagem, etc. O crescimento da Internet e o "comércio eletrônico" introduziram novas dimensões de complexidade no processo de desenvolvimento de programas. Começaram a surgir linguagens que buscam superar esses novos desafios de desenvolvimento de aplicações em um contexto heterogêneo ( arquiteturas de hardware incompatíveis, sistemas operacionais incompatíveis, plataformas operando com uma ou mais interfaces gráficas incompatíveis, etc). Apareceram C++ e linguagens como Eifell, Objective C, Cedar/Mesa (elaborada pela Xerox, para fazer pesquisa de dados), Delphi (uma evolução da lingaugem Pascal) entre outras. E, "o próximo passo ou um paradigma completamente novo"28, surge a linguagem JAVA.

A origem da Java está ligada a um grupo de pesquisa e desenvolvimento da Sun Microsystems formado em 1990, liderado por Patrick Naughton e James Gosling, que buscava uma nova ferramenta de comunicação e programação, independente da arquitetura de qualquer dispositivo eletrônico. Em 1994, após o surgimento do NCSA Mosaic e a popularização da Internet, a equipe refocalizou seus esforços para criar uma linguagem para aplicações multimídia on line.

Conforme Linden47, Java foi inspirada por várias linguagens: tem a concorrência da Mesa, tratamento de exceções como Modula-3, linking dinâmico de código novo e gerenciamento automático de memória como LISP, definição de interfaces como Objective C, e declarações ordinárias como C. Apesar destas qualidades, todas importantes, na verdade duas outras realmente fazem a diferença e tornam Java extremamente atrativa: sua portabilidade e o novo conceito de arquitetura neutra.

Portabilidade significa que Java foi projetada objeticando aplicações para vários sistemas heterogêneos que podem compor uma rede como a Internet, por exempo, e as diferentes características dessa rede. Java procura obter os mesmos resultados de processamento nas diferentes plataformas.

Por arquitetura neutra entende-se que programas em Java são compilados para se obter um código objeto (byte code na terminologia Java) que poderá ser executado em um Power PC que use o sistema operacional OS/2, ou em um sistema baseado no chip Pentium debaixo do Windows 95 ou em um Macintosh usando MacOs, ou em uma estação de trabalho Sparc rodando Unix. Ou seja, em qualquer computador, desde que tal computador implemente o ambiente necessário para isso, denominado conceitualemente de Máquina Virtual Java.


Com a linguagem Java começou superar-se a barreira para a Internet tornar-se um computador: a barreira que impede o uso de um software utilizado em um determinado lugar, executando-o em qualquer plataforma.

 


Arquiteturas de computadores e sistemas operacionais

[topo]

O termo arquitetura de computador vem da possibilidade de se visualizar uma máquina como um conjunto hierárquico de níveis que permite entender como os computadores estão organizados. Os primeiros computadores digitais por exemplo somente possuiam dois níveis. O primeiro é chamado o nível da lógica digital, formado no início por válvulas e depois por transistores, circuitos integrados, etc. O segundo é chamado de nível 1, também chamado de nível de microprograma, que é o nível da linguagem da máquina, onde toda a programação era feita, através de zeros e uns, e que posteriormente seria o responsável por interpretar as instruções do nível 2.

Com Maurice Wilkes em 1951 surgiu outro nível, onde as instruções eram escritas de um modo mais conveniente para o entendimento humano: a técnica consistia em substituir cada instrução desse novo nível por um conjunto de instruções do nível anterior (nível da máquina) ou examinar uma instrução de cada vez e executar a sequência de instruções equivalentes do nível da máquina. Denominam-se estes procedimentos por tradução e interpretação. Isto simplificou o hardware que agora somente tinha um conjunto mínimo de instruções e portanto menos circuitos eram necessários.

A partir daí a evolução do hardware avança juntamente com as novas descobertas científicas: quase na mesma época do aparecimento dos transistores, por exemplo, surgiu o conceito de barramento de dados, que acelerou a velocidade dos computadores. Ao mesmo tempo apareceram os grandes sistemas operacionais, (simplificadamente, um conjunto de programas mantidos no computador durante todo o tempo, liberando o programador de tarefas relacionadas diretamente com o funcionamento da máquina), como o DOS e OS, da IBM. Estes evoluíram possibilitando novos conceitos que melhoraram a performance das máquinas, como por exemplo os sistemas de multiprogramação, isto é, a possibilidade de vários programas serem executados em paralelo em uma mesma da máquina. Se um destes programas tiver origem em um terminal remoto, tal sistema será chamado de tempo compartilhado. Um importante marco que possibilitou esses avanços foi a introdução de processadores de entrada e saída, também chamados de canais. Isso motivou o aparecimento dos conceitos de concorrência, comunicação e sincronização: uma vez que dois processadores estão operando simultaneamente, surge a necessidade de prover mecanismos para sincronizá-los e estabelecer um canal de comunicação entre eles.

É a era das arquiteturas mainframes: o suporte às tarefas computacionais e o desenvolvimento das aplicações eram feitos numa área central, denominada centro de computação. Terminais conectados diretamente à máquina eram utilizados somente por pessoas relacionadas às aplicações disponíveis.

Nos anos 70 surgiram os supercomputadores, máquinas que inovaram na arquitetura. Até o momento, o crescimento da eficiência dos computadores estava limitado pela tecnologia, mais especificamente pelo processamento escalar que exigia que o processador central de um computador terminasse uma tarefa para começar a realizar outra, produzindo o gargalo de von Neumann. Um avanço significativo veio com o supercomputador Cray-1, da Cray Research§7, em 1971. Foi a primeira máquina pipeline, cujo processador executava uma instrução dividindo-a em partes, como na linha de montagem de um carro. Enquanto a segunda parte de uma instrução estava sendo processada, a primeira parte de outra instrução começava a ser trabalhada. A evolução seguinte foi a denominada máquina vetorial, ou máquina SIMD (single instruction multiple data) cujo processador trabalhava com mais de um conjunto de dados ao mesmo tempo. Um pouco depois surgiu a arquitetura MIMD (multiple instructions multiple data) e apareceram máquinas com múltiplos processadores como a Connection Machine, com 65.536 processadores§8.

Há primariamente três limites para a performance dos supercomputadores: a velocidade do processador, o gasto de tempo (o termo técnico, amplamente utilizado na Computação, é overhead), que envolve fazer um grande número de processadores trabalharem juntos em uma única tarefa, e a velocidade de entrada e saída entre os processadores e entre os processadores e a memória§9. A velocidade dos processadores aumenta a cada dia, mas a um alto custo de pesquisa e desenvolvimento, e a realidade é que se está alcançando os limites dos processadores baseados em silício. Seymour Cray demonstrou que a tecnologia de gálio arsênico poderia ser a solução, mas é muito difícil trabalhar com ele e poucas indústrias estariam aptas a desenvolver processadores desse tipo. A solução, como se falará mais abaixo caminha para o uso de um maior número de processadores, dando maior velocidade ao computador pelo uso desses processadores através do processamento paralelo.

Com a tecnologia VLSI (quarta geração de computadores) surgiram os minicomputadores, o que possibilitou muitas empresas e universidades informatizarem seus departamentos. Os grandes usuários interligavam os minicomputadores para enviar tarefas aos seus mainframes. A arquitetura principal continuava no entanto estabelecida no centro de computação. Do minicomputador para o computador pessoal foi somente um passo, e no início da década de 1980 apareceram os primeiros PC's. Ainda nos anos de 1980 apareceram as arquiteturas RISC (Reduced Instruction Set Code), com a promessa de ganho de desempenho pela eliminação do conceito de microprograma. De qualquer maneira estas máquinas ainda são máquinas de von Neumann tradicionais, com todas as suas limitações, a maior delas a velocidade dos circuitos que não pode crescer indefinidamente.

As tentativas de quebrar o gargalo de von Neumann e o início da descentralização dos sistemas, com o surgimento das arquiteturas de rede que possibilitaram a universalização do uso da tecnologia da Computação, fizeram emergir e desenvolver as arquiteturas paralelas de hardware.

A idéia de incluir paralelismo nos computadores é tão antiga quanto os próprios computadores. Trabalhos desenvolvidos por von Neumann na década de 1940 já discutiam a possibilidade de algoritmos paralelos para a solução de equações diferenciais. O sistema Model V, desenvolvido entre 1944 e 1947 por G. R. Stibitz e S. B. Willians nos laboratórios da Bell Telephone é um exemplo típico de máquina paralela. Constituído por dois processadores e de três posições de entrada e saída, esse multiprocessador primitivo tanto era capaz de executar dois programas distintos como era possível que os dois processadores ficassem alocados para um mesmo programa. Posteriormente foi desenvolvido o Illiac IV, na década de 1960, constituído por 64 processadores. Como foi citado, a partir da década de 1970 começaram a ser produzidos supercomputadores baseados em arquiteturas paralelas.

Juntamente com as arquiteturas evoluiram os sistemas operacionais e a evolução das linhas de processadores de uma empresa como a Intel servem para refletir a evolução da indústria dos computadores em um determinado período. Como destaque podem-se citar o MS-DOS, o OS/2 e o UNIX. Especialmente este último, que surgiu como fruto dos trabalhos de um engenheiro da Bell Labs, Ken Thompson, foi popularizado nos meios universitários que usavam computadores PDP-11/45, durante a década de 1970. A palavra UNIX espalhou-se rapidamente por todo o mundo e no início de 1980 este sistema operacional estava disponível em mais máquinas do que qualquer outro sistema operacional da época, continuando hoje ainda a ser amplamente utilizado.

A mais nova arquitetura, que determinou a mais recente evolução da Computação foi o resultado da rápida convergência das tecnologias de comunicações de dados, telecomunicações e a própria informática. É a Internet, ou modelo computacional baseado em uma rede, que teve sua origem nos anos da década de 1970, como um esforço do Departamento de Defesa dos EUA para conectar a sua rede experimental, chamada ARPAnet, a várias outras redes de rádio e satélites. Espalhou-se logo em seguida nos meios acadêmicos e está bastante popularizada.

 


A Computação como Ciência

[topo]

Ao lado dessa evolução do hardware e do software, a Computação abriu-se em leque e novas tendências surgiram dentro dela, incorporando estas duas entidades.

A Inteligência Artificial, a Teoria da Complexidade Computacional§10 e a Teoria de Bancos de Dados abriram novos campos de estudo. Na década de 1960 a Ciência da Computação tornou-se uma disciplina verdadeira. A primeira pessoa a receber um título de Ph. D. de um departamento de Ciência da Computação, foi Richard Wexelblat, na Universidade da Pensilvânia , em 1965. Consolidaram-se os estudos sobre a Teoria dos Autômatos e a Teoria de Linguagens Formais, principalmente com Noam Chomsky e Michael Rabin. O nascimento do ramo das especificações formais, que introduziu um novo paradigma no desenvolvimento de sistemas computacionais, veio dentro dessa década, com o início das buscas pela corretude de programas através do uso de métodos formais.

R. W Floyd, em 1967, propôs que a semântica de linguagens de programação fosse definida independentemente dos porcessadores específicos a que se destinam aquela linguagem. A definição pode ser dada, segundo Floyd, em termos do método para a prova de programas expresso na linguagem. O seu trabalho introduziu o que passou a ser conhecido como o método das anotações (assertivas) indutivas para a verificação (prova) de programas e uma técnica envolvendo "conjuntos com ordenação bem fundada para provar a terminação de um programa§11.

Uma extensão das idéias de Floyd foi proposta por C. A. Hoare em 1969. Hoare formulou uma teoria axiomáticana de programas que permite a aplicação do método das invariantes de Floyd a textos de programas expressos em linguagens de programação cuja semântica é precisamente formulada. Este trabalho tornou-se ainda um dos fundamentos do que se chamou mais tarde "programação estruturada". Dijkstra desenvolveu a idéia de que a definição (no estilo proposto por Hoare) pode ser usada para a derivação (síntese) de um programa e não apenas para sua verificação49.

A partir dessas pesquisas surgiu a Engenharia de Software, que busca garantir a corretude na construção de sistemas. O desenvolvimento de sistemas computacionais até então era feito de uma maneira quase que artesanal. Não havia critério orientativo algum durante o processo. Isso acabou sendo fatal, como o revelaram certos estudos, elaborados na década de 1970, sobre o desenvolvimento de sistemas: ausência de corretude e consistência, baixa qualidade, manutenção extremamente custosa em função de problemas não detectados por ausência de uma validação de requisitos mais rigorosa, não reaproveitamento de código, prazos de implementação não cumpridos em consequência de erros detectados ao longo desta mesma fase de implementação, etc.

Obedecendo a um grau de formalização maior, apareceram como primeira reação a essa abordagem informal§12 modelos e métodos de desenvolvimento de sistemas chamados estruturados, que na verdade são conjuntos de normas e regras que guiam as várias fases de desenvolvimento de sistemas e as transições entre elas. É a abordagem sistemática. Ainda aqui não está presente um formalismo definido com regras precisas. A prototipação e a orientação a objeto são abordagens que podem ser consideradas sistemáticas.

A abordagem rigorosa já apresenta um sistema linguístico formal para documentar as etapas de desenvolvimento e regras estritas para a passagem de uma etapa a outra. Não se exige que as demonstrações de corretude das transformações realizadas sejam feitas formalmente, bastando uma argumentação intuitiva§13. E finalmente a abordagem puramente formal, rigorosa, com a exigência de que todas as demonstrações necessárias para garantir a corretude do processo sejam realizadas formalmente.

É necessário notar que essas duas últimas abordagens exigem um conhecimento mais profundo do raciocínio lógico formal e de um sistema linguístico formal adequado. Embora a abordagem formal se apresente como único meio de se dar uma garantia real à atividade de construção de sistemas, muitos autores mostram-se céticos quanto ao verdadeiro impacto que ela venha a ter na prática, devido à dificuldade de aprendizado do necessário arcabouço matemático.

Donald E. Knuth iniciou nos fins dessa década um rigoroso tratado sobre as bases matemáticas para a análise de algoritmos, produzindo os três conhecidos volumes do The Art of Computer Programming, que propiciaram a base para o amadurecimento dos estudos da complexidade de algoritmos. Pode-se dizer que o trabalho de Knuth é um dos grandes marcos da Computação no século XX: antes de Knuth não havia um corpo sistemático do estudo da programação e dos algoritmos.

Ainda no campo da Complexidade Computacional novos avanços se deram a partir de 1971, com o trabalho de Steve Cook e Richard Karp sobre problemas NP-completos§14 e os estudos sobre criptografia de Ronald Rivest, Adi Shamir e Leonard Adleman. Em 1977 H.J. Bremermann desenvolveu alguns trabalhos pioneiros dentro da teoria da complexidade, mostrando os limites físicos na arquitetura de computadores de qualquer tipo e que estes limites físicos atuam como fatores restritivos para a computação de determinados problemas. De acordo com ele, existe um tempo chamado limite fundamental para a velocidade dos computadores que não pode ser ultrapassado. Tal limite deriva-se da idéia de que a velocidade máxima de transmissão de sinal entre os componentes internos da máquina é limitada pela velocidade da luz. Mesmo que se pudessem construir máquinas muito pequenas, otimizando-se a trajetória de transmissão de sinais, esse limite não pode ser ultrapassado. E ainda que se chegue a uma máquina cuja velocidade de transmissão seja próxima à da luz, existem problemas computacionais que são intratáveis, como por exemplo os "problemas NP": mesmo com a velocidade da luz tais problemas poderiam levar a idade do universo para serem processados71.

 


A inteligência artificial

[topo]

É um dos ramos da Ciência da Computação merecedor de especial destaque, tal sua gama de influência nas pesquisas e novas áreas que se abriram a partir do seu início. É aquela área da Computação, em termos mais gerais, voltada para o estudo de técnicas de construção de programas que permitam ao computador simular aspectos do comportamento da inteligência, tais como jogar xadrez, provar teoremas lógicos, compreeder de partes específicas de uma linguagem como por exemplo o português, etc.

Os primórdios da Inteligência Artificial (IA a partir de agora) remontam à década de 1940. Começou a predominar nestes anos o movimento ciberneticista, que acreditava entre outras coisas que a atividade humana poderia um dia ser estudada por meio de modelos matemáticos, como se faz com outros tantos fenômenos da natureza. Seguindo os trabalhos de Gödel, muitos matemáticos imbuíram-se do ideal de formalizar a noção de procedimento e sobre o que poderia ser feito através de um algoritmo e vieram a tona os trabalhos de Turing, Church, Kleene e Post§15. Os resultados destes esforços acabaram por ser equivalentes e se estabeleceram os limites do que é computável§16.

No ano de 1943 foram publicados os trabalhos de Warren McCulloch e Walter Pitts, que propuseram um modelo de neurônios artificiais, onde cada neurônio era caracterizado como sendo "on" ou "off", e era representado por uma chave onde "on" seria a resposta a estímulos por um dado número de neurônios vizinhos. Eles mostraram que qualquer função computável poderia ser processada por algum tipo de rede de neurônios conectados e que os conectivos lógicos poderiam ser implementados através de estruturas de rede simples51. Estão presentes aqui as pesquisas de Claude Shannon, que entre outras coisas descreveu em termos lógicos o funcionamento de certos sistemas materiais, e vice-versa: sistemas materiais que poderiam representar um raciocínio lógico. A fusão das idéias de Shannon e Boole, junto a um tratamento simplificado do neurônio do cérebro humano, tornou possível o trabalho de McCulloch e Pitts, que propuseram um modelo de neurônio artificial (há um excelente trabalho sobre este assunto em1). Queriam esses dois pesquisadores mostrar que se os neurônios artificiais pudessem efetuar computações lógicas, estaria aberto o caminho para simular o raciocínio humano.

Os trabalhos de Warren McCulloch e Walter Pitts tiveram grande sucesso e outros trabalhos apareceram, mas logo foram objeto de fortes críticas. Frank Rosemblatt e seus colegas da Universidade de Cornell projetaram uma máquina parecida com o modelo de McCulloch e Pitts, denominada Perceptron§17. Marvin Minsky e Seymour Papert mostraram algumas limitações dos perceptrons, como por exemplo a impossibilidade de executarem operações lógicas do tipo "ou exclusivo". De qualquer maneira surgiu uma primeira vertente da emergente IA: a que buscava a simulação do cérebro humano do ponto de vista físico, para simular a atividade mental, e que fará surgir anos mais tarde, na década de 1970, a Ciência Cognitiva ou Conexionismo, que está apoiada em um paradigma da IA de processamento serial da informação e no "approach" da manipulação simbólica para linguística.

Outra vertente por onde se encaminharam os estudos da IA foi a chamada Inteligência Artificial simbólica, que buscava a representação e a simulação dos estados e do comportamento mentais através de programas computacionais. A representação e simulação da inteligência não estaria na construção de um determinado tipo de hardware, mas no desenvolvimento de um software que opere sobre dados. Isto teve profundos reflexos nas pesquisas posteriores e suscitou inúmeros debates, sobretudo na filosofia, sobre as relações entre a mente e o cérebro§18. Em71, capítulo 4, há um capítulo sobre as grandes objeções levantadas ao termo IA no sentido forte, o qual diz que um computador adequadamente programado é uma mente e reproduz estados mentais.

Em 1950 Turing introduziu através de um artigo, Computing Machinery and Intelligence, o chamado 'Turing Test"§19, considerado também um dos primeiros esforços no campo da Inteligência Artificial 65. Mais tarde o próprio Turing (1953) escreveu um programa de xadrez para computadores que tinham a arquitetura de von Neumann. Ao mesmo tempo, Marvin Minsky e Deam Edmonds, do Departamento de Matemática de Princeton, construíram o primeiro computador baseado em rede neural, em 1951, o SNARC. Era um computador analógico para simular uma rede de 40 neurônios65.

John McCarthy, outra figura influente da IA, após formar-se em Princeton, dirigiu-se ao Dartmouth College e convenceu Minsky, Shannon e Nathaniel Rochester, um pesquisador da IBM, a ajudá-lo a trazer pesquisadores interessados em teoria dos autômatos, redes neurais e no estudo da inteligência. Allen Newell e Herbert Simon, da Carnegie Mellon University elaboraram o LT (Logic Theorist)§20, um programa capaz de trabalhar não-numericamente e que provou a maioria dos teoremas do segundo capítulo do Principia Mathematica, de Russell e Whitehead. Em 1952, Arthur Samuel mostrou que os computadores não fazem somente o que se lhes pede, mas são capazes de "aprender". Outros programas provadores de teoremas se seguiram ao LT e em 1958, com McCarthy surgiu o LISP, que se tornou a linguagem de programação predominante para IA a partir daí.

McCarthy seguiu para Stanford na busca da representação do raciocínio através da lógica formal (seu trabalho recebeu grande impulso quando J. A. Robinson elaborou um algoritmo completo para a prova de teorema na lógica de primeira ordem). Estas aplicações da lógica incluíam robótica e um projeto para demonstrar a completa integração entre raciocínio lógico e atividade física. Minsky estava mais interessado em descobrir programas para resolver problemas que exigiam inteligência para ser solucionados: problemas de analogia geométrica que aparecem nos testes de QI, problemas de álgebra, etc65.

Os anos de 1966 a 1974 foram marcados por um certo ceticismo diante das dificuldades que começaram a ser encontradas, como por exemplo a não tratabilidade de muitos problemas de IA, acentuada pelos primeiros estudos dos problemas NP, as limitações das estruturas básicas usadas para gerar comportamento inteligente, como por exemplo os algoritmos de aprendizado por back-propagation65.

A década de 1970 marcou a busca pelos sistemas baseados em conhecimento e pelos sistemas especialistas, protagonizada inicialmente por Ed Feigenbaum, Bruce Buchanan e Joshua Lederberg. Os sistemas especialistas são solucionadores de problemas acoplados a grandes bancos de dados onde o conhecimento humano específico sobre determinado assunto encontra-se armazenado. O sistema deverá fornecer respostas a consultas, dar conselhos a um leigo sobre um determinado assunto, auxiliar especialistas, ensinar, etc. A idéia subjacente é que a inteligência não é somente raciocínio mas também memória. A grande meta é a preservação do conhecimento de especialistas após a morte destes. O problema, ainda em aberto, é a difícil tarefa de se representar o conhecimento, aliás nome de uma nova área surgida dentro da IA para solucionar os inúmeros problemas surgidos, principalmente os de como representar o "senso comum", o "sexto sentido" ou ainda a intuição, termos que resistem a uma conceituação clara. Ou ainda qualquer tipo de conhecimento não representável por uma expressão simbólica como ensinar alguém a jogar bola. Como formalizar estas coisas? Mais ainda: até que ponto a formalização é um instrumento eficiente para a representação do conhecimento? De qualquer maneira surgiram os sistemas especialistas para diagnóstico médico, manipulação de linguagens, etc.

Lembrando o trabalho de H.J. Bremermann citado no item anterior (A Computação como Ciência), sobre os limites físicos que impedem a construção de um dispositivo com velocidade 'ilimitada' (maior que a da luz por exemplo), deve-se reparar que esses mesmos limites estão presentes também dentro das reações químicas e nos impulsos elétricos que se dão nas complexas conexões dos neurônios do cérebro. Se a mente humana consegue resolver determinados problemas intratáveis (o problema da parada na máquina de Turing por exemplo) e funciona de maneira algorítmica (como pensa determinda corrente de estudiosos da simulação da mente por computador), as operações mentais tem algo a mais do que as características físicas do cérebro humano. Ou então há processamentos mentais não algorítmicos, e se cai no problema da impossibilidade de uma representação formal disso. São debates em aberto e que geram um saudável intercâmbio de idéias entre a Computação e outras áreas do conhecimento humano como a Psicologia, Biologia e Filosofia.

Também a robótica demandou estudos da área de IA, principalmente no que se refere à Visão Computacional. Os anos da década de 1980 foram os da introdução da IA na indústria e um retorno ao uso de redes neurais. De 1987 para cá houve uma mudança tanto no conteúdo quanto na metodologia das pesquisas em IA. Agora é mais comum trabalhar em teorias existentes do que a proposição de novas, e basear-se em teoremas rigorosos ou em fortes evidências experimentais do que sobre intuição. O campo do reconhecimento da voz é um exemplo disto.

 


Um anexo: a cibernética

[topo]

O nascimento da cibernética como ciência está associado aos trabalhos de Norbert Wiener (1894-1964). Na II Guerra Mundial ele foi encarregado pelo governo norte-americano de resolver os problemas de controle automático da direção de tiro na artilharia antiaérea. Wiener desenvolveu suas investigações no MIT e idealizou um sistema mediante o qual o erro, ou diferença entre o objetivo que se pretendia alcançar e o efeito real alcançado, era medido e utilizado para regular o próprio sistema, corrigindo as variáveis de velocidade, ângulo de tiro, etc. O fenômeno de auto-regulação recebeu o nome de realimentação (feedback).

Wiener alcunhou o termo "cibernética" tomando diretamente o vocábulo grego "kybernetiké", que significa "a arte de governar um barco". Este termo tinha um amplo uso no pensamento grego, em referência precisamente a fenômenos muito similares ao estudado pelo engenheiro norte-americano. Assim ele próprio define a cibernética como "controle e comunicação no animal e na máquina", como aparece no título de seu livro Cybernetics67.

A Cibernética é uma teoria formada pelos aspectos relevantes de outras quatro teorias: da informação, dos jogos, do controle e do algoritmo. Estão diretamente relacionados com essa teoria os trabalhos de:

Embora a cibernética como ciência não tenha como objetivo o computador - para ela é apenas mais uma das muitas estruturas existentes no universo -, ela criou juntamente com a teoria da informação de Shannon um novo caminho para se tentar entender o homem e as máquinas. Ao se ocupar das estruturas e funções lógico-matemáticas de auto-regulação, independentemente de que estejam inscritas e se cumpram em um organismo vivo, ou em uma população humana ou em um computador eletrônico, acabou tomando parte indiretamente no desenvolvimento do hardware e do software.

A idéia de informação como uma das características fundamentais do universo levou Wiener e Shannon, separadamente, a demonstrarem que muitas coisas, desde o movimento aleatório de partículas subatômicas até o comportamento de redes baseadas em chaveamentos elétricos ou alguns aspectos do discurso humano, estão relacionados de um modo que possam ser expressados através de algumas equações matemáticas básicas§21. Estas equações foram úteis na construção de computadores e redes telefônicas: muitos conceitos elaborados e delineados pela cibernética e teoria da informação tornaram-se centrais no projeto lógico de máquinas e na criação do software.

 


Notas


§1.Large Scale Integration, Very Large Scale Integration, Ultra Large Scale Integration.

§2. No capítulo sobre a "A grande corrida das linguagens" se falará um pouco sobre esse paradigma

§3. Aparece aqui novamente este termo, utilizado por Knuth38 e John Backus77 e, de acordo com este último significava naqueles primeiros tempos "para muitos simplesmente escrever códigos mnemônicos e endereço simbólico, para outros o simples processo de acessar subrotinas de uma biblioteca e inserir nelas os endereços dos operandos. A maior parte dos sistemas de 'programação automática' eram programas de montagem ou conjuntos de subrotinas ou os sistemas interpretativos (...)"77.

§4. O paradigma ou arquitetura de von Neumann refere-se ao conceito de programa armazenado, conforme documento apresentado por Neumann em junho de 1945 sobre o EDVAC. As linguagens imperativas, preocupadas com performance de execução, têm em em conta o trânsito dos dados entre a unidade central de processamento e os dipositivos onde estão armazenadas instruções e informações .

§5. Falando de uma maneira mais técnica e bastante genérica, significa que o foco da atenção do programador recai mais nos dados da aplicação e nos métodos para manipulá-los do que nos estritos procedimentos.

§6. Em termos gerais significa o partilhamento de uma aplicação em duas. A interface do usuário e a maioria dos programas é executada no cliente, o qual será provavelmente uma estação de trabalho ou um PC de alta performance. Os dados da aplicação residem no servidor, provavelmente em um banco de dados de um computador de grande porte. Desta maneira mantêm-se os dados onde podem ser melhor protegidos, atualizados, salvos, enquanto que o poder computacional fica distribuído diretamente pelas mesas de trabalho dos 'clientes'.

 §7. Muito da história dos primeiros tempos dos supercomputadores coincide com a história daquele que é considerado o pai dos supercomputadores, Seymour Cray (1926-1996), fundador da Cray Research, que liderou a construção dos computadores mais rápidos do mundo durante vários anos. Seymour Cray inventou ou contribuiu diretamente na criação de múltiplas tecnologias usadas pela indústria dos supercomputadores, entre as quais está: a tecnologia de vetor de registradores no CRAY-1, a tecnologia so semicondutor de gálio arsênico e a arquitetura RISC (Reduced Instruction Set Computing).

§8. Deve-se observar que apesar da capacidade de execução paralela de centenas de tarefas, dependendo de como é feita a comunicação entre os processadores, a eficiência de tais máquinas pode ser frustante e as pesquisas continuam em busca de uma maior eficiência.

§9. A velocidade de entrada/saida entre a memória principal (tecnicamente conhecida como RAM) e os dispositivos de armazenamento é um problema que afeta todos os tipos de computadores. Mas como os supercomputadores tem uma grande quantidade de memória principal, este problema pode ser resolvido facilmente com um gasto mais generoso de dinheiro

§10. A Teoria da Complexidade Computacional é um ramo da Computação que estuda o grau de dificuldade envolvido na resolução algorítmica de classes de problemas. Um dos principais tópicos abordados diz respeito à eficiência (em termos de tempo) envolvida na execução de um algoritmo.

§11. O objetivo é escolher essas proposições de tal forma que elas sejam satisfeitas cada vez que o fluxo de controle do programa passe pelo ponto anotado e de maneira que cada ciclo do fluxograma seja "cortado" (anotado) por uma proposição. Cada proposição deve ser verdadeira toda vez que ela é atingida. Como toda proposição deve ser verdadeira toda vez que ela é atingida, toda proposição é uma invariante da computação (o método também é conhecido como método das invariantes)

§12. Para estabelecer uma distinção entre as várias espécies de abordagem vamos seguir uma classificação sugerida por Bjorner70, de acordo com o grau de formalização.

§13. É importante notar que a prova formal pode ser feita.

§14. Um problema dito P (de polinomial) é executado em um computador com um número de passos dado pela fórmula Ank ( A e k são inteiros fixos e n é o número de dados de entrada). Algoritmos NP (de tempo não determinístico polinomial) executam em tempo exponencial, em um número de passos 2n ou n! (problema do caixeiro viajante por exemplo, a solução de alguns teoremas lógicos de primeira ordem, o problema da torre de Hanói, etc.).

§15.Como foi visto, Turing desenvolveu a Máquina de Turing, Church desenvolveu o cálculo-lambda (que forneceu a base para a linguagem LISP, desenvolvida por McCarthy, uma das favoritas do pessoal da IA), Kleene desenvolveu a teoria das funções recursivas, enquanto Emil Post introduziu sistemas para reescrita de cadeias de símbolos (a gramática de Chomsky é um caso particular disso).

§16. Como um dos subprodutos do trabalho de Church, ficou estabelecido que tudo aquilo que um ser humano possar fazer manipulando símbolos, seguindo um finito e bem definido conjunto de regras, uma máquina equipada com o conveniente programa também poderá fazê-lo.

§17. Pode-se imaginar um Perceptron como um dispositivo para o reconhecimento de um conjunto de padrões, não específico, isto é, com capacidade de "aprender" a reconhecer os padrões de um conjunto após um número finito de tentativas.

§18. Na verdade tais indagações remontam ao filósofo Renè Descartes que introduziu a primeira fissura no pensamento filosófico de até então, ao cavar um fosso profundo entre a matéria e o espírito humano.

§19. Ele propôs uma definição de "pensamento" usando um jogo: um homem teria de decidir, baseado em uma conversa via teletipo, se a entidade que estava na sala ao lado, respondendo a um teste, era um ser humano ou um computador. Se a distinção não pudesse ser feita, então poderia ser dito que o computador estava "pensando"74.

§20. Newell e Simon também inventaram a linguagem IPL, para processamento de listas, para escrever o LT. Como não tinham compilador, traduziram manualmente para o correspondente código de máquina.

§21. Sobre estas idéias tão sumariamente enunciadas remetemos ao livro Cibernética, capítulo introdutório78.

 [topo]