CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-igraph

High performance graph data structures and algorithms for Python

Pending
Overview
Eval results
Files

sequences.mddocs/

Vertex and Edge Sequences

Efficient sequence classes for accessing and manipulating collections of vertices and edges with filtering and attribute operations. These classes provide powerful query and manipulation capabilities for graph elements.

Capabilities

Vertex Sequences

Collections of vertices with advanced filtering, selection, and attribute manipulation methods.

class VertexSeq:
    def __init__(self, graph, vertices=None):
        """
        Create vertex sequence.
        
        Parameters:
        - graph: Graph object
        - vertices: list/range, vertex indices (None for all vertices)
        """

    def __len__(self):
        """Get number of vertices in sequence."""

    def __getitem__(self, key):
        """
        Access vertices by index or slice.
        
        Parameters:
        - key: int/slice/str, vertex index, slice, or attribute name
        
        Returns:
        Vertex or VertexSeq or attribute values
        """

    def select(self, *args, **kwargs):
        """
        Filter vertices by criteria.
        
        Parameters:
        - *args: vertex indices or boolean conditions
        - **kwargs: attribute-based filters
        
        Returns:
        VertexSeq, filtered vertices
        """

    def find(self, *args, **kwargs):
        """
        Find first vertex matching criteria.
        
        Parameters:
        - *args: search criteria
        - **kwargs: attribute filters
        
        Returns:
        Vertex, first match
        """

    def attributes(self):
        """
        Get list of vertex attribute names.
        
        Returns:
        list of str, attribute names
        """

    @property
    def indices(self):
        """
        Get vertex indices.
        
        Returns:
        list of int, vertex indices in sequence
        """

Usage Examples:

import igraph as ig

# Create sample graph with attributes
g = ig.Graph([(0,1), (1,2), (2,0), (1,3), (3,4)], directed=False)
g.vs["name"] = ["Alice", "Bob", "Carol", "Dave", "Eve"]
g.vs["age"] = [25, 30, 28, 35, 22]
g.vs["city"] = ["NYC", "LA", "NYC", "LA", "Chicago"]

# Access all vertices
all_vertices = g.vs
print(f"Total vertices: {len(all_vertices)}")

# Access by index
vertex_0 = g.vs[0]
print(f"Vertex 0: {vertex_0}")

# Access by slice
first_three = g.vs[0:3]
print(f"First three vertices: {first_three.indices}")

# Access attributes
names = g.vs["name"]
ages = g.vs["age"]
print(f"Names: {names}")
print(f"Ages: {ages}")

# Get available attributes
print(f"Available attributes: {g.vs.attributes()}")

Vertex Selection and Filtering

Advanced filtering capabilities using attribute values, graph properties, and custom criteria.

class VertexSeq:
    def select(self, *args, **kwargs):
        """
        Advanced vertex filtering.
        
        Selection methods:
        - By index: vs.select(0, 2, 4)
        - By range: vs.select(range(5, 10))
        - By attribute value: vs.select(name="Alice")
        - By attribute condition: vs.select(age_gt=30)
        - By degree: vs.select(_degree_gt=5)
        - By boolean list: vs.select([True, False, True, ...])
        - By lambda: vs.select(lambda v: v.degree() > 2)
        
        Attribute conditions:
        - attr_eq, attr_ne: equal, not equal
        - attr_lt, attr_le: less than, less or equal
        - attr_gt, attr_ge: greater than, greater or equal
        - attr_in, attr_notin: in list, not in list
        
        Graph property conditions:
        - _degree, _indegree, _outdegree: vertex degrees
        - _between: vertices between given vertices
        
        Returns:
        VertexSeq, filtered vertices
        """

Usage Examples:

# Select by attribute values
nyc_vertices = g.vs.select(city="NYC")
print(f"NYC vertices: {nyc_vertices.indices}")

# Select by attribute conditions
older_vertices = g.vs.select(age_gt=27)
young_vertices = g.vs.select(age_le=25)
print(f"Older than 27: {older_vertices['name']}")
print(f"25 or younger: {young_vertices['name']}")

