Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
jzaki authored Sep 1, 2020
2 parents baf6634 + 6d53d5b commit 87953bc
Show file tree
Hide file tree
Showing 62 changed files with 320,041 additions and 6 deletions.
7 changes: 1 addition & 6 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
.eggs
*.egg-info
*.csv
simulations/.ipynb_checkpoints
monkeytype.sqlite3

__pycache__
Expand All @@ -17,8 +16,4 @@ Pipfile.lock
notebooks
build

notes.txt

simulations/validation/
testing/models/external_dataset.py
testing/models/historical_state_access.py
*.pickle
Empty file added demos/README.md
Empty file.
6 changes: 6 additions & 0 deletions demos/adoption_funnel/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.idea

src/__pycache__
src/sim/__pycache__
src/sim/model/__pycache__
src/sim/model/parts/__pycache__
21 changes: 21 additions & 0 deletions demos/adoption_funnel/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2020 Matt Barlin

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
9 changes: 9 additions & 0 deletions demos/adoption_funnel/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Adoption Funnel

Building a Markov mixing process to exhibit the dynamics of an adoption process as a finite state machine.
## State Machine
![State Machine](images/state_machine.png)

Develop a module to be utilized within other cadCAD models as a consequence of a driving signal.
## cadCAD Specification
![cadCAD Specification](images/adoption_cadcad_spec.png)
1,001 changes: 1,001 additions & 0 deletions demos/adoption_funnel/adoption_funnel_cadcad_param_threshold.ipynb

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added demos/adoption_funnel/images/state_machine.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file.
Empty file.
58 changes: 58 additions & 0 deletions demos/adoption_funnel/src/sim/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@

from cadCAD.configuration import Experiment #.append_configs
from cadCAD.configuration.utils import config_sim
# if test notebook is in parent above /src
from src.sim.model.state_variables import genesis_states
from src.sim.model.partial_state_update_block import partial_state_update_block #, partial_state_update_block_B
from src.sim.model.sys_params import sys_params #as sys_params_A
from src.sim.model.utils import *

from copy import deepcopy
from cadCAD import configs
import scipy.stats as stats
# import networkx as nx
import numpy as np

from typing import Dict, List

# from .utils import *

# if test notebook is in /src
# from model.state_variables import genesis_states
# from model.partial_state_update_block import partial_state_update_block
# from model.sys_params import sys_params as sys_params_A

from src.sim.sim_setup import SIMULATION_TIME_STEPS, MONTE_CARLO_RUNS

# sys_params: Dict[str, List[int]] = sys_params

sim_config = config_sim(
{
'N': MONTE_CARLO_RUNS,
'T': range(SIMULATION_TIME_STEPS), # number of timesteps
'M': sys_params,
}
)

exp = Experiment()

# Experiment.append_configs()
exp.append_configs(
sim_configs=sim_config,
initial_state=genesis_states,
partial_state_update_blocks=partial_state_update_block
)


# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # GENESIS SWEEP LOGIC # # # # # # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

for c in configs: # for each configuration object
c.initial_state = deepcopy(c.initial_state) # make a deepcopy of the initial state dict (it's shared across configs by default)
# for k in c.initial_state: # for each state variable
# if k in c.sim_config['M']: # if there is a param with the same name in the params dict
# c.initial_state[k] = c.sim_config['M'][k] # assign the param value to the initial value of the state variable

c.initial_state['pool'] = Adoption_Pool(c.sim_config['M']['SOURCE_POOL'])
# c.initial_state['network'] = init_network(c.initial_state['network'], c.sim_config['M'])
Empty file.
30 changes: 30 additions & 0 deletions demos/adoption_funnel/src/sim/model/partial_state_update_block.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from src.sim.model.parts.marketing_signal import *
from src.sim.model.parts.adoption import *

partial_state_update_block = [
{
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# MARKETING SIGNAL GENERATION
'policies': {
'marketing_rate': p_marketing_rate,
'p_marketing_shock' : p_marketing_shock,
},
'variables': {
'signal': s_signal,
}
},
{
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# ADOPTION STATE
'policies': {
'reputation' : p_reputation,
'experience' : p_experience,
},
'variables': {
# 'adoption': s_adoption, # AGENT BASED
'pool': s_pool, # SUB POPULATION BASED

}
},

]
Empty file.
59 changes: 59 additions & 0 deletions demos/adoption_funnel/src/sim/model/parts/adoption.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# import networkx as nx
import numpy as np

# from ..utils import *

def p_reputation(params, substep, state_history, prev_state, **kwargs):
"""
Policy for steady marketing spend signal generation.
"""
# params = params[0]
constant = params['THRESHOLD']
random = np.random.normal(params['THRESHOLD'], scale = 1.0)
return {'reputation': constant}


def p_experience(params, substep, state_history, prev_state, **kwargs):
"""
Policy for steady marketing spend signal generation.
"""
# params = params[0]
constant = params['EXO_EXPERIENCE']
random = np.random.normal(params['EXO_EXPERIENCE'], scale = 1.0)
return {'experience': constant}


def s_adoption(params, substep, state_history, prev_state, policy_input, **kwargs):
"""
State for generating signal from marketing.
"""
key = 'adoption'

