Skip to content

Commit 87a995b

Browse files
authored
Upgrade QISKit depdencies (#261)
* Bumped to version: 0.4.6 * Upgraded external dependencies * Make graph code in QISKit compatible with NetworkX 2.0 NetworkX 1.11 which is required by qiskit uses some deprecated functions for plotting that generate a warning with matplotlib. The proposed changes make QISKit compatible with both versions of NetworkX. In a second step we should upgrade the code to use only NetworkX 2.0 and later since some functions were added that make things more elegant. See https://networkx.github.io/documentation/stable/release/migration_guide_from_1.x_to_2.0.html * Reintroduce AppVeyor (#252) Re-enable the AppVeyor CI, as the conflicts with the version were hopefully solved after bumping the scipy dependency and others.
1 parent 8d0069c commit 87a995b

File tree

8 files changed

+80
-79
lines changed

8 files changed

+80
-79
lines changed

appveyor.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,6 @@
1515

1616
version: 1.0.{build}
1717

18-
branches:
19-
only:
20-
- invalidbranch
21-
2218
environment:
2319
matrix:
2420
- PYTHON_VERSION: 3.5
@@ -45,7 +41,7 @@ install:
4541

4642
# Use py.test for output of xunit test results.
4743
test_script:
48-
- py.test -s -v --junit-xml=test_results.xml
44+
- py.test -v --junit-xml=test_results.xml
4945

5046
# Upload the test results to appveyor so they are shown on the "Tests" tab.
5147
on_finish:

qiskit/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,6 @@
4141
from ._result import Result
4242
from ._util import _check_ibmqe_version
4343

44-
__version__ = '0.4.5'
44+
__version__ = '0.4.6'
4545

4646
_check_ibmqe_version()

qiskit/dagcircuit/_dagcircuit.py

Lines changed: 22 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ def rename_register(self, regname, newname):
120120
self.output_map[(newname, i)] = self.output_map[(regname, i)]
121121
self.output_map.pop((regname, i), None)
122122
# n node d = data
123-
for _, d in self.multi_graph.nodes_iter(data=True):
123+
for _, d in self.multi_graph.nodes(data=True):
124124
if d["type"] == "in" or d["type"] == "out":
125125
if d["name"][0] == regname:
126126
d["name"] = (newname, d["name"][1])
@@ -141,7 +141,7 @@ def rename_register(self, regname, newname):
141141
if d["condition"][0] == regname:
142142
d["condition"] = (newname, d["condition"][1])
143143
# eX = edge, d= data
144-
for _, _, d in self.multi_graph.edges_iter(data=True):
144+
for _, _, d in self.multi_graph.edges(data=True):
145145
if d["name"][0] == regname:
146146
d["name"] = (newname, d["name"][1])
147147

@@ -195,7 +195,7 @@ def _add_wire(self, name, isClassical=False):
195195
self.multi_graph.node[out_node]["type"] = "out"
196196
self.multi_graph.node[in_node]["name"] = name
197197
self.multi_graph.node[out_node]["name"] = name
198-
self.multi_graph.edge[in_node][out_node][0]["name"] = name
198+
self.multi_graph.adj[in_node][out_node][0]["name"] = name
199199
else:
200200
raise DAGCircuitError("duplicate wire %s" % name)
201201

@@ -369,7 +369,7 @@ def apply_operation_back(self, name, qargs, cargs=None, params=None,
369369
# and adding new edges from the operation node to each output node
370370
al = [qargs, all_cbits]
371371
for q in itertools.chain(*al):
372-
ie = self.multi_graph.predecessors(self.output_map[q])
372+
ie = list(self.multi_graph.predecessors(self.output_map[q]))
373373
assert len(ie) == 1, "output node has multiple in-edges"
374374
self.multi_graph.add_edge(ie[0], self.node_counter, name=q)
375375
self.multi_graph.remove_edge(ie[0], self.output_map[q])
@@ -581,8 +581,7 @@ def compose_back(self, input_circuit, wire_map=None):
581581
# Compose
582582
self.basis = union_basis
583583
self.gates = union_gates
584-
topological_sort = nx.topological_sort(input_circuit.multi_graph)
585-
for node in topological_sort:
584+
for node in nx.topological_sort(input_circuit.multi_graph):
586585
nd = input_circuit.multi_graph.node[node]
587586
if nd["type"] == "in":
588587
# if in wire_map, get new name, else use existing name
@@ -640,8 +639,7 @@ def compose_front(self, input_circuit, wire_map=None):
640639
# Compose
641640
self.basis = union_basis
642641
self.gates = union_gates
643-
ts = nx.topological_sort(input_circuit.multi_graph, reverse=True)
644-
for n in ts:
642+
for n in reversed(list(nx.topological_sort(input_circuit.multi_graph))):
645643
nd = input_circuit.multi_graph.node[n]
646644
if nd["type"] == "out":
647645
# if in wire_map, get new name, else use existing name
@@ -769,8 +767,7 @@ def qasm(self, decls_only=False, add_swap=False,
769767
out += "gate swap a,b { cx a,b; cx b,a; cx a,b; }\n"
770768
# Write the instructions
771769
if not decls_only:
772-
ts = nx.topological_sort(self.multi_graph)
773-
for n in ts:
770+
for n in nx.topological_sort(self.multi_graph):
774771
nd = self.multi_graph.node[n]
775772
if nd["type"] == "op":
776773
if nd["condition"] is not None:
@@ -843,9 +840,9 @@ def _make_pred_succ_maps(self, n):
843840
nodes for the operation node n in self.multi_graph.
844841
"""
845842
pred_map = {e[2]['name']: e[0] for e in
846-
self.multi_graph.in_edges_iter(nbunch=n, data=True)}
843+
self.multi_graph.in_edges(nbunch=n, data=True)}
847844
succ_map = {e[2]['name']: e[1] for e in
848-
self.multi_graph.out_edges_iter(nbunch=n, data=True)}
845+
self.multi_graph.out_edges(nbunch=n, data=True)}
849846
return pred_map, succ_map
850847

851848
def _full_pred_succ_maps(self, pred_map, succ_map, input_circuit,
@@ -874,7 +871,7 @@ def _full_pred_succ_maps(self, pred_map, succ_map, input_circuit,
874871
full_succ_map[w] = self.output_map[w]
875872
full_pred_map[w] = self.multi_graph.predecessors(
876873
self.output_map[w])[0]
877-
assert len(self.multi_graph.predecessors(self.output_map[w])) == 1,\
874+
assert len(list(self.multi_graph.predecessors(self.output_map[w]))) == 1,\
878875
"too many predecessors for (%s,%d) output node" % (
879876
w[0], w[1])
880877
return full_pred_map, full_succ_map
@@ -913,8 +910,7 @@ def substitute_circuit_all(self, name, input_circuit, wires=None):
913910
# that we add from the input_circuit.
914911
self.basis = union_basis
915912
self.gates = union_gates
916-
ts = nx.topological_sort(self.multi_graph)
917-
for n in ts:
913+
for n in nx.topological_sort(self.multi_graph):
918914
nd = self.multi_graph.node[n]
919915
if nd["type"] == "op" and nd["name"] == name:
920916
if nd["condition"] is None:
@@ -930,8 +926,7 @@ def substitute_circuit_all(self, name, input_circuit, wires=None):
930926
# Now that we know the connections, delete node
931927
self.multi_graph.remove_node(n)
932928
# Iterate over nodes of input_circuit
933-
tsin = nx.topological_sort(input_circuit.multi_graph)
934-
for m in tsin:
929+
for m in nx.topological_sort(input_circuit.multi_graph):
935930
md = input_circuit.multi_graph.node[m]
936931
if md["type"] == "op":
937932
# Insert a new node
@@ -955,8 +950,8 @@ def substitute_circuit_all(self, name, input_circuit, wires=None):
955950
for w in full_pred_map:
956951
self.multi_graph.add_edge(full_pred_map[w], full_succ_map[w],
957952
name=w)
958-
o_pred = self.multi_graph.predecessors(
959-
self.output_map[w])
953+
o_pred = list(self.multi_graph.predecessors(
954+
self.output_map[w]))
960955
if len(o_pred) > 1:
961956
assert len(o_pred) == 2, \
962957
"expected 2 predecessors here"
@@ -1023,8 +1018,7 @@ def substitute_circuit_one(self, node, input_circuit, wires=None):
10231018
# Now that we know the connections, delete node
10241019
self.multi_graph.remove_node(node)
10251020
# Iterate over nodes of input_circuit
1026-
tsin = nx.topological_sort(input_circuit.multi_graph)
1027-
for m in tsin:
1021+
for m in nx.topological_sort(input_circuit.multi_graph):
10281022
md = input_circuit.multi_graph.node[m]
10291023
if md["type"] == "op":
10301024
# Insert a new node
@@ -1049,7 +1043,7 @@ def substitute_circuit_one(self, node, input_circuit, wires=None):
10491043
for w in full_pred_map:
10501044
self.multi_graph.add_edge(
10511045
full_pred_map[w], full_succ_map[w], name=w)
1052-
o_pred = self.multi_graph.predecessors(self.output_map[w])
1046+
o_pred = list(self.multi_graph.predecessors(self.output_map[w]))
10531047
if len(o_pred) > 1:
10541048
assert len(o_pred) == 2, "expected 2 predecessors here"
10551049
p = [x for x in o_pred if x != full_pred_map[w]]
@@ -1064,8 +1058,7 @@ def get_named_nodes(self, name):
10641058
% name)
10651059

10661060
# Iterate through the nodes of self in topological order
1067-
ts = nx.topological_sort(self.multi_graph)
1068-
for n in ts:
1061+
for n in nx.topological_sort(self.multi_graph):
10691062
nd = self.multi_graph.node[n]
10701063
if nd["type"] == "op" and nd["name"] == name:
10711064
nlist.append(n)
@@ -1213,8 +1206,7 @@ def serial_layers(self):
12131206
same structure as in layers().
12141207
"""
12151208
layers_list = []
1216-
ts = nx.topological_sort(self.multi_graph)
1217-
for n in ts:
1209+
for n in nx.topological_sort(self.multi_graph):
12181210
nxt_nd = self.multi_graph.node[n]
12191211
if nxt_nd["type"] == "op":
12201212
new_layer = DAGCircuit()
@@ -1260,21 +1252,21 @@ def collect_runs(self, namelist):
12601252
# Iterate through the nodes of self in topological order
12611253
# and form tuples containing sequences of gates
12621254
# on the same qubit(s).
1263-
ts = nx.topological_sort(self.multi_graph)
1255+
ts = list(nx.topological_sort(self.multi_graph))
12641256
nodes_seen = dict(zip(ts, [False] * len(ts)))
12651257
for node in ts:
12661258
nd = self.multi_graph.node[node]
12671259
if nd["type"] == "op" and nd["name"] in namelist \
12681260
and not nodes_seen[node]:
12691261
group = [node]
12701262
nodes_seen[node] = True
1271-
s = self.multi_graph.successors(node)
1263+
s = list(self.multi_graph.successors(node))
12721264
while len(s) == 1 and \
12731265
self.multi_graph.node[s[0]]["type"] == "op" and \
12741266
self.multi_graph.node[s[0]]["name"] in namelist:
12751267
group.append(s[0])
12761268
nodes_seen[s[0]] = True
1277-
s = self.multi_graph.successors(s[0])
1269+
s = list(self.multi_graph.successors(s[0]))
12781270
if len(group) > 1:
12791271
group_list.append(tuple(group))
12801272
return set(group_list)
@@ -1285,8 +1277,7 @@ def count_ops(self):
12851277
Returns a dictionary of counts keyed on the operation name.
12861278
"""
12871279
op_dict = {}
1288-
ts = nx.topological_sort(self.multi_graph)
1289-
for node in ts:
1280+
for node in nx.topological_sort(self.multi_graph):
12901281
nd = self.multi_graph.node[node]
12911282
name = nd["name"]
12921283
if nd["type"] == "op":

qiskit/mapper/_coupling.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ def compute_distance(self):
165165
"""
166166
if not self.connected():
167167
raise CouplingError("coupling graph not connected")
168-
lengths = nx.all_pairs_shortest_path_length(self.G.to_undirected())
168+
lengths = dict(nx.all_pairs_shortest_path_length(self.G.to_undirected()))
169169
self.dist = {}
170170
for i in self.qubits.keys():
171171
self.dist[i] = {}

qiskit/mapper/_mapping.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -778,16 +778,15 @@ def optimize_1q_gates(circuit):
778778
if right_name == "u3":
779779
new_params = list(right_parameters)
780780

781-
nx.set_node_attributes(unrolled.multi_graph, 'name',
782-
{run[0]: right_name})
781+
nx.set_node_attributes(unrolled.multi_graph, name='name',
782+
values={run[0]: right_name})
783783
# params is a list of sympy symbols and the str() method
784784
# will return Python expressions. To get the correct
785785
# OpenQASM expression, we need to replace "**" with "^".
786-
nx.set_node_attributes(unrolled.multi_graph, 'params',
787-
{run[0]: tuple(map(lambda x:
788-
str(x).replace("**", "^"),
789-
new_params))})
790-
786+
nx.set_node_attributes(unrolled.multi_graph, name='params',
787+
values={run[0]: tuple(map(lambda x:
788+
str(x).replace("**", "^"),
789+
new_params))})
791790
# Delete the other nodes in the run
792791
for node in run[1:]:
793792
unrolled._remove_op_node(node)

requirements.txt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
IBMQuantumExperience>=1.8.26
2-
matplotlib>=2.0,<=2.1
3-
networkx>=1.11,<1.12
4-
numpy>=1.13,<=1.14
2+
matplotlib>=2.1,<2.2
3+
networkx>=1.11,<2.1
4+
numpy>=1.13,<1.15
55
ply==3.10
6-
scipy>=0.19,<=1.0
6+
scipy>=0.19,<1.1
77
Sphinx>=1.6,<1.7
8-
sympy>=1.0
8+
sympy>=1.0

setup.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010

1111
requirements = [
1212
"IBMQuantumExperience>=1.8.26",
13-
"matplotlib>=2.0,<=2.1",
14-
"networkx>=1.11,<1.12",
15-
"numpy>=1.13,<=1.14",
13+
"matplotlib>=2.1,<2.2",
14+
"networkx>=1.11,<2.1",
15+
"numpy>=1.13,<1.15",
1616
"ply==3.10",
17-
"scipy>=0.19,<=1.0",
17+
"scipy>=0.19,<1.1",
1818
"Sphinx>=1.6,<1.7",
1919
"sympy>=1.0"
2020
]
@@ -79,7 +79,7 @@ def compile():
7979

8080
setup(
8181
name="qiskit",
82-
version="0.4.5",
82+
version="0.4.6",
8383
description="Software for developing quantum computing programs",
8484
long_description="""QISKit is a software development kit for writing
8585
quantum computing experiments, programs, and applications. Works with

test/python/test_mapper.py

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def test_math_domain_error(self):
6262
if version_info.minor == 5: # Python 3.5
6363
self.assertEqual(result1.get_counts("test"), {'0001': 507, '0101': 517})
6464
else: # Python 3.6 and higher
65-
self.assertEqual(result1.get_counts("test"), {'0001': 480, '0101': 544})
65+
self.assertEqual(result1.get_counts("test"), {'0001': 517, '0101': 507})
6666

6767
def test_optimize_1q_gates_issue159(self):
6868
"""Test change in behavior for optimize_1q_gates that removes u1(2*pi) rotations.
@@ -96,31 +96,46 @@ def test_random_parameter_circuit(self):
9696
result1 = self.qp.execute(["rand"], backend="local_qasm_simulator",
9797
coupling_map=coupling_map, seed=self.seed)
9898
res = result1.get_counts("rand")
99+
100+
expected_result = {'10000': 97, '00011': 24, '01000': 120, '10111': 59,
101+
'01111': 37, '11010': 14, '00001': 34, '00100': 42,
102+
'10110': 41, '00010': 102, '00110': 48, '10101': 19,
103+
'01101': 61, '00111': 46, '11100': 28, '01100': 1,
104+
'00000': 86, '11111': 14, '11011': 9, '10010': 35,
105+
'10100': 20, '01001': 21, '01011': 19, '10011': 10,
106+
'11001': 13, '00101': 4, '01010': 2, '01110': 17,
107+
'11000': 1}
108+
99109
# TODO: the circuit produces different results under different versions
100-
# of Python, which defeats the purpose of the "seed" parameter. A proper
101-
# fix should be issued - this is a workaround for this particular test.
110+
# of Python and NetworkX package, which defeats the purpose of the
111+
# "seed" parameter. A proper fix should be issued - this is a workaround
112+
# for this particular test.
102113
if version_info.minor == 5: # Python 3.5
103-
self.assertEqual(res, {'00101': 3, '00011': 22, '11100': 27,
104-
'01100': 1, '10011': 15, '00111': 53,
105-
'01000': 110, '11111': 19, '00100': 54,
106-
'01111': 17, '10101': 11, '11010': 20,
107-
'10111': 60, '01110': 6, '00110': 40,
108-
'11001': 16, '11011': 9, '01010': 9,
109-
'01011': 16, '11110': 4, '00000': 89,
110-
'10110': 34, '00010': 113, '10010': 25,
111-
'00001': 25, '01001': 41, '10000': 96,
112-
'11000': 1, '10100': 20, '01101': 68})
113-
else:
114-
self.assertEqual(res, {'10000': 98, '11010': 22, '00000': 88,
115-
'00010': 120, '10110': 55, '01111': 26,
116-
'00100': 51, '10111': 62, '01101': 70,
117-
'01000': 95, '01100': 6, '01011': 13,
118-
'00111': 45, '00110': 30, '10011': 14,
119-
'10100': 21, '11100': 28, '00001': 26,
120-
'01001': 33, '00101': 5, '11001': 7,
121-
'10101': 20, '11110': 1, '11111': 20,
122-
'00011': 15, '11000': 2, '10010': 27,
123-
'01010': 4, '11011': 6, '01110': 14})
114+
import networkx
115+
if networkx.__version__ == '1.11':
116+
expected_result = {'01001': 41, '10010': 25, '00111': 53,
117+
'01101': 68, '10101': 11, '10110': 34,
118+
'01110': 6, '11100': 27, '00100': 54,
119+
'11010': 20, '10100': 20, '01100': 1,
120+
'10000': 96, '11000': 1, '11011': 9,
121+
'10011': 15, '00101': 3, '00001': 25,
122+
'00010': 113, '01011': 16, '11111': 19,
123+
'11001': 16, '00011': 22, '00000': 89,
124+
'00110': 40, '01000': 110, '10111': 60,
125+
'11110': 4, '01010': 9, '01111': 17}
126+
else:
127+
expected_result = {'01001': 32, '11110': 1, '10010': 36,
128+
'11100': 34, '11011': 10, '00001': 41,
129+
'00000': 83, '10000': 94, '11001': 15,
130+
'01011': 24, '00100': 43, '11000': 5,
131+
'11010': 9, '01100': 5, '10100': 23,
132+
'01101': 54, '01110': 6, '00011': 13,
133+
'10101': 12, '00111': 36, '00110': 40,
134+
'01000': 119, '11111': 19, '01010': 8,
135+
'10111': 61, '10110': 52, '01111': 23,
136+
'00010': 110, '00101': 2, '10011': 14}
137+
138+
self.assertEqual(res, expected_result)
124139

125140
def test_symbolic_unary(self):
126141
"""Test symbolic math in DAGBackend and optimizer with a prefix.

0 commit comments

Comments
 (0)