Hubert Baechli: ICMB portfolio
  • About
  1. How knowledge is distributed
    in the population?
    Mayby!!
  2. Grouped in Slots
  • hubert_baechli_ICMB_HS24
  • Assignment 1:
    Hello World
  • Assignment 2:
    Economic Simulation
    • Sketchbook
    • Notebook(Final)
  • Snippets
    • Beta Distribution
  • How knowledge is distributed
    in the population?
    Mayby!!
    • Simple learningcurve
    • with updated learn rate
    • Random meetings
    • Grouped in Slots
    • in a Day Structure
    • Areas of Knowledge
    • with prefernces
    • Selected Meetings
    • Bounded rationality

On this page

  • Simulating random meetings (Grouped in Slots)
  • Definitions
    • Population for testing the Functions
  • Functions
    • Knowledge
      • Set Knowledge
      • Update Knowledge
    • LearnRate
      • Set LearnRate
      • Update LearnRate by Knowledge
    • StudyTime
      • Set StudyTime
      • Update StudyTime
    • Data Management
      • Select a Sub Population
      • Integrate Sub Population
    • Timelines
      • Get Agents-Timelines
    • Learning
    • Slots
      • Select a random Slot of pairs
      • Sets Slot parameter by Slot-ID’s
      • Learning by Slots
    • Plots
      • Plot Timeline
  • Simulation
    • … Special Cases
      • Only one Agent with Knowledge (0.8)
  1. How knowledge is distributed
    in the population?
    Mayby!!
  2. Grouped in Slots

Grouped in Slots

  • Show All Code
  • Hide All Code

  • View Source
Author

Hubert Baechli

Simulating random meetings (Grouped in Slots)

The basic idea is that when two agents meet, they learn together. Later, this should happen in a network. In the beginning, I will let the agents meet randomly in the population to see if the implementation of joint learning works.

If it works as it should, it will be expanded so that a certain percentage of the population meets at the same time.

Definitions

Loading some Packages for easier Data management and Presentation of Results

Code
library(tidyverse)  
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.1     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.1
✔ purrr     1.0.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
Code
# set.seed(1)

Population for testing the Functions

Code
nA = 5            # number of Agents
ID = seq_len(nA)  # ID of the Agents

Pop <- tibble( ID = ID )
Pop
# A tibble: 5 × 1
     ID
  <int>
1     1
2     2
3     3
4     4
5     5

Functions

Knowledge

Functions to set and update Knowledge

Set Knowledge

Needs

  1. A Population (Pop) with several Agents defined by ID’s

  2. A value for the Knowledge (K) between 0 and 1. could be a scalar or e vector with the same length as the Population

  3. optional for future implementations a name (Typ) for the specific Knowledge

Code
set_Knowledge <- function(Pop = Pop,
                          Typ = FALSE,
                          K = Knowledge) {
  Kname <- "Knowledge"
  if (Typ != FALSE) {
    Kname <- paste(Kname, Typ, sep = "_")
  }
  Pop <- Pop %>%
    mutate(!!Kname := K)

  return(Pop)
}

Output

  1. Population with the defined Knowledge
Code
K <- seq_len(nA)/5

Pop <- set_Knowledge( Pop = Pop, K = 0.5 )
Pop <- set_Knowledge( Pop = Pop, Typ = "A", K = K )
Pop
# A tibble: 5 × 3
     ID Knowledge Knowledge_A
  <int>     <dbl>       <dbl>
1     1       0.5         0.2
2     2       0.5         0.4
3     3       0.5         0.6
4     4       0.5         0.8
5     5       0.5         1  

Update Knowledge

Needs

  1. A Population (Pop) with several Agents defined by ID’s

  2. A value to add to the Knowledge. could be a scalar or e vector with the same length as the Population. if not defined 0 is used to add

  3. A value to multiplie (fac) the Knowledge. could be a scalar or e vector with the same length as the Population. if not defined 1 is used for the multiplikation

  4. optional for future implementations a name (Typ) for the specific Knowledge

Hints

  • The add operation is always used first!

  • If the Knowledge is not defined before it will be generated with the start value (add) and the multiplication with the value (fac)

Code
update_Knowledge <- function(Pop = Pop,
                            Typ = FALSE,
                            add = 0,
                            fac = 1) {
  Kname <- "Knowledge"
  if (Typ != FALSE) {
    Kname <- paste(Kname, Typ, sep = "_")
  }
  if (Kname %in% colnames(Pop)) {
    Pop <- Pop %>%
      mutate( !!Kname := ( .data[[Kname]] + add ) * fac )
  } else {
    Pop <- set_Knowledge(Pop = Pop, K = add, Typ = Typ)
    Pop <- Pop %>%
      mutate( !!Kname := .data[[Kname]] * fac )
  }
  return(Pop)
}

Output

  1. Population with the defined Knowledge
Code
add <- seq_len(nA)/20
fac <- seq_len(nA)/10 

Pop <- update_Knowledge( Pop = Pop, add = add ) 
Pop <- update_Knowledge( Pop = Pop, Typ = "A", fac = fac ) 
Pop <- update_Knowledge( Pop = Pop, Typ = "B", add = add, fac = fac ) 
Pop
# A tibble: 5 × 4
     ID Knowledge Knowledge_A Knowledge_B
  <int>     <dbl>       <dbl>       <dbl>
1     1      0.55        0.02       0.005
2     2      0.6         0.08       0.02 
3     3      0.65        0.18       0.045
4     4      0.7         0.32       0.08 
5     5      0.75        0.5        0.125

LearnRate

Functions to set and update the learn rate

Set LearnRate

Needs

  1. A Population (Pop) with several Agents defined by ID’s

  2. A value for the learn rate (LR) greater than 0 and up to 1. could be a scalar or e vector with the same length as the Population

Hints

  • LernRate 0 leads to Problems so it ist limited it to 1E-3
Code
set_LearnRate <- function(Pop = Pop,
                          LR = LearnRate) {
  LRname <- "LearnRate"
  Pop <- Pop %>%
    mutate(!!LRname := LR,
           !!LRname := pmax(.data[[LRname]],1E-3))
  return(Pop)
}

Output

  1. Population with the defined learn rate
