High-level description
TheILPSolver class implements the Cassiopeia-ILP algorithm for inferring a maximum parsimony phylogenetic tree. It constructs a potential graph of possible evolutionary states and uses Gurobi, an ILP solver, to find the maximum parsimony Steiner Tree within this graph. This tree represents the proposed phylogenetic relationship between the input samples.
Code Structure
TheILPSolver class inherits from the CassiopeiaSolver abstract class. It overrides the solve method to implement the Cassiopeia-ILP algorithm. The main steps involve inferring a potential graph, generating a Steiner Tree ILP model, solving the ILP problem, post-processing the solution, and populating the resulting tree in a CassiopeiaTree object.
References
ilp_solver_utilities: This module provides utility functions for inferring the potential graph and other ILP-related operations.dissimilarity_functions: This module provides functions for calculating dissimilarity between character states, including weighted Hamming distance.solver_utilities: This module provides general utility functions for tree solvers, such as transforming priors into weights.gurobipy: This module provides the interface to the Gurobi optimizer.
Symbols
ILPSolver
Description
This class implements the Cassiopeia-ILP algorithm for phylogenetic tree inference.Inputs
Outputs
Thesolve method does not return any value but populates the provided CassiopeiaTree object with the inferred tree.
Internal Logic
Thesolve method performs the following steps:
- Preprocessing: Checks for ambiguous states, prepares the character matrix, and transforms priors into weights if necessary.
- Root Identification: Identifies the root of the tree based on the least common ancestor of all samples.
- Potential Graph Inference: Infers the potential graph using the
infer_potential_graphmethod. - Steiner Tree Model Generation: Generates a Gurobi ILP model for the Steiner Tree problem using the
generate_steiner_modelmethod. - ILP Solution: Solves the ILP problem using the
solve_steiner_instancemethod. - Solution Post-processing: Post-processes the solution to remove self-loops and enforce a single parent for each node using the
post_process_steiner_solutionmethod. - Tree Population: Appends sample names to the solution, removes spurious leaves, and populates the
CassiopeiaTreeobject with the resulting tree.
infer_potential_graph
Description
This method infers the potential graph, a network of possible evolutionary intermediates, from the character matrix.Inputs
Outputs
Internal Logic
- Edge Inference: Calls the
ilp_solver_utilities.infer_potential_graph_cythonfunction to obtain the edges of the potential graph in character string format. - Edge Decoding: Decodes the character strings into tuples representing character states.
- Graph Construction: Creates a Networkx directed graph and adds the decoded edges.
- Edge Weighting: Adds edge weights based on the provided weights or the number of mutations along each edge using the
add_edge_weightsmethod.
add_edge_weights
Description
This method annotates edges in the potential graph with weights.Inputs
Outputs
Internal Logic
Iterates through the edges of the potential graph and calculates the weight for each edge using either the provided weights or the weighted Hamming distance between the character states of the connected nodes.generate_steiner_model
Description
This method generates a Gurobi ILP model for the Steiner Tree problem.Inputs
Outputs
Internal Logic
- Model Initialization: Creates a Gurobi model instance.
- Variable Addition: Adds flow variables for each edge and binary variables indicating edge usage.
- Constraint Addition: Adds constraints for flow conservation and edge usage.
- Objective Definition: Sets the objective function to minimize the total weight of the used edges.
solve_steiner_instance
Description
This method solves the Steiner Tree problem using the generated Gurobi model.Inputs
Outputs
Internal Logic
- Parameter Configuration: Sets Gurobi parameters, including convergence criteria, MIP gap, and logging options.
- Model Optimization: Calls the
model.optimize()method to solve the ILP problem. - Solution Recovery: Extracts the solutions from the Gurobi model and converts them into Networkx directed graphs.
post_process_steiner_solution
Description
This method post-processes the Steiner Tree solution to remove self-loops and enforce a single parent for each node.Inputs
Outputs
Internal Logic
- Self-loop Removal: Removes any self-loops from the solution.
- Spurious Root Removal: Removes any spurious roots, ensuring only one root remains.
- Single Parent Enforcement: For nodes with multiple parents, selects the parent with the highest edge weight and removes edges to other parents.
__append_sample_names_and_remove_spurious_leaves
Description
This private method appends sample names to the character states in the tree and prunes spurious leaves.Inputs
Outputs
Internal Logic
- Sample Appending: Appends sample names to the deepest nodes in the tree that correspond to their character states.
- Spurious Leaf Removal: Removes any extant nodes that do not have samples appended to them and prunes their lineages.
Side Effects
Thesolve method modifies the provided CassiopeiaTree object by populating it with the inferred tree.
Dependencies
Error Handling
TheILPSolver class raises ILPSolverError exceptions in the following cases:
- If the input character matrix contains ambiguous states.
- If the root node is not found in the potential graph.
- If any target node is not found in the potential graph.
- If Gurobi is not installed.
- If the potential graph cannot be inferred with the specified parameters.
Logging
Thesolve method logs progress and information about the potential graph inference and Steiner Tree optimization to the specified log file.