# Select by multiple conditions
nyc_older = g.vs.select(city="NYC", age_gt=27)
print(f"NYC and older than 27: {nyc_older['name']}")

# Select by degree
high_degree = g.vs.select(_degree_gt=1)
print(f"High degree vertices: {high_degree['name']}")

# Select by index list
specific_vertices = g.vs.select([0, 2, 4])
print(f"Specific vertices: {specific_vertices['name']}")

# Select with lambda function
lambda_selection = g.vs.select(lambda v: v["age"] < 30 and v.degree() >= 2)
print(f"Lambda selection: {lambda_selection['name']}")

# Select by attribute list membership
la_chicago = g.vs.select(city_in=["LA", "Chicago"])
print(f"LA or Chicago: {la_chicago['name']}")

# Exclude vertices
not_bob = g.vs.select(name_ne="Bob")
print(f"Not Bob: {not_bob['name']}")

Edge Sequences

Collections of edges with specialized filtering for network topology analysis.

class EdgeSeq:
    def __init__(self, graph, edges=None):
        """
        Create edge sequence.
        
        Parameters:
        - graph: Graph object  
        - edges: list/range, edge indices (None for all edges)
        """

    def select(self, *args, **kwargs):
        """
        Filter edges by criteria.
        
        Special edge filters:
        - _source, _target: source/target vertex conditions
        - _between: edges between vertex sets
        - _within: edges within vertex set  
        - _incident: edges incident to vertices
        
        Returns:
        EdgeSeq, filtered edges
        """

    def find(self, *args, **kwargs):
        """
        Find first edge matching criteria.
        
        Returns:
        Edge, first match
        """

    def attributes(self):
        """
        Get edge attribute names.
        
        Returns:
        list of str, attribute names
        """

    @property
    def indices(self):
        """
        Get edge indices.
        
        Returns:
        list of int, edge indices
        """

Usage Examples:

# Add edge attributes
g.es["weight"] = [1.0, 2.5, 1.8, 0.9, 3.2]
g.es["type"] = ["friend", "work", "family", "friend", "work"]

# Access all edges
all_edges = g.es
print(f"Total edges: {len(all_edges)}")

# Access edge attributes
weights = g.es["weight"]
types = g.es["type"]
print(f"Edge weights: {weights}")
print(f"Edge types: {types}")

# Select by attribute
friend_edges = g.es.select(type="friend")
heavy_edges = g.es.select(weight_gt=2.0)
print(f"Friend edges: {friend_edges.indices}")
print(f"Heavy edges (>2.0): {heavy_edges.indices}")

# Select by source/target vertices
from_alice = g.es.select(_source=0)  # Alice is vertex 0
to_bob = g.es.select(_target=1)     # Bob is vertex 1
print(f"Edges from Alice: {from_alice.indices}")
print(f"Edges to Bob: {to_bob.indices}")

# Select edges between specific vertices
alice_bob = g.es.select(_between=([0], [1]))
print(f"Edges between Alice and Bob: {alice_bob.indices}")

# Select edges within a set (internal edges)
core_vertices = [0, 1, 2]  # Alice, Bob, Carol
internal_edges = g.es.select(_within=core_vertices)
print(f"Internal edges in core: {internal_edges.indices}")

# Select edges incident to vertices
incident_to_bob = g.es.select(_incident=1)
print(f"Edges incident to Bob: {incident_to_bob.indices}")

Advanced Edge Selection

Complex edge filtering patterns for network analysis.

Usage Examples:

# Multiple source/target conditions
multi_source = g.es.select(_source_in=[0, 1])  # From Alice or Bob
multi_target = g.es.select(_target_in=[2, 3])  # To Carol or Dave
print(f"From Alice/Bob: {multi_source.indices}")
print(f"To Carol/Dave: {multi_target.indices}")

# Edges between two sets of vertices
group1 = [0, 1]      # Alice, Bob
group2 = [2, 3, 4]   # Carol, Dave, Eve
between_groups = g.es.select(_between=(group1, group2))
print(f"Between groups: {between_groups.indices}")

# Combine topological and attribute filters
heavy_friend_edges = g.es.select(type="friend", weight_gt=1.5)
print(f"Heavy friendship edges: {heavy_friend_edges.indices}")