Code
LR <- seq_len(nA)/5  
Pop <- set_LearnRate( Pop = Pop, LR = 1 ) 
Pop
# A tibble: 5 × 5
     ID Knowledge Knowledge_A Knowledge_B LearnRate
  <int>     <dbl>       <dbl>       <dbl>     <dbl>
1     1      0.55        0.02       0.005         1
2     2      0.6         0.08       0.02          1
3     3      0.65        0.18       0.045         1
4     4      0.7         0.32       0.08          1
5     5      0.75        0.5        0.125         1

Update LearnRate by Knowledge

Needs

  1. A Population (Pop) with several Agents defined by ID’s and Knowledge

  2. optional for future implementations a name (Typ) for the specific Knowledge

Hints

  • The learn rate is defined as 50% of the Knowledge for each Agent
Code
update_LearnRate_Knowledge <- function(Pop = Pop,
                                       Typ = FALSE) {
  LR <- "LearnRate"
  Kname <- "Knowledge"
  if (Typ != FALSE) {
    Kname <- paste(Kname, Typ, sep = "_")
  }
  if (Kname %in% colnames(Pop)) {
    Pop <- Pop %>%
      mutate( !!LR := .data[[Kname]] * 0.5 )
  }
  return(Pop)
}

Output

  1. Population with the defined learn rate
Code
Pop <- update_LearnRate_Knowledge( Pop = Pop )  
Pop
# A tibble: 5 × 5
     ID Knowledge Knowledge_A Knowledge_B LearnRate
  <int>     <dbl>       <dbl>       <dbl>     <dbl>
1     1      0.55        0.02       0.005     0.275
2     2      0.6         0.08       0.02      0.3  
3     3      0.65        0.18       0.045     0.325
4     4      0.7         0.32       0.08      0.35 
5     5      0.75        0.5        0.125     0.375

StudyTime

Functions to set and update the StudyTime

Set StudyTime

Needs

  1. A Population (Pop) with several Agents defined by ID’s

  2. A value for the StudyTime (ST). could be a scalar or a vector with the same length as the Population

Hints

  • If StudyTime isn’t given the Population will be initialising with 0
Code
set_StudyTime <- function(Pop = Pop,
                          ST = 0) {
  STname <- "StudyTime"
  Pop <- Pop %>%
    mutate(!!STname := ST)
  return(Pop)
}

Output

  1. Population with the defined StudyTime
Code
Pop <- set_StudyTime( Pop = Pop, ST = 3)  
Pop
# A tibble: 5 × 6
     ID Knowledge Knowledge_A Knowledge_B LearnRate StudyTime
  <int>     <dbl>       <dbl>       <dbl>     <dbl>     <dbl>
1     1      0.55        0.02       0.005     0.275         3
2     2      0.6         0.08       0.02      0.3           3
3     3      0.65        0.18       0.045     0.325         3
4     4      0.7         0.32       0.08      0.35          3
5     5      0.75        0.5        0.125     0.375         3

Update StudyTime

Needs

  1. A Population (Pop) with several Agents defined by ID’s and StudyTime

  2. A Time (dT) that should added.

Hints

  • If StudyTime isn’t defined in Population it will be initialising with dT
Code
update_StudyTime <- function(Pop = Pop,
                             dT = TimeToAdd) {
  STname <- "StudyTime"
  if (STname %in% colnames(Pop)) {
    Pop <- Pop %>%
      mutate( !!STname := .data[[STname]] + dT )
  } else {
    Pop <- set_StudyTime(Pop = Pop, ST = dT )
  }
  return(Pop)
}

Output

  1. Population with the defined StudyTime
Code
Pop <- update_StudyTime( Pop = Pop, dT = 1)   
Pop
# A tibble: 5 × 6
     ID Knowledge Knowledge_A Knowledge_B LearnRate StudyTime
  <int>     <dbl>       <dbl>       <dbl>     <dbl>     <dbl>
1     1      0.55        0.02       0.005     0.275         4
2     2      0.6         0.08       0.02      0.3           4
3     3      0.65        0.18       0.045     0.325         4
4     4      0.7         0.32       0.08      0.35          4
5     5      0.75        0.5        0.125     0.375         4

Data Management

Functions to select and reintegrate a Sub Populations

Select a Sub Population

Needs

  1. A Population (Pop) with several Agents defined by ID’s

  2. A vector wit ID’s(IDs). If no vector is defined it needs a (n, witch is initialised by 2) for selecting random ID’s

  3. A value (n) if the selection should be random

Hints

  • If StudyTime isn’t given the Population will be initialising with 0
Code
sel_SubPop <- function(Pop = Pop,
                       IDs = NULL,
                       n = 2) {
    if (is.null(IDs)) {
      IDs <- sample( Pop[["ID"]], size=n )
    }
  SubPop <- list()
  SubPop$sel <- Pop %>%
    filter(ID %in% IDs) %>%
    arrange(match(ID, IDs))
  SubPop$rest <- Pop %>%
    filter(!ID %in% IDs)
  return(SubPop)
}

Output

  1. List with Sub Population ($sel) and the rest of the Population($rest)
Code
SubPop <- sel_SubPop( Pop = Pop )
SubPop$sel
# A tibble: 2 × 6
     ID Knowledge Knowledge_A Knowledge_B LearnRate StudyTime
  <int>     <dbl>       <dbl>       <dbl>     <dbl>     <dbl>
1     3      0.65        0.18       0.045     0.325         4
2     1      0.55        0.02       0.005     0.275         4
Code
SubPop$rest
# A tibble: 3 × 6
     ID Knowledge Knowledge_A Knowledge_B LearnRate StudyTime
  <int>     <dbl>       <dbl>       <dbl>     <dbl>     <dbl>
1     2      0.6         0.08       0.02      0.3           4
2     4      0.7         0.32       0.08      0.35          4
3     5      0.75        0.5        0.125     0.375         4
Code
SubPop <- sel_SubPop( Pop = Pop , IDs = c(2, 1))
SubPop$sel
# A tibble: 2 × 6
     ID Knowledge Knowledge_A Knowledge_B LearnRate StudyTime
  <int>     <dbl>       <dbl>       <dbl>     <dbl>     <dbl>
