Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lattice does not support all rustworkx graph representations. #1347

Open
MarcoBarroca opened this issue Feb 29, 2024 · 3 comments
Open

Lattice does not support all rustworkx graph representations. #1347

MarcoBarroca opened this issue Feb 29, 2024 · 3 comments
Labels
type: documentation Issues related to documentation

Comments

@MarcoBarroca
Copy link
Contributor

MarcoBarroca commented Feb 29, 2024

Environment

  • Qiskit Nature version: 0.7.2
  • Python version: 3.11
  • Operating system: Mac OS ARM

What is happening?

When creating a Lattice from a rustworkx graph Lattice() only supports graphs of the form

graph = rx.PyGraph(multigraph=False)
graph.extend_from weighted_edge_list(
    [(0, 1, 1), (0, 2, 2),
     (1, 3, 2), (3, 0, 3)])

rustworkx support two types of weighted graph representations. The above or

graph = rx.PyGraph(multigraph=False)
graph.extend_from weighted_edge_list(
    [(0, 1, {'weight': 1}), (0, 2, {'weight': 2}),
     (1, 3, {'weight': 2}), (3, 0, {'weight': 3})])

Using the second one results in

ValueError: Unsupported weight {'weight': 1} on edge with index 0.

How can we reproduce the issue?

This should reproduce it with the necessary imports:

graph = rx.PyGraph(multigraph=False)
graph.extend_from_weighted_edge_list(
    [(0, 1, {'weight': 1}), (0, 2, {'weight': 2}),
     (1, 3, {'weight': 2}), (3, 0, {'weight': 3})])

lattice = Lattice(graph)

What should happen?

A lattice should be constructed given a rustworkx graph in any of the two forms.

Any suggestions?

Either modify lattice.py to take both into account or modify the graph object to be of the correct format.

@mrossinek
Copy link
Member

rustworkx graph cans actually store arbitrary data as payloads of their nodes and edges.
You cannot possibly cover all possible such payloads and expect the code to extract a weight from it.

That said, the payload which is supported (i.e. just a plain weight) should probably be documented properly. Right now, the only mention of this fact is here:

ValueError: If the graph edges are non-numeric.

Therefore, this is either a documentation issue or a feature request to support more types although I would not be sure how this would work in a general case because the Hamiltonian generators which use the lattice would need to be adapted to interpret non-numeric payloads, too.

@mrossinek mrossinek added type: documentation Issues related to documentation and removed bug labels Apr 12, 2024
@MarcoBarroca
Copy link
Contributor Author

This is relevant because networkx graphs only store weights as values in the dictionary and if Lattice() is given a NetworkX graphs it does the following:


if not isinstance(graph, PyGraph):
            _optionals.HAS_NETWORKX.require_now("Lattice construction from networkx.Graph")
            graph = networkx_converter(graph)
            

The network_converter() will keep the format networkx uses into the rustworkx graph.

I stumbled into this issue trying to take a weighted graph that was built elsewhere with NetworkX into a Lattice(). I had to manually convert it to rustworkx to make sure it wasn’t using a dictionary for the weights before building the lattice.

@MarcoBarroca
Copy link
Contributor Author

Here is an example.

G = nx.Graph()
edges=[[1,2],[0,3],[2,3],[0,1]]
for edge in edges:
    edge_1 = edge[0]
    edge_2 = edge[1]
    weight = 1.0
    G.add_edge(edge_1, edge_2,weight=weight)

general_lattice = Lattice(G)

Gives ValueError: Unsupported weight {'weight': 1.0} on edge with index 0.

To fix it we have to manually convert it to an adequately formatted rustworkx object. This works:

G = nx.Graph()
edges=[[1,2],[0,3],[2,3],[0,1]]
for edge in edges:
    edge_1 = edge[0]
    edge_2 = edge[1]
    weight = 1.0
    G.add_edge(edge_1, edge_2,weight=weight)

rG = rx.PyGraph(multigraph=G.is_multigraph())
nodes = list(G.nodes)
node_indices = dict(zip(nodes, rG.add_nodes_from(nodes)))
rG.add_edges_from(
        [(node_indices[x[0]], node_indices[x[1]], x[2]['weight']) for x in G.edges(data=True)]
    ) 


general_lattice = Lattice(rG)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: documentation Issues related to documentation
Projects
None yet
Development

No branches or pull requests

2 participants