Basic Eigenvector Simulation
In the post PageRank and Token Design we discuss the basic ideas surrounding Eigenvector-based algorithms and their applications in decentralized cryptonetworks and DePIN. In this post, we walk through an intentionally simplified example to show how a producer graph would look in a generic marketplace.
You can visualize a network as a bipartite graph representing producers and buyers as nodes, with weighted edges capturing transactions between them. Edge weights track the cumulative fees contributed by producer from transactions with buyer .
To capture both the economic activity and the network influence of each node, we introduce a graph value metric that incorporates eigenvector centrality. For each producer , we define the graph value as:
Where:
- is the absolute value of the eigenvector centrality of node
- is a tunable parameter between 0 and 1
- is the sum of all edge weights connected to
Using the absolute value in the calculation:
Ensures Non-negativity: This approach guarantees that all centrality measures contribute positively to the graph value, aligning with the typical requirements of token distribution mechanisms where negative contributions are not practical.
Preserves the Interpretative Integrity: While taking the absolute value can sometimes mask the directionality (if relevant), in many network applications, especially those involving token distributions or influence measures, the magnitude of centrality is more critical than its direction.
The eigenvector centrality is calculated by solving the eigenvector equation:
The eigenvector centrality is calculated by solving the eigenvector equation:
Where:
- is the adjacency matrix of the graph
- is the largest eigenvalue
- is the corresponding eigenvector
The eigenvector centrality of a node is its corresponding value in the normalized eigenvector .
This graph value metric combines the node's economic activity (represented by the sum of edge weights) with its structural importance in the network (represented by its eigenvector centrality). The parameter allows for tuning the balance between these two factors.
Simple Example of a Dynamic Graph
Let's simulate a small network with 2 producers (P1, P2) and 3 buyers (B1, B2, B3). We'll use for our calculations.
In Python, we can defined a function calculate_graph_values
that performs our calculations with the NetworkX package.
import numpy as np
import networkx as nx
def calculate_graph_values(G, alpha=0.5):
# Ensure consistent node ordering
node_order = ['P1', 'P2', 'B1', 'B2', 'B3']
# Create adjacency matrix
A = nx.to_numpy_array(G, nodelist=node_order)
# Calculate eigenvector centrality
eigenvalues, eigenvectors = np.linalg.eig(A)
largest_index = np.argmax(eigenvalues)
eigenvector = eigenvectors[:, largest_index].real
# Normalize eigenvector
eigenvector = np.abs(eigenvector) / np.linalg.norm(eigenvector)
# Calculate graph values for producers
graph_values = {}
for i, node in enumerate(node_order):
if node.startswith('P'):
economic_activity = sum(G[node][neighbor]['weight'] for neighbor in G[node])
graph_values[node] = alpha * eigenvector[i] + (1 - alpha) * economic_activity
return A, eigenvector, graph_values
Initial transaction graph:
We will define an initial graph:
# Create initial graph
G = nx.Graph()
G.add_edge('P1', 'B1', weight=2)
G.add_edge('P2', 'B2', weight=3)
G.add_edge('P2', 'B3', weight=1)
Visually, this will look like this:
When we run the graph through our calculate_graph_values
function as:
A, eigenvector, graph_values = calculate_graph_values(G)
we produce the following results.
Updated adjacency matrix :
P1 | P2 | B1 | B2 | B3 | |
---|---|---|---|---|---|
P1 | 0 | 0 | 2 | 0 | 0 |
P2 | 0 | 0 | 0 | 3 | 1 |
B1 | 2 | 0 | 0 | 0 | 0 |
B2 | 0 | 3 | 0 | 0 | 0 |
B3 | 0 | 1 | 0 | 0 | 0 |
Solving , we get the normalized absolute eigenvector value for each node:
Node | Value |
---|---|
P1 | 0.0000 |
P2 | 0.7071 |
B1 | 0.0000 |
B2 | 0.6708 |
B3 | 0.2236 |
Transaction from P1 to B2 with = 2
Next, we will add a new transaction with revenue contribution 2
between node P1
and node B2
.
# Stage 2: New transaction P1 to B2
G.add_edge('P1', 'B2', weight=2)
Updated transaction graph:
When we run the updated graph through our calculate_graph_values
function as:
A, eigenvector, graph_values = calculate_graph_values(G)
we produce the following results.
Updated adjacency matrix :
P1 | P2 | B1 | B2 | B3 | |
---|---|---|---|---|---|
P1 | 0 | 0 | 2 | 2 | 0 |
P2 | 0 | 0 | 0 | 3 | 1 |
B1 | 2 | 0 | 0 | 0 | 0 |
B2 | 2 | 3 | 0 | 0 | 0 |
B3 | 0 | 1 | 0 | 0 | 0 |
Solving , we get the normalized absolute eigenvector value for each node:
Node | Value |
---|---|
P1 | 0.4571 |
P2 | 0.5395 |
B1 | 0.2354 |
B2 | 0.6521 |
B3 | 0.1389 |
Transaction from P2 to B1 with = 1
Next, we will add a new transaction with revenue contribution 1
between node P2
and node B1
.
# Stage 2: New transaction P1 to B2
G.add_edge('P2', 'B1', weight=1)
Updated transaction graph:
When we run the updated graph through our calculate_graph_values
function as:
A, eigenvector, graph_values = calculate_graph_values(G)
we produce the following results.
Updated adjacency matrix :
P1 | P2 | B1 | B2 | B3 | |
---|---|---|---|---|---|
P1 | 0 | 0 | 2 | 2 | 0 |
P2 | 0 | 0 | 1 | 3 | 1 |
B1 | 2 | 1 | 0 | 0 | 0 |
B2 | 2 | 3 | 0 | 0 | 0 |
B3 | 0 | 1 | 0 | 0 | 0 |
Solving , we get the normalized absolute eigenvector value for each node:
Node | Value |
---|---|
P1 | 0.4516 |
P2 | 0.5441 |
B1 | 0.3446 |
B2 | 0.6037 |
B3 | 0.1296 |
Overview of the basic MEC Token distributions
Throughout the simulation, we observe:
- The graph value of P1 increased significantly after its transaction with B2, reflecting both increased economic activity and improved network position by connecting with the P2 graph.
- P2's graph value increased more modestly but consistently, benefiting from both its initial strong position and new transaction.
- The eigenvector centrality captures the nodes' importance in the network structure, which changes with new connections.
- The combined metric balances economic activity with network influence, providing a more comprehensive measure of each producer's contribution to the platform.