Projeto de Iniciação Científica: O Uso de Programação Multiagente no Estudo da Difusão de Inovações Tecnológicas

(Parte do projeto de pesquisa CNPq 18/2012)

 

João Pedro Azevedo Maldos (Bolsista)

Escola de Administração de Empresas de São Paulo (FGV – EAESP)

 

Júlio César Bastos de Figueiredo (Orientador)

Escola de Administração de Empresas de São Paulo (FGV – EAESP)

O objetivo deste projeto foi estudar como o uso do modelo de difusão de Frank Bass (1969), aliado ao uso de modelos computacionais baseados no paradigma da programação multiagente, podem auxiliar as empresas na formulação e análise de projetos de difusão de inovações tecnológicas.  O estudo foi dividido em duas etapas, correspondentes aos trabalhos realizados pelo pesquisador no segundo semestre de 2011 e no primeiro semestre de 2012. Na primeira etapa foi feita a implementação do modelo de programação multiagente proposto por Michael Samuels (2009) para estudar, com base nas teorias de Frank Bass (1969) e Rogers (1995), a difusão de inovações tecnológicas. A segunda etapa, realizada ao longo do primeiro semestre de 2012, estendeu o modelo de Samuels (2009) considerando modificações que incorporam aspectos não considerados no modelo original como, por exemplo, a possibilidade de considerar variações nos parâmetros de difusão. Tais variações seriam função de outras varáveis exógenas, tais como, por exemplo, a renda da população. Por fim, o modelo final foi convertido em um simulador e disponibilizado no ambiente WEB para estimular o debate e sugestões.

download model file: jmaldos.nlogo

CÓDIGO FONTE

breed 
[ 
  pessoas 
]
 
globals
[
  tempo
  renda
  
  ;influências internas (contato interpessoal)
  contatos
  velho-contatos
  contatos-por-tempo
  conversas-inicio
  velho-conversas-inicio
  inicios-por-tempo
  conversa-fim
  velho-conversa-fim
  fins-por-tempo
  conversas-ativas
  total-amigos     ;total de conversas: amigos, estranhos, etc
  
  ;influências externas (mass media)
  externas
]
 
patches-own
[
  intensidade
  cor-original
]
 
pessoas-own
[
  tipo                     ;super-early-adopters, inovadores, early-adopters, early-majority, late majority, laggards, nulos
  aceitacao                ;número arbitrário
  muda-agente?  
  iniciador?               ;quem iniciou a conversa
  parceiro                 ;quem é o parceiro atual na conversa
  media?           
  inicia-tempo             ;quando a conversa comecou
  termina-tempo            ;quando a conversa vai terminar
  num-conversas            ;número de conversas (cumulativo)
  total-tempo-interacoes   ;tempo gasto em conversas (cumulativo)
  num-externas             ;número de interacao com medias externas (cumulativo)
  tempo-total-externa      ;tempo total gasto em medias externas (cumulativo)
  memoria                  ;lista de parceiros
]
 
 
;SETUP
to setup
  ca
  setup-globais  
  setup-patches
  setup-pessoas
  setup-plot
end
 
to setup-globais
  random-seed semente
  set tempo 0
  set renda 0
  
  ;internas
  set contatos 0
  set velho-contatos 0
  set contatos-por-tempo 0.0
  set conversas-inicio 0
  set velho-conversas-inicio 0
  set inicios-por-tempo 0
  set conversa-fim 0
  set velho-conversa-fim 0
  set fins-por-tempo 0
  set conversas-ativas 0
  set total-amigos 0
    
  ;externas
  set externas 0
