Barbells, Fractals & Memelords: Scaling Strategies for Ethical Action
Tinkering in graph theory, networks & numerical simulation
Intro
This is in an exercise in quantitative tinkering around some ideas that are often treated more conceptually & qualitatively. I’m taking the opportunity to play with modeling tools & techniques I haven’t used much (& some I have).
I hope these (initially) simple models might demonstrate some angles & approaches, suggest further lines of inquiry, & serve as a basis for further exploration. I also include many references & resources I found useful.
General Problem Statement
Can apparent tensions between localism & globalism — microsolidarity & systems change — be reconciled by fractal strategies, operative & effective at all scales? (self-similar, ‘scale-free’)
Or else by something like a barbell portfolio strategy: mostly invested in the safer bets (high-probability, low-impact) of localism, but also exposed to asymmetric payoffs (low-probability, high-impact) at larger scales?
Or will memelords growth-hack the revolution?
(these are not necessarily mutually-exclusive)
Contents & Caveat
There’s a fair bit of blathering before the technical stuff & original work.
Here’s a table of contents to navigate around that. (links only work on web)
(Far better: read this post in a collapsible Roam Research graph here)
(& find all the code used in this post in this repo)
- Intro
- General Problem Statement
- Motivation & Acknowledgments
- Minimal Problem Specification
- Technical Approach & Antecedents
- Building the Network
- Simulating System Dynamics
- A final look at all simulations, grouped by strategy
- …And all simulations grouped by graph structure
- (Tentative) Conclusion & Future Directions
Motivation & Acknowledgments
The contours of this semi-congealed research question have been coming into focus for me for some time, in several interrelated clusters:
1. Taxonomies of complexity, & related analytic & strategic methods
a la Cynefin, Metamodernism & the Model of Hierarchical Complexity, Robust Decision Making, the broader history of complexity science, etc
2. Taxonomies of ethical & moral development, strategy & action
a la Human(e) Metrics & Systems / Tech, Rooted Cosmopolitanism, Microsolidarity, Bildung, Spiral Dynamics (kinda), etc
3. The topic of this post: Scaling laws (or opportunities) for social change.
which entails all of the above (as mentioned: these are all interrelated)
I plan to write more on these themes, but they are not novel or original to me, as the many references in this post demonstrate. I’m motivated by & indebted to a confluence of related (if oblique & apophenic) material.
(…as one does in the engineered serendipity of our preferential attachments, memetic meanderings & self-cultivated-yet-emergent information ecologies).
Some of the most salient references, in addition to those mentioned above:
- Mutual Aid, Solidarity economy, Commons Transition, Game ~B
- Localism as expressed in ‘think globally act locally’, ‘the personal is political’ & the place-basedness of Indigenous Knowledge systems
(& again Microsolidarity & Rooted Cosmopolitanism) - Optionality, barbell strategies, Emergent Strategy
- Scaling laws
While these are mostly conceptual & qualitative sources, qualitative & quantitive approaches are critical to holistic sensemaking & solutions. Quantitative methods are more my forte, & while there are many technical precedents to approaching these sorts of questions, few (that I found) address it directly, so here it goes.
Minimal Problem Specification
The general problem statement above is …a lot. So we’ll distill it down to a much narrower form to design a minimum viable approach as proof of concept for further iteration.
We essentially want to know if there are strategies that work both locally & globally — at micro, meso, & macro scales — to direct ethical action & spur social change.
Or in other words: produce the feedback loop where the good gets better
We need to concretely define all these terms, but first recall that we have 3 candidate strategies (not necessarily mutually exclusive):
- Fractal: doing the same thing at all scales (roughly)
- Barbell: e.g. 80–20 split of local & global ‘investments’
- Memelord: a memetic vanguard of core actors, & peripheral propagation thru the system. (suggested by this & related work)
Here’s a minimal specification as a start:
Given
- a network with some realistic or empirically-useful structure
- some scarce resource distributed such that many lack while few have extreme excess
…can we design strategies of the sort suggested above, which result in a more optimal distribution (minimized precarity), yet are realistic or feasible to implement?
This distills our original problem statement down to something resembling a toy econometric or resource planning problem. But as with any complex modeling task (or any task really), starting simple is the only sane way to proceed*, despite what trend hoppers, dilettantes & consultants might say.
* I realize there is also a philosophy of model contraction, vs expansion
Technical Approach & Antecedents
In addition to the many qualitative treatments already mentioned, there are myriad ways to approach & model this problem quantitatively:
- Operations Research & (Combinatorial) Optimization: linear / integer programming, e.g. transportation problem
- Evolutionary / genetic programming & Reinforcement Learning
- Agent-based modeling, simulation, systems dynamics modeling
- Graph theory, network analysis
I initially thought OR was the logical place to start, but as I concretely conceptualized the problem, it was obviously more important to model relationships, fuzzy stochasticity & emergent dynamics than clear static costs, constraints & objective functions. This nudged me toward graph theory, network analysis & simulation, e.g. agent-based modeling & system dynamics.
I did some background research on similar approaches, & there are A LOT. This is not a literature review (though I might summarize some later), but here’s a short list of the most relevant resources I consulted, from most accessible to more technical:
Economic models
- The AI Economist: Improving Equality and Productivity with AI-Driven Tax Policies (Salesforce blog)
- Is Inequality Inevitable? Wealth naturally trickles up in free-market economies, model suggests (Scientific American)
- The Emergence of Inequality (Scott E Page)
- Emergent Inequality and Endogenous Dynamics in a Simple Behavioral Macroeconomic Model (SSRN, 2019)
- How Market Ecology Explains Market Malfunction (PNAS, 2020)
Scaling, Networks & Agent-based models
- Growth, innovation, scaling, and the pace of life in cities (PNAS)
- Decision-Making in Agent-Based Modeling: A Current Review and Future Prospectus (Frontiers in Evolutionary Ecology, 2019)
- Social Simulation Week 2020 Workshop on Agent-based models of social networks (Youtube, 2020)
- Introduction to stochastic actor-based models for network dynamics (Social Networks, 2010) [pdf]
- Social network analysis and agent-based modeling in social epidemiology (EP-I, 2012)
- Best Friends Forever? Modeling the Mechanisms of Friendship Network Formation (Winter Simulation Conference, 2020)
- Intelligent Agents in Co‑Evolving Knowledge Networks (Mathematics, 2021)
- Small and Other Worlds: Global Network Structures from Local Processes (American Journal of Sociology, 2005) [pdf]
- The Critical Periphery in the Growth of Social Protests (PLOS ONE, 2015)
Operations Research
- Probability and Algorithms, chapters 8 & 9 (Book, 1992)
- Multi-commodity flow problem (wikipedia)
Building the Network
Finally, the main event.
But first some basic terminology:
Establishing the network architecture & data structures felt foundational to further iteration & simulation. So I decided on an initial stack of tidygraph (built on igraph) & ggraph, in R — since it is the best data science language, & I didn’t want to mess around with goofy software like NetLogo.
(I’m aware of the irony).
Random Graphs
Started with a few classic network architectures, so-called random graphs. While not the most realistic representations of real world networks, they have some well-characterized empirical properties (as good simple models should):
- Erdős–Rényi (docs) — the og & (near) simplest random graph, theorized in 1959. Nodes are randomly connected via a specified probability, producing a Poisson degree distribution. (degree = a node’s # of edges)
- Barabási–Albert (docs) — models the scale-free character posited of many real world networks, (a power-law degree distribution) via preferential attachment
- Watts–Strogatz (small world) (docs) — reflects the small-world property (aka six-degrees of separation) of many real social networks. But like ER above, produces a Poisson degree distribution, rarer in real networks.
NB, it’s also not trivially obvious what characteristics of real networks we are or should be modeling. E.g. Facebook friends or Twitter followers are probably not the most relevant topologies for actual individual outcomes in the world.
Code & outputs
This is not a tutorial, so I won’t explain all the code, but these are good tutorials:
- Tidygraph Example
- Introduction to Network Analysis with R — several packages
- Graph analysis using the tidyverse
- A Social Network Simulation In The Tidyverse
- Social Network Analysis in R part 1: Ego Network
For initial simplicity & visual clarity, I’m keeping it Dunbar (150 nodes) & static (graph size & structure will not evolve)
library(tidyverse)
library(tidygraph)
library(ggraph)
library(igraph)# initialize graph via {tidygraph} function
graph_er <- play_erdos_renyi(150, 0.03, directed = F)# visualize via {ggraph}
ggraph(graph_er) +
geom_edge_link() +
geom_node_point() +
theme_graph()
graph_ba <- play_barabasi_albert(150, power = .01, directed = F)ggraph(graph_ba, layout = "graphopt") +
geom_edge_link() +
geom_node_point() +
theme_graph()
graph_sw <- play_smallworld(1, 150, 1, .2, loops = F, multiple = F)ggraph(graph_sw, layout = 'nicely') +
geom_edge_link() +
geom_node_point() +
theme_graph()
These are sightly enough little graphs, but I want to enrich them with more information & stochasticity, as a basis for further simulation.
(Recall our minimal specs above)
Given
- a social network with some realistic or empirically-useful structure
- some scarce resource distributed such that many lack while few have extreme excess
So in addition to the random distribution of edges (connections) between the nodes, I want to weight those connections as a representation of the ‘strength’ of relationship. Then: create asymmetrically-distributed ‘resources’ among the nodes, with an ‘endangered’ threshold indicating a level of resource precarity. I also add a ‘growth probability’ value to each node for later use.
Then let’s see what we got, reshaping nodes by their resources, & edges by weight:
mmmm…graphy.
After a similar approach with our other graphs:
We can see some of the respective attributes of each of these graph models mentioned above, but let’s quantify them with some summary statistics.
A look at the initial resource distribution, which is identical for all graphs:
as.list(graph_er)$nodes$resources %>% summary()# Min. 1st Qu. Median Mean 3rd Qu. Max.
# 1.25 49.45 118.77 540.64 320.69 19337.38as.list(graph_er)$nodes %>% as_tibble() %>%
ggplot() + geom_histogram(aes(resources), binwidth = 100) +
theme_minimal()
We see the steep lognormal decay with a median value of 119 & sparse outliers up to nearly 20k (hi elon).
Let’s zoom in a bit & plot the smoothed density to get a better view, along with a ‘precarity threshold’ below which nodes will be considered endangered:
We can also see the degree distributions of our graphs (i.e. the number of ‘edges’ or connections between nodes), which vary as described above. We’ll also include counts of total edges as well as ‘cliques’, or groups of mutually-connected nodes. These are all basic indicators of the connectedness of a graph.
Here we see the skewed, fat tailed power law distribution of the BA graph, & the more symmetrical Poisson distributions of the other graphs (but with considerably different spread & kurtosis). Later we’ll see how these differences in the ‘connectedness’ of nodes (& total number of edges) affects transactions throughout the network & overall system dynamics.
And a quick look at the distribution of edge weights, which we’ll use to indicate the ‘strength’ of relationships between nodes.
Although the number of edges & degree distributions vary across graphs, the edge weight distributions are consistent, as we defined them all as normal distributions:
as.list(graph_er)$edges$edge_weight %>% summary()
# Min. 1st Qu. Median Mean 3rd Qu. Max.
# 0.0000 0.3637 0.4661 0.4681 0.5697 1.0000# plot edge weight histogram & density
as.list(graph_er)$edges %>% as_tibble() %>%
ggplot(aes(edge_weight)) + geom_histogram(aes(y=..density..), binwidth = .03) +
geom_density(aes(y=..density..)) +
theme_minimal()
Ok, I’m happy with my little model graphworlds, ready to run some simulations
Simulating System Dynamics
First we’ll program some baseline dynamics for our networks, prior to any resource-sharing solidarity strategies.
I’m still not going for ultra-realism here, just a simple model with recognizable emergent dynamics. So at each time-step, we’ll increment each node’s resources by a probabilistic cost & growth function:
Then we’ll implement & visualize our baseline simulation via the following function, which logs various values at each iteration & produces a series of plots which we’ll compile into an animated gif:
library(gifski)# create gif via gifski::save_gif, for 7 'years' worth of 'monthly' iterations
save_gif(sim_gif_maker_er(7), gif_file = "sim_er_7.gif", width = 800, height = 850,
delay = .12, loop = TRUE, progress = TRUE, res=133)
Then lets see what we get:
There’s a lot going on here, so bears a few views to take it all in, but here’s a rundown of the major points:
- The
iteration
counter at the top left enumerates the discrete time-steps in the the simulation: here meant to be analogous to ‘months’ in the 7 ‘year’ simulation (so 84 total iterations) - The
endangered
counter &precarity proportion
reflect the total number & relative proportion of nodes falling below our ‘precarity threshold’ of 15resources
- On the graph itself, we see the growth & contraction of individual nodes according to their
resource
level (turning red when below the precarity threshold), per the probabilistic cost & growth function defined above - The histogram / density chart at the bottom depicts the
resource distribution
of the entire network as it changes over time, along withmedian
&mean
indicators
Taken together, we see a system with baseline dynamics in which:
- The total number & relative proportion of precarious nodes increases over time (from
< 10%
to> 40%
) - Few nodes experience tremendous resource growth while most contract — as indicated by the leftward lurch of the resource distribution peak (aka its mode), as well as the divergence of the
median
(leftward) &mean
(rightward)
In other words we have a system of exacerbating inequality: rich get richer, poor get poorer. The Matthew Effect in motion, which should be broadly familiar to us (though not precisely realistic).
(We can also plot these dynamics statically via the log of iteration values we stored in the sim_stats_er
dataframe):
l1 <- ggplot(data=sim_stats_er, aes(x=iteration, y=median_resources)) +
geom_line() + theme_minimal()
l2 <- ggplot(data=sim_stats_er, aes(x=iteration, y=log(mean_resources))) +
geom_line() + theme_minimal()
l3 <- ggplot(data=sim_stats_er, aes(x=iteration, y=precarity_proportion)) +
geom_area() + ylim(c(0,1)) + theme_minimal()l1/l2/l3
Right. So revisiting to our original research question:
Given
- a network with some realistic or empirically-useful structure
- some scarce resource distributed such that many lack while few have extreme excess
…can we design strategies of the sort suggested [below], which result in a more optimal distribution (minimized precarity), yet are realistic or feasible to implement?
…
1. Fractal: doing the same thing at all scales (roughly)
2. Barbell: e.g. 80–20 split of local & global ‘investments’
3. Memelord: a memetic vanguard of core actors, & peripheral propagation thru the system. (suggested by this & related work)
We’ve got our (crude, but hopefully) empirically-useful network & baseline dynamics of increasing precarity, which we hope to mitigate via the proposed strategies. So let’s design & implement those strategies, starting at the top.
Fractal Strategy
We defined our Fractal Strategy as: doing the same thing at all scales (roughly)
Since we kept our initial random graphs simple & Dunbar-sized, there isn’t much of a meaningful notion of ‘scale’ at this point. I plan to explore that sort of complexity in future iterations of this study, but for now will just construct a one-size-fits-all strategy to apply across the scale-constrained graph as our fractal strategy.
In this strategy, all connected nodes will exchange resources according to the following solidarity-inspired rule:
If a node has 3x more resources than its peer node, it will send resources to that node in an amount determined by the wealthier node’s current resources, scaled by the edge_weight (i.e. relationship strength) between nodes
In code:
Then our updated simulation & animation function:
Run it for 7 ‘years’:
# create gif via gifski::save_gif, for 7 'years' worth of 'monthly' iterations
save_gif(sim_gif_maker_er(7), gif_file = "fractal_er_7.gif", width = 800, height = 850,
delay = .12, loop = TRUE, progress = TRUE, res=133)
Output:
We see that our fractal solidarity strategy results in quite different dynamics than the baseline system:
- Both total
endangered
node count & relativeprecarity proportion
stabilize at levels slightly below initial conditions, rather than spiking - Resource distribution
median
&mean
both steadily increase as network resource growth is much more broadly distributed
(things seem to go off the rails & get a bit pathological at the end, at least graphically, but ok, we’re still just tinkering here)
A final look at all relevant plots in parallel:
So it seems our fractal strategy had roughly the desired effect on our Erdős–Rényi graph (although precarity is not eliminated).
But before implementing other strategies, let’s see how the above dynamics play out in our other graphs. (all code can be found in this repo)
Barabási–Albert
BA notes:
- similar baseline dynamics
- but due to power-law degree distribution (resulting in an overall less-connected graph), our fractal strategy is not as effective in mitigating precarity as it was in the Erdős–Rényi graph (Poisson degree distribution)
- —
median
network resources do not increase nearly as much, & themode
hardly moves, thus theprecarity proportion
still increases moderately
Watts–Strogatz (small world)
WS notes:
- again, baseline dynamics consistent with our other graphs
- & also again, a less effective fractal strategy, this time owing to the graph’s ‘small world’ nature, where nodes are connected in clusters or ‘neighborhoods’ with limited connections between clusters. (despite a Poisson degree distribution)
- — thus we see resource growth concentrated in lower left clusters & scarcely making it to some areas of the graph. (a dynamic we might again recognize in our own world)
- — & again, overall
median
network resources increase less, & themode
hardly moves, while theprecarity proportion
increases moderately
So we see initially that, while consistently mitigating the worst of the baseline dynamics, our fractal strategy’s effectiveness appears to be dependent on the underlying network structure.
Let’s see how our remaining 2 strategies fare.
Barbell Strategy
We defined our Barbell Strategy as: 80–20 split of local & global ‘investments’.
To implement, we’ll simply add logic on top of the fractal strategy which diverts 20% of the resources that would have been allocated to individual nodes from their wealthier connections, & allocate them ‘globally’ to the entire graph. A sort of graphworld UBI.
This requires only a few additional lines of code, which can be found in the full codebase here.
The outputs:
Barbell strategy notes:
- The 80–20 local / global split of fractal strategy resource reallocations has an immense impact on the overall network, eliminating precarity in the first few iterations in all graph structures, making the optimal strategy so far
- (also, I clearly need to implement some sort of growth constraints in the more realistic iterations of this study to come)
But let’s see our final strategy.
Memelord Strategy
We defined our Memelord Strategy as: a memetic vanguard of core actors, & peripheral propagation thru the system.
This required a more complex implementation than our other strategies, including adding core-periphery metadata to the nodes of our graphs, inspired by some previous work. Core-periphery detection methods attempt to identify more connected or influential core nodes in the network, as well as less connected & influential periphery nodes. There are a variety of approaches, but as yet no consensus, so again I kept it fairly simple initially, using Kleinberg’s hub centrality scores as measures of coreness.
To get a sense of what this did, we can plot our graphs & size by hub score
rather than resources
as we previously did:
We can also plot the hub score distributions & compare to our previously plotted degree distributions (which are obviously related):
So with this additional network information, we can implement our Memelord Strategy logic as follows:
- Nodes are influenced to reallocate their resources based on:
- — the strength of their connection (edge weight) to “influencer” nodes
- — in combination with the the influencer nodes’ clout (
hub_score
) - — as well as the strength of the influencer nodes’ connection to other nodes, which are candidates to receive the resource
So in this strategy, nodes do not (necessarily) send resources to their direct connections (adjacent nodes), but rather to other nodes who are mutually connected to influencer ‘hub’ nodes (proportionate to their hubness & connection strengths across the full edge path).
Otherwise, the same ‘3x resource’ evaluation is made as in the other strategies.
Again, the code can be found in the full codebase here.
Here’s what we get:
Memelord strategy notes:
- Similar to the Fractal Strategy, resource reallocation is much more constrained than in the Barbell Strategy, with influencers acting as chokepoints or bottlenecks, resulting in limited mitigation of precarity
- Network structure has an obvious impact here, as less hubby (interconnected) structures result in less influencer reach, which further constrains resource flows
So let’s see all our simulations stacked up against each other.
A final look at all simulations, grouped by strategy
Baseline simulations
To reiterate baseline simulation dynamics notes from above, which are fairly consistent across graphs:
- The total number & relative proportion of precarious nodes increases over time (from
< 10%
to> 40%
) - Few nodes experience tremendous resource growth while most contract — as indicated by the leftward lurch of the resource distribution peak (aka its mode), as well as the divergence of the
median
(leftward) &mean
(rightward)
Fractal Strategy Simulations
Fractal strategy notes:
- This strategy stabilizes & mitigates
precarity
across all graphs, compared with baseline dynamics, but its effectiveness is constrained by network structure & overall connectedness, with precarity ultimately increasing in the latter 2 graphs - A similar dynamic applies to
median
& total graph resource growth, where we see growth concentrated in certain ‘neighborhoods’ more than others
Barbell Strategy Simulations
Barbell strategy notes from above:
- The 80–20 local / global split of fractal strategy resource reallocations has an immense impact on the overall network, eliminating precarity in the first few iterations in all graph structures, making the optimal strategy so far
- (also, I clearly need to implement some sort of growth constraints in the more realistic iterations of this study to come)
Memelord Strategy Simulations
Memelord strategy notes from above:
- Similar to the Fractal Strategy, resource reallocation is much more constrained than in the Barbell Strategy, with influencers acting as chokepoints or bottlenecks, resulting in limited mitigation of precarity
- Network structure has an obvious impact here, as less hubby (interconnected) structures result in less influencer reach, which further constrains resource flows
…And all simulations grouped by graph structure
Erdős–Rényi
Baseline simulation & reference graphs, followed by strategy simulations:
Erdős–Rényi notes:
- The interconnected nature of the ER graph makes it among the most amenable network structure to each of our solidarity strategies
- Unfortunately, it is also considered among the least empirically accurate with regard to real-world networks
- In a recurring theme, the Barbell Strategy performs best on this graph
Barabási–Albert
Baseline simulation & reference graphs, followed by strategy simulations:
Barabási–Albert notes:
- The scale-free nature of the BA graph (power-law degree distribution) puts it somewhere between our other two graphs in terms of connectedness, which results in a similar middling effectiveness for our strategies.
- While disputed, many real world networks appear to at least resemble power-law dynamics, making it an especially empirically useful model
- Again, Barbell outperforms
Watts–Strogatz (small world)
Baseline simulation & reference graphs, followed by strategy simulations:
Watts–Strogatz (small world) notes:
- The segregated nature of small-world ‘neighborhoods’ (clusters of nodes with short-path connections within but few connections between clusters) present challenges for most of our network strategies, as resource flows become concentrated among few clusters & bottlenecked across the graph
- While this graph’s overall connectedness (e.g. thin-tailed Poisson degree-distribution) appears to be less common in real networks, the small-world property has been observed in many real-world social networks, & we should beware of the impact of similar parochial dynamics on solidarity & equity efforts.
- — (so membership in, or bridge-building between, multiple memetic tribes might truly be god’s work)
- Once again, even the aforementioned constraints are overcome by the Barbell Strategy
(Tentative) Conclusion & Future Directions
We set out to do some initial quantitative tinkering around scaling dynamics for ethical actions, exploring tensions between ‘localist’ & ‘globalist’ orientations & some candidate strategies to navigate those tensions:
- Fractal: doing the same thing at all scales (roughly)
- Barbell: e.g. 80–20 split of local & global ‘investments’
- Memelord: a memetic vanguard of core actors, & peripheral propagation thru the system
Our initial simulations, while not aiming for realism or empirical precision, demonstrated some potential strategies & their effectiveness across different basic network topologies.
Two salient provisional observations:
- Network structures which result in similar dynamics & outcomes under a baseline simulation, nonetheless appear to differentially impact the effectiveness of proposed solidarity strategies.
— The most impactful characteristics appear related to connectedness & the nature of connection formation (e.g. degree distribution & hub dependence) - A Barbell Strategy (80–20 split of local & global activity) appeared to be the most robust & invariant to network-specific constraints affecting other strategies.
— Intuitively, even simple, relatively small global efforts easily scaled to overcome the local choke-points, bottlenecks & parochialism that constrained the other single-path, less diversified strategies
Still, this was a very preliminary investigation into emergent dynamics in toy mechanistic models. Network science is a young but deep field & I’ve only scratched the surface here, not to mention the intersections with Complex Systems theory, agent-based modeling, etc.
Future Directions
In addition to related clusters of research questions mentioned in the Motivation section above, there are several obvious directions for future iterations & refinements:
(Also appreciate any feedback, commentary or suggestions)
- More realistic, empirically-driven network models & dynamics
- More sophisticated implementation of conceptual strategies (as well as new qualitative strategies, & interactions beyond ‘resource’ exchange )
- Dynamic evolution of network structures (e.g. temporal dynamics in graph size, connections & edge weights, also responsive to stochastic strategies)
— (Tyson Yunkaporta mentioned somewhere: representing the land as an agent in agent-based model simulation) - Larger networks & scaling structures, & many more stochastic simulation runs with ensembled results
- More formal mathematical descriptions & measures
- Codebase refactoring & optimization
Until then, let’s keep working towards the feedback loop where the good gets better.
Thanks for reading, follow me & check out my other posts. Also, please comment with thoughts, suggestions or corrections!
—
Follow on twitter: @dnlmc
LinkedIn: linkedin.com/in/dnlmc
Github: https://github.com/dnlmc