1     2      0.6         0.08       0.02      0.3           4
2     1      0.55        0.02       0.005     0.275         4
Code
SubPop$rest
# A tibble: 3 × 6
     ID Knowledge Knowledge_A Knowledge_B LearnRate StudyTime
  <int>     <dbl>       <dbl>       <dbl>     <dbl>     <dbl>
1     3      0.65        0.18       0.045     0.325         4
2     4      0.7         0.32       0.08      0.35          4
3     5      0.75        0.5        0.125     0.375         4

Integrate Sub Population

Needs

  1. A Sub Population (SubPop) with Agents defined by ID’s which are also defined in Population

  2. A Population (Pop) with several Agents defined by ID’s

Hints

  • SubPop and Pop has to have the same cols
Code
int_SubPop <- function(SubPop = SubPop,
                       Pop = Pop) {
  col_sort <- colnames(Pop)
  SubPop <- SubPop[, col_sort]
  IDs <- SubPop[["ID"]]
  Pop[Pop$ID %in% IDs,] <- SubPop
  Pop <- Pop %>%
    arrange(ID)
  return(Pop)
}

Output

  1. Population with the defined StudyTime
Code
Pop
# A tibble: 5 × 6
     ID Knowledge Knowledge_A Knowledge_B LearnRate StudyTime
  <int>     <dbl>       <dbl>       <dbl>     <dbl>     <dbl>
1     1      0.55        0.02       0.005     0.275         4
2     2      0.6         0.08       0.02      0.3           4
3     3      0.65        0.18       0.045     0.325         4
4     4      0.7         0.32       0.08      0.35          4
5     5      0.75        0.5        0.125     0.375         4
Code
SubPop <- sel_SubPop(Pop = Pop, n = 2 )$sel
SubPop <- set_Knowledge(Pop = SubPop, K = 0)
SubPop
# A tibble: 2 × 6
     ID Knowledge Knowledge_A Knowledge_B LearnRate StudyTime
  <int>     <dbl>       <dbl>       <dbl>     <dbl>     <dbl>
1     3         0        0.18       0.045     0.325         4
2     2         0        0.08       0.02      0.3           4
Code
Pop <- int_SubPop(SubPop = SubPop, Pop = Pop)
Pop
# A tibble: 5 × 6
     ID Knowledge Knowledge_A Knowledge_B LearnRate StudyTime
  <int>     <dbl>       <dbl>       <dbl>     <dbl>     <dbl>
1     1      0.55        0.02       0.005     0.275         4
2     2      0           0.08       0.02      0.3           4
3     3      0           0.18       0.045     0.325         4
4     4      0.7         0.32       0.08      0.35          4
5     5      0.75        0.5        0.125     0.375         4

Timelines

saving Timelines during Simulations

Get Agents-Timelines

Needs

  1. A container name for the Timeline

  2. A value for the Time

  3. A Population (Pop) with several Agents defined by ID’s

  4. A colname from the Population which should followed ver Time

  5. optional parameter Sum. Ich Sum = 1 a mean and median is calculated for each Time

Code
get_Timeline <- function(TL = Timeline,
                          Time = 0,
                          Pop = Pop,
                          Info = name,
                          Sum = 0) {
  TLadd <- tibble( ID = Pop[["ID"]],
                   Time = Time,
                   !!Info := Pop[[Info]])
  if (Sum == 1) {
    Sumname1 <- paste(Info,"mean", sep = "_")
    Sumname2 <- paste(Info,"median", sep = "_")
    TLadd <- TLadd %>%
        mutate(!!Sumname1 := mean(Pop[[Info]], na.rm = TRUE),
               !!Sumname2 := median(Pop[[Info]], na.rm = TRUE))
    }
  if (Time == 0) {
    TL <- TLadd
  } else {
    TL <- bind_rows(TL, TLadd)
  }
  return(TL) 
}

Output

  1. A Timeline in a long format
Code
Timeline <- get_Timeline( TL = Timeline, 
                           Time = 0, 
                           Pop = Pop, 
                           Info = "Knowledge", 
                           Sum = 1)
Timeline <- get_Timeline( TL = Timeline, 
                           Time = 1, 
                           Pop = Pop, 
                           Info = "Knowledge", 
                           Sum = 1)
Timeline
# A tibble: 10 × 5
      ID  Time Knowledge Knowledge_mean Knowledge_median
   <int> <dbl>     <dbl>          <dbl>            <dbl>
 1     1     0      0.55            0.4             0.55
 2     2     0      0               0.4             0.55
 3     3     0      0               0.4             0.55
 4     4     0      0.7             0.4             0.55
 5     5     0      0.75            0.4             0.55
 6     1     1      0.55            0.4             0.55
 7     2     1      0               0.4             0.55
 8     3     1      0               0.4             0.55
 9     4     1      0.7             0.4             0.55
10     5     1      0.75            0.4             0.55

Learning

Learning with a exponential lern rate

Needs

  1. A Population (Pop) with several Agents defined by ID’s and Knowledge

  2. optional for future implementations a name (Typ) for the specific Knowledge

  3. A value for the learn rate (LR). could be a scalar or e vector with the same length as the Population

  4. A value for the study time (ST). could be a scalar or e vector with the same length as the Population

Hints

  • If learn rate isn’t given the values from the Population will be used, if this is missing in the Population 0 is used.
Code
learn <- function(Pop = Pop,
                  Typ = FALSE,
                  LR = FALSE,
                  ST = StudyTime) {
  Kname <- "Knowledge"
  if (Typ != FALSE) {
    Kname <- paste(Kname, Typ, sep = "_")
  }
  if (Kname %in% colnames(Pop)) {
    K <- Pop[[Kname]]
  }
  if (LR == FALSE) {
    if ("LearnRate" %in% colnames(Pop)) {
      LR <- Pop[["LearnRate"]]
    }
  }

  T0 <- ( 1 - K )^( 1 / -LR )   # assumed time learnd allready
  K <- 1 - ( T0 + ST )^( -LR )  # Knowledge after time learnd
  
  Pop <- set_Knowledge(Pop = Pop, Typ = Typ, K = K)
  Pop <- update_StudyTime(Pop = Pop, dT = ST)
  return(Pop)
}

Output

  1. Population with updated Knowledge