end
 
 
to setup-patches
  ask patches
  [
    set pcolor black
    set intensidade (random 100)
    set cor-original black
  ]
  
  if Tech1-externa?
  [
    let x int (x-adota / 100 * max-pxcor)
    let y int (y-adota / 100 * max-pycor)
    let s int (s-adota / 100 * (max-pxcor + 1))
    ask patches
    [
      if (pxcor > x - s) and (pxcor < x + s) and (pycor > y - s) and (pycor < y + s)
      [
        set pcolor violet
        set cor-original violet
      ]
    ]
  ]
  
  if Tech2-externa?
  [
    let x int (x-romper / 100 * max-pxcor)
    let y int (y-romper / 100 * max-pycor)
    let s int (s-romper / 100 * (max-pxcor + 1))
    ask patches
    [
      if (pxcor > x - s) and (pxcor < x + s) and (pycor > y - s) and (pycor < y + s)
      [
        set pcolor magenta
        set cor-original magenta
      ]
    ]
  ]
  
  if Suavidade > 0
  [
    repeat Suavidade [ diffuse intensidade 1 ]
    reescala
    recolore
  ]
  
end
    
to reescala
  let maior max [ intensidade ] of patches
  let menor min [ intensidade ] of patches
  ask patches
  [
    set intensidade (((intensidade - menor) * 100) / (maior - menor ))
  ]
  let nmaior max [ intensidade ] of patches
  let nmenor min [ intensidade ] of patches
  print (word "Intensidade vai de " menor " a " maior " mudando de " nmenor " a " nmaior)
 
end
 
to recolore
  ask patches
  [
    ifelse cor-original = violet
    [
      set pcolor scale-color violet intensidade 0 100
    ]
    
    [ifelse cor-original = magenta
      [ set pcolor scale-color magenta intensidade 0 100 ]
      [ set pcolor cor-original ] ;ignora patches de cor preta
    ]
  ]
  
end
    
to setup-pessoas
  create-pessoas populacao-total
  [
    setxy random-pxcor random-pycor
    set termina-tempo 0
    set total-tempo-interacoes 0
    set num-conversas 0
    set tempo-total-externa 0
    set num-externas 0
    set parceiro nobody
    set shape "person"
    set muda-agente? false
    set iniciador? false
    set media? false
    set memoria []
    
    let tipo-prob (random 100)
    ifelse (tipo-prob < prob-tech2-cumulativa)
    [
      set-tech2
      if random 100 < tech2-agente [ set-muda-agente ] ;geeks que preferem ter tudo antes de todos
    ]
    [
      ifelse (tipo-prob < prob-tech1-cumulativa)
      [
        set-tech1
        if random 10 < tech1-agente [ set-muda-agente ] ;inovadores
      ]
      [
        ifelse (tipo-prob < prob-early-adopter-cumulativa) [ set-early-adopter ] ;aceita facilmente
        [ ifelse (tipo-prob < prob-early-majority-cumulativa) [set-early-majority ] ;aceita um pouco menos facilmente
          [ ifelse (tipo-prob < prob-late-majority-cumulativa) [ set-late-majority ] ;relutante em aceitar
            [ ifelse (tipo-prob < prob-laggard-cumulativa) [ set-laggard ] ;muito relutante em aceitar
              [ set-nulo ] ;o resto - que nunca aceitarao
            ]
          ]
        ]
      ]
    ]
  ]
end
 
to set-tech2
  set tipo 0
  set aceitacao tech2
  set color red
end
 
to set-tech1
  set tipo 1
  set aceitacao tech1
  set color orange
end
 
to set-early-adopter
  set tipo 2
  set aceitacao earlyadopter
  set color yellow
end
 
to set-early-majority
  set tipo 3
  set aceitacao earlymajority
  set color lime
end
 
to set-late-majority
  set tipo 4
  set aceitacao latemajority
  set color cyan
end
 
to set-laggard
  set tipo 5
  set aceitacao laggard
  set color blue
end
 
to set-nulo
  set tipo 6
  set aceitacao nulo
  set color violet
end
 
to set-muda-agente
  set muda-agente? true
  set shape "face happy"
end
 
 
;GRÁFICOS E OUTPUTS
 
to setup-plot ;é um histograma, nao colocar limites - o modelo irá auto colocar
  set-current-plot "Tipo de Adocao"
  set-histogram-num-bars 7
  update-plot-tipo
end
 
