forked from Qiskit/rustworkx
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reorganize code into modules (Qiskit#396)
The organization steps were: * Group code by topics in api.rst * For small topics, use topic.rs * For larger topics, create topic/mod.rs for the Python implementations and topic/xyz.rs for implementations Details worth sharing are: * weight_callable and NodeRemoved stayed at lib.rs because they are omnipresent; because they are pure Rust code I thought it was a reasonable place * wrap_pyfunction(module_name::function_name) is currently not supported, so all functions had to be imported * Some modules from the "Others" section in the docs are small; they could be grouped together but other_algo did not feel very descriptive Closes Qiskit#300 * Reorganize dag algorithms into new file * Reorganize shortest path algorithms in new file * Move astar to short path file * Reorganize matching in new file * Reorganize random_circuit in new file * Run cargo fmt * Move layout to its own module * Run cargo fmt * Move isomorphism to its own module * Move matching to its own module * Move shortest_path to its own module * Remove weight_callable duplication * Move floyd_warshall to its own file * Move num_shortest_path_unweighted to its own file * Move all_pairs_dijkstra to its own file * Rename to dag_algo * Move tree algorithms to its own file * Move connectivity to its own file * Move dag_algo to its own module * Move traversal to its own module * Temporarily allow module inception * Rename isomorphism and layouts * Move simple_path to its own file * Move transitivity to its own file * Move core_number to its own file * Create representation_algo * Move digraph_union to union * Move graph_greedy_coloring to its own file * Move code from traversal to dag_algo * Revert "Rename isomorphism and layouts" This reverts commit 22abf85. * Move more items into connectivity module * Rename random_circuit to random_graph * Avoid module inception in isomorphism.rs * Avoid module inception in layout.rs * Simplify names in layout module * Add details to CONTRIBUTING.md * Fix tox -edocs issues * Minor CONTRIBUTING.md fixes
- Loading branch information
1 parent
0919144
commit 2f74f7f
Showing
33 changed files
with
5,830 additions
and
5,151 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
// Licensed under the Apache License, Version 2.0 (the "License"); you may | ||
// not use this file except in compliance with the License. You may obtain | ||
// a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
// License for the specific language governing permissions and limitations | ||
// under the License. | ||
|
||
#![allow(clippy::float_cmp)] | ||
|
||
use crate::graph; | ||
|
||
use ahash::RandomState; | ||
use hashbrown::{HashMap, HashSet}; | ||
use indexmap::IndexMap; | ||
use std::cmp::Reverse; | ||
|
||
use pyo3::prelude::*; | ||
use pyo3::types::PyDict; | ||
use pyo3::Python; | ||
|
||
use petgraph::graph::NodeIndex; | ||
use petgraph::prelude::*; | ||
use petgraph::visit::NodeCount; | ||
|
||
use rayon::prelude::*; | ||
|
||
/// Color a PyGraph using a largest_first strategy greedy graph coloring. | ||
/// | ||
/// :param PyGraph: The input PyGraph object to color | ||
/// | ||
/// :returns: A dictionary where keys are node indices and the value is | ||
/// the color | ||
/// :rtype: dict | ||
#[pyfunction] | ||
#[pyo3(text_signature = "(graph, /)")] | ||
fn graph_greedy_color( | ||
py: Python, | ||
graph: &graph::PyGraph, | ||
) -> PyResult<PyObject> { | ||
let mut colors: IndexMap<usize, usize, RandomState> = | ||
IndexMap::with_hasher(RandomState::default()); | ||
let mut node_vec: Vec<NodeIndex> = graph.graph.node_indices().collect(); | ||
let mut sort_map: HashMap<NodeIndex, usize> = | ||
HashMap::with_capacity(graph.node_count()); | ||
for k in node_vec.iter() { | ||
sort_map.insert(*k, graph.graph.edges(*k).count()); | ||
} | ||
node_vec.par_sort_by_key(|k| Reverse(sort_map.get(k))); | ||
for u_index in node_vec { | ||
let mut neighbor_colors: HashSet<usize> = HashSet::new(); | ||
for edge in graph.graph.edges(u_index) { | ||
let target = edge.target().index(); | ||
let existing_color = match colors.get(&target) { | ||
Some(node) => node, | ||
None => continue, | ||
}; | ||
neighbor_colors.insert(*existing_color); | ||
} | ||
let mut count: usize = 0; | ||
loop { | ||
if !neighbor_colors.contains(&count) { | ||
break; | ||
} | ||
count += 1; | ||
} | ||
colors.insert(u_index.index(), count); | ||
} | ||
let out_dict = PyDict::new(py); | ||
for (index, color) in colors { | ||
out_dict.set_item(index, color)?; | ||
} | ||
Ok(out_dict.into()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
// Licensed under the Apache License, Version 2.0 (the "License"); you may | ||
// not use this file except in compliance with the License. You may obtain | ||
// a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
// License for the specific language governing permissions and limitations | ||
// under the License. | ||
|
||
#![allow(clippy::float_cmp)] | ||
|
||
use hashbrown::{HashMap, HashSet}; | ||
|
||
use pyo3::prelude::*; | ||
use pyo3::types::PyDict; | ||
use pyo3::Python; | ||
|
||
use petgraph::graph::NodeIndex; | ||
use petgraph::prelude::*; | ||
use petgraph::EdgeType; | ||
|
||
use rayon::prelude::*; | ||
|
||
pub fn core_number<Ty>( | ||
py: Python, | ||
graph: &StableGraph<PyObject, PyObject, Ty>, | ||
) -> PyResult<PyObject> | ||
where | ||
Ty: EdgeType, | ||
{ | ||
let node_num = graph.node_count(); | ||
if node_num == 0 { | ||
return Ok(PyDict::new(py).into()); | ||
} | ||
|
||
let mut cores: HashMap<NodeIndex, usize> = HashMap::with_capacity(node_num); | ||
let mut node_vec: Vec<NodeIndex> = graph.node_indices().collect(); | ||
let mut degree_map: HashMap<NodeIndex, usize> = | ||
HashMap::with_capacity(node_num); | ||
let mut nbrs: HashMap<NodeIndex, HashSet<NodeIndex>> = | ||
HashMap::with_capacity(node_num); | ||
let mut node_pos: HashMap<NodeIndex, usize> = | ||
HashMap::with_capacity(node_num); | ||
|
||
for k in node_vec.iter() { | ||
let k_nbrs: HashSet<NodeIndex> = | ||
graph.neighbors_undirected(*k).collect(); | ||
let k_deg = k_nbrs.len(); | ||
|
||
nbrs.insert(*k, k_nbrs); | ||
cores.insert(*k, k_deg); | ||
degree_map.insert(*k, k_deg); | ||
} | ||
node_vec.par_sort_by_key(|k| degree_map.get(k)); | ||
|
||
let mut bin_boundaries: Vec<usize> = | ||
Vec::with_capacity(degree_map[&node_vec[node_num - 1]] + 1); | ||
bin_boundaries.push(0); | ||
let mut curr_degree = 0; | ||
for (i, v) in node_vec.iter().enumerate() { | ||
node_pos.insert(*v, i); | ||
let v_degree = degree_map[v]; | ||
if v_degree > curr_degree { | ||
for _ in 0..v_degree - curr_degree { | ||
bin_boundaries.push(i); | ||
} | ||
curr_degree = v_degree; | ||
} | ||
} | ||
|
||
for v_ind in 0..node_vec.len() { | ||
let v = node_vec[v_ind]; | ||
let v_nbrs = nbrs[&v].clone(); | ||
for u in v_nbrs { | ||
if cores[&u] > cores[&v] { | ||
nbrs.get_mut(&u).unwrap().remove(&v); | ||
let pos = node_pos[&u]; | ||
let bin_start = bin_boundaries[cores[&u]]; | ||
*node_pos.get_mut(&u).unwrap() = bin_start; | ||
*node_pos.get_mut(&node_vec[bin_start]).unwrap() = pos; | ||
node_vec.swap(bin_start, pos); | ||
bin_boundaries[cores[&u]] += 1; | ||
*cores.get_mut(&u).unwrap() -= 1; | ||
} | ||
} | ||
} | ||
|
||
let out_dict = PyDict::new(py); | ||
for (v_index, core) in cores { | ||
out_dict.set_item(v_index.index(), core)?; | ||
} | ||
Ok(out_dict.into()) | ||
} |
Oops, something went wrong.