Code
Pop <- tibble( ID = ID )
Pop <- set_Knowledge(Pop = Pop, K = 0.1)
Pop <- set_LearnRate(Pop = Pop, LR = 1)
Pop
# A tibble: 5 × 3
     ID Knowledge LearnRate
  <int>     <dbl>     <dbl>
1     1       0.1         1
2     2       0.1         1
3     3       0.1         1
4     4       0.1         1
5     5       0.1         1
Code
Pop <- learn( Pop = Pop, ST = 1)
Pop
# A tibble: 5 × 4
     ID Knowledge LearnRate StudyTime
  <int>     <dbl>     <dbl>     <dbl>
1     1     0.526         1         1
2     2     0.526         1         1
3     3     0.526         1         1
4     4     0.526         1         1
5     5     0.526         1         1

Slots

Functions to select and sets learning slots from a Population

Select a random Slot of pairs

Needs

  1. A Population (Pop) with several Agents defined by ID’s

  2. A size of the Slot in percents of the population

Hints

  • because it leads to trouble will selecting otherwise the calculated n is limited at the moment between 1 and half of the Population
Code
sel_Slot_rnd <- function(Pop = Pop,
                         psize = PrecentOfPop) {   
  sID <- "Slot_ID"
  n <- round(nrow(Pop)*psize / 2, 0)
  n <- max(n, 1)
  n <- min(n, round(nrow(Pop) / 2, 0))
 
  SubPop <- sel_SubPop( Pop = Pop, n = n)   
  Slot1 <- SubPop$sel %>%     
    mutate(!!sID := seq_len(n)) 
  SubPop <- sel_SubPop( Pop = SubPop$rest, n = n) 
  Slot2 <- SubPop$sel %>%     
    mutate(!!sID := seq_len(n))
  Slot <- bind_rows(Slot1, Slot2)
  return(Slot)  
  }  

Output

  1. A random Slot-Population with Slot ID’s which marks the pairs
Code
Pop
# A tibble: 5 × 4
     ID Knowledge LearnRate StudyTime
  <int>     <dbl>     <dbl>     <dbl>
1     1     0.526         1         1
2     2     0.526         1         1
3     3     0.526         1         1
4     4     0.526         1         1
5     5     0.526         1         1
Code
round(nrow(Pop) / 2,0)
[1] 2
Code
Slot <- sel_Slot_rnd(Pop = Pop, psize = 0.8)
Slot
# A tibble: 4 × 5
     ID Knowledge LearnRate StudyTime Slot_ID
  <int>     <dbl>     <dbl>     <dbl>   <int>
1     4     0.526         1         1       1
2     3     0.526         1         1       2
3     2     0.526         1         1       1
4     1     0.526         1         1       2

Sets Slot parameter by Slot-ID’s

Needs

  1. A Slot of paird Agents defined by Slot_ID’s

  2. A duration of the slot. could be a scalar or a vector with the same length as the number of pairs in the Slot

Code
set_SlotPar <- function(Slot = Slot,
                    ST = SlotDuration) {
  LRname <- "LearnRate"
  sLRname <- "Slot_LearnRate"
  Slot <- Slot %>%
    group_by(Slot_ID) %>%
    mutate( !!sLRname := mean(.data[[LRname]], na.rm = TRUE),
            Slot_Duration := ST) %>%
    ungroup()
  return(Slot)
}

Output

  1. A random Slot-Population with Slot ID’s which marks the pairs, learn rate and duration of the Slot defined by pairs
Code
Slot <- set_SlotPar(Slot = Slot, ST = 1)
Slot
# A tibble: 4 × 7
     ID Knowledge LearnRate StudyTime Slot_ID Slot_LearnRate Slot_Duration
  <int>     <dbl>     <dbl>     <dbl>   <int>          <dbl>         <dbl>
1     4     0.526         1         1       1              1             1
2     3     0.526         1         1       2              1             1
3     2     0.526         1         1       1              1             1
4     1     0.526         1         1       2              1             1

Learning by Slots

Learning with a exponential learn rate defined by pairs

Needs

  1. A Slot-Population with several paired Agents defined by Slot-ID’s. Prepaerd by the function set_SlotPar()

  2. optional for future implementations a name (Typ) for the specific Knowledge

Code
learn_Slot <- function(Slot = Slot,
                       Typ = FALSE) {
  Kname <- "Knowledge"
  if (Typ != FALSE) {
    Kname <- paste(Kname, Typ, sep = "_")
  }
  LRname <- "Slot_LearnRate"
  STname <- "Slot_Duration"
  K <- Slot[[Kname]]
  LR <- Slot[[LRname]]
  ST <- Slot[[STname]]

  T0 <- ( 1 - K )^( 1 / -LR )   # assumed time learnd allready
  K <- 1 - ( T0 + ST )^( -LR )  # Knowledge after time learnd
  Slot <- set_Knowledge(Pop = Slot, Typ = Typ, K = K)
  Slot <- update_StudyTime(Pop = Slot, dT = ST)
  return(Slot)
}

Output

  1. Slot-Population with updated Knowledge
Code
Slot <- learn_Slot(Slot = Slot)
Slot
# A tibble: 4 × 7
     ID Knowledge LearnRate StudyTime Slot_ID Slot_LearnRate Slot_Duration
  <int>     <dbl>     <dbl>     <dbl>   <int>          <dbl>         <dbl>
1     4     0.679         1         2       1              1             1
2     3     0.679         1         2       2              1             1
3     2     0.679         1         2       1              1             1
4     1     0.679         1         2       2              1             1
Code
Pop <- int_SubPop(SubPop = Slot, Pop = Pop)
Pop
# A tibble: 5 × 4
     ID Knowledge LearnRate StudyTime
  <int>     <dbl>     <dbl>     <dbl>
1     1     0.679         1         2
2     2     0.679         1         2
3     3     0.679         1         2
4     4     0.679         1         2
5     5     0.526         1         1

Plots

Plot Timeline

Needs

  1. A Timeline from get_Timeline