to update-plot-pop ;populacao
  let total count pessoas
  let t2 count pessoas with [ tipo = 0 ]
  let t1 count pessoas with [ tipo = 1 ]
  let potenciais ( total - t2 - t1 )
  set-current-plot "Populacoes"
  set-current-plot-pen "Total"
  plot total
  set-current-plot-pen "Potenciais"
  plot potenciais
  set-current-plot-pen "Adopters"
  plot ( t1 + t2 )
  set-current-plot-pen "Tech2"
  plot count pessoas with [ tipo = 0 ]
  set-current-plot-pen "Tech1"
  plot count pessoas with [tipo = 1]
  set-current-plot-pen "EarlyAdopter"
  plot count pessoas with [tipo = 2]
  set-current-plot-pen "EarlyMajority"
  plot count pessoas with [tipo = 3]
  set-current-plot-pen "LateMajority"
  plot count pessoas with [tipo = 4]
  set-current-plot-pen "Laggard"
  plot count pessoas with [tipo = 5]
  set-current-plot-pen "Nulos"
  plot count pessoas with [tipo = 6]
end
 
to update-plot-stats ;contatos, conversas e encontros
  set-current-plot "Nivel de Familiaridade"
  set-current-plot-pen "Nivel de Familiaridade"
  ifelse ( conversas-inicio > 0 )
    [ plot total-amigos / conversas-inicio ]
    [ plot 0 ]
end
 
to update-plot-encontros ;histogramas de encontros
  set-current-plot "Conversas por pessoa"
  set-current-plot-pen "Interna"
  histogram [ num-conversas ] of pessoas
end
 
to update-plot-tipo ;histograma do tipo tech1
  set-current-plot "Tipo de Adocao"
  set-current-plot-pen "Tipo"
  histogram [ tipo ] of pessoas
end
 
to update-plot-renda
  set-current-plot "Evolucao da Renda"
  set-current-plot-pen "Renda"
  plot renda
end
 
;MONITORES
 
to update-monitores
  set contatos-por-tempo ( contatos - velho-contatos )
  set inicios-por-tempo ( conversas-inicio - velho-conversas-inicio )
  set fins-por-tempo ( conversa-fim - velho-conversa-fim )
  set conversas-ativas ( conversas-inicio - conversa-fim )
  set velho-contatos contatos
  set velho-conversas-inicio conversas-inicio
  set velho-conversa-fim conversa-fim
end
 
;; << REGRAS DE INTERAcaO >> A PARTE PRINCIPAL DO MODELO!!!!!
 
to checar-adocao-externa ;checa adocao para Tech1
  ifelse ( media? = false )
  [
    set externas ( externas + 1 )
    set media? true
    set parceiro self
    set inicia-tempo tempo
    set termina-tempo round ( random-exponential tempo-ouvindo ) + tempo
    print ( word tempo ": fator externo influenciou adocao iniciada para " who " para acontecer até " termina-tempo )
  ]
  [
    ifelse tempo >= termina-tempo
    [
      set media? false
      set parceiro nobody
      let prob-de-adocao (( [intensidade] of patch-here / 100 ) *  prob-de-adocao-tech1-externa )
      if random-float 100 < (1.0 / aceitacao ) * prob-de-adocao
      [
        set-tech1
      ]
    move-para-longe
    set num-externas ( num-externas + 1 )
    set tempo-total-externa ( termina-tempo - inicia-tempo + tempo-total-externa )
    print ( word tempo ": " who " do tipo " tipo " terminou de adotar uma secao de mass media com a probabilidade de adocao de " prob-de-adocao )
  ]
  [
    print ( word tempo " : " who " está vendo uma apresentacao de mass media para o tipo tech1 de inovacao")
  ]
]
end
 