prev_state['adoption'].apply_signal(prev_state['signal'])
# value = policy_input['reputation'] + policy_input['experience']
prev_state['adoption'].set_threshold(params['THRESHOLD'])
prev_state['adoption'].determine_state(prev_state['signal'])
value = prev_state['adoption']
return (key, value)

def s_pool(params, substep, state_history, prev_state, policy_input, **kwargs):
"""
State for generating signal from marketing.
"""
# params = params[0]
key = 'pool'

prev_state['pool'].apply_signal(prev_state['signal'])


# value = policy_input['reputation'] + policy_input['experience']
# FIX THIS!
prev_state['pool'].set_threshold(ext_threshold=params['THRESHOLD'])

prev_state['pool'].calculate_drip(params['LEAK_COEFFICIENT'])
# print(prev_state['pool'])
prev_state['pool'].update_pools(params['LEAK_COEFFICIENT'])
# print(prev_state['pool'])
# prev_state['pool'].determine_state(prev_state['signal'])
value = prev_state['pool']
return (key, value)
40 changes: 40 additions & 0 deletions demos/adoption_funnel/src/sim/model/parts/marketing_signal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# import networkx as nx
import numpy as np

# from ..utils import *

def p_marketing_rate(params, substep, state_history, prev_state, **kwargs):
# params = params[0]
"""
Policy for steady marketing spend signal generation.
"""
constant = params['MARKETING_STEADY']
random = np.random.normal(params['MARKETING_STEADY'], scale = 1.0)
return {'steady_signal': constant}

def p_marketing_shock(params, substep, state_history, prev_state, **kwargs):
"""
Policy for shock marketing (spend and other sources).
"""
# Expected number of shocks
# coded through parameter
# params = params[0]
freq = params['MARKETING_SHOCK_FREQ'] * 0.5

# expected but randomized through poisson
if np.random.poisson(freq) > params['MARKETING_SHOCK_FREQ']:
shock = params['MARKETING_SHOCK_MAG']
else:
shock = 0
return {'shock_signal': shock}

def s_signal(params, substep, state_history, prev_state, policy_input, **kwargs):
"""
State for generating signal from marketing.
"""
key = 'signal'

value = policy_input['steady_signal'] + policy_input['shock_signal']
return (key, value)


23 changes: 23 additions & 0 deletions demos/adoption_funnel/src/sim/model/state_variables.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from datetime import datetime
# import networkx as nx
import numpy as np

# from copy import deepcopy
# import scipy.stats as stats
# from .sys_params import sys_params
from src.sim.model.utils import *

# Initial Values
signal = 0
# state = 0
adoption = Adoption()
# pool = Adoption_Pool() # Iniialized in config loop using source_pool parameter

## Genesis States #################################################
genesis_states = {
'timestamp': datetime.strptime('2020-01-01 00:00:00', '%Y-%m-%d %H:%M:%S'),
'signal': signal,
# 'adoption': adoption, # Agent Based
# 'pool' : pool, # Iniialized in config loop using source_pool parameter

}
49 changes: 49 additions & 0 deletions demos/adoption_funnel/src/sim/model/sys_params.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# import networkx as nx
from pprint import pprint

import numpy as np
import itertools

### MARKETING PARAMETERS #################################
# uniform distribution of marketing signalling
MARKETING_STEADY = [500]

# Noisy shock marketing signalling magnitude and expected frequency
MARKETING_SHOCK_MAG = [1234]
MARKETING_SHOCK_FREQ = [2]

### EXTERNAL EXPERIENCE PARAMETERS #################################
# If UX/UI are not part of the model. Can use as an external signal to
# generate stochastic process for experience.
EXO_EXPERIENCE = [140]

### POPULATION POOL PARAMETERS #################################
SOURCE_POOL = [100000] #, 12]

### INITIAL THRESHOLD VALUE PARAMETERS #################################
THRESHOLD = [0.1, 1, 2, 3]
LEAK_COEFFICIENT = [0.01]


#### USE ONLY FOR A/B WITH PARAMETER SWEEPS OR MULTIPLE PARAMETER SWEEPS #####

factors = [MARKETING_STEADY,SOURCE_POOL, THRESHOLD, LEAK_COEFFICIENT]
product = list(itertools.product(*factors))
MARKETING_STEADY,SOURCE_POOL, THRESHOLD, LEAK_COEFFICIENT = zip(*product)
MARKETING_STEADY = list(MARKETING_STEADY)
SOURCE_POOL = list(SOURCE_POOL)
THRESHOLD = list(THRESHOLD)
LEAK_COEFFICIENT = list(LEAK_COEFFICIENT)



# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
sys_params = {
'MARKETING_STEADY': MARKETING_STEADY,
'MARKETING_SHOCK_MAG': MARKETING_SHOCK_MAG,
'MARKETING_SHOCK_FREQ': MARKETING_SHOCK_FREQ,
'EXO_EXPERIENCE': EXO_EXPERIENCE,
'SOURCE_POOL': SOURCE_POOL,
'THRESHOLD': THRESHOLD,
'LEAK_COEFFICIENT': LEAK_COEFFICIENT,
}
Loading

0 comments on commit 87953bc

Please sign in to comment.