Code
plt_Timeline <- function(TL = Timeline) {
  ggplot(data = TL, aes(x = Time)) +
  geom_line(aes(y = Knowledge, group = ID, color = "Agents"), 
            alpha = 0.5,
            linetype = "solid") +
  geom_line(aes(y = Knowledge_mean, color = "Mean"),
            linetype = "solid")  +
  geom_line(aes(y = Knowledge_median, color = "Median"),
            linetype = "dashed") +
  ggtitle("Timeline") +
  xlab("Number of Slots") +
  ylab("Knowledge") +
  scale_y_continuous(
    limits = c(0, 1),
    breaks = seq(0, 1, 0.2)
  ) +
  scale_color_manual(
    values = c("Agents" = "grey", "Mean" = "black", "Median" = "black"),
    labels = c("Agents" = "Agents", "Mean" = "Mean", "Median" = "Median")
  ) +
  theme_light() +
  theme(legend.title = element_blank(),
        legend.position = "top",
        legend.justification = "left"
        )
}

Output

  1. ggplot2

Simulation

A learning process with updated learn rate by current knowledge when Agents meet randomly by Slots

Needs

  1. A Population (Pop) with several Agents defined by ID’s and Knowledge

  2. optional for future implementations a name (Typ) for the specific Knowledge

  3. A size of the Slot in percents of the population

  4. A duration of the slot. could be a scalar or a vector with the same length as the number of pairs in the Slot

  5. A number of Slots (STn)

Code
sim_Slot <- function(Pop = Pop,
                     Typ = FALSE,
                     psize = PrecentOfPop,
                     ST = 1,
                     STn = Itterations) {
  Kname <- "Knowledge"
  if (Typ != FALSE) {
    Kname <- paste(Kname, Typ, sep = "_")
  }
  Pop <- update_LearnRate_Knowledge( Pop = Pop )
  Pop <- set_StudyTime( Pop = Pop )
  TL <- get_Timeline( TL =TL,
                       Time = 0,
                       Pop = Pop,
                       Info = Kname,
                       Sum = 1 )
  for(i in 1:STn) {
    Slot <- sel_Slot_rnd( Pop = Pop, psize = psize )
    Slot <- set_SlotPar(Slot = Slot, ST = ST)
    Slot <- learn_Slot(Slot = Slot, Typ = Typ)
    Slot <- update_LearnRate_Knowledge( Pop = Slot )
    Pop <- int_SubPop( SubPop = Slot, Pop = Pop )
    TL <- get_Timeline( TL =TL,
                         Time = i,
                         Pop = Pop,
                         Info = Kname,
                         Sum = 1 )
  }
    
  Output <- list( Pop = Pop,
                  TL = TL)
  return(Output)
}

Output

  1. A List with the new Population and a Timeline over the number of itterations
Code
nA <- 50                          # number of Agents
ID <- seq_len(nA)                 # ID of the Agents
K <- (seq_len(nA)-1)/50           # Knowledge

nM <- 160                         # number of meetings(mean)
psize <- 0.6
STn <- (nM * nA ) / (psize * nA )

Pop <- tibble( ID = ID )
Pop <- set_Knowledge( Pop = Pop, K = K )
Pop
# A tibble: 50 × 2
      ID Knowledge
   <int>     <dbl>
 1     1      0   
 2     2      0.02
 3     3      0.04
 4     4      0.06
 5     5      0.08
 6     6      0.1 
 7     7      0.12
 8     8      0.14
 9     9      0.16
10    10      0.18
# ℹ 40 more rows
Code
res <- sim_Slot(Pop = Pop,
                psize = psize,
                ST = 1,
                STn = STn)

mean(res$Pop[["StudyTime"]])
[1] 159.6
Code
res$Pop
# A tibble: 50 × 4
      ID Knowledge LearnRate StudyTime
   <int>     <dbl>     <dbl>     <dbl>
 1     1     0.872     0.436       163
 2     2     0.867     0.434       153
 3     3     0.874     0.437       164
 4     4     0.872     0.436       158
 5     5     0.871     0.435       160
 6     6     0.873     0.437       161
 7     7     0.874     0.437       164
 8     8     0.873     0.436       161
 9     9     0.872     0.436       155
10    10     0.875     0.438       170
# ℹ 40 more rows
Code
plt_Timeline(res$TL)

… Special Cases

Only one Agent with Knowledge (0.8)

Code
K <- 0           # Knowledge

Pop <- tibble( ID = ID )
Pop <- set_Knowledge( Pop = Pop, K = K )
Pop[ID == 1, "Knowledge"] <- 0.8
Pop
# A tibble: 50 × 2
      ID Knowledge
   <int>     <dbl>
 1     1       0.8
 2     2       0  
 3     3       0  
 4     4       0  
 5     5       0  
 6     6       0  
 7     7       0  
 8     8       0  
 9     9       0  
10    10       0  
# ℹ 40 more rows
Code
res <- sim_Slot(Pop = Pop,
                psize = psize,
                ST = 1,
                STn = STn)

res$Pop
# A tibble: 50 × 4
      ID Knowledge LearnRate StudyTime
   <int>     <dbl>     <dbl>     <dbl>
 1     1     0.864     0.432       152
 2     2     0.825     0.413       162
 3     3     0.817     0.409       156
 4     4     0.816     0.408       159
 5     5     0.817     0.408       154
 6     6     0.821     0.411       161
 7     7     0.820     0.410       157
 8     8     0.817     0.408       162
 9     9     0.825     0.413       168
10    10     0.828     0.414       168
# ℹ 40 more rows
Code
plt_Timeline(res$TL)

Back to top
Random meetings
in a Day Structure
Source Code
---
title: "Grouped in Slots"
author: "Hubert Baechli"

execute: 
  cache: false
---

# Simulating random meetings (Grouped in Slots)

The basic idea is that when two agents meet, they learn together. Later, this should happen in a network. In the beginning, I will let the agents meet randomly in the population to see if the implementation of joint learning works.

If it works as it should, it will be expanded so that a certain percentage of the population meets at the same time.

# Definitions

Loading some Packages for easier Data management and Presentation of Results

```{r}
library(tidyverse)  
# set.seed(1)
```

## Population for testing the Functions

```{r}
nA = 5            # number of Agents
ID = seq_len(nA)  # ID of the Agents

Pop <- tibble( ID = ID )
Pop
```

# Functions

## Knowledge

Functions to set and update Knowledge