# Edges involving high-degree vertices
high_deg_vertices = g.vs.select(_degree_gt=1).indices
edges_with_hubs = g.es.select(_incident_in=high_deg_vertices)
print(f"Edges involving hubs: {edges_with_hubs.indices}")

# Complex lambda selection
complex_edges = g.es.select(lambda e: e["weight"] > 1.0 and 
                           g.vs[e.source]["age"] + g.vs[e.target]["age"] > 55)
print(f"Complex selection: {complex_edges.indices}")

Attribute Access and Manipulation

Efficient batch operations on vertex and edge attributes.

class VertexSeq:
    def __setitem__(self, attr, values):
        """
        Set attribute values for vertices in sequence.
        
        Parameters:
        - attr: str, attribute name
        - values: list/value, attribute values
        """

    def __delitem__(self, attr):
        """
        Delete attribute from vertices.
        
        Parameters:
        - attr: str, attribute name to delete
        """

class EdgeSeq:
    def __setitem__(self, attr, values):
        """Set attribute values for edges."""
    
    def __delitem__(self, attr):
        """Delete attribute from edges."""

Usage Examples:

# Set new attributes
g.vs["degree"] = g.degree()
g.vs["normalized_age"] = [age/max(g.vs["age"]) for age in g.vs["age"]]

# Set attributes for filtered vertices
nyc_vertices = g.vs.select(city="NYC")
nyc_vertices["region"] = "East Coast"

high_degree = g.vs.select(_degree_gt=1)
high_degree["is_hub"] = True

# Set edge attributes
g.es["normalized_weight"] = [w/max(g.es["weight"]) for w in g.es["weight"]]

# Conditional attribute setting
for v in g.vs:
    if v["age"] >= 30:
        v["generation"] = "Millennial"
    else:
        v["generation"] = "Gen Z"

# Batch attribute operations
young_vertices = g.vs.select(age_lt=30)
young_vertices["category"] = "Young Adult"

# Delete attributes
del g.vs["normalized_age"]  # Remove from all vertices
del nyc_vertices["region"]  # Remove from filtered set

# Get attribute statistics
ages = g.vs["age"]
print(f"Age stats - Min: {min(ages)}, Max: {max(ages)}, Avg: {sum(ages)/len(ages):.1f}")

weights = g.es["weight"]  
print(f"Weight stats - Min: {min(weights)}, Max: {max(weights)}, Avg: {sum(weights)/len(weights):.1f}")

Sequence Operations

Mathematical and set operations on vertex and edge sequences.

class VertexSeq:
    def union(self, other):
        """Union with another vertex sequence."""
    
    def intersection(self, other):
        """Intersection with another vertex sequence."""
    
    def difference(self, other):
        """Difference from another vertex sequence."""

# Similar operations available for EdgeSeq

Usage Examples:

# Set operations on vertex sequences
nyc_vertices = g.vs.select(city="NYC")
young_vertices = g.vs.select(age_lt=30)
high_degree = g.vs.select(_degree_gt=1)

# Union (vertices in either set)
nyc_or_young = nyc_vertices.union(young_vertices)
print(f"NYC or young: {nyc_or_young['name']}")

# Intersection (vertices in both sets)
nyc_and_young = nyc_vertices.intersection(young_vertices)  
print(f"NYC and young: {nyc_and_young['name']}")

# Difference (vertices in first set but not second)
nyc_not_young = nyc_vertices.difference(young_vertices)
print(f"NYC but not young: {nyc_not_young['name']}")

# Chain operations
complex_selection = nyc_vertices.union(high_degree).intersection(young_vertices)
print(f"Complex selection: {complex_selection['name']}")

# Edge sequence operations
friend_edges = g.es.select(type="friend")
heavy_edges = g.es.select(weight_gt=2.0)

friend_or_heavy = friend_edges.union(heavy_edges)
friend_and_heavy = friend_edges.intersection(heavy_edges)
print(f"Friend or heavy edges: {friend_or_heavy.indices}")
print(f"Heavy friend edges: {friend_and_heavy.indices}")

