Many network interactions include both positive and negative edges to account for ‘against’ or ‘for’ types of relationships that cannot be modeled using regular network algorithms. Structural balance theory is attributed to Heider (1946) and Cartwright and Harary (1956). The theory briefly describes four types balanced triads that is:
Enemy of an enemy is a friend
Friend of a friend is a friend
Enemy of a friend is an enemy
Friend of an enemy is an enemy
These relationship can be observed in Figure 1.
We can define an undirected signed network as \(G = (V, E, \sigma)\) where \(\sigma\) is the sign function that maps edges to \(\{-1, 1\}\).
The network is structually balanced if it can be partitioned into two sets \(V_+\) and \(V_-\) such that all edges between \(V_+\) and \(V_-\) are negative and all edges within \(V_+\) and \(V_-\) are positive.
The network is k-balanced if it can be partitioned into \(k\) sets \(V_1, V_2, ..., V_k\) such that all edges between \(V_i\) and \(V_j\) are negative for \(i \neq j\) and all edges within \(V_i\) are positive.
Edges are said to be frustrated if positive edges have different endpoint colors or negative edges have the same endpoint colors.
It is reasonable to develop clustering models that minimize the number of frustrated edges. However, this is an NP-hard problem. Aref and Neal (2021) have developed an integer linear programming model that minimizes the number of frustrated edges. The model is as follows:
\[\begin{align*}
\min_{f_{ij}} & \sum_{(i,j) \in E} f_{ij} \\
\text{s.t.} & \sum_{c \in C} x_{ic} = 1 & \forall i \in V \\
& f_{ij} \ge x_{ic} - x_{jc} & \forall (i,j) \in E^+, \forall c \in C \\
& f_{ij} \ge x_{ic} + x_{jc} - 1 & \forall (i,j) \in E^-, \forall c \in C \\
& x_{ic} \in \{0, 1\} & \forall i \in V, \forall c \in C \\
& f_{ij} \in \{0,1\} & \forall (i,j) \in E
\end{align*}\]
where:
\(E\) is the set of edges in the network
\(V\) is the set of nodes in the network
\(C\) is the set of communities in the network
\(f_{ij}\) is a binary variable indicating whether edge \((i,j)\) is frustrated
\(x_{ic}\) is a binary variable indicating whether node \(i\) belongs to community \(c\)
Here is an application of frustration minimization that particularly clusters the network into two communities based on the AND model developed by Samin Aref et al. (2020)
Some codes to read or generate signed networks are provided below followed by the application of the AND model.
Code
import networkx as nximport numpy as npdef graph_from_adjacency_matrix_signed(A, mode='undirected'): unique_elements = np.unique(A)for element in unique_elements:if element notin (-1, 0, 1):raiseValueError("A should only have entries -1, 0, 1")if mode =='undirected': G = nx.from_numpy_matrix(A, create_using=nx.Graph())else: G = nx.from_numpy_matrix(A, create_using=nx.DiGraph())for (u, v, wt) in G.edges.data('weight'):if wt <0: G.edges[u, v]['weight'] =-1elif wt >0: G.edges[u, v]['weight'] =1else: G.edges[u, v]['weight'] =0return G
Code
import networkx as nximport numpy as npdef graph_from_edgelist_signed(el, signs, directed=False):iflen(el[0]) !=2:raiseValueError("graph_from_edgelist_signed expects a numpy array with two columns")iflen(signs) !=len(el):raiseValueError("signs and el must have the same length")ifnotall(sign in [-1, 1] for sign in signs):raiseValueError("signs should only have entries -1 or 1")if directed: G = nx.DiGraph()else: G = nx.Graph()for i inrange(len(el)): G.add_edge(el[i][0], el[i][1], sign=signs[i])return G
Code
import networkx as nximport numpy as npdef sample_gnp_signed(n, p, p_neg, directed=False, loops=False):if p_neg isNone:raiseValueError("p_neg is missing with no default")# Create a graph based on the Erdos-Renyi modelif directed: G = nx.fast_gnp_random_graph(n, p, directed=True)else: G = nx.fast_gnp_random_graph(n, p)# Assign a sign to each edge with a given probability p_negfor edge in G.edges(): G.edges[edge]['sign'] = np.random.choice([-1, 1], p=[p_neg, 1-p_neg])return G
Code
nsign = sample_gnp_signed(15, 0.4, 0.5)
Code
import networkx as nx#!pip install pulpfrom pulp import LpVariable, LpProblem, LpMinimize, lpSumdef frustration_exact(g):#if 'sign' not in g.edges.data():#raise ValueError("Network does not have a sign edge attribute") A = nx.to_numpy_array(g, weight='sign', dtype=int)#d = A.sum(axis=1) n =len(g) x = [[LpVariable(f'x_{i}_{j}', 0, 1, 'Binary') for j inrange(n)] for i inrange(n)] y = [LpVariable(f'y_{i}', 0, 1, 'Binary') for i inrange(n)] prob = LpProblem("FrustrationExact", LpMinimize) objective = ( lpSum(y[i] + y[j] -2* x[i][j] for i inrange(n) for j inrange(i +1, n) if A[i, j] ==1) + lpSum(1- (y[i] + y[j] -2* x[i][j]) for i inrange(n) for j inrange(i +1, n) if A[i, j] ==-1) ) prob += objectivefor i inrange(n):for j inrange(i +1, n):if A[i, j] ==1: prob += x[i][j] <= y[i] prob += x[i][j] <= y[j]elif A[i, j] ==-1: prob += x[i][j] >= y[i] + y[j] -1 prob.solve() partition = [val.varValue for val in y] frustration = prob.objective.value()return {'frustration': frustration, 'partition': partition}
Code
#frustration_exact(nsign)
References
1: Aref, Samin, and Zachary P. Neal. “Identifying hidden coalitions in the US House of Representatives by optimally partitioning signed networks based on generalized balance.” Scientific reports 11.1 (2021): 19939.
2: Aref, Samin, Andrew J. Mason, and Mark C. Wilson. “A modeling and computational study of the frustration index in signed networks.” Networks 75.1 (2020): 95-110.