### Set Knowledge

#### Needs

1.  A Population (Pop) with several Agents defined by ID's

2.  A value for the Knowledge (K) between 0 and 1. could be a scalar or e vector with the same length as the Population

3.  optional for future implementations a name (Typ) for the specific Knowledge

```{r}
set_Knowledge <- function(Pop = Pop,
                          Typ = FALSE,
                          K = Knowledge) {
  Kname <- "Knowledge"
  if (Typ != FALSE) {
    Kname <- paste(Kname, Typ, sep = "_")
  }
  Pop <- Pop %>%
    mutate(!!Kname := K)

  return(Pop)
}
```

#### Output

1.  Population with the defined Knowledge

```{r}
K <- seq_len(nA)/5

Pop <- set_Knowledge( Pop = Pop, K = 0.5 )
Pop <- set_Knowledge( Pop = Pop, Typ = "A", K = K )
Pop
```

### Update Knowledge

#### Needs

1.  A Population (Pop) with several Agents defined by ID's

2.  A value to add to the Knowledge. could be a scalar or e vector with the same length as the Population. if not defined 0 is used to add

3.  A value to multiplie (fac) the Knowledge. could be a scalar or e vector with the same length as the Population. if not defined 1 is used for the multiplikation

4.  optional for future implementations a name (Typ) for the specific Knowledge

#### Hints

-   The add operation is always used first!

-   If the Knowledge is not defined before it will be generated with the start value (add) and the multiplication with the value (fac)

```{r}
update_Knowledge <- function(Pop = Pop,
                            Typ = FALSE,
                            add = 0,
                            fac = 1) {
  Kname <- "Knowledge"
  if (Typ != FALSE) {
    Kname <- paste(Kname, Typ, sep = "_")
  }
  if (Kname %in% colnames(Pop)) {
    Pop <- Pop %>%
      mutate( !!Kname := ( .data[[Kname]] + add ) * fac )
  } else {
    Pop <- set_Knowledge(Pop = Pop, K = add, Typ = Typ)
    Pop <- Pop %>%
      mutate( !!Kname := .data[[Kname]] * fac )
  }
  return(Pop)
}
```

#### Output

1.  Population with the defined Knowledge

```{r}
add <- seq_len(nA)/20
fac <- seq_len(nA)/10 

Pop <- update_Knowledge( Pop = Pop, add = add ) 
Pop <- update_Knowledge( Pop = Pop, Typ = "A", fac = fac ) 
Pop <- update_Knowledge( Pop = Pop, Typ = "B", add = add, fac = fac ) 
Pop
```

## LearnRate

Functions to set and update the learn rate

### Set LearnRate

#### Needs

1.  A Population (Pop) with several Agents defined by ID's

2.  A value for the learn rate (LR) greater than 0 and up to 1. could be a scalar or e vector with the same length as the Population

#### Hints

-   LernRate 0 leads to Problems so it ist limited it to 1E-3

```{r}
set_LearnRate <- function(Pop = Pop,
                          LR = LearnRate) {
  LRname <- "LearnRate"
  Pop <- Pop %>%
    mutate(!!LRname := LR,
           !!LRname := pmax(.data[[LRname]],1E-3))
  return(Pop)
}
```

#### Output

1.  Population with the defined learn rate

```{r}
LR <- seq_len(nA)/5  
Pop <- set_LearnRate( Pop = Pop, LR = 1 ) 
Pop
```

### Update LearnRate by Knowledge

#### Needs

1.  A Population (Pop) with several Agents defined by ID's and Knowledge

2.  optional for future implementations a name (Typ) for the specific Knowledge

#### Hints

-   The learn rate is defined as 50% of the Knowledge for each Agent

```{r}
update_LearnRate_Knowledge <- function(Pop = Pop,
                                       Typ = FALSE) {
  LR <- "LearnRate"
  Kname <- "Knowledge"
  if (Typ != FALSE) {
    Kname <- paste(Kname, Typ, sep = "_")
  }
  if (Kname %in% colnames(Pop)) {
    Pop <- Pop %>%
      mutate( !!LR := .data[[Kname]] * 0.5 )
  }
  return(Pop)
}
```

#### Output

1.  Population with the defined learn rate

```{r}
Pop <- update_LearnRate_Knowledge( Pop = Pop )  
Pop
```

## StudyTime

Functions to set and update the StudyTime

### Set StudyTime

#### Needs

1.  A Population (Pop) with several Agents defined by ID's

2.  A value for the StudyTime (ST). could be a scalar or a vector with the same length as the Population

#### Hints

-   If StudyTime isn't given the Population will be initialising with 0

```{r}
set_StudyTime <- function(Pop = Pop,
                          ST = 0) {
  STname <- "StudyTime"
  Pop <- Pop %>%
    mutate(!!STname := ST)
  return(Pop)
}
```

#### Output

1.  Population with the defined StudyTime

```{r}
Pop <- set_StudyTime( Pop = Pop, ST = 3)  
Pop
```

### Update StudyTime

#### Needs

1.  A Population (Pop) with several Agents defined by ID's and StudyTime

2.  A Time (dT) that should added.

#### Hints

-   If StudyTime isn't defined in Population it will be initialising with dT

```{r}
update_StudyTime <- function(Pop = Pop,
                             dT = TimeToAdd) {
  STname <- "StudyTime"
  if (STname %in% colnames(Pop)) {
    Pop <- Pop %>%
      mutate( !!STname := .data[[STname]] + dT )
  } else {
    Pop <- set_StudyTime(Pop = Pop, ST = dT )
  }
  return(Pop)
}
```

#### Output

1.  Population with the defined StudyTime

```{r}
Pop <- update_StudyTime( Pop = Pop, dT = 1)   
Pop
```

## Data Management

Functions to select and reintegrate a Sub Populations

### Select a Sub Population

#### Needs

1.  A Population (Pop) with several Agents defined by ID's

2.  A vector wit ID's(IDs). If no vector is defined it needs a (n, witch is initialised by 2) for selecting random ID's

3.  A value (n) if the selection should be random

#### Hints

-   If StudyTime isn't given the Population will be initialising with 0

