Innovation
Innovation: technological progress, combinatorial evolution, and the adoption of new products.
AdjacentPossibleElement(label, visual=None, *, x=0.1, d=0.0, r=5.0)
Bases: Element
Combinatorial system of entities, with the share that exists and the share its new pairs can produce.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the system. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
x
|
Annotated[object, StateSpec(domain=closed_open(0, oo))]
|
The share of existing entities, the diversity. |
0.1
|
d
|
Annotated[object, StateSpec(domain=closed_open(0, oo))]
|
The share of new entities, the adjacent possible. |
0.0
|
r
|
Annotated[object, ParameterSpec()]
|
The rule density, the number of productive pairs per entity. |
5.0
|
Examples:
>>> from skcomplex.models.economics.innovation import AdjacentPossibleElement
>>> AdjacentPossibleElement('system', r=2.0).r
2.0
Source code in src/skcomplex/models/economics/innovation/_diversity.py
53 54 55 56 57 58 59 60 61 62 63 64 65 | |
HouseholdElement(label, visual=VisualSpec('agents', {'color_by': 'phone', 'color_range': (0.0, 1.0)}), *, income=1.0, phone=0, social_class=MIDDLE, growth=0.02, threshold=1.2)
Bases: Element
Household whose income grows every year and that gets a phone when it can afford one and a neighbour has one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the agent or group. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
VisualSpec('agents', {'color_by': 'phone', 'color_range': (0.0, 1.0)})
|
income
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The initial income, relative to the mean income at the start. |
1.0
|
phone
|
Annotated[float, StateSpec(domain=NN)]
|
1 for a household with a phone and 0 otherwise. |
0
|
social_class
|
Annotated[float, StateSpec(domain=NN)]
|
0 for the upper, 1 for the middle, and 2 for the lower class. |
MIDDLE
|
growth
|
Annotated[float, ParameterSpec()]
|
The yearly growth rate of the income. |
0.02
|
threshold
|
Annotated[float, ParameterSpec(domain=closed_open(0, oo))]
|
The income from which a household can afford a phone. |
1.2
|
Examples:
>>> from skcomplex.models.economics.innovation import HouseholdElement
>>> GroupElement('households', element=HouseholdElement, size=4, values={'threshold': 1.5}).size
4
Source code in src/skcomplex/models/economics/innovation/_adoption.py
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | |
get_income(agent, model)
staticmethod
Return the income grown by a year.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
HouseholdView
|
The household. |
required |
model
|
ModelView
|
The model view of the growth. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
income |
float
|
The income of the next year. |
Source code in src/skcomplex/models/economics/innovation/_adoption.py
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | |
get_phone(agent, model)
staticmethod
Return 1 for a household that has a phone or gets one, affordable with a neighbour that has one, else 0.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
agent
|
HouseholdView
|
The household. |
required |
model
|
ModelView
|
The model view of the adoption. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
phone |
float
|
1 for a household with a phone and 0 otherwise. |
Source code in src/skcomplex/models/economics/innovation/_adoption.py
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | |
InventionInteraction(label, *, technologies, max_components=12, max_inputs=3)
Bases: Interaction
Random wiring of technologies of the pool into a circuit, kept if it computes a wanted function more cheaply.
A circuit has between one and max_inputs inputs and wires between two and max_components technologies in a
row, each pin to an input or to the output of an earlier technology. The output of the last one is the circuit's
output. A circuit that computes a wanted function joins the pool, or replaces the technology of that function when
it uses fewer NAND gates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the interaction. |
required |
technologies
|
Annotated[str, RoleSpec()]
|
The path of the group of technologies. |
required |
max_components
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The largest number of technologies in a circuit. |
12
|
max_inputs
|
Annotated[float, ParameterSpec(domain=open(0, oo))]
|
The largest number of inputs of a circuit. |
3
|
Examples:
>>> from skcomplex.models.economics.innovation import InventionInteraction
>>> InventionInteraction('invention', technologies='technologies', max_components=6).max_components
6
Source code in src/skcomplex/models/economics/innovation/_invention.py
71 72 73 74 75 76 77 78 79 80 81 82 | |
invent(model)
Wire a random circuit and add it to the pool if it computes a wanted function better.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
ModelView
|
The model. |
required |
Source code in src/skcomplex/models/economics/innovation/_invention.py
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | |
PartElement(label, visual=None, *, cost=1.0)
Bases: Element
PartElement of a technology, described by its unit cost.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the agent or group. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
cost
|
Annotated[float, StateSpec(domain=closed_open(0, oo))]
|
The initial unit cost. |
1.0
|
Examples:
>>> from skcomplex.core.elements import GroupElement
>>> from skcomplex.models.economics.innovation import PartElement
>>> GroupElement('components', element=PartElement, size=5, values={'cost': 0.5}).size
5
Source code in src/skcomplex/models/economics/innovation/_part.py
38 39 40 41 42 43 44 45 46 | |
RedesignInteraction(label, *, components, dependencies=())
Bases: Interaction
Attempt to cut the cost of a technology by redesigning a random component and the components that depend on it.
The redesigned components get new costs drawn uniformly from [0, 1], and the redesign is kept only if the total
cost falls. dependencies[i][j] is 1 when a change of component j requires a change of component i.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the interaction. |
required |
components
|
Annotated[str, RoleSpec()]
|
The path of the group of components. |
required |
dependencies
|
Sequence[Sequence[float]]
|
The design structure matrix. |
()
|
Examples:
>>> from skcomplex.models.economics.innovation import RedesignInteraction
>>> RedesignInteraction('redesign', components='components', dependencies=[[1.0]]).dependencies
[[1.0]]
Source code in src/skcomplex/models/economics/innovation/_redesign.py
43 44 45 46 47 48 49 50 51 52 | |
redesign(model)
Propose new costs for a random component and its dependents and keep them if the total cost falls.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
ModelView
|
The model. |
required |
Source code in src/skcomplex/models/economics/innovation/_redesign.py
67 68 69 70 71 72 73 74 75 76 77 78 79 80 | |
TechnologyElement(label, visual=None, *, arity=2, table=NAND[1], cost=1)
Bases: Element
Logic circuit in the pool of technologies, described by the truth table of the function it computes.
Bit r of the table is the output on the inputs whose bits form r, with the first input as the lowest bit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
label
|
str
|
The label of the agent or group. |
required |
visual
|
VisualSpec | None
|
How the element is drawn, or |
None
|
arity
|
Annotated[float, StateSpec(domain=NN)]
|
The number of inputs. |
2
|
table
|
Annotated[float, StateSpec(domain=NN)]
|
The truth table. |
NAND[1]
|
cost
|
Annotated[float, StateSpec(domain=NN)]
|
The number of NAND gates in the circuit. |
1
|
Examples:
>>> from skcomplex.models.economics.innovation import TechnologyElement
>>> GroupElement(
... 'technologies', element=TechnologyElement, size=3, values={'arity': [2, 0, 0], 'table': [7, 0, 1]}
... ).size
3
Source code in src/skcomplex/models/economics/innovation/_technology.py
70 71 72 73 74 75 76 77 78 79 80 81 82 | |
arthur_polak(*, max_components=12, max_inputs=3)
Return Arthur and Polak's evolution of technology, which builds logic functions from NAND gates.
The pool starts with the NAND gate and the constants 0 and 1. Every step wires a random circuit from the pool and keeps it when it computes a wanted function, negation, two-input and, or, exclusive or, nor, equivalence, and implication, or three-input and, or, parity, and majority, so simple inventions become the building blocks of complex ones.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
max_components
|
int
|
The largest number of technologies in a circuit. |
12
|
max_inputs
|
int
|
The largest number of inputs of a circuit. |
3
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the pool |
Examples:
>>> from skcomplex.models.economics.innovation import arthur_polak
>>> arthur_polak().elements[0].check().prepare().size_
3
Source code in src/skcomplex/models/economics/innovation/_technology.py
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | |
bass_diffusion(market=1000.0, *, adopters=0.0, p=0.03, q=0.38)
Return the Bass diffusion model, people who adopt a new product through advertising and word of mouth.
A market of N people splits into potential adopters P and adopters A. Potential adopters adopt at the rate
(p + q A / N) P, where the coefficient of innovation p captures adoption from external influence, such as
advertising, and the coefficient of imitation q adoption from contact with adopters. People are conserved, so
the adoption is a flow from P to A. With q > p the adoption rate rises to a peak at the time
log(q / p) / (p + q) and the adopters follow an S-shaped curve. Starting without adopters, the closed form is
A(t) = N (1 - exp(-(p + q) t)) / (1 + (q / p) exp(-(p + q) t)). The defaults are the mean coefficients that
Sultan, Farley and Lehmann (1990) estimated over many products, with time in years.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
market
|
float
|
The market potential |
1000.0
|
adopters
|
float
|
The initial adopters, a part of the market. |
0.0
|
p
|
float
|
The coefficient of innovation, per year. |
0.03
|
q
|
float
|
The coefficient of imitation, per year. |
0.38
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the potential adopters |
Examples:
>>> from skcomplex.models.economics.innovation import bass_diffusion
>>> bass_diffusion(market=500.0, adopters=10.0).elements[0].P
490.0
Source code in src/skcomplex/models/economics/innovation/_bass.py
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | |
creative_phase_transition(x=0.1, *, r=5.0)
Return the diversity of a combinatorial system, which jumps from sparse to full above a critical rule density.
The share of existing entities x grows by the share d of new entities that pairs of existing entities can
produce, x_{t+1} = x_t + d_t and d_{t+1} = r (1 - x_{t+1}) (x_{t+1}^2 - x_t^2), with the rule density r.
The first step produces d_0 = r x_0^2 (1 - x_0), and no step produces more than the entities that do not exist
yet. The final diversity changes discontinuously with r and x_0.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
float
|
The initial share of existing entities. |
0.1
|
r
|
float
|
The rule density, the number of productive pairs per entity. |
5.0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the diversity |
Examples:
>>> from skcomplex.models.economics.innovation import creative_phase_transition
>>> creative_phase_transition(r=2.0).elements[0].r
2.0
Source code in src/skcomplex/models/economics/innovation/_diversity.py
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | |
nk_technology(n_components=10, d=2, *, random_state=0)
Return McNerney's model of technological improvement, whose cost falls as a power of the cumulative production.
Every step is one unit of production and one attempt to redesign a random component together with the components that depend on it. Redesigns are kept only when they cut the total cost, which falls like Wright's law, more slowly for designs whose components depend on more others.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_components
|
int
|
The number of components. |
10
|
d
|
int
|
The number of components that a redesign of one component changes, itself included. |
2
|
random_state
|
int | Generator | None
|
The seed or generator of the design structure matrix and the initial costs. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the group |
Examples:
>>> from skcomplex.models.economics.innovation import nk_technology
>>> nk_technology(5, 1).interactions[0].dependencies[0]
[1.0, 0.0, 0.0, 0.0, 0.0]
Source code in src/skcomplex/models/economics/innovation/_technology.py
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | |
phone_adoption(shape=(30, 30), *, growth=0.02, threshold=1.2, initial_share=0.1, class_incomes=(1.6, 1.0, 0.6), random_state=0)
Return Hamill and Gilbert's adoption of fixed-line phones by British households from 1951.
One household lives in every cell of a torus. The upper class lives in the top left quadrant, the lower class in the bottom left, and the middle class elsewhere, so neighbours tend to be alike. Incomes are lognormal, scaled by class and normalised to a mean of 1, and grow every year. A household gets a phone once its income reaches the threshold and one of its eight neighbours has a phone. Households decide one after the other in a new random order every year, so phones spread along chains of affording neighbours within a year. The first owners are a cluster of affording households grown from the richest upper-class household.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
shape
|
Sequence[int]
|
The number of columns and rows. |
(30, 30)
|
growth
|
float
|
The yearly growth rate of incomes. |
0.02
|
threshold
|
float
|
The income from which a household can afford a phone. |
1.2
|
initial_share
|
float
|
The share of households with a phone at the start. |
0.1
|
class_incomes
|
Sequence[float]
|
The income scale of the upper, middle, and lower classes. |
(1.6, 1.0, 0.6)
|
random_state
|
int | Generator | None
|
The seed or generator of the incomes. |
0
|
Returns:
| Name | Type | Description |
|---|---|---|
system |
System
|
The model, with the group |
Examples:
>>> from skcomplex.models.economics.innovation import phone_adoption
>>> phone_adoption((10, 10)).elements[0].check().prepare().size_
100
Source code in src/skcomplex/models/economics/innovation/_adoption.py
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 | |