Commit 195e4249 authored by Christoph Groth's avatar Christoph Groth
Browse files

Merge branch 'python3'

parents 2de760a3 0f3068d1
......@@ -11,6 +11,7 @@ import tinyarray as ta
import numpy as np
from scipy import sparse as sp
from itertools import chain
import types
from .graph.core cimport CGraph, gintArraySlice
from .graph.defs cimport gint
......@@ -84,8 +85,15 @@ def make_sparse(ham, args, CGraph gr, diag,
rows_cols[1, k] = j + from_off[n_fs]
k += 1
return sp.coo_matrix((data[:k], rows_cols[:, :k]),
shape=(to_off[-1], from_off[-1]))
# hack around a bug in Scipy + Python 3 + memoryviews
# see https://github.com/scipy/scipy/issues/5123 for details
np_data = np.asarray(data)
np_rows_cols = np.asarray(rows_cols)
np_to_off = np.asarray(to_off)
np_from_off = np.asarray(from_off)
return sp.coo_matrix((np_data[:k], np_rows_cols[:, :k]),
shape=(np_to_off[-1], np_from_off[-1]))
@cython.boundscheck(False)
......@@ -147,8 +155,15 @@ def make_sparse_full(ham, args, CGraph gr, diag,
rows_cols[0, k + 1] = rows_cols[1, k] = j + from_off[fs]
k += 2
return sp.coo_matrix((data[:k], rows_cols[:, :k]),
shape=(to_off[-1], from_off[-1]))
# hack around a bug in Scipy + Python 3 + memoryviews
# see https://github.com/scipy/scipy/issues/5123 for details
np_data = np.asarray(data)
np_rows_cols = np.asarray(rows_cols)
np_to_off = np.asarray(to_off)
np_from_off = np.asarray(from_off)
return sp.coo_matrix((np_data[:k], np_rows_cols[:, :k]),
shape=(np_to_off[-1], np_from_off[-1]))
@cython.boundscheck(False)
......@@ -327,3 +342,13 @@ def hamiltonian_submatrix(self, args=(), to_sites=None, from_sites=None,
mat = func(ham, args, self.graph, diag, from_sites,
n_by_to_site, to_norb, to_off, from_norb, from_off)
return (mat, to_norb, from_norb) if return_norb else mat
# workaround for Cython functions not having __get__ and
# Python 3 getting rid of unbound methods
cdef class HamiltonianSubmatrix:
def __get__(self, obj, objtype):
if obj is None:
return hamiltonian_submatrix
else:
return types.MethodType(hamiltonian_submatrix, obj)
......@@ -6,15 +6,13 @@
# the file AUTHORS.rst at the top-level directory of this distribution and at
# http://kwant-project.org/authors.
from __future__ import division
__all__ = ['Builder', 'Site', 'SiteFamily', 'SimpleSiteFamily', 'Symmetry',
'HoppingKind', 'Lead', 'BuilderLead', 'SelfEnergyLead', 'ModesLead']
import abc
import warnings
import operator
from itertools import izip, islice, chain
from itertools import islice, chain
import tinyarray as ta
import numpy as np
from . import system, graph, KwantDeprecationWarning
......@@ -84,7 +82,7 @@ class Site(tuple):
return self.family.pos(self.tag)
class SiteFamily(object):
class SiteFamily(object, metaclass=abc.ABCMeta):
"""Abstract base class for site families.
Site families are the 'type' of `Site` objects. Within a family, individual
......@@ -107,7 +105,6 @@ class SiteFamily(object):
site belonging to this family with a given tag.
"""
__metaclass__ = abc.ABCMeta
def __init__(self, canonical_repr, name):
self.canonical_repr = canonical_repr
......@@ -224,7 +221,7 @@ def validate_hopping(hopping):
################ Symmetries
class Symmetry(object):
class Symmetry(object, metaclass=abc.ABCMeta):
"""Abstract base class for spatial symmetries.
Many physical systems possess a discrete spatial symmetry, which results in
......@@ -249,7 +246,6 @@ class Symmetry(object):
typical example of this is when the vector defining a translational
symmetry is not a lattice vector.
"""
__metaclass__ = abc.ABCMeta
@abc.abstractproperty
def num_directions(self):
......@@ -430,7 +426,7 @@ class HermConjOfFunc(object):
################ Leads
class Lead(object):
class Lead(object, metaclass=abc.ABCMeta):
"""Abstract base class for leads that can be attached to a `Builder`.
To attach a lead to a builder, append it to the builder's `~Builder.leads`
......@@ -442,7 +438,6 @@ class Lead(object):
interface : sequence of sites
"""
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def finalized(self):
......@@ -567,7 +562,7 @@ def edges(seq):
# izip, when given the same iterator twice, turns a sequence into a
# sequence of pairs.
seq_iter = iter(seq)
result = izip(seq_iter, seq_iter)
result = zip(seq_iter, seq_iter)
next(result) # Skip the special loop edge.
return result
......@@ -766,7 +761,7 @@ class Builder(object):
result.H = self.H
return result
def __nonzero__(self):
def __bool__(self):
return bool(self.H)
def expand(self, key):
......@@ -974,13 +969,13 @@ class Builder(object):
initially (but always the equivalent ones).
"""
try:
return self.H.viewkeys()
return self.H.keys()
except AttributeError:
return frozenset(self.H)
def site_value_pairs(self):
"""Return an iterator over all (site, value) pairs."""
for site, hvhv in self.H.iteritems():
for site, hvhv in self.H.items():
yield site, hvhv[1]
def hoppings(self):
......@@ -990,7 +985,7 @@ class Builder(object):
`Builder` symmetry, and are not necessarily the ones that were set
initially (but always the equivalent ones).
"""
for tail, hvhv in self.H.iteritems():
for tail, hvhv in self.H.items():
for head, value in edges(hvhv):
if value is Other:
continue
......@@ -998,7 +993,7 @@ class Builder(object):
def hopping_value_pairs(self):
"""Return an iterator over all (hopping, value) pairs."""
for tail, hvhv in self.H.iteritems():
for tail, hvhv in self.H.items():
for head, value in edges(hvhv):
if value is Other:
continue
......@@ -1201,7 +1196,7 @@ class Builder(object):
#### Make graph.
g = graph.Graph()
g.num_nodes = len(sites) # Some sites could not appear in any edge.
for tail, hvhv in self.H.iteritems():
for tail, hvhv in self.H.items():
for head in islice(hvhv, 2, None, 2):
if tail == head:
continue
......@@ -1225,7 +1220,7 @@ class Builder(object):
msg = 'When finalizing lead {0}:'.format(lead_nr)
warnings.warn(w.__class__(' '.join((msg,) + w.args)),
stacklevel=3)
except ValueError, e:
except ValueError as e:
# Re-raise the exception with an additional message.
msg = 'Problem finalizing lead {0}:'.format(lead_nr)
e.args = (' '.join((msg,) + e.args),)
......
......@@ -19,8 +19,6 @@ good enough to pass the "dieharder" battery of tests: see the function `test` of
this module.
"""
from __future__ import division
from math import pi, log, sqrt, cos
from hashlib import md5
from struct import unpack
......@@ -35,30 +33,22 @@ BPF_MASK = 2**53 - 1
RECIP_BPF = 2**-BPF
# TODO: Remove the following workaround for Python 2.6 once we do not support it
# anymore.
if sys.version_info < (2, 7):
def uniform2(input, salt=''):
"""Return two independent [0,1)-distributed numbers."""
try:
input = bytes(buffer(input)) + salt
except TypeError:
# Tinyarray does not provide the old buffer protocol, so buffer does
# not work. However, bytearray does work!
input = bytearray(input) + salt
a, b = unpack('qq', md5(input).digest())
a &= BPF_MASK
b &= BPF_MASK
return a * RECIP_BPF, b * RECIP_BPF
else:
def uniform2(input, salt=''):
"""Return two independent [0,1)-distributed numbers."""
input = memoryview(input).tobytes() + salt
a, b = unpack('qq', md5(input).digest())
a &= BPF_MASK
b &= BPF_MASK
return a * RECIP_BPF, b * RECIP_BPF
def str_to_bytes(s):
"""Return bytes if the input is a string, else return the object as-is."""
try:
return s.encode('utf8')
except AttributeError:
return s
def uniform2(input, salt=''):
"""Return two independent [0,1)-distributed numbers."""
input = str_to_bytes(input)
salt = str_to_bytes(salt)
input = memoryview(input).tobytes() + salt
a, b = unpack('qq', md5(input).digest())
a &= BPF_MASK
b &= BPF_MASK
return a * RECIP_BPF, b * RECIP_BPF
def uniform(input, salt=''):
......@@ -96,8 +86,8 @@ def test(n=20000):
f = tempfile.NamedTemporaryFile(delete=False)
try:
for x in xrange(n):
for y in xrange(n):
for x in range(n):
for y in range(n):
a = array((x, y))
i = int(2**32 * uniform(a))
f.write(pack('I', i))
......
......@@ -11,6 +11,6 @@
# Merge the public interface of all submodules.
__all__ = []
for module in ['core', 'defs', 'slicer', 'utils']:
exec 'from . import {0}'.format(module)
exec 'from .{0} import *'.format(module)
exec '__all__.extend({0}.__all__)'.format(module)
exec('from . import {0}'.format(module))
exec('from .{0} import *'.format(module))
exec('__all__.extend({0}.__all__)'.format(module))
......@@ -6,8 +6,8 @@
# the file AUTHORS.rst at the top-level directory of this distribution and at
# http://kwant-project.org/authors.
from StringIO import StringIO
from itertools import izip_longest
from io import StringIO
from itertools import zip_longest
import numpy as np
from nose.tools import assert_equal, assert_raises
from kwant.graph.core import (Graph, NodeDoesNotExistError,
......@@ -41,12 +41,12 @@ def test_num_nodes():
def test_large():
num_edges = 1000
graph = Graph()
for i in xrange(num_edges):
for i in range(num_edges):
graph.add_edge(i, i + 1)
g = graph.compressed()
g2 = graph.compressed(twoway=True)
assert_equal(num_edges, g.num_nodes - 1)
for i in xrange(num_edges):
for i in range(num_edges):
assert_equal(tuple(g.out_neighbors(i)), (i + 1,))
assert_equal(tuple(g2.in_neighbors(i + 1)), (i,))
......@@ -71,7 +71,7 @@ def test_small():
check_dot(dot_expect, g)
g = g.compressed(twoway=True)
for edge_should, edge_is in izip_longest(edges, g):
for edge_should, edge_is in zip_longest(edges, g):
assert_equal(edge_should, edge_is)
edge_ids = []
......
......@@ -19,13 +19,13 @@ def _DISABLED_test_edge_dissection():
size = 5
graph = Graph()
for i in xrange(size - 1):
for i in range(size - 1):
offset = i * size
for j in xrange(size - 1):
for j in range(size - 1):
graph.add_edge(offset + j, offset + j + 1)
graph.add_edge(offset + j + 1, offset + j)
if i > 0:
for j in xrange(size):
for j in range(size):
graph.add_edge(offset + j, offset + j - size)
graph.add_edge(offset + j - size, offset + j)
g = graph.compressed()
......
......@@ -17,32 +17,32 @@ def _DISABLED_test_bisect():
size = 5
graph = Graph()
for i in xrange(size-1):
for i in range(size - 1):
offset = i * size
for j in xrange(size-1):
for j in range(size - 1):
graph.add_edge(offset + j, offset + j + 1)
graph.add_edge(offset + j + 1, offset + j)
if i > 0:
for j in xrange(size):
for j in range(size):
graph.add_edge(offset + j, offset + j - size)
graph.add_edge(offset + j - size, offset + j)
g = graph.compressed()
parts = bisect(g)
for i in xrange(g.num_nodes):
for i in range(g.num_nodes):
assert_true(parts[i] == 0 or parts[i] == 1)
def _DISABLED_test_reset():
size = 5
graph = Graph()
for i in xrange(size-1):
for i in range(size - 1):
offset = i * size
for j in xrange(size-1):
for j in range(size - 1):
graph.add_edge(offset + j, offset + j + 1)
graph.add_edge(offset + j + 1, offset + j)
if i > 0:
for j in xrange(size):
for j in range(size):
graph.add_edge(offset + j, offset + j - size)
graph.add_edge(offset + j - size, offset + j)
g = graph.compressed()
......
......@@ -11,13 +11,13 @@ from kwant.graph import slicer
def assert_sanity(graph, slices):
# Slices must comprise all of the graph.
slclist = [slices[j][i] for j in xrange(len(slices))
for i in xrange(len(slices[j]))]
slclist = [slices[j][i] for j in range(len(slices))
for i in range(len(slices[j]))]
slclist.sort()
assert slclist == [i for i in xrange(graph.num_nodes)]
assert slclist == [i for i in range(graph.num_nodes)]
# Nodes may only have neighbors in neighboring slices.
for j in xrange(len(slices)):
for j in range(len(slices)):
for node in slices[j]:
for neigh in graph.out_neighbors(node):
if j > 0 and j < len(slices) - 1:
......@@ -39,8 +39,8 @@ def test_rectangle():
sys = kwant.Builder()
lead = kwant.Builder(kwant.TranslationalSymmetry((-1, 0)))
lat = kwant.lattice.square()
lead[(lat(0, i) for i in xrange(w))] = 0
sys[(lat(j, i) for j in xrange(l) for i in xrange(w))] = 0
lead[(lat(0, i) for i in range(w))] = 0
sys[(lat(j, i) for j in range(l) for i in range(w))] = 0
for s in [lead, sys]:
for kind in [kwant.builder.HoppingKind((1, 0), lat),
kwant.builder.HoppingKind((0, 1), lat)]:
......@@ -57,7 +57,7 @@ def test_rectangle():
# we know that all slices must have the same shape.
assert len(slices) == l
for j in xrange(l):
for j in range(l):
assert len(slices[j]) == w
assert_sanity(fsys.graph, slices)
......@@ -83,7 +83,7 @@ def test_induced_subgraph():
num_nodes = 6
graph = Graph()
for i in xrange(num_nodes-1):
for i in range(num_nodes - 1):
graph.add_edge(i, i + 1)
graph.add_edge(1, 0)
g = graph.compressed()
......
......@@ -6,8 +6,6 @@
# the file AUTHORS.rst at the top-level directory of this distribution and at
# http://kwant-project.org/authors.
from __future__ import division
__all__ = ['TranslationalSymmetry', 'general', 'Polyatomic', 'Monatomic',
'chain', 'square', 'triangular', 'honeycomb', 'kagome']
......@@ -617,7 +615,6 @@ class TranslationalSymmetry(builder.Symmetry):
det_m = int(round(np.linalg.det(m)))
if det_m == 0:
print m
raise RuntimeError('Adding site family failed.')
det_x_inv_m = np.array(np.round(det_m * np.linalg.inv(m)), dtype=int)
......
......@@ -11,6 +11,6 @@ from . import lapack
# Merge the public interface of the other submodules.
for module in ['decomp_lu', 'decomp_ev', 'decomp_schur']:
exec 'from . import {0}'.format(module)
exec 'from .{0} import *'.format(module)
exec '__all__.extend({0}.__all__)'.format(module)
exec('from . import {0}'.format(module))
exec('from .{0} import *'.format(module))
exec('__all__.extend({0}.__all__)'.format(module))
......@@ -61,13 +61,13 @@ def lu_factor(a, overwrite_a=False):
return lapack.cgetrf(a)
def lu_solve((lu, ipiv, singular), b):
def lu_solve(matrix_factorization, b):
"""Solve a linear system of equations, a x = b, given the LU
factorization of a
Parameters
----------
(lu, piv, singular)
matrix_factorization
Factorization of the coefficient matrix a, as given by lu_factor
b : array (vector or matrix)
Right-hand side
......@@ -77,7 +77,7 @@ def lu_solve((lu, ipiv, singular), b):
x : array (vector or matrix)
Solution to the system
"""
(lu, ipiv, singular) = matrix_factorization
if singular:
raise RuntimeWarning("In lu_solve: the flag singular indicates "
"a singular matrix. Result of solve step "
......@@ -102,7 +102,7 @@ def lu_solve((lu, ipiv, singular), b):
return lapack.cgetrs(lu, ipiv, b)
def rcond_from_lu((lu, ipiv, singular), norm_a, norm="1"):
def rcond_from_lu(matrix_factorization, norm_a, norm="1"):
"""Compute the reciprocal condition number from the LU decomposition as
returned from lu_factor(), given additionally the norm of the matrix a in
norm_a.
......@@ -112,7 +112,7 @@ def rcond_from_lu((lu, ipiv, singular), norm_a, norm="1"):
Parameters
----------
(lu, piv, singular)
matrix_factorization
Factorization of the matrix a, as given by lu_factor
norm_a : float or complex
norm of the original matrix a (type of norm is specified in norm)
......@@ -126,9 +126,10 @@ def rcond_from_lu((lu, ipiv, singular), norm_a, norm="1"):
reciprocal condition number of a with respect to the type of matrix
norm specified in norm
"""
(lu, ipiv, singular) = matrix_factorization
if not norm in ("1", "I"):
raise ValueError("norm in rcond_from_lu must be either '1' or 'I'")
norm = norm.encode('utf8') # lapack expects bytes
ltype, lu = lapack.prepare_for_lapack(False, lu)
......
......@@ -36,7 +36,7 @@ def prepare_for_fortran(overwrite, *args):
# Make sure we have NumPy arrays
mats = [None]*len(args)
for i in xrange(len(args)):
for i in range(len(args)):
if args[i] is not None:
arr = np.asanyarray(args[i])
if not np.issubdtype(arr.dtype, np.number):
......
......@@ -245,7 +245,7 @@ def zgetrs(np.ndarray[np.complex128_t, ndim=2] LU,
# Wrappers for xGECON
def sgecon(np.ndarray[np.float32_t, ndim=2] LU,
float normA, char *norm = "1"):
float normA, char *norm = b"1"):
cdef l_int N, info
cdef float rcond
cdef np.ndarray[np.float32_t, ndim=1] work
......@@ -266,7 +266,7 @@ def sgecon(np.ndarray[np.float32_t, ndim=2] LU,
return rcond
def dgecon(np.ndarray[np.float64_t, ndim=2] LU,
double normA, char *norm = "1"):
double normA, char *norm = b"1"):
cdef l_int N, info
cdef double rcond
cdef np.ndarray[np.float64_t, ndim=1] work
......@@ -287,7 +287,7 @@ def dgecon(np.ndarray[np.float64_t, ndim=2] LU,
return rcond
def cgecon(np.ndarray[np.complex64_t, ndim=2] LU,
float normA, char *norm = "1"):
float normA, char *norm = b"1"):
cdef l_int N, info
cdef float rcond
cdef np.ndarray[np.complex64_t, ndim=1] work
......@@ -308,7 +308,7 @@ def cgecon(np.ndarray[np.complex64_t, ndim=2] LU,
return rcond
def zgecon(np.ndarray[np.complex128_t, ndim=2] LU,
double normA, char *norm = "1"):
double normA, char *norm = b"1"):
cdef l_int N, info
cdef double rcond
cdef np.ndarray[np.complex128_t, ndim=1] work
......
......@@ -6,13 +6,12 @@
# the file AUTHORS.rst at the top-level directory of this distribution and at
# http://kwant-project.org/authors.
from __future__ import division
__all__ = ['lll', 'cvp', 'voronoi']
import numpy as np
from itertools import product
def gs_coefficient(a, b):
"""Gram-Schmidt coefficient."""
return np.dot(a, b) / np.linalg.norm(b)**2
......
......@@ -43,16 +43,16 @@ class _Random:
mat = np.empty((n, m), dtype = dtype)
if issubclass(dtype, np.complexfloating):
for i in xrange(n):
for j in xrange(m):
for i in range(n):
for j in range(m):
mat[i,j] = self._randf() + 1j * self._randf()
elif issubclass(dtype, np.floating):
for i in xrange(n):
for j in xrange(m):
for i in range(n):
for j in range(m):
mat[i,j] = self._randf()
elif issubclass(dtype, np.integer):
for i in xrange(n):
for j in xrange(m):
for i in range(n):
for j in range(m):
mat[i,j] = self._randi()
return mat
......@@ -61,13 +61,13 @@ class _Random:
vec = np.empty(n, dtype = dtype)
if issubclass(dtype, np.complexfloating):
for i in xrange(n):
for i in range(n):
vec[i] = self._randf() + 1j * self._randf()
elif issubclass(dtype, np.floating):
for i in xrange(n):
for i in range(n):
vec[i] = self._randf()
elif issubclass(dtype, np.integer):
for i in xrange(n):
for i in range(n):
vec[i] = self._randi()
return vec
......
......@@ -12,7 +12,7 @@ from kwant.linalg import (
convert_r2c_gen_schur, order_gen_schur, evecs_from_gen_schur)
from nose.tools import assert_equal, assert_true
import numpy as np
from _test_utils import _Random, assert_array_almost_equal
from ._test_utils import _Random, assert_array_almost_equal
def test_gen_eig():
def _test_gen_eig(dtype):
......
......@@ -6,7 +6,7 @@
# the file AUTHORS.rst at the top-level directory of this distribution and at
# http://kwant-project.org/authors.
from __future__ import division
import numpy as np
from kwant.linalg import lll
......
......@@ -17,7 +17,7 @@ from kwant.builder import Builder, HoppingKind