```{r}
sel_SubPop <- function(Pop = Pop,
                       IDs = NULL,
                       n = 2) {
    if (is.null(IDs)) {
      IDs <- sample( Pop[["ID"]], size=n )
    }
  SubPop <- list()
  SubPop$sel <- Pop %>%
    filter(ID %in% IDs) %>%
    arrange(match(ID, IDs))
  SubPop$rest <- Pop %>%
    filter(!ID %in% IDs)
  return(SubPop)
}
```

#### Output

1.  List with Sub Population (\$sel) and the rest of the Population(\$rest)

```{r}
SubPop <- sel_SubPop( Pop = Pop )
SubPop$sel
SubPop$rest
```

```{r}
SubPop <- sel_SubPop( Pop = Pop , IDs = c(2, 1))
SubPop$sel
SubPop$rest
```

### Integrate Sub Population

#### Needs

1.  A Sub Population (SubPop) with Agents defined by ID's which are also defined in Population

2.  A Population (Pop) with several Agents defined by ID's

#### Hints

-   SubPop and Pop has to have the same cols

```{r}
int_SubPop <- function(SubPop = SubPop,
                       Pop = Pop) {
  col_sort <- colnames(Pop)
  SubPop <- SubPop[, col_sort]
  IDs <- SubPop[["ID"]]
  Pop[Pop$ID %in% IDs,] <- SubPop
  Pop <- Pop %>%
    arrange(ID)
  return(Pop)
}
```

#### Output

1.  Population with the defined StudyTime

```{r}
Pop
SubPop <- sel_SubPop(Pop = Pop, n = 2 )$sel
SubPop <- set_Knowledge(Pop = SubPop, K = 0)
SubPop
Pop <- int_SubPop(SubPop = SubPop, Pop = Pop)
Pop
```

## Timelines

saving Timelines during Simulations

### Get Agents-Timelines

#### Needs

1.  A container name for the Timeline

2.  A value for the Time

3.  A Population (Pop) with several Agents defined by ID's

4.  A colname from the Population which should followed ver Time

5.  optional parameter Sum. Ich Sum = 1 a mean and median is calculated for each Time

```{r}
get_Timeline <- function(TL = Timeline,
                          Time = 0,
                          Pop = Pop,
                          Info = name,
                          Sum = 0) {
  TLadd <- tibble( ID = Pop[["ID"]],
                   Time = Time,
                   !!Info := Pop[[Info]])
  if (Sum == 1) {
    Sumname1 <- paste(Info,"mean", sep = "_")
    Sumname2 <- paste(Info,"median", sep = "_")
    TLadd <- TLadd %>%
        mutate(!!Sumname1 := mean(Pop[[Info]], na.rm = TRUE),
               !!Sumname2 := median(Pop[[Info]], na.rm = TRUE))
    }
  if (Time == 0) {
    TL <- TLadd
  } else {
    TL <- bind_rows(TL, TLadd)
  }
  return(TL) 
}
```

#### Output

1.  A Timeline in a long format

```{r}
Timeline <- get_Timeline( TL = Timeline, 
                           Time = 0, 
                           Pop = Pop, 
                           Info = "Knowledge", 
                           Sum = 1)
Timeline <- get_Timeline( TL = Timeline, 
                           Time = 1, 
                           Pop = Pop, 
                           Info = "Knowledge", 
                           Sum = 1)
Timeline

```

## **Learning**

Learning with a exponential lern rate

#### Needs

1.  A Population (Pop) with several Agents defined by ID's and Knowledge

2.  optional for future implementations a name (Typ) for the specific Knowledge

3.  A value for the learn rate (LR). could be a scalar or e vector with the same length as the Population

4.  A value for the study time (ST). could be a scalar or e vector with the same length as the Population

#### Hints

-   If learn rate isn't given the values from the Population will be used, if this is missing in the Population 0 is used.

```{r}
learn <- function(Pop = Pop,
                  Typ = FALSE,
                  LR = FALSE,
                  ST = StudyTime) {
  Kname <- "Knowledge"
  if (Typ != FALSE) {
    Kname <- paste(Kname, Typ, sep = "_")
  }
  if (Kname %in% colnames(Pop)) {
    K <- Pop[[Kname]]
  }
  if (LR == FALSE) {
    if ("LearnRate" %in% colnames(Pop)) {
      LR <- Pop[["LearnRate"]]
    }
  }

  T0 <- ( 1 - K )^( 1 / -LR )   # assumed time learnd allready
  K <- 1 - ( T0 + ST )^( -LR )  # Knowledge after time learnd
  
  Pop <- set_Knowledge(Pop = Pop, Typ = Typ, K = K)
  Pop <- update_StudyTime(Pop = Pop, dT = ST)
  return(Pop)
}
```

#### Output

1.  Population with updated Knowledge

```{r}
Pop <- tibble( ID = ID )
Pop <- set_Knowledge(Pop = Pop, K = 0.1)
Pop <- set_LearnRate(Pop = Pop, LR = 1)
Pop

Pop <- learn( Pop = Pop, ST = 1)
Pop
```

## Slots

Functions to select and sets learning slots from a Population

### Select a random Slot of pairs

#### Needs

1.  A Population (Pop) with several Agents defined by ID's

2.  A size of the Slot in percents of the population

#### Hints

-   because it leads to trouble will selecting otherwise the calculated n is limited at the moment between 1 and half of the Population

```{r}
sel_Slot_rnd <- function(Pop = Pop,
                         psize = PrecentOfPop) {   
  sID <- "Slot_ID"
  n <- round(nrow(Pop)*psize / 2, 0)
  n <- max(n, 1)
  n <- min(n, round(nrow(Pop) / 2, 0))
 
  SubPop <- sel_SubPop( Pop = Pop, n = n)   
  Slot1 <- SubPop$sel %>%     
    mutate(!!sID := seq_len(n)) 
  SubPop <- sel_SubPop( Pop = SubPop$rest, n = n) 
  Slot2 <- SubPop$sel %>%     
    mutate(!!sID := seq_len(n))
  Slot <- bind_rows(Slot1, Slot2)
  return(Slot)  
  }  
```

#### Output

1.  A random Slot-Population with Slot ID's which marks the pairs

```{r}
Pop
round(nrow(Pop) / 2,0)
Slot <- sel_Slot_rnd(Pop = Pop, psize = 0.8)
Slot
```