Sequence Iteration and Comprehensions

Efficient iteration patterns and list comprehensions with sequences.

Usage Examples:

# Iterate over vertices
for vertex in g.vs:
    print(f"Vertex {vertex.index}: {vertex['name']}, degree: {vertex.degree()}")

# Iterate over filtered vertices  
for vertex in g.vs.select(age_gt=28):
    print(f"Older vertex: {vertex['name']} (age {vertex['age']})")

# List comprehensions with sequences
vertex_info = [(v['name'], v['age'], v.degree()) for v in g.vs]
print("Vertex info:", vertex_info)

# Edge iteration
for edge in g.es:
    source_name = g.vs[edge.source]['name']
    target_name = g.vs[edge.target]['name']
    print(f"Edge: {source_name} -- {target_name} ({edge['type']}, {edge['weight']})")

# Filtered edge iteration
for edge in g.es.select(weight_gt=1.5):
    print(f"Heavy edge: {edge.source} -- {edge.target}")

# Create derived attributes using comprehensions
g.vs["name_length"] = [len(name) for name in g.vs["name"]]
g.es["weight_category"] = ["light" if w < 2.0 else "heavy" for w in g.es["weight"]]

# Complex comprehensions
g.vs["connection_strength"] = [
    sum(g.es.select(_incident=v.index)["weight"]) 
    for v in g.vs
]

# Neighborhood analysis
for vertex in g.vs.select(_degree_gt=2):
    neighbors = [g.vs[n]['name'] for n in g.neighbors(vertex.index)]
    print(f"{vertex['name']} is connected to: {neighbors}")

Performance Optimization

Efficient patterns for working with large graphs and sequences.

Usage Examples:

# Efficient attribute access patterns
def analyze_large_graph(graph):
    """Efficient analysis of large graphs using sequences."""
    
    # Pre-compute commonly used attributes
    degrees = graph.degree()
    betweenness = graph.betweenness()
    
    # Batch attribute setting (more efficient than individual)
    graph.vs["degree"] = degrees
    graph.vs["betweenness"] = betweenness
    graph.vs["normalized_betw"] = [b/max(betweenness) for b in betweenness]
    
    # Use indices for fast filtering
    high_degree_indices = [i for i, d in enumerate(degrees) if d > 10]
    high_degree_vs = graph.vs[high_degree_indices]
    
    # Efficient edge filtering
    important_edges = graph.es.select(_source_in=high_degree_indices, 
                                     _target_in=high_degree_indices)
    
    return high_degree_vs, important_edges

# Memory-efficient iteration for very large graphs
def process_vertices_in_chunks(graph, chunk_size=1000):
    """Process vertices in chunks to manage memory."""
    n_vertices = graph.vcount()
    
    for start in range(0, n_vertices, chunk_size):
        end = min(start + chunk_size, n_vertices)
        chunk = graph.vs[start:end]
        
        # Process chunk
        for vertex in chunk:
            # Do processing here
            pass
        
        print(f"Processed vertices {start} to {end-1}")

# Efficient neighbor analysis  
def analyze_neighborhoods(graph):
    """Efficient neighborhood analysis."""
    # Pre-compute all neighborhoods
    all_neighbors = [set(graph.neighbors(i)) for i in range(graph.vcount())]
    
    # Analyze without repeated graph queries
    for i, vertex in enumerate(graph.vs):
        neighbor_ages = [graph.vs[n]["age"] for n in all_neighbors[i]]
        vertex["avg_neighbor_age"] = sum(neighbor_ages) / len(neighbor_ages) if neighbor_ages else 0

# Usage for large graphs
if g.vcount() > 1000:
    high_deg, important_edges = analyze_large_graph(g)
    process_vertices_in_chunks(g, chunk_size=500)
else:
    # Use simpler patterns for small graphs
    analyze_neighborhoods(g)

Install with Tessl CLI

npx tessl i tessl/pypi-igraph

docs

analysis.md

clustering.md

community.md

data-types.md

graph-creation.md

graph-structure.md

index.md

io-formats.md

layout.md

sequences.md

visualization.md

tile.json