to checar-rompimento-externo ;tech2
  ifelse ( media? = false )
  [
    set externas ( externas + 1 )
    set media? true
    set parceiro self
    set inicia-tempo tempo
    set termina-tempo round ( random-exponential tempo-ouvindo ) + tempo
    print ( word tempo " : fator externo influenciou o rompimento iniciado para " who " para acontecer até " termina-tempo )
  ]
  [
    ifelse tempo >= termina-tempo
    [
      set media? false
      set parceiro nobody
      let prob-de-adocao (( [intensidade] of patch-here / 100 ) * prob-de-adocao-tech1-externa )
      if random-float 100 < (1.0 / aceitacao ) * prob-de-adocao
      [
        set-tech2
      ]
      move-para-longe
      set num-externas ( num-externas + 1 )
      set tempo-total-externa ( termina-tempo - inicia-tempo + tempo-total-externa )
      print ( word tempo " : " who " do tipo " tipo " terminou uma secao de rompimento de mass media com a probabilidade de adocao de " prob-de-adocao )
    ]
    [
      print ( word tempo " : " who " está vendo uma apresentacao de mass media para o tipo tech2 de inovacao rompedora" )
    ]
  ]
end
 
to mover
  rt random-float 45
  fd movimento
  setxy pxcor pycor ;centraliza no patch
end
 
to move-para-longe
  rt random-float 180
  jump int ( s-adota / 100 * max-pxcor ) ;move-se para longe do centro de mass media
  setxy pxcor pycor ;centraliza no patch
end
 
 
to iniciar ;faz parceria com alguém no patch que nao está com outro parceiro
  ifelse (any? other pessoas-here with [ parceiro = nobody ] )
  [
    set contatos ( contatos + 1 )
    ifelse ( random-float 100 ) < prob-conversa
    [
      converse
    ]
    [
      print ( word tempo " : nenhuma conversa foi iniciada por " who )
    ]
  ]
  [
    print ( word tempo " : nenhum possivel parceiro para " who )
  ]
end
 
 
to converse
       let amigo 0
       let eu self
       
       set parceiro one-of other turtles-here with 
       [ 
         parceiro = nobody 
       ]
           
       ask parceiro
       [ 
         set parceiro eu 
       ]
       
       ifelse ( member? parceiro memoria = true ) 
         [
           set amigo amigo + 1
         ]
         [ 
           set memoria lput parceiro memoria 
         ]
       ifelse ( member? self [ memoria ] of parceiro = true) 
         [
          set amigo amigo + 1
         ]
         [ 
          ask parceiro
            [ 
             set memoria ( lput self [ memoria ] of parceiro ) 
            ]
         ]
             
       set iniciador? true
       ask parceiro 
       [
          set iniciador? false
       ]
       
       set inicia-tempo tempo
       ask parceiro 
       [
          set inicia-tempo tempo
       ]
       let conversas-fim round (( random-float duracao-conversa) + tempo )
       ask parceiro
       [
         set termina-tempo conversas-fim
       ]
       
       ifelse ( amigo = 2 )
       [
         ask patch-here
         [ 
           set pcolor sky
         ]
       ]
       [
         ifelse ( amigo = 1 )
         [
           ask patch-here
           [
             set pcolor blue
           ]
         ]
         [
           ask patch-here
           [
             set pcolor pink
           ]
         ]
       ]
       
       set conversas-inicio ( conversas-inicio + 1 )
       set total-amigos ( total-amigos + amigo )
       
       print ( word tempo " : conversa entre ID " who " do tipo " tipo " com a lista de memória " memoria " e ID " [ who ] of parceiro " do tipo " 
               [ tipo ] of parceiro " com a lista de memória " [ memoria ] of parceiro " ao nivel " amigo " até " termina-tempo " em [ "xcor","ycor"]" )