### Sets Slot parameter by Slot-ID's

#### Needs

1.  A Slot of paird Agents defined by Slot_ID's

2.  A duration of the slot. could be a scalar or a vector with the same length as the number of pairs in the Slot

```{r}
set_SlotPar <- function(Slot = Slot,
                    ST = SlotDuration) {
  LRname <- "LearnRate"
  sLRname <- "Slot_LearnRate"
  Slot <- Slot %>%
    group_by(Slot_ID) %>%
    mutate( !!sLRname := mean(.data[[LRname]], na.rm = TRUE),
            Slot_Duration := ST) %>%
    ungroup()
  return(Slot)
}

```

#### Output

1.  A random Slot-Population with Slot ID's which marks the pairs, learn rate and duration of the Slot defined by pairs

```{r}
Slot <- set_SlotPar(Slot = Slot, ST = 1)
Slot
```

### **Learning by Slots**

Learning with a exponential learn rate defined by pairs

#### Needs

1.  A Slot-Population with several paired Agents defined by Slot-ID's. Prepaerd by the function set_SlotPar()

2.  optional for future implementations a name (Typ) for the specific Knowledge

```{r}
learn_Slot <- function(Slot = Slot,
                       Typ = FALSE) {
  Kname <- "Knowledge"
  if (Typ != FALSE) {
    Kname <- paste(Kname, Typ, sep = "_")
  }
  LRname <- "Slot_LearnRate"
  STname <- "Slot_Duration"
  K <- Slot[[Kname]]
  LR <- Slot[[LRname]]
  ST <- Slot[[STname]]

  T0 <- ( 1 - K )^( 1 / -LR )   # assumed time learnd allready
  K <- 1 - ( T0 + ST )^( -LR )  # Knowledge after time learnd
  Slot <- set_Knowledge(Pop = Slot, Typ = Typ, K = K)
  Slot <- update_StudyTime(Pop = Slot, dT = ST)
  return(Slot)
}
```

#### Output

1.  Slot-Population with updated Knowledge

```{r}
Slot <- learn_Slot(Slot = Slot)
Slot
Pop <- int_SubPop(SubPop = Slot, Pop = Pop)
Pop
```

## **Plots**

### Plot Timeline

#### Needs

1.  A Timeline from get_Timeline

```{r}
plt_Timeline <- function(TL = Timeline) {
  ggplot(data = TL, aes(x = Time)) +
  geom_line(aes(y = Knowledge, group = ID, color = "Agents"), 
            alpha = 0.5,
            linetype = "solid") +
  geom_line(aes(y = Knowledge_mean, color = "Mean"),
            linetype = "solid")  +
  geom_line(aes(y = Knowledge_median, color = "Median"),
            linetype = "dashed") +
  ggtitle("Timeline") +
  xlab("Number of Slots") +
  ylab("Knowledge") +
  scale_y_continuous(
    limits = c(0, 1),
    breaks = seq(0, 1, 0.2)
  ) +
  scale_color_manual(
    values = c("Agents" = "grey", "Mean" = "black", "Median" = "black"),
    labels = c("Agents" = "Agents", "Mean" = "Mean", "Median" = "Median")
  ) +
  theme_light() +
  theme(legend.title = element_blank(),
        legend.position = "top",
        legend.justification = "left"
        )
}
```

#### Output

1.  ggplot2

# **Simulation**

A learning process with updated learn rate by current knowledge when Agents meet randomly by Slots

#### Needs

1.  A Population (Pop) with several Agents defined by ID's and Knowledge

2.  optional for future implementations a name (Typ) for the specific Knowledge

3.  A size of the Slot in percents of the population

4.  A duration of the slot. could be a scalar or a vector with the same length as the number of pairs in the Slot

5.  A number of Slots (STn)

```{r}
sim_Slot <- function(Pop = Pop,
                     Typ = FALSE,
                     psize = PrecentOfPop,
                     ST = 1,
                     STn = Itterations) {
  Kname <- "Knowledge"
  if (Typ != FALSE) {
    Kname <- paste(Kname, Typ, sep = "_")
  }
  Pop <- update_LearnRate_Knowledge( Pop = Pop )
  Pop <- set_StudyTime( Pop = Pop )
  TL <- get_Timeline( TL =TL,
                       Time = 0,
                       Pop = Pop,
                       Info = Kname,
                       Sum = 1 )
  for(i in 1:STn) {
    Slot <- sel_Slot_rnd( Pop = Pop, psize = psize )
    Slot <- set_SlotPar(Slot = Slot, ST = ST)
    Slot <- learn_Slot(Slot = Slot, Typ = Typ)
    Slot <- update_LearnRate_Knowledge( Pop = Slot )
    Pop <- int_SubPop( SubPop = Slot, Pop = Pop )
    TL <- get_Timeline( TL =TL,
                         Time = i,
                         Pop = Pop,
                         Info = Kname,
                         Sum = 1 )
  }
    
  Output <- list( Pop = Pop,
                  TL = TL)
  return(Output)
}
```

#### Output

1.  A List with the new Population and a Timeline over the number of itterations

```{r}
nA <- 50                          # number of Agents
ID <- seq_len(nA)                 # ID of the Agents
K <- (seq_len(nA)-1)/50           # Knowledge

nM <- 160                         # number of meetings(mean)
psize <- 0.6
STn <- (nM * nA ) / (psize * nA )

Pop <- tibble( ID = ID )
Pop <- set_Knowledge( Pop = Pop, K = K )
Pop

res <- sim_Slot(Pop = Pop,
                psize = psize,
                ST = 1,
                STn = STn)

mean(res$Pop[["StudyTime"]])
res$Pop
plt_Timeline(res$TL)

```

## ... Special Cases

### Only one Agent with Knowledge (0.8)

```{r}
K <- 0           # Knowledge

Pop <- tibble( ID = ID )
Pop <- set_Knowledge( Pop = Pop, K = K )
Pop[ID == 1, "Knowledge"] <- 0.8
Pop

res <- sim_Slot(Pop = Pop,
                psize = psize,
                ST = 1,
                STn = STn)

res$Pop
plt_Timeline(res$TL)
```