end
 
 
to interage
    ifelse (tempo <= termina-tempo) 
    [
       ifelse (tempo > inicia-tempo) 
       [
         print (word tempo ": conversa acontecendo entre " who " e " [ who ] of parceiro )
       ]
       [
         print (word tempo ": ligacao já estabelecida entre  " who " e " [ who ] of parceiro)
       ]
    ]
    [
       ifelse tipo > 1 and [ tipo ] of parceiro = 1 
       [
         if tech1-switch
          [
           if random-float 50000 < (1.0 / aceitacao) * renda * alfa
           [
               set-tech1
           ]
         ]
       ]
       [
         ifelse tipo > 1 and [ tipo ] of parceiro = 0 
         [
           if tech2-switch 
           [
             if random-float 50000 < (1.0 / aceitacao) * renda * beta
             [
                set-tech2
             ]
           ]
         ]
         [
              print (word tempo ": nenhuma mudanca para o ID " who " do tipo " tipo " como parceiro de " [ who ] of parceiro " com tipo " [ tipo ] of parceiro )
         ]
       ]
       
       set num-conversas ( num-conversas + 1 )
       set total-tempo-interacoes ( termina-tempo - inicia-tempo + total-tempo-interacoes )
       ifelse iniciador? 
       [
          set conversa-fim ( conversa-fim + 1 )
          ask patch-here
         [
             set pcolor  cor-original
         ]
          print ( word tempo ": iniciador " who " termina conversa com " [ who ] of parceiro )
       ]
       [
          print ( word tempo ": recipiente " who " termina conversa com iniciador " [ who ] of parceiro )
       ]
       set parceiro nobody
       rt random-float 45
       jump 5 * movimento
    ]
end
    
 
to repensar-adocao
    ifelse random-float 100 < prob-tech1-para-potencial
    [
      set-early-adopter
      print (word tempo ": " who " renegou de tech1 para early adopter" )
    ]
     [
      if tech2-switch and random-float 100 < prob-tech1-para-tech2
      [
        set-tech2
        print (word tempo ": " who "mudou de tech1 para inovador tech2")
      ]
    ]
end
  
to repensa-rompimento
    ifelse random-float 100 < prob-tech2-para-potencial
    [
      set-early-adopter
      print (word tempo ": " who " renegou de tech2 para early adopter" )
    ]
    [
      if tech1-switch and random-float 100 < prob-tech2-para-tech1 
      [
        set-tech1
        print (word tempo ": " who " mudou de volta de tech2 para inovador tech1" )
      ]
    ]
end
 
 
to ir
  set tempo tempo + 1
  set renda (renda + incremento-renda)
    
  ;Pessoas que nao estao em uma conversa irao:
  ; (a) Pensar sobre seu status de adocao atual, podendo mudar de ideia sobre uma adocao ou rompimento. Eles podem
  ;     retornar para um adotante potencial, onde estarao sujeitos a influências de fatores internos e externos.
  ;     Se já sao "tecnólogos", podem adotar o rompimento se já sao um tech1 ou escolher a adocao se sao tech2.
  ;     Note que o último caso é baseado em reflexao pessoal e nao em influências de fatores externos ou internos.
  ; (b) Se mover.
  ; (c) Checar se estao em um patch de "centro de mass media", em que eles podem adotar após ouvirem a mensagem do centro.
  ; (d) Checar se há alguém em volta para conversar sobre tecnologias.
  ;Seestao pareados, eles dao um "update" em seu tipo.
  ask pessoas 
  [
      without-interruption ;influência externa só ocorre para aqueles cujo tipo nao é o mesmo do tipo do centro de media
      [
        if Tech1-externa? and [ pcolor ] of patch-here >= 110.0 and [ pcolor ] of patch-here < 120.0 and tipo != 1 
        [
          checar-adocao-externa
        ]
        if Tech2-externa? and [ pcolor ] of patch-here >= 120.0 and [ pcolor ] of patch-here < 130.0 and tipo != 0 
        [
          checar-rompimento-externo
        ]
        
        ;influência interna: se o parceiro = eu mesmo, mass media está em efeito, entao a influência interna é ignorada.
        ifelse parceiro = nobody 
        [  
            if tipo = 1 [ repensar-adocao ]
            if tipo = 0 [ repensa-rompimento ]
            mover
            if [ pcolor ] of patch-here = black [ iniciar ]
        ]
        [
            if parceiro != self 
            [
              interage
            ]
        ]
      ]
   ]
  
  update-plot-pop
  update-plot-stats
  update-plot-encontros
  update-plot-tipo
  update-monitores
  update-plot-renda
  
end