From c678a38513c2259d0fb38fcab36896911f3837ff Mon Sep 17 00:00:00 2001 From: joncrall Date: Wed, 26 Aug 2020 20:14:23 -0400 Subject: [PATCH 01/54] Start branch for 0.5.10 --- CHANGELOG.md | 5 ++++- netharn/__init__.py | 2 +- super_setup.py | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ad6538..a941f92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,10 @@ This changelog follows the specifications detailed in: [Keep a Changelog](https: This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html), although we have not yet reached a `1.0.0` release. -## Version 0.5.9 - Unreleased +## Version 0.5.10 - Unreleased + + +## Version 0.5.9 - Released 2020-08-26 ### Changed diff --git a/netharn/__init__.py b/netharn/__init__.py index 77ae9ac..7f01e3a 100644 --- a/netharn/__init__.py +++ b/netharn/__init__.py @@ -4,7 +4,7 @@ mkinit netharn --noattrs --dry mkinit netharn --noattrs """ -__version__ = '0.5.9' +__version__ = '0.5.10' try: # PIL 7.0.0 removed PIL_VERSION, which breaks torchvision, monkey patch it diff --git a/super_setup.py b/super_setup.py index aa6b163..5ef8844 100755 --- a/super_setup.py +++ b/super_setup.py @@ -753,7 +753,7 @@ def make_netharn_registry(): # netharn - training harness { - 'name': 'netharn', 'branch': 'dev/0.5.9', 'remote': 'public', + 'name': 'netharn', 'branch': 'dev/0.5.10', 'remote': 'public', 'remotes': {'public': 'git@gitlab.kitware.com:computer-vision/netharn.git'}, }, ] -- GitLab From f654479fd88c257cd5108fe6e0de2a2e38db0163 Mon Sep 17 00:00:00 2001 From: joncrall Date: Thu, 27 Aug 2020 10:58:15 -0400 Subject: [PATCH 02/54] Fix manage snapshots name/nice stuff --- dev/manage_snapshots.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index ddc08d9..33feabd 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -221,8 +221,14 @@ def _devcheck_remove_dead_runs(workdir, dry=True, dead_num_snap_thresh=10, # Partion your "name" sessions into broken and live symlinks. # For each live link remember what the real path is. broken_links = [] + dnames = [] + nice_dpath = join(workdir, 'fit', 'nice') name_dpath = join(workdir, 'fit', 'name') - for dname in os.listdir(name_dpath): + if exists(name_dpath): + dnames += os.listdir(name_dpath) + if exists(nice_dpath): + dnames += os.listdir(nice_dpath) + for dname in dnames: dpath = join(name_dpath, dname) if is_symlink_broken(dpath): broken_links.append(dpath) -- GitLab From 6b17d0fd27ba91d882676813584edcbfcbdb34fe Mon Sep 17 00:00:00 2001 From: joncrall Date: Thu, 27 Aug 2020 11:00:55 -0400 Subject: [PATCH 03/54] wip --- dev/manage_snapshots.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index 33feabd..8f16007 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -143,11 +143,20 @@ def session_info(dpath): name = basename(dirname(dpath)) info['name'] = name fitdir = dirname(dirname(dirname(dpath))) + target = None name_dpath = join(fitdir, 'name', name) - try: - target = realpath(ub.util_links._readlink(name_dpath)) - except Exception: - target = None + if exists(name_dpath): + try: + target = realpath(ub.util_links._readlink(name_dpath)) + except Exception: + target = None + else: + nice_dpath = join(fitdir, 'nice', name) + if exists(nice_dpath): + try: + target = realpath(ub.util_links._readlink(nice_dpath)) + except Exception: + target = None info['linked'] = (target == dpath) info['dpath'] = dpath -- GitLab From e678f7c6a6d3a803395b9438afe03dd045120ea4 Mon Sep 17 00:00:00 2001 From: joncrall Date: Thu, 27 Aug 2020 11:04:43 -0400 Subject: [PATCH 04/54] wip --- dev/manage_snapshots.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index 8f16007..726d148 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -230,15 +230,14 @@ def _devcheck_remove_dead_runs(workdir, dry=True, dead_num_snap_thresh=10, # Partion your "name" sessions into broken and live symlinks. # For each live link remember what the real path is. broken_links = [] - dnames = [] nice_dpath = join(workdir, 'fit', 'nice') name_dpath = join(workdir, 'fit', 'name') + dpaths = [] if exists(name_dpath): - dnames += os.listdir(name_dpath) + dpaths += [join(name_dpath, d) for d in os.listdir(name_dpath)] if exists(nice_dpath): - dnames += os.listdir(nice_dpath) - for dname in dnames: - dpath = join(name_dpath, dname) + dpaths += [join(name_dpath, d) for d in os.listdir(nice_dpath)] + for dpath in dpaths: if is_symlink_broken(dpath): broken_links.append(dpath) -- GitLab From a9549a91332428605ba8c4e060b4058bc19d5ab6 Mon Sep 17 00:00:00 2001 From: joncrall Date: Thu, 27 Aug 2020 11:05:05 -0400 Subject: [PATCH 05/54] wip --- dev/manage_snapshots.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index 726d148..3002b68 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -236,7 +236,7 @@ def _devcheck_remove_dead_runs(workdir, dry=True, dead_num_snap_thresh=10, if exists(name_dpath): dpaths += [join(name_dpath, d) for d in os.listdir(name_dpath)] if exists(nice_dpath): - dpaths += [join(name_dpath, d) for d in os.listdir(nice_dpath)] + dpaths += [join(nice_dpath, d) for d in os.listdir(nice_dpath)] for dpath in dpaths: if is_symlink_broken(dpath): broken_links.append(dpath) -- GitLab From 21cb2587e1c4666d0022203fa91e6e29a77eeee1 Mon Sep 17 00:00:00 2001 From: joncrall Date: Thu, 27 Aug 2020 11:05:52 -0400 Subject: [PATCH 06/54] wip --- dev/manage_snapshots.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index 3002b68..ade5361 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -269,7 +269,7 @@ def _devcheck_remove_dead_runs(workdir, dry=True, dead_num_snap_thresh=10, for p in empty_dpaths: ub.delete(p) for p in broken_links: - os.unlink(info['dpath']) + os.unlink(p) class Session(ub.NiceRepr): -- GitLab From 6c1ef892e89136286805cee6e92ee6bfd0752c36 Mon Sep 17 00:00:00 2001 From: joncrall Date: Wed, 2 Sep 2020 11:17:14 -0400 Subject: [PATCH 07/54] Disable UTF-8 Support, rework of manage snapshots, small test changes --- CHANGELOG.md | 13 ++ dev/manage_snapshots.py | 169 +++++++++++++++++------- netharn/analytic/receptive_field_for.py | 43 +++++- netharn/fit_harn.py | 17 ++- netharn/layers/norm.py | 20 +++ 5 files changed, 200 insertions(+), 62 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a941f92..0a89904 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,19 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## Version 0.5.10 - Unreleased +### Added +* `allow_unicode` option to `FitHarnPreferences`, which can be set to False to + disable utf8 characters in output formatting. + +### Fixed +* Typo: directory `explit_checkpoints` renamed to `explicit_checkpoints`. + + +### Deprecated +* Deprecate `colored` option in `FitHarnPreferences`. Use `NO_COLOR` environ to + disable ANSI coloring instead. + + ## Version 0.5.9 - Released 2020-08-26 ### Changed diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index ade5361..ab18442 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -13,6 +13,7 @@ import numpy as np import os import parse import ubelt as ub +import copy def byte_str(num, unit='auto', precision=2): @@ -129,13 +130,97 @@ def get_file_info(fpath): return info +def _demodata_workdir(): + """ + Make a work directory with various types of sessions + """ + workdir = ub.ensure_app_cache_dir('netharn/tests/sessions') + def _demodata_toy_sesssion(workdir, name='demo_session', lr=1e-4): + """ + workdir = ub.ensure_app_cache_dir('netharn/tests/sessions') + workdir + """ + # This will train a toy model with toy data using netharn + import netharn as nh + hyper = nh.HyperParams(**{ + 'workdir' : ub.ensure_app_cache_dir('netharn/tests/sessions'), + 'name' : name, + 'xpu' : nh.XPU.coerce('cpu'), + 'datasets' : {'train': nh.data.ToyData2d(size=3, rng=0), 'vali': nh.data.ToyData2d(size=3, rng=0)}, + 'loaders' : {'batch_size': 64}, + 'model' : (nh.models.ToyNet2d, {}), + 'optimizer' : (nh.optimizers.SGD, {'lr': lr}), + 'criterion' : (nh.criterions.FocalLoss, {}), + 'initializer' : (nh.initializers.KaimingNormal, {}), + 'monitor' : (nh.Monitor, {'max_epoch': 1}), + }) + harn = nh.FitHarn(hyper) + harn.preferences['use_tensorboard'] = False + harn.preferences['timeout'] = 1 + harn.run() # TODO: make this run faster if we don't need to rerun + + _demodata_toy_sesssion(workdir, name='demo_session1', lr=1e-3) + _demodata_toy_sesssion(workdir, name='demo_session2', lr=1e-3) + _demodata_toy_sesssion(workdir, name='demo_session3', lr=1e-3) + _demodata_toy_sesssion(workdir, name='demo_session2', lr=1e-4) + _demodata_toy_sesssion(workdir, name='demo_session3', lr=1e-4) + _demodata_toy_sesssion(workdir, name='demo_session3', lr=1e-5) + return workdir + + +def collect_sessions(workdir): + """ + Netharn writes all training runs into a work directory under + /fit/runs//. And makes symlinks in + /fit/name/. This collects all sessions within a workdir that + match the filter criteria. + + workdir = _demodata_workdir() + all_sessions = collect_sessions(workdir) + + """ + run_dpath = join(workdir, 'fit', 'runs') + training_dpaths = list(glob.glob(join(run_dpath, '*/*'))) + + all_sessions = [] + for dpath in training_dpaths: + session = Session(dpath) + all_sessions.append(session) + return all_sessions + + +class Session(ub.NiceRepr): + """ + NEW: object to maintain info / manipulate a specific training directory + + TODO: + - [ ] Lazy properties + - [ ] Better convinience methods + - [ ] Log parsing + """ + def __init__(session, dpath): + session.dpath = dpath + info, details = session_info(session.dpath) + session.info = info + session.details = details + + def __nice__(session): + return repr(session.info) + + def session_info(dpath): """ Stats about a training session """ info = {} snap_dpath = join(dpath, 'torch_snapshots') - snapshots = os.listdir(snap_dpath) if exists(snap_dpath) else [] + check_dpath = join(dpath, 'checkpoints') + if exists(check_dpath): + snapshots = os.listdir(snap_dpath) if exists(snap_dpath) else [] + elif exists(snap_dpath): + pass + else: + snapshots = [] dpath = realpath(dpath) if True: @@ -159,7 +244,15 @@ def session_info(dpath): target = None info['linked'] = (target == dpath) + best_snapshot_fpath = join(dpath, 'best_snapshot.pt') + details = {} + details['best_snapshot'] = best_snapshot_fpath if exists(best_snapshot_fpath) else None + details['deployed'] = list(glob.glob(join(dpath, '*.zip'))) + details['snapshots'] = snapshots + info['dpath'] = dpath + info['has_deploy'] = bool(details['deployed']) + info['has_best'] = bool(details['best_snapshot']) info['num_snapshots'] = len(snapshots) info['size'] = float(ub.cmd('du -s ' + dpath)['out'].split('\t')[0]) if len(snapshots) > 0: @@ -168,7 +261,7 @@ def session_info(dpath): unixtime = max(timestamps) dt = datetime.datetime.fromtimestamp(unixtime) info['last_modified'] = dt - return info + return info, details def _devcheck_remove_dead_runs(workdir, dry=True, dead_num_snap_thresh=10, @@ -186,37 +279,35 @@ def _devcheck_remove_dead_runs(workdir, dry=True, dead_num_snap_thresh=10, workdir = '.' import xdev globals().update(xdev.get_func_kwargs(_devcheck_remove_dead_runs)) + + workdir = _demodata_workdir() + _devcheck_remove_dead_runs(workdir) """ - import ubelt as ub - import copy print('Checking for dead / dangling sessions in your runs dir') - # Find if any run directory is empty run_dpath = join(workdir, 'fit', 'runs') - training_dpaths = list(glob.glob(join(run_dpath, '*/*'))) - - all_sessions = [] - for dpath in training_dpaths: - session = session_info(dpath) - all_sessions.append(session) + all_sessions = collect_sessions(workdir) + # Find if any run directory is empty now = datetime.datetime.now() long_time_ago = now - datetime.timedelta(days=safe_num_days) for session in all_sessions: - if session['num_snapshots'] == 0: - session['decision'] = 'bad' - elif session['num_snapshots'] < dead_num_snap_thresh: - dt = session['last_modified'] + info = session.info + if not (info['has_deploy'] or info['num_snapshots'] or info['has_best']): + info['decision'] = 'bad' + elif info['num_snapshots'] < dead_num_snap_thresh: + dt = info['last_modified'] if dt < long_time_ago: - session['decision'] = 'iffy' + info['decision'] = 'iffy' else: - session['decision'] = 'good' + info['decision'] = 'good' else: - session['decision'] = 'good' + info['decision'] = 'good' - nice_groups = ub.group_items(all_sessions, lambda x: x['name']) + all_info = [s.info for s in all_sessions] + nice_groups = ub.group_items(all_info, lambda x: x['name']) for name, group in nice_groups.items(): print(' --- {} --- '.format(name)) group = sorted(group, key=lambda x: x['size']) @@ -247,7 +338,7 @@ def _devcheck_remove_dead_runs(workdir, dry=True, dead_num_snap_thresh=10, if len(os.listdir(dpath)) == 0: empty_dpaths.append(dpath) - decision_groups = ub.group_items(all_sessions, lambda x: x['decision']) + decision_groups = ub.group_items(all_info, lambda x: x['decision']) print('Empty dpaths: {:>4}'.format(len(empty_dpaths))) print('Broken links: {:>4}'.format(len(broken_links))) @@ -272,30 +363,12 @@ def _devcheck_remove_dead_runs(workdir, dry=True, dead_num_snap_thresh=10, os.unlink(p) -class Session(ub.NiceRepr): - """ - UNFINISHED: - NEW: object to maintain info / manipulate a specific training directory - """ - def __init__(session, dpath): - session.dpath = dpath - session.info = session_info(session.dpath) - - def __nice__(session): - return repr(session.info) +def _devcheck_manage_monitor(workdir, dry=True): + all_sessions = collect_sessions(workdir) -def _devcheck_manage_monitor(workdir, dry=True): # Get all the images in the monitor directories # (this is a convention and not something netharn does by default) - run_dpath = join(workdir, 'fit', 'runs') - training_dpaths = list(glob.glob(join(run_dpath, '*/*'))) - - all_sessions = [] - for dpath in training_dpaths: - session = Session(dpath) - all_sessions.append(session) - # UNFINISHED all_files = [] factor = 100 @@ -382,15 +455,14 @@ def _devcheck_manage_snapshots(workdir, recent=5, factor=10, dry=True): USE_RANGE_HUERISTIC = True - run_dpath = join(workdir, 'fit', 'runs') - snapshot_dpaths = list(glob.glob(join(run_dpath, '**/torch_snapshots'), recursive=True)) - print('checking {} snapshot paths'.format(len(snapshot_dpaths))) + all_sessions = collect_sessions(workdir) + print('Checking sessions = {}'.format(ub.repr2(all_sessions, nl=1))) all_keep = [] all_remove = [] - for snapshot_dpath in snapshot_dpaths: - snapshots = sorted(glob.glob(join(snapshot_dpath, '_epoch_*.pt'))) + for session in all_sessions: + snapshots = session.details['snapshots'] epoch_to_snap = { int(parse.parse('{}_epoch_{num:d}.pt', path).named['num']): path for path in snapshots @@ -425,7 +497,7 @@ def _devcheck_manage_snapshots(workdir, recent=5, factor=10, dry=True): print('keep = {!r}'.format(sorted(keep))) print('kill = {!r}'.format(sorted(kill))) - print('Keep {}/{} from {}'.format(len(keep), len(existing_epochs), snapshot_dpath)) + print('Keep {}/{} from {}'.format(len(keep), len(existing_epochs), session.info['dpath'])) all_keep += [tokeep] all_remove += [toremove] @@ -440,12 +512,11 @@ def _devcheck_manage_snapshots(workdir, recent=5, factor=10, dry=True): for path in ub.flatten(all_remove): total += os.path.getsize(path) - total_mb = total / 2 ** 20 if dry: - print('Cleanup would delete {} snapshots and free {!r} MB'.format(len(all_remove), total_mb)) + print('Cleanup would delete {} snapshots and free {}'.format(len(all_remove), byte_str(total))) print('Use -f to confirm and force cleanup') else: - print('About to free {!r} MB'.format(total_mb)) + print('About to free {}'.format(byte_str(total))) for path in ub.flatten(all_remove): ub.delete(path, verbose=True) diff --git a/netharn/analytic/receptive_field_for.py b/netharn/analytic/receptive_field_for.py index 0d10905..a768ee1 100644 --- a/netharn/analytic/receptive_field_for.py +++ b/netharn/analytic/receptive_field_for.py @@ -1001,13 +1001,42 @@ def effective_receptive_feild(module, inputs, output_key=None, sigma=0, >>> kwplot.imshow(emperical_field['impact'], doclf=True) Ignore: + >>> def forward(self, x): + >>> # See note [TorchScript super()] + >>> x = self.conv1(x) + >>> x = self.bn1(x) + >>> x = self.relu(x) + >>> x = self.maxpool(x) + >>> # + >>> x = self.layer1(x) + >>> x = self.layer2(x) + >>> x = self.layer3(x) + >>> x = self.layer4(x) + >>> # + >>> #x = self.avgpool(x) + >>> #x = torch.flatten(x, 1) + >>> #x = self.fc(x) + >>> return x >>> xpu = nh.XPU.coerce('auto') - >>> module = xpu.move(torchvision.models.resnet50()) - >>> inputs = xpu.move(torch.rand(8, 3, 224, 224)) - >>> emperical_field = effective_receptive_feild(module, inputs) + >>> module1 = torchvision.models.resnet50() + >>> ub.inject_method(module1, forward) + >>> module1 = xpu.move(module1) + >>> module2 = torchvision.models.resnet50(pretrained=True) + >>> module2 = xpu.move(module2) + >>> ub.inject_method(module2, forward) + >>> import kwimage + >>> img = kwimage.grab_test_image(dsize=(224, 224)) + >>> inputs = torch.from_numpy(img.transpose(2, 0, 1)[None, :] / 255.).float() + >>> inputs = xpu.move(inputs) + >>> #inputs = xpu.move(torch.rand(8, 3, 224, 224)) + >>> ignore_norms = 1 + >>> emperical_field1 = effective_receptive_feild(module1, inputs, ignore_norms=ignore_norms) + >>> emperical_field2 = effective_receptive_feild(module2, inputs, ignore_norms=ignore_norms) >>> import kwplot >>> kwplot.autompl() - >>> kwplot.imshow(emperical_field['impact'], doclf=True) + >>> kwplot.imshow(inputs[0].data.cpu().numpy(), fnum=1, pnum=(1, 3, 1), title='input', doclf=1) + >>> kwplot.imshow(emperical_field1['impact'], fnum=1, pnum=(1, 3, 2), title='pretrained=False') + >>> kwplot.imshow(emperical_field2['impact'], doclf=0, fnum=1, pnum=(1, 3, 3), title='pretrained=True') """ import netharn as nh @@ -1043,10 +1072,10 @@ def effective_receptive_feild(module, inputs, output_key=None, sigma=0, outputs = module(inputs) # Note: grab a single (likely FCN) output channel - if callable(output_key): - output_y = output_key(outputs) - elif output_key is None: + if output_key is None: output_y = outputs + elif callable(output_key): + output_y = output_key(outputs) else: output_y = outputs[output_key] # elif isinstance(output_key, (six.string_types, int)): diff --git a/netharn/fit_harn.py b/netharn/fit_harn.py index e2937e4..cd91ab6 100644 --- a/netharn/fit_harn.py +++ b/netharn/fit_harn.py @@ -88,7 +88,6 @@ Example: >>> # non-algorithmic behavior configs (do not change learned models) >>> harn.preferences['use_tensorboard'] = False >>> harn.preferences['timeout'] = 0.5 - >>> # harn.preferences['colored'] = False >>> # start training. >>> harn.initialize(reset='delete') >>> harn.run() # note: run calls initialize it hasn't already been called. @@ -763,7 +762,7 @@ class ProgMixin(object): else: bs = 'x{}'.format(batch_size) parts = [bs] + parts - if six.PY2: + if not harn.preferences['allow_unicode'] or six.PY2: # work around a unicode issue with tqdm in python2 msg = ' | ' .join(parts) + ' |' else: @@ -900,7 +899,8 @@ class LogMixin(object): if harn._log: msg = strip_ansi(six.text_type(msg)) # Encode to prevent errors on windows terminals - # On windows there is a sometimes a UnicodeEncodeError: For more details see: https://wiki.python.org/moin/PrintFails + # On windows there is a sometimes a UnicodeEncodeError: + # For more details see: https://wiki.python.org/moin/PrintFails if sys.platform.startswith('win32'): harn._log.debug(msg.encode('utf8')) else: @@ -1100,7 +1100,7 @@ class SnapshotMixin(object): are: checkpoint, explicit, and initial. explicit (bool, default=False): if True, the snapshot is also - tagged by a hash and saved to the explit_checkpoints directory. + tagged by a hash and saved to the explicit_checkpoints directory. DEPRECTATED, use mode. Returns: @@ -1116,7 +1116,7 @@ class SnapshotMixin(object): mode = 'explicit' if mode == 'explicit': - dpath = ub.ensuredir((harn.train_dpath, 'explit_checkpoints')) + dpath = ub.ensuredir((harn.train_dpath, 'explicit_checkpoints')) stamp = ub.timestamp() save_fname = '_epoch_{:08d}_{}.pt'.format(harn.epoch, stamp) elif mode == 'checkpoint': @@ -2804,7 +2804,12 @@ class FitHarnPreferences(scfg.Config): 'colored': scfg.Value(True, help=( 'allow for ANSI colored text in stdout logs, ' - 'otherwise it is stripped')), + 'otherwise it is stripped. ' + 'DEPRECATED use NO_COLOR environ instead')), + + 'allow_unicode': scfg.Value(True, help=( + 'allow for unicode characters in messages, otherwise ' + ' we approximate them with ascii')), } diff --git a/netharn/layers/norm.py b/netharn/layers/norm.py index 8aaa267..e175bda 100644 --- a/netharn/layers/norm.py +++ b/netharn/layers/norm.py @@ -87,6 +87,26 @@ class InputNorm(common.Module): >>> # Specifying either the mean or the std is ok. >>> partial1 = InputNorm(mean=50)(inputs) >>> partial2 = InputNorm(std=29)(inputs) + + import torch + + model = torch.nn.Sequential(*[ + InputNorm(mean=10, std=0.2), + torch.nn.Conv2d(3, 3, 3), + ]) + inputs = torch.rand(2, 3, 5, 7) * 100 + optim = torch.optim.SGD(model.parameters(), lr=1e-3) + + for i in range(100): + optim.zero_grad() + x = model(inputs).sum() + x.backward() + optim.step() + + std = model[0].mean + mean = model[0].std + print('std = {!r}'.format(std)) + print('mean = {!r}'.format(mean)) """ def __init__(self, mean=None, std=None): -- GitLab From 58801e7e0ef322539325a42c1e8d1013c9e487f0 Mon Sep 17 00:00:00 2001 From: joncrall Date: Thu, 3 Sep 2020 17:17:38 -0400 Subject: [PATCH 08/54] Actually fix unicode error --- netharn/fit_harn.py | 2 +- netharn/layers/perceptron.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/netharn/fit_harn.py b/netharn/fit_harn.py index cd91ab6..d70508b 100644 --- a/netharn/fit_harn.py +++ b/netharn/fit_harn.py @@ -784,7 +784,7 @@ class ProgMixin(object): def _update_main_prog_desc(harn): lrs = set(harn._current_lrs()) lr_str = ','.join(['{:.4g}'.format(lr) for lr in lrs]) - if six.PY2: + if not harn.preferences['allow_unicode'] or six.PY2: desc = 'epoch lr:{} | {}'.format(lr_str, harn.monitor.message()) else: desc = 'epoch lr:{} │ {}'.format(lr_str, harn.monitor.message()) diff --git a/netharn/layers/perceptron.py b/netharn/layers/perceptron.py index 6c6f327..0d6ba03 100644 --- a/netharn/layers/perceptron.py +++ b/netharn/layers/perceptron.py @@ -20,7 +20,8 @@ class MultiLayerPerceptronNd(common.Module): input and output channels) out_channels (int): dropout (float, default=0): amount of dropout to use - norm (str, default='batch'): type of normalization layer (e.g. batch or group) + norm (str, default='batch'): type of normalization layer + (e.g. batch or group), set to None for no normalization. noli (str, default='relu'): type of nonlinearity residual (bool, default=False): if true includes a resitual skip connection between inputs and -- GitLab From 194fedab925cda8d5e232b2e135329fdaacda4e0 Mon Sep 17 00:00:00 2001 From: joncrall Date: Mon, 7 Sep 2020 13:07:57 -0400 Subject: [PATCH 09/54] Using fork of network algorithm candidate for embedding --- netharn/initializers/_nx_ext/__init__.py | 76 + netharn/initializers/_nx_ext/_bseq_expt.py | 392 + .../initializers/_nx_ext/balanced_sequence.py | 1140 ++ .../_nx_ext/balanced_sequence_cython.cpp | 10787 ++++++++++++++++ .../_nx_ext/balanced_sequence_cython.html | 4497 +++++++ .../_nx_ext/balanced_sequence_cython.pyx | 344 + netharn/initializers/_nx_ext/benchmarks.py | 387 + netharn/initializers/_nx_ext/demodata.py | 239 + .../initializers/_nx_ext/path_embedding.py | 143 + .../_nx_ext/tests/test_balanced_sequence.py | 32 + .../_nx_ext/tests/test_path_embedding.py | 260 + .../_nx_ext/tests/test_tree_embedding.py | 109 + .../initializers/_nx_ext/tree_embedding.py | 512 + netharn/initializers/_nx_extensions.py | 1004 -- .../_nx_extensions_cython_backend.pyx | 46 - netharn/initializers/balanced_sequence.py | 969 -- netharn/initializers/bseq2.py | 612 - netharn/initializers/functional.py | 8 +- netharn/schedulers/core.py | 50 + 19 files changed, 18972 insertions(+), 2635 deletions(-) create mode 100644 netharn/initializers/_nx_ext/__init__.py create mode 100644 netharn/initializers/_nx_ext/_bseq_expt.py create mode 100644 netharn/initializers/_nx_ext/balanced_sequence.py create mode 100644 netharn/initializers/_nx_ext/balanced_sequence_cython.cpp create mode 100644 netharn/initializers/_nx_ext/balanced_sequence_cython.html create mode 100644 netharn/initializers/_nx_ext/balanced_sequence_cython.pyx create mode 100644 netharn/initializers/_nx_ext/benchmarks.py create mode 100644 netharn/initializers/_nx_ext/demodata.py create mode 100644 netharn/initializers/_nx_ext/path_embedding.py create mode 100644 netharn/initializers/_nx_ext/tests/test_balanced_sequence.py create mode 100644 netharn/initializers/_nx_ext/tests/test_path_embedding.py create mode 100644 netharn/initializers/_nx_ext/tests/test_tree_embedding.py create mode 100644 netharn/initializers/_nx_ext/tree_embedding.py delete mode 100644 netharn/initializers/_nx_extensions.py delete mode 100644 netharn/initializers/_nx_extensions_cython_backend.pyx delete mode 100644 netharn/initializers/balanced_sequence.py delete mode 100644 netharn/initializers/bseq2.py diff --git a/netharn/initializers/_nx_ext/__init__.py b/netharn/initializers/_nx_ext/__init__.py new file mode 100644 index 0000000..c0e9e1b --- /dev/null +++ b/netharn/initializers/_nx_ext/__init__.py @@ -0,0 +1,76 @@ +""" +TEMPORARY FORK +-------------- + +CommandLine: + sedr networkx.algorithms.isomorphism._embedding netharn.initializers._nx_ext + sedr netharn.initializers._nx_ext netharn.initializers._nx_ext * True + + +Subpackages for helpers and such related to the ordered subtree embedding / +isomorphism problems. + +Contains routines for solving balanced sequence and path subproblems. Only the +final graph-based API is exposed, but modification to the internals (is / will +be) available via keyword arguments. + +balanced_sequence.py - core python implementations for the longest common +balanced sequence subproblem. + +balanced_sequence_cython.pyx - +faster alternative implementsions for balanced_sequence.py + +tree_embedding.py - defines reduction from tree problem to balanced sequence +problems. + +path_embedding.py - defines reduction from path problem to tree problem (not +core, this is just useful for testing among other things). + +demodata.py - Contains data for docstrings, benchmarks, and synthetic problems + + +Outstanding Issues +------------------ +- [ ] Multiple implementations of the algorithm backend / data structure + reduction, need to reduce the impelmentation and / or determine a better + mechansim for allowing the user to switch between them. + +- [ ] strhack is not a good API in `tree_to_seq` + +- [ ] Should we return which edges were contracted in each tree to create the + embeddings? That seems useful (but maybe not equivalent to the embeddings + themselves?) + +- [ ] How to deal with cython + networkx? Do we need to fix that skbuild with + pypy? + +- [ ] The open_to_node problem: + Note, we may be able to simply use the position of each opening token + as a proxy for unique tokens. Pass in an ordered list of nodes, then + just use their indexes. + + +CommandLine +----------- +xdoctest -m netharn.initializers._nx_ext list +xdoctest -m netharn.initializers._nx_ext all + +# Run all tests in this module +DPATH=$(python -c " +import os; import netharn.initializers._nx_ext as m; +print(os.path.dirname(m.__file__))") +pytest --xdoctest $DPATH --xdoc-analysis=dynamic + +# The mkinit tool helps autogenerate explicit `__init__.py` files +mkinit ~/code/networkx/netharn.initializers._nx_ext/__init__.py -w +""" + +__submodules__ = [ + 'tree_embedding', +] + +# from netharn.initializers._nx_ext import tree_embedding +from netharn.initializers._nx_ext.tree_embedding import ( + maximum_common_ordered_tree_embedding) + +__all__ = ['maximum_common_ordered_tree_embedding'] diff --git a/netharn/initializers/_nx_ext/_bseq_expt.py b/netharn/initializers/_nx_ext/_bseq_expt.py new file mode 100644 index 0000000..5fad7de --- /dev/null +++ b/netharn/initializers/_nx_ext/_bseq_expt.py @@ -0,0 +1,392 @@ +from netharn.initializers._nx_ext.balanced_sequence import UnbalancedException, IdentityDict # NOQA +from netharn.initializers._nx_ext.balanced_sequence import generate_all_decomp, _cython_lcs_backend, _lcs_iter_simple_alt2, _lcs_iter_prehash2, _lcs_recurse, _lcs_iter_simple, _lcs_iter_simple_alt1, _lcs_iter_prehash # NOQA + + +def _lcs_iter_simple_alt3(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node): + """ + Depth first stack trajectory and replace try except statements with ifs + + This is the current best pure-python algorithm candidate + + >>> full_seq1 = '{({})([[]([]){(()(({()[]({}{})}))){}}])}' + >>> full_seq2 = '{[({{}}{{[][{}]}(()[(({()})){[]()}])})]}' + >>> open_to_close = {'{': '}', '(': ')', '[': ']'} + >>> full_seq1 = '[][[]][]' + >>> full_seq2 = '[[]][[]]' + >>> open_to_close = {'[': ']'} + >>> import operator as op + >>> node_affinity = op.eq + >>> open_to_node = IdentityDict() + >>> res = _lcs_iter_simple_alt3(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node) + >>> embeddings, val, delseq = res + >>> print('embeddings = {!r}'.format(embeddings[0])) + >>> print('delseq = {!r}'.format(delseq[0])) + """ + all_decomp1 = generate_all_decomp(full_seq1, open_to_close, open_to_node) + all_decomp2 = generate_all_decomp(full_seq2, open_to_close, open_to_node) + + key0 = (full_seq1, full_seq2) + frame0 = key0 + stack = [frame0] + + # Memoize mapping (seq1, seq2) -> best size, embeddings, deleted edges + _results = {} + + # Populate base cases + empty1 = type(next(iter(all_decomp1.keys())))() + empty2 = type(next(iter(all_decomp2.keys())))() + best = (empty1, empty2) + base_result = (0, best, ([], [])) + for seq1 in all_decomp1.keys(): + key1 = seq1 + t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[key1] + _results[(seq1, empty2)] = base_result + _results[(head1, empty2)] = base_result + _results[(tail1, empty2)] = base_result + _results[(head_tail1, empty2)] = base_result + + for seq2 in all_decomp2.keys(): + key2 = seq2 + t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[key2] + _results[(empty1, seq2)] = base_result + _results[(empty1, head2)] = base_result + _results[(empty1, tail2)] = base_result + _results[(empty1, head_tail2)] = base_result + + del frame0 + del empty1 + del empty2 + del best + del base_result + + while stack: + key = stack[-1] + if key not in _results: + seq1, seq2 = key + + t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[seq1] + t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[seq2] + + # Case 2: The current edge in sequence1 is deleted + try_key = (head_tail1, seq2) + if try_key in _results: + cand1 = _results[try_key] + x, y, z = cand1 + z1, z2 = z + z1 = z1 + [a1] + z2 = z2 + [a2] + z3 = (z1, z2) + cand1 = (x, y, z3) + else: + # stack.append(key) + stack.append(try_key) + continue + + # Case 3: The current edge in sequence2 is deleted + try_key = (seq1, head_tail2) + if try_key in _results: + cand2 = _results[try_key] + x, y, z = cand2 + z1, z2 = z + z1 = z1 + [a1] + z2 = z2 + [a2] + z3 = (z1, z2) + cand2 = (x, y, z3) + else: + # stack.append(key) + stack.append(try_key) + continue + + # Case 1: The LCS involves this edge + affinity = node_affinity(t1, t2) + if affinity: + try_key = (head1, head2) + if try_key in _results: + pval_h, new_heads, delseq_h = _results[try_key] + else: + # stack.append(key) + stack.append(try_key) + continue + + try_key = (tail1, tail2) + if try_key in _results: + pval_t, new_tails, delseq_t = _results[try_key] + else: + # stack.append(key) + stack.append(try_key) + continue + + new_head1, new_head2 = new_heads + new_tail1, new_tail2 = new_tails + + subseq1 = a1 + new_head1 + b1 + new_tail1 + subseq2 = a2 + new_head2 + b2 + new_tail2 + + res3 = (subseq1, subseq2) + val3 = pval_h + pval_t + affinity + + h1, h2 = delseq_h + t1, t2 = delseq_t + + delseq3 = (h1 + t1, h2 + t2) + cand3 = (val3, res3, delseq3) + else: + cand3 = (-1, None) + + # We solved the frame + _results[key] = max(cand1, cand2, cand3) + stack.pop() + + val, best, delseq = _results[key0] + found = (best, val, delseq) + return found + + +def balanced_decomp2(sequence, open_to_close, start=0): + gen = generate_balance2(sequence, open_to_close) + for tup in gen: + (bal_curr, tok_curr, idx1, idx2) = tup + if idx2 == start: + stop = idx1 + assert bal_curr + break + + return start, stop + # pop_open = sequence[0:1] + # pop_close = sequence[head_stop:head_stop + 1] + # head = sequence[1:head_stop] + # tail = sequence[head_stop + 1:] + # head_tail = head + tail + # return pop_open, pop_close, head, tail, head_tail + + +def generate_balance2(sequence, open_to_close, start=0): + """ + Alternate version that also returns index information + + Yields + ------ + bool, T, int, int + is balanced + opening token + opening token index + current token index + + + Example + ------- + >>> open_to_close = {0: 1} + >>> seq = sequence = [0, 0, 0, 1, 1, 1, 0, 1] + >>> gen = list(generate_balance2(sequence, open_to_close)) + >>> for flag, token, idx1, idx2 in gen: + >>> print('flag={:d}, token={}, {}, {}'.format(flag, token, idx1, idx2)) + + balanced_decomp2(sequence, open_to_close) + """ + stack = [] + # Traversing the Expression + for curr_idx, token in enumerate(sequence, start=start): + + if token in open_to_close: + # Push opening elements onto the stack + stack.append((token, curr_idx)) + open_idx = -1 + else: + # Check that closing elements + if not stack: + raise UnbalancedException + prev_open, open_idx = stack.pop() + want_close = open_to_close[prev_open] + + if token != want_close: + raise UnbalancedException + + # If the stack is empty the sequence is currently balanced + currently_balanced = not bool(stack) + yield currently_balanced, token, curr_idx, open_idx + + if stack: + raise UnbalancedException + + +def generate_all_decomp2(full_seq, open_to_close, open_to_node=None): + """ + Alternate version where we keep track of indices instead + + Example + ------- + >>> full_seq = '0010010010111101' + >>> open_to_close = {'0': '1'} + >>> full_seq = '{[{}]}[()]' + >>> open_to_close = {'[': ']', '{': '}', '(': ')'} + >>> list(generate_balance2(full_seq, open_to_close)) + >>> all_decomp = generate_all_decomp2(full_seq, open_to_close) + + >>> from netharn.initializers._nx_ext import demodata + >>> full_seq, open_to_close = demodata.random_balanced_sequence(5, mode='number') + >>> all_decomp = generate_all_decomp2(full_seq, open_to_close) + """ + if open_to_node is None: + open_to_node = IdentityDict() + all_decomp = {} + + start = 0 + stop = len(full_seq) + deleted = [] + stack = [ + ('f', full_seq, start, stop, deleted) + ] + + DEBUG = 1 + + while stack: + t, seq, seq_start, seq_stop, seq_del = stack.pop() + if DEBUG: + import ubelt as ub + print('-----') + print(list(full_seq)) + + isdel = ['X' if b else ' ' for b in ub.boolmask(seq_del, len(full_seq))] + sep = ' : ' + pos = list(' ' * len(full_seq)) + pos[seq_start] = 'S' + pos[seq_stop - 1] = 'T' + prefix = ': ' + def padjoin(s): + return sep.join(['{:>2}'.format(c) for c in s]) + print(prefix + padjoin(range(len(full_seq)))) + print(prefix + padjoin(full_seq) + ' <- full_seq') + print(prefix + padjoin(isdel) + ' <- seq_del') + print(prefix + padjoin(pos) + ' <- seq_start, seq_stop') + + val = seq_start, seq_stop, seq_del + print('seq = {}, {!r}, {}'.format(t, seq, val)) + base = full_seq[seq_start:seq_stop] + print('base = {!r}'.format(base)) + rel_pad_del = [idx - seq_start for idx in seq_del if idx >= seq_start] + keep_idxs = sorted(set(range(len(base))) - set(rel_pad_del)) + newlist = [base[idx] for idx in keep_idxs] + try: + recon = ''.join(newlist) + except TypeError: + recon = tuple(newlist) + print('recon = {!r}'.format(recon)) + if seq: + rel_start, rel_stop = balanced_decomp2(seq, open_to_close) + + rel_head_start = rel_start + 1 + rel_head_stop = rel_stop + rel_tail_start = rel_stop + 1 + rel_tail_stop = len(seq) + if DEBUG > 1: + print('rel_start = {!r}'.format(rel_start)) + print('rel_stop = {!r}'.format(rel_stop)) + print('rel_head_start = {!r}'.format(rel_head_start)) + print('rel_head_stop = {!r}'.format(rel_head_stop)) + print('rel_tail_start = {!r}'.format(rel_tail_start)) + print('rel_tail_stop = {!r}'.format(rel_tail_stop)) + + rel_pad_del = [idx - seq_start for idx in seq_del if seq_start <= idx <= seq_stop] + if DEBUG: + print('rel_pad_del = {!r}'.format(rel_pad_del)) + + # I think there is a cumsum way of doing this, I'm being dense atm + # seq = '3' * 10 + # rel_pad_del = [4, 5, 9, 11] + hack_map = list(range(1 + len(seq) + len(rel_pad_del))) + for idx in sorted(rel_pad_del, reverse=True): + del hack_map[idx] + + if DEBUG: + print('hack_map = {!r}'.format(hack_map)) + + # I believe it is the case that the deleted indexes will only be + # able to cause a shift in the abs_tail_stop, the abs_tail_start, + # abs_head_stop, and abs_head_start should never "conflict" with + # the deleted indexes (I think). + + # num_del_after_tail_start = sum(abs_tail_start <= i <= seq_stop for i in seq_del) + # print('num_del_after_tail_start = {!r}'.format(num_del_after_tail_start)) + # num_del_before_tail_start = sum(0 <= i <= rel_tail_stop for i in rel_pad_del) + + abs_head_start = hack_map[rel_head_start] + seq_start + abs_head_stop = hack_map[rel_head_stop] + seq_start + + abs_tail_start = hack_map[rel_tail_start] + seq_start + abs_tail_stop = hack_map[rel_tail_stop] + seq_start + + if DEBUG > 1: + print('abs_head_start = {!r}'.format(abs_head_start)) + print('abs_head_stop = {!r}'.format(abs_head_stop)) + + print('abs_tail_start = {!r}'.format(abs_tail_start)) + print('abs_tail_stop = {!r}'.format(abs_tail_stop)) + + head_sl = slice(rel_head_start, rel_head_stop) + tail_sl = slice(rel_tail_start, rel_tail_stop) + + head = seq[head_sl] + tail = seq[tail_sl] + head_tail = head + tail + + head_del = seq_del + tail_del = seq_del + + if abs_head_stop == abs_head_start: + # case where tail is empty (which head_tail doesnt matter + # anyway but this is just a POC + abs_head_tail_start = abs_tail_start + else: + abs_head_tail_start = abs_head_start + + if abs_tail_stop == abs_tail_start: + # case where tail is empty (which head_tail doesnt matter + # anyway but this is just a POC + abs_head_tail_stop = abs_head_stop + else: + abs_head_tail_stop = abs_tail_stop + + abs_del_start = seq_start + rel_start + abs_del_stop = seq_start + rel_stop + + # head_tail_del = [abs_del_start, abs_del_stop] + seq_del + assert abs_del_start < abs_head_tail_start + if abs_del_stop < abs_head_tail_stop: + head_tail_del = [abs_del_stop] + seq_del + else: + head_tail_del = seq_del + + # seq[head_sl] + seq[tail_sl] + + # pop_open, pop_close, head, tail, head_tail = balanced_decomp2(seq, open_to_close) + # node = open_to_node[pop_open[0]] + all_decomp[seq] = (seq_start, seq_stop, seq_del) + # (node, pop_open, pop_close, head, tail, head_tail) + + if abs_head_stop > len(full_seq): + raise AssertionError + if abs_tail_stop > len(full_seq): + raise AssertionError + if abs_head_tail_stop > len(full_seq): + raise AssertionError + + if head: + if DEBUG: + print('head = {!r}'.format(head)) + head_del = [i for i in head_del if abs_head_start <= i < abs_head_stop] + stack.append(('h', head, abs_head_start, abs_head_stop, head_del)) + if tail: + if DEBUG: + print('tail = {!r}'.format(tail)) + tail_del = [i for i in tail_del if abs_tail_start <= i < abs_tail_stop] + stack.append(('t', tail, abs_tail_start, abs_tail_stop, tail_del)) + if tail and head: + if DEBUG: + print('head_tail = {!r}'.format(head_tail)) + print('head_tail_del = {!r}'.format(head_tail_del)) + head_tail_del = [i for i in head_tail_del if abs_head_tail_start <= i < abs_head_tail_stop] + stack.append(('ht', head_tail, abs_head_tail_start, abs_head_tail_stop, head_tail_del)) + if DEBUG: + assert seq == recon + + return all_decomp diff --git a/netharn/initializers/_nx_ext/balanced_sequence.py b/netharn/initializers/_nx_ext/balanced_sequence.py new file mode 100644 index 0000000..3ac524b --- /dev/null +++ b/netharn/initializers/_nx_ext/balanced_sequence.py @@ -0,0 +1,1140 @@ +""" +Balanced sequences are used via reduction to solve the maximum common subtree +embedding problem. +""" +import operator + + +def longest_common_balanced_sequence( + seq1, seq2, open_to_close, open_to_node=None, + node_affinity='auto', impl='iter-prehash2'): + """ + Finds the longest common balanced sequence between two sequences + + Parameters + ---------- + seq1, seq2: Iterable + two input balanced sequences + + open_to_close : Dict + a mapping from opening to closing tokens in the balanced sequence + + open_to_node : Dict | None + a dictionary that maps a sequence token to a token corresponding to an + original problem (e.g. a tree node), if unspecified an identity mapping + is assumed. FIXME: see outstanding issues. + WILL LIKELY CHANGE IN THE FUTURE + + node_affinity : None | str | callable + Function for to determine if two nodes can be matched. The return is + interpreted as a weight that is used to break ties. If None then any + node can match any other node and only the topology is important. + The default is "eq", which is the same as ``operator.eq``. + + impl : str + Determines the backend implementation. There are currently 8 different + backend implementations: + + recurse, iter, iter-prehash, iter-prehash2, iter-alt1, iter-alt2, + iter-alt2-cython, and iter-prehash2-cython. + + Example + ------- + >>> # extremely simple case + >>> seq1 = '[][[]][]' + >>> seq2 = '[[]][[]]' + >>> open_to_close = {'[': ']'} + >>> best, value = longest_common_balanced_sequence(seq1, seq2, open_to_close) + >>> subseq1, subseq2 = best + >>> print('subseq1 = {!r}'.format(subseq1)) + subseq1 = '[][[]]' + + >>> # 1-label case from the paper (see Example 5) + >>> # https://pdfs.semanticscholar.org/0b6e/061af02353f7d9b887f9a378be70be64d165.pdf + >>> seq1 = '0010010010111100001011011011' + >>> seq2 = '001000101101110001000100101110111011' + >>> open_to_close = {'0': '1'} + >>> best, value = longest_common_balanced_sequence(seq1, seq2, open_to_close) + >>> subseq1, subseq2 = best + >>> print('subseq1 = {!r}'.format(subseq1)) + >>> assert value == 13 + subseq1 = '00100101011100001011011011' + + >>> # 3-label case + >>> seq1 = '{({})([[]([]){(()(({()[]({}{})}))){}}])}' + >>> seq2 = '{[({{}}{{[][{}]}(()[(({()})){[]()}])})]}' + >>> open_to_close = {'{': '}', '(': ')', '[': ']'} + >>> best, value = longest_common_balanced_sequence(seq1, seq2, open_to_close) + >>> subseq1, subseq2 = best + >>> print('subseq1 = {!r}'.format(subseq1)) + >>> assert value == 10 + subseq1 = '{{}[][]()(({()})){}}' + """ + if node_affinity == 'auto' or node_affinity == 'eq': + node_affinity = operator.eq + if node_affinity is None: + def _matchany(a, b): + return True + node_affinity = _matchany + if open_to_node is None: + open_to_node = IdentityDict() + full_seq1 = seq1 + full_seq2 = seq2 + if impl == 'recurse': + _memo = {} + _seq_memo = {} + best, value = _lcs_recurse( + full_seq1, full_seq2, open_to_close, node_affinity, open_to_node, + _memo, _seq_memo) + elif impl == 'iter': + best, value = _lcs_iter_simple( + full_seq1, full_seq2, open_to_close, node_affinity, open_to_node) + elif impl == 'iter-prehash': + best, value = _lcs_iter_prehash( + full_seq1, full_seq2, open_to_close, node_affinity, open_to_node) + elif impl == 'iter-prehash2': + best, value = _lcs_iter_prehash2( + full_seq1, full_seq2, open_to_close, node_affinity, open_to_node) + elif impl == 'iter-alt1': + best, value = _lcs_iter_simple_alt1( + full_seq1, full_seq2, open_to_close, node_affinity, open_to_node) + elif impl == 'iter-alt2': + best, value = _lcs_iter_simple_alt2( + full_seq1, full_seq2, open_to_close, node_affinity, open_to_node) + elif impl == 'iter-alt2-cython': + balanced_sequence_cython = _cython_lcs_backend(error='raise') + best, value = balanced_sequence_cython._lcs_iter_simple_alt2_cython( + full_seq1, full_seq2, open_to_close, node_affinity, open_to_node) + elif impl == 'iter-prehash2-cython': + balanced_sequence_cython = _cython_lcs_backend(error='raise') + best, value = balanced_sequence_cython._lcs_iter_prehash2_cython( + full_seq1, full_seq2, open_to_close, node_affinity, open_to_node) + else: + raise KeyError(impl) + return best, value + + +def available_impls_longest_common_balanced_sequence(): + """ + Returns all available implementations for + :func:`longest_common_balanced_sequence`. + """ + from netharn.initializers._nx_ext import balanced_sequence + impls = [] + if balanced_sequence._cython_lcs_backend(): + impls += [ + 'iter-alt2-cython', + 'iter-prehash2-cython', + ] + + # Pure python backends + impls += [ + 'iter-prehash2', + 'iter-alt2', + 'iter-alt1', + 'iter-prehash', + 'iter', + 'recurse', + ] + return impls + + +def _cython_lcs_backend(error='ignore'): + """ + Returns the cython backend if available, otherwise None + """ + try: + from netharn.initializers._nx_ext import balanced_sequence_cython + except Exception: + if error == 'ignore': + return None + elif error == 'raise': + raise + else: + raise KeyError(error) + else: + return balanced_sequence_cython + + +def _lcs_iter_simple_alt2(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node): + """ + Depth first stack trajectory and replace try except statements with ifs + + This is the current best pure-python algorithm candidate + + >>> full_seq1 = '{({})([[]([]){(()(({()[]({}{})}))){}}])}' + >>> full_seq2 = '{[({{}}{{[][{}]}(()[(({()})){[]()}])})]}' + >>> open_to_close = {'{': '}', '(': ')', '[': ']'} + >>> full_seq1 = '[][[]][]' + >>> full_seq2 = '[[]][[]]' + >>> open_to_close = {'[': ']'} + >>> import operator as op + >>> node_affinity = op.eq + >>> open_to_node = IdentityDict() + >>> res = _lcs_iter_simple_alt2(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node) + >>> val, embeddings = res + """ + all_decomp1 = generate_all_decomp(full_seq1, open_to_close, open_to_node) + all_decomp2 = generate_all_decomp(full_seq2, open_to_close, open_to_node) + + key0 = (full_seq1, full_seq2) + frame0 = key0 + stack = [frame0] + + # Memoize mapping (seq1, seq2) -> best size, embeddings, deleted edges + _results = {} + + # Populate base cases + empty1 = type(next(iter(all_decomp1.keys())))() + empty2 = type(next(iter(all_decomp2.keys())))() + best = (empty1, empty2) + base_result = (0, best) + for seq1 in all_decomp1.keys(): + key1 = seq1 + t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[key1] + _results[(seq1, empty2)] = base_result + _results[(head1, empty2)] = base_result + _results[(tail1, empty2)] = base_result + _results[(head_tail1, empty2)] = base_result + + for seq2 in all_decomp2.keys(): + key2 = seq2 + t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[key2] + _results[(empty1, seq2)] = base_result + _results[(empty1, head2)] = base_result + _results[(empty1, tail2)] = base_result + _results[(empty1, head_tail2)] = base_result + + del frame0 + del empty1 + del empty2 + del best + del base_result + + while stack: + key = stack[-1] + if key not in _results: + seq1, seq2 = key + + t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[seq1] + t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[seq2] + + # Case 2: The current edge in sequence1 is deleted + try_key = (head_tail1, seq2) + if try_key in _results: + cand1 = _results[try_key] + else: + # stack.append(key) + stack.append(try_key) + continue + + # Case 3: The current edge in sequence2 is deleted + try_key = (seq1, head_tail2) + if try_key in _results: + cand2 = _results[try_key] + else: + # stack.append(key) + stack.append(try_key) + continue + + # Case 1: The LCS involves this edge + affinity = node_affinity(t1, t2) + if affinity: + try_key = (head1, head2) + if try_key in _results: + pval_h, new_heads = _results[try_key] + else: + # stack.append(key) + stack.append(try_key) + continue + + try_key = (tail1, tail2) + if try_key in _results: + pval_t, new_tails = _results[try_key] + else: + # stack.append(key) + stack.append(try_key) + continue + + new_head1, new_head2 = new_heads + new_tail1, new_tail2 = new_tails + + subseq1 = a1 + new_head1 + b1 + new_tail1 + subseq2 = a2 + new_head2 + b2 + new_tail2 + + res3 = (subseq1, subseq2) + val3 = pval_h + pval_t + affinity + cand3 = (val3, res3) + else: + cand3 = (-1, None) + + # We solved the frame + _results[key] = max(cand1, cand2, cand3) + stack.pop() + + val, best = _results[key0] + found = (best, val) + return found + + +def _lcs_iter_prehash2(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node): + """ + Version of the lcs iterative algorithm where we precompute hash values + + See :func:`longest_common_balanced_sequence` for parameter details. + """ + + all_decomp1 = generate_all_decomp_prehash(full_seq1, open_to_close, open_to_node) + all_decomp2 = generate_all_decomp_prehash(full_seq2, open_to_close, open_to_node) + + key_decomp1 = {} + key_decomp2 = {} + _results = {} + # Populate base cases + empty1 = type(next(iter(all_decomp1.keys())))() + empty2 = type(next(iter(all_decomp2.keys())))() + empty1_key = hash(empty1) + empty2_key = hash(empty2) + best = (empty1, empty2) + base_result = (0, best) + for seq1, info1 in all_decomp1.items(): + seq1_key = hash(seq1) + head1_key, tail1_key, head_tail1_key = all_decomp1[seq1][5:8] + _results[(seq1_key, empty2_key)] = base_result + _results[(head1_key, empty2_key)] = base_result + _results[(tail1_key, empty2_key)] = base_result + _results[(head_tail1_key, empty2_key)] = base_result + key_decomp1[seq1_key] = info1 + + for seq2, info2 in all_decomp2.items(): + seq2_key = hash(seq2) + head2_key, tail2_key, head_tail2_key = all_decomp2[seq2][5:8] + _results[(empty1_key, seq2_key)] = base_result + _results[(empty1_key, head2_key)] = base_result + _results[(empty1_key, tail2_key)] = base_result + _results[(empty1_key, head_tail2_key)] = base_result + key_decomp2[seq2_key] = info2 + + full_seq1_key = hash(full_seq1) + full_seq2_key = hash(full_seq2) + key0 = (full_seq1_key, full_seq2_key) + frame0 = key0, full_seq1, full_seq2 + stack = [frame0] + missing_frames = [] + while stack: + frame = stack[-1] + key, seq1, seq2 = frame + seq1_key, seq2_key = key + if key not in _results: + missing_frames.clear() + + info1 = key_decomp1[seq1_key] + tok1, seq1, head1, tail1, head_tail1, head1_key, tail1_key, head_tail1_key, a1, b1 = info1 + + # if seq2_key not in key_decomp2: + info2 = key_decomp2[seq2_key] + tok2, seq2, head2, tail2, head_tail2, head2_key, tail2_key, head_tail2_key, a2, b2 = info2 + + affinity = node_affinity(tok1, tok2) + + # Case 2: The current edge in sequence1 is deleted + try_key = (head_tail1_key, seq2_key) + if try_key in _results: + cand1 = _results[try_key] + else: + miss_frame = try_key, head_tail1, seq2 + stack.append(miss_frame) + continue + + # Case 3: The current edge in sequence2 is deleted + try_key = (seq1_key, head_tail2_key) + if try_key in _results: + cand2 = _results[try_key] + else: + miss_frame = try_key, seq1, head_tail2 + stack.append(miss_frame) + continue + + # Case 1: The LCS involves this edge + if affinity: + try_key = (head1_key, head2_key) + if try_key in _results: + pval_h, new_heads = _results[try_key] + else: + miss_frame = try_key, head1, head2 + stack.append(miss_frame) + continue + + try_key = (tail1_key, tail2_key) + if try_key in _results: + pval_t, new_tails = _results[try_key] + else: + miss_frame = try_key, tail1, tail2 + stack.append(miss_frame) + continue + + new_head1, new_head2 = new_heads + new_tail1, new_tail2 = new_tails + + subseq1 = a1 + new_head1 + b1 + new_tail1 + subseq2 = a2 + new_head2 + b2 + new_tail2 + + res3 = (subseq1, subseq2) + val3 = pval_h + pval_t + affinity + cand3 = (val3, res3) + else: + cand3 = (-1, None) + + # We solved the frame + _results[key] = max(cand1, cand2, cand3) + stack.pop() + + # The stack pop is our solution + (val, best) = _results[key0] + found = (best, val) + return found + + +def _lcs_recurse(seq1, seq2, open_to_close, node_affinity, open_to_node, _memo, _seq_memo): + """ + Surprisingly, this recursive implementation is one of the faster + pure-python methods for certain input types. However, its major drawback is + that it can raise a RecurssionError if the inputs are too deep. + """ + if not seq1: + return (seq1, seq1), 0 + elif not seq2: + return (seq2, seq2), 0 + else: + key1 = hash(seq1) # using hash(seq) is faster than seq itself + key2 = hash(seq2) + key = hash((key1, key2)) + if key in _memo: + return _memo[key] + + if key1 in _seq_memo: + a1, b1, head1, tail1, head1_tail1 = _seq_memo[key1] + else: + a1, b1, head1, tail1, head1_tail1 = balanced_decomp_unsafe(seq1, open_to_close) + _seq_memo[key1] = a1, b1, head1, tail1, head1_tail1 + + if key2 in _seq_memo: + a2, b2, head2, tail2, head2_tail2 = _seq_memo[key2] + else: + a2, b2, head2, tail2, head2_tail2 = balanced_decomp_unsafe(seq2, open_to_close) + _seq_memo[key2] = a2, b2, head2, tail2, head2_tail2 + + # Case 2: The current edge in sequence1 is deleted + best, val = _lcs_recurse(head1_tail1, seq2, open_to_close, node_affinity, open_to_node, _memo, _seq_memo) + + # Case 3: The current edge in sequence2 is deleted + cand, val_alt = _lcs_recurse(seq1, head2_tail2, open_to_close, node_affinity, open_to_node, _memo, _seq_memo) + if val_alt > val: + best = cand + val = val_alt + + # Case 1: The LCS involves this edge + t1 = open_to_node[a1[0]] + t2 = open_to_node[a2[0]] + affinity = node_affinity(t1, t2) + if affinity: + new_heads, pval_h = _lcs_recurse(head1, head2, open_to_close, node_affinity, open_to_node, _memo, _seq_memo) + new_tails, pval_t = _lcs_recurse(tail1, tail2, open_to_close, node_affinity, open_to_node, _memo, _seq_memo) + + new_head1, new_head2 = new_heads + new_tail1, new_tail2 = new_tails + + subseq1 = a1 + new_head1 + b1 + new_tail1 + subseq2 = a2 + new_head2 + b2 + new_tail2 + + cand = (subseq1, subseq2) + val_alt = pval_h + pval_t + affinity + if val_alt > val: + best = cand + val = val_alt + + found = (best, val) + _memo[key] = found + return found + + +def _lcs_iter_simple(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node): + """ + Converts _lcs_recursive to an iterative algorithm using a fairly + straightforward method that effectivly simulates callstacks. + Uses a breadth-first trajectory and try-except to catch missing + memoized results (which seems to be slightly slower than if statements). + """ + all_decomp1 = generate_all_decomp(full_seq1, open_to_close, open_to_node) + all_decomp2 = generate_all_decomp(full_seq2, open_to_close, open_to_node) + + args0 = (full_seq1, full_seq2) + frame0 = args0 + stack = [frame0] + + _results = {} + # Populate base cases + empty1 = type(next(iter(all_decomp1.keys())))() + empty2 = type(next(iter(all_decomp2.keys())))() + best = (empty1, empty2) + base_result = (0, best) + for seq1 in all_decomp1.keys(): + key1 = seq1 + t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[key1] + _results[(seq1, empty2)] = base_result + _results[(head1, empty2)] = base_result + _results[(tail1, empty2)] = base_result + _results[(head_tail1, empty2)] = base_result + + for seq2 in all_decomp2.keys(): + key2 = seq2 + t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[key2] + _results[(empty1, seq2)] = base_result + _results[(empty1, head2)] = base_result + _results[(empty1, tail2)] = base_result + _results[(empty1, head_tail2)] = base_result + + del args0 + del frame0 + del empty1 + del empty2 + del best + del base_result + + missing_frames = [] + while stack: + key = stack.pop() + if key not in _results: + seq1, seq2 = key + missing_frames.clear() + + t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[seq1] + t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[seq2] + + # Case 2: The current edge in sequence1 is deleted + try: + try_key = (head_tail1, seq2) + cand1 = _results[try_key] + except KeyError: + missing_frames.append(try_key) + + # Case 3: The current edge in sequence2 is deleted + try: + try_key = (seq1, head_tail2) + cand2 = _results[try_key] + except KeyError: + missing_frames.append(try_key) + + # Case 1: The LCS involves this edge + affinity = node_affinity(t1, t2) + if affinity: + try: + try_key = (head1, head2) + pval_h, new_heads = _results[try_key] + except KeyError: + missing_frames.append(try_key) + + try: + try_key = (tail1, tail2) + pval_t, new_tails = _results[try_key] + except KeyError: + missing_frames.append(try_key) + + if not missing_frames: + new_head1, new_head2 = new_heads + new_tail1, new_tail2 = new_tails + + subseq1 = a1 + new_head1 + b1 + new_tail1 + subseq2 = a2 + new_head2 + b2 + new_tail2 + + res3 = (subseq1, subseq2) + val3 = pval_h + pval_t + affinity + cand3 = (val3, res3) + else: + cand3 = (-1, None) + + if missing_frames: + # We did not solve this frame yet + stack.append(key) + stack.extend(missing_frames) + # stack.extend(missing_frames[::-1]) + else: + # We solved the frame + _results[key] = max(cand1, cand2, cand3) + + val, best = _results[key] + found = (best, val) + return found + + +def _lcs_iter_simple_alt1(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node): + """ + Depth first stack trajectory + """ + all_decomp1 = generate_all_decomp(full_seq1, open_to_close, open_to_node) + all_decomp2 = generate_all_decomp(full_seq2, open_to_close, open_to_node) + + args0 = (full_seq1, full_seq2) + frame0 = args0 + stack = [frame0] + + _results = {} + # Populate base cases + empty1 = type(next(iter(all_decomp1.keys())))() + empty2 = type(next(iter(all_decomp2.keys())))() + best = (empty1, empty2) + base_result = (0, best) + for seq1 in all_decomp1.keys(): + key1 = seq1 + t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[key1] + _results[(seq1, empty2)] = base_result + _results[(head1, empty2)] = base_result + _results[(tail1, empty2)] = base_result + _results[(head_tail1, empty2)] = base_result + + for seq2 in all_decomp2.keys(): + key2 = seq2 + t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[key2] + _results[(empty1, seq2)] = base_result + _results[(empty1, head2)] = base_result + _results[(empty1, tail2)] = base_result + _results[(empty1, head_tail2)] = base_result + + del args0 + del frame0 + del empty1 + del empty2 + del best + del base_result + + while stack: + key = stack.pop() + if key not in _results: + seq1, seq2 = key + + t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[seq1] + t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[seq2] + + # Case 2: The current edge in sequence1 is deleted + try: + try_key = (head_tail1, seq2) + cand1 = _results[try_key] + except KeyError: + stack.append(key) + stack.append(try_key) + continue + + # Case 3: The current edge in sequence2 is deleted + try: + try_key = (seq1, head_tail2) + cand2 = _results[try_key] + except KeyError: + stack.append(key) + stack.append(try_key) + continue + + # Case 1: The LCS involves this edge + affinity = node_affinity(t1, t2) + if affinity: + try: + try_key = (head1, head2) + pval_h, new_heads = _results[try_key] + except KeyError: + stack.append(key) + stack.append(try_key) + continue + + try: + try_key = (tail1, tail2) + pval_t, new_tails = _results[try_key] + except KeyError: + stack.append(key) + stack.append(try_key) + continue + + new_head1, new_head2 = new_heads + new_tail1, new_tail2 = new_tails + + subseq1 = a1 + new_head1 + b1 + new_tail1 + subseq2 = a2 + new_head2 + b2 + new_tail2 + + res3 = (subseq1, subseq2) + val3 = pval_h + pval_t + affinity + cand3 = (val3, res3) + else: + cand3 = (-1, None) + + # We solved the frame + _results[key] = max(cand1, cand2, cand3) + + val, best = _results[key] + found = (best, val) + return found + + +def _lcs_iter_prehash(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node): + """ + Version of the lcs iterative algorithm where we precompute hash values. + Uses a breadth-first trajectory. + """ + all_decomp1 = generate_all_decomp_prehash(full_seq1, open_to_close, open_to_node) + all_decomp2 = generate_all_decomp_prehash(full_seq2, open_to_close, open_to_node) + + key_decomp1 = {} + key_decomp2 = {} + _results = {} + # Populate base cases + empty1 = type(next(iter(all_decomp1.keys())))() + empty2 = type(next(iter(all_decomp2.keys())))() + empty1_key = hash(empty1) + empty2_key = hash(empty2) + best = (empty1, empty2) + base_result = (0, best) + for seq1, info1 in all_decomp1.items(): + seq1_key = hash(seq1) + head1_key, tail1_key, head_tail1_key = all_decomp1[seq1][5:8] + _results[(seq1_key, empty2_key)] = base_result + _results[(head1_key, empty2_key)] = base_result + _results[(tail1_key, empty2_key)] = base_result + _results[(head_tail1_key, empty2_key)] = base_result + key_decomp1[seq1_key] = info1 + + for seq2, info2 in all_decomp2.items(): + seq2_key = hash(seq2) + head2_key, tail2_key, head_tail2_key = all_decomp2[seq2][5:8] + _results[(empty1_key, seq2_key)] = base_result + _results[(empty1_key, head2_key)] = base_result + _results[(empty1_key, tail2_key)] = base_result + _results[(empty1_key, head_tail2_key)] = base_result + key_decomp2[seq2_key] = info2 + + full_seq1_key = hash(full_seq1) + full_seq2_key = hash(full_seq2) + key0 = (full_seq1_key, full_seq2_key) + frame0 = key0, full_seq1, full_seq2 + stack = [frame0] + missing_frames = [] + while stack: + frame = stack.pop() + key, seq1, seq2 = frame + seq1_key, seq2_key = key + if key not in _results: + missing_frames.clear() + + try: + info1 = key_decomp1[seq1_key] + except KeyError: + info1 = balanced_decomp_prehash(seq1, open_to_close) + key_decomp1[seq1_key] = info1 + tok1, seq1, head1, tail1, head_tail1, head1_key, tail1_key, head_tail1_key, a1, b1 = info1 + + try: + info2 = key_decomp2[seq2_key] + except KeyError: + info2 = balanced_decomp_prehash(seq2, open_to_close) + key_decomp2[seq2_key] = info2 + tok2, seq2, head2, tail2, head_tail2, head2_key, tail2_key, head_tail2_key, a2, b2 = info2 + + affinity = node_affinity(tok1, tok2) + + # Case 2: The current edge in sequence1 is deleted + try: + try_key = (head_tail1_key, seq2_key) + cand1 = _results[try_key] + except KeyError: + miss_frame = try_key, head_tail1, seq2 + missing_frames.append(miss_frame) + + # Case 3: The current edge in sequence2 is deleted + try: + try_key = (seq1_key, head_tail2_key) + cand2 = _results[try_key] + except KeyError: + miss_frame = try_key, seq1, head_tail2 + missing_frames.append(miss_frame) + + # Case 1: The LCS involves this edge + if affinity: + try: + try_key = (head1_key, head2_key) + pval_h, new_heads = _results[try_key] + except KeyError: + miss_frame = try_key, head1, head2 + missing_frames.append(miss_frame) + + try: + try_key = (tail1_key, tail2_key) + pval_t, new_tails = _results[try_key] + except KeyError: + miss_frame = try_key, tail1, tail2 + missing_frames.append(miss_frame) + + if not missing_frames: + new_head1, new_head2 = new_heads + new_tail1, new_tail2 = new_tails + + subseq1 = a1 + new_head1 + b1 + new_tail1 + subseq2 = a2 + new_head2 + b2 + new_tail2 + + res3 = (subseq1, subseq2) + val3 = pval_h + pval_t + affinity + cand3 = (val3, res3) + else: + cand3 = (-1, None) + + if missing_frames: + # We did not solve this frame yet + stack.append(frame) + stack.extend(missing_frames[::-1]) + else: + # We solved the frame + _results[key] = max(cand1, cand2, cand3) + + # The stack pop is our solution + (val, best) = _results[key] + found = (best, val) + return found + + +class UnbalancedException(Exception): + """ + Denotes that a sequence was unbalanced + """ + pass + + +class IdentityDict: + """ + Used when ``open_to_node`` is unspecified + """ + def __getitem__(self, key): + return key + + +def generate_all_decomp(seq, open_to_close, open_to_node=None): + """ + Generates all decompositions of a single balanced sequence by + recursive decomposition of the head, tail, and head|tail. + + Parameters + ---------- + seq : Tuple | str + a tuple of hashable items or a string where each character is an item + + open_to_close : Dict + a dictionary that maps opening tokens to closing tokens in the balanced + sequence problem. + + open_to_node : Dict + a dictionary that maps a sequence token to a token corresponding to an + original problem (e.g. a tree node) + + Returns + ------- + Dict : mapping from a sub-sequence to its decomposition + + Notes + ----- + In the paper: See Definition 2, 4, Lemma, 1, 2, 3, 4. + + Example + ------- + >>> # Example 2 in the paper (one from each column) + >>> seq = '00100100101111' + >>> open_to_close = {'0': '1'} + >>> all_decomp = generate_all_decomp(seq, open_to_close) + >>> assert len(all_decomp) == len(seq) // 2 + >>> import pprint + >>> pprint.pprint(all_decomp) + {'00100100101111': ('0', '0', '1', '010010010111', '', '010010010111'), + '0010010111': ('0', '0', '1', '01001011', '', '01001011'), + '001011': ('0', '0', '1', '0101', '', '0101'), + '01': ('0', '0', '1', '', '', ''), + '010010010111': ('0', '0', '1', '', '0010010111', '0010010111'), + '01001011': ('0', '0', '1', '', '001011', '001011'), + '0101': ('0', '0', '1', '', '01', '01')} + + Example + ------- + >>> open_to_close = {'{': '}', '(': ')', '[': ']'} + >>> seq = '({[[]]})[[][]]{{}}' + >>> all_decomp = generate_all_decomp(seq, open_to_close) + >>> node, *decomp = all_decomp[seq] + >>> pop_open, pop_close, head, tail, head_tail = decomp + >>> print('node = {!r}'.format(node)) + >>> print('pop_open = {!r}'.format(pop_open)) + >>> print('pop_close = {!r}'.format(pop_close)) + >>> print('head = {!r}'.format(head)) + >>> print('tail = {!r}'.format(tail)) + >>> print('head_tail = {!r}'.format(head_tail)) + node = '(' + pop_open = '(' + pop_close = ')' + head = '{[[]]}' + tail = '[[][]]{{}}' + head_tail = '{[[]]}[[][]]{{}}' + >>> decomp_alt = balanced_decomp(seq, open_to_close) + >>> assert decomp_alt == tuple(decomp) + + Example + ------- + >>> from netharn.initializers._nx_ext.demodata import random_balanced_sequence + >>> seq, open_to_close = random_balanced_sequence(10) + >>> all_decomp = generate_all_decomp(seq, open_to_close) + """ + if open_to_node is None: + open_to_node = IdentityDict() + all_decomp = {} + stack = [seq] + while stack: + seq = stack.pop() + if seq not in all_decomp and seq: + pop_open, pop_close, head, tail, head_tail = balanced_decomp(seq, open_to_close) + node = open_to_node[pop_open[0]] + all_decomp[seq] = (node, pop_open, pop_close, head, tail, head_tail) + if head: + if tail: + stack.append(head_tail) + stack.append(tail) + stack.append(head) + elif tail: + stack.append(tail) + return all_decomp + + +def balanced_decomp(sequence, open_to_close): + """ + Generates a decomposition of a balanced sequence. + + Parameters + ---------- + sequence : str + balanced sequence to be decomposed + + open_to_close: dict + a dictionary that maps opening tokens to closing tokens in the balanced + sequence problem. + + Returns + ------- + : tuple[T, T, T, T, T] + where ``T = type(sequence)`` + Contents of this tuple are: + + 0. a1 - a sequence of len(1) containing the current opening token + 1. b1 - a sequence of len(1) containing the current closing token + 2. head - head of the sequence + 3. tail - tail of the sequence + 4. head_tail - the concatanted head and tail + + Example + ------- + >>> # Example 3 from the paper + >>> sequence = '001000101101110001000100101110111011' + >>> open_to_close = {'0': '1'} + >>> a1, b1, head, tail, head_tail = balanced_decomp(sequence, open_to_close) + >>> print('head = {!r}'.format(head)) + >>> print('tail = {!r}'.format(tail)) + head = '010001011011' + tail = '0001000100101110111011' + + Example + ------- + >>> open_to_close = {0: 1} + >>> sequence = [0, 0, 0, 1, 1, 1, 0, 1] + >>> a1, b1, head, tail, head_tail = balanced_decomp(sequence, open_to_close) + >>> print('a1 = {!r}'.format(a1)) + >>> print('b1 = {!r}'.format(b1)) + >>> print('head = {!r}'.format(head)) + >>> print('tail = {!r}'.format(tail)) + >>> print('head_tail = {!r}'.format(head_tail)) + a1 = [0] + b1 = [1] + head = [0, 0, 1, 1] + tail = [0, 1] + head_tail = [0, 0, 1, 1, 0, 1] + >>> a2, b2, tail1, tail2, head_tail2 = balanced_decomp(tail, open_to_close) + + Example + ------- + >>> open_to_close = {'{': '}', '(': ')', '[': ']'} + >>> sequence = '({[[]]})[[][]]' + >>> a1, b1, head, tail, head_tail = balanced_decomp(sequence, open_to_close) + >>> print('a1 = {!r}'.format(a1)) + >>> print('b1 = {!r}'.format(b1)) + >>> print('head = {!r}'.format(head)) + >>> print('tail = {!r}'.format(tail)) + >>> print('head_tail = {!r}'.format(head_tail)) + a1 = '(' + b1 = ')' + head = '{[[]]}' + tail = '[[][]]' + head_tail = '{[[]]}[[][]]' + >>> a2, b2, tail1, tail2, head_tail2 = balanced_decomp(tail, open_to_close) + >>> print('a2 = {!r}'.format(a2)) + >>> print('b2 = {!r}'.format(b2)) + >>> print('tail1 = {!r}'.format(tail1)) + >>> print('tail2 = {!r}'.format(tail2)) + >>> print('head_tail2 = {!r}'.format(head_tail2)) + a2 = '[' + b2 = ']' + tail1 = '[][]' + tail2 = '' + head_tail2 = '[][]' + """ + gen = generate_balance(sequence, open_to_close) + + bal_curr, tok_curr = next(gen) + pop_open = sequence[0:1] + want_close = open_to_close[tok_curr] + + head_stop = 1 + for head_stop, (bal_curr, tok_curr) in enumerate(gen, start=1): + if tok_curr is None: + break + elif bal_curr and tok_curr == want_close: + pop_close = sequence[head_stop:head_stop + 1] + break + head = sequence[1:head_stop] + tail = sequence[head_stop + 1:] + head_tail = head + tail + return pop_open, pop_close, head, tail, head_tail + + +def generate_balance(sequence, open_to_close): + """ + Iterates through a balanced sequence and reports if the sequence-so-far + is balanced at that position or not. + + Parameters + ---------- + sequence: List[Tuple] | str: + an input balanced sequence + + open_to_close : Dict + a mapping from opening to closing tokens in the balanced sequence + + Raises + ------ + UnbalancedException - if the input sequence is not balanced + + Yields + ------ + Tuple[bool, T]: + boolean indicating if the sequence is balanced at this index, + and the current token + + Example + ------- + >>> open_to_close = {0: 1} + >>> sequence = [0, 0, 0, 1, 1, 1] + >>> gen = list(generate_balance(sequence, open_to_close)) + >>> for flag, token in gen: + >>> print('flag={:d}, token={}'.format(flag, token)) + + Example + ------- + >>> from netharn.initializers._nx_ext.demodata import random_balanced_sequence + >>> sequence, open_to_close = random_balanced_sequence(4) + >>> print('sequence = {!r}'.format(sequence)) + >>> gen = list(generate_balance(sequence, open_to_close)) + >>> for flag, token in gen: + >>> print('flag={:d}, token={}'.format(flag, token)) + """ + stack = [] + # Traversing the Expression + for token in sequence: + + if token in open_to_close: + # Push opening elements onto the stack + stack.append(token) + else: + # Check that closing elements + if not stack: + raise UnbalancedException + prev_open = stack.pop() + want_close = open_to_close[prev_open] + + if token != want_close: + raise UnbalancedException + + # If the stack is empty the sequence is currently balanced + currently_balanced = not bool(stack) + yield currently_balanced, token + + if stack: + raise UnbalancedException + + +def generate_all_decomp_prehash(seq, open_to_close, open_to_node): + """ + Like :func:`generate_all_decomp` but additionally returns the + precomputed hashes of the sequences. + """ + all_decomp = {} + stack = [seq] + while stack: + seq = stack.pop() + if seq: + # key = hash(seq) + key = seq + if key not in all_decomp: + info = balanced_decomp_prehash(seq, open_to_close, open_to_node) + head, tail, head_tail = info[2:5] + all_decomp[key] = info + stack.append(head_tail) + stack.append(head) + stack.append(tail) + return all_decomp + + +def balanced_decomp_prehash(seq, open_to_close, open_to_node): + """ + Like :func:`balanced_decomp` but additionally returns the + precomputed hashes of the sequences. + """ + pop_open, pop_close, head, tail, head_tail = balanced_decomp_unsafe(seq, open_to_close) + head_key = hash(head) + tail_key = hash(tail) + head_tail_key = hash(head_tail) + node = open_to_node[pop_open[0]] + a = pop_open + b = pop_close + info = (node, seq, head, tail, head_tail, head_key, tail_key, head_tail_key, a, b) + return info + + +def balanced_decomp_unsafe(sequence, open_to_close): + """ + Same as :func:`balanced_decomp` but assumes that ``sequence`` is valid + balanced sequence in order to execute faster. + """ + gen = generate_balance_unsafe(sequence, open_to_close) + + bal_curr, tok_curr = next(gen) + pop_open = sequence[0:1] + want_close = open_to_close[tok_curr] + + head_stop = 1 + for head_stop, (bal_curr, tok_curr) in enumerate(gen, start=1): + if bal_curr and tok_curr == want_close: + pop_close = sequence[head_stop:head_stop + 1] + break + head = sequence[1:head_stop] + tail = sequence[head_stop + 1:] + head_tail = head + tail + return pop_open, pop_close, head, tail, head_tail + + +def generate_balance_unsafe(sequence, open_to_close): + """ + Same as :func:`generate_balance` but assumes that ``sequence`` is valid + balanced sequence in order to execute faster. + """ + stacklen = 0 + for token in sequence: + if token in open_to_close: + stacklen += 1 + else: + stacklen -= 1 + yield stacklen == 0, token diff --git a/netharn/initializers/_nx_ext/balanced_sequence_cython.cpp b/netharn/initializers/_nx_ext/balanced_sequence_cython.cpp new file mode 100644 index 0000000..38e742a --- /dev/null +++ b/netharn/initializers/_nx_ext/balanced_sequence_cython.cpp @@ -0,0 +1,10787 @@ +/* Generated by Cython 0.29.20 */ + +/* BEGIN: Cython Metadata +{ + "distutils": { + "language": "c++", + "name": "networkx.algorithms.isomorphism._embedding.balanced_sequence_cython", + "sources": [ + "/home/joncrall/code/networkx/networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx" + ] + }, + "module_name": "networkx.algorithms.isomorphism._embedding.balanced_sequence_cython" +} +END: Cython Metadata */ + +#define PY_SSIZE_T_CLEAN +#include "Python.h" +#ifndef Py_PYTHON_H + #error Python headers needed to compile C extensions, please install development version of Python. +#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000) + #error Cython requires Python 2.6+ or Python 3.3+. +#else +#define CYTHON_ABI "0_29_20" +#define CYTHON_HEX_VERSION 0x001D14F0 +#define CYTHON_FUTURE_DIVISION 0 +#include +#ifndef offsetof + #define offsetof(type, member) ( (size_t) & ((type*)0) -> member ) +#endif +#if !defined(WIN32) && !defined(MS_WINDOWS) + #ifndef __stdcall + #define __stdcall + #endif + #ifndef __cdecl + #define __cdecl + #endif + #ifndef __fastcall + #define __fastcall + #endif +#endif +#ifndef DL_IMPORT + #define DL_IMPORT(t) t +#endif +#ifndef DL_EXPORT + #define DL_EXPORT(t) t +#endif +#define __PYX_COMMA , +#ifndef HAVE_LONG_LONG + #if PY_VERSION_HEX >= 0x02070000 + #define HAVE_LONG_LONG + #endif +#endif +#ifndef PY_LONG_LONG + #define PY_LONG_LONG LONG_LONG +#endif +#ifndef Py_HUGE_VAL + #define Py_HUGE_VAL HUGE_VAL +#endif +#ifdef PYPY_VERSION + #define CYTHON_COMPILING_IN_PYPY 1 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #undef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 0 + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #if PY_VERSION_HEX < 0x03050000 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #elif !defined(CYTHON_USE_ASYNC_SLOTS) + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #undef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 0 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #undef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 1 + #undef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 0 + #undef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 0 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #undef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 0 + #undef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 0 + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 +#elif defined(PYSTON_VERSION) + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 1 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #undef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 0 + #undef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 0 + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 +#else + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 1 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #if PY_VERSION_HEX < 0x02070000 + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #elif !defined(CYTHON_USE_PYTYPE_LOOKUP) + #define CYTHON_USE_PYTYPE_LOOKUP 1 + #endif + #if PY_MAJOR_VERSION < 3 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #elif !defined(CYTHON_USE_ASYNC_SLOTS) + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #if PY_VERSION_HEX < 0x02070000 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #elif !defined(CYTHON_USE_PYLONG_INTERNALS) + #define CYTHON_USE_PYLONG_INTERNALS 1 + #endif + #ifndef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 1 + #endif + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #if PY_VERSION_HEX < 0x030300F0 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #elif !defined(CYTHON_USE_UNICODE_WRITER) + #define CYTHON_USE_UNICODE_WRITER 1 + #endif + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #ifndef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 1 + #endif + #ifndef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 1 + #endif + #ifndef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000) + #endif + #ifndef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1) + #endif + #ifndef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1) + #endif + #ifndef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3) + #endif +#endif +#if !defined(CYTHON_FAST_PYCCALL) +#define CYTHON_FAST_PYCCALL (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1) +#endif +#if CYTHON_USE_PYLONG_INTERNALS + #include "longintrepr.h" + #undef SHIFT + #undef BASE + #undef MASK + #ifdef SIZEOF_VOID_P + enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) }; + #endif +#endif +#ifndef __has_attribute + #define __has_attribute(x) 0 +#endif +#ifndef __has_cpp_attribute + #define __has_cpp_attribute(x) 0 +#endif +#ifndef CYTHON_RESTRICT + #if defined(__GNUC__) + #define CYTHON_RESTRICT __restrict__ + #elif defined(_MSC_VER) && _MSC_VER >= 1400 + #define CYTHON_RESTRICT __restrict + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define CYTHON_RESTRICT restrict + #else + #define CYTHON_RESTRICT + #endif +#endif +#ifndef CYTHON_UNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +#endif +#ifndef CYTHON_MAYBE_UNUSED_VAR +# if defined(__cplusplus) + template void CYTHON_MAYBE_UNUSED_VAR( const T& ) { } +# else +# define CYTHON_MAYBE_UNUSED_VAR(x) (void)(x) +# endif +#endif +#ifndef CYTHON_NCP_UNUSED +# if CYTHON_COMPILING_IN_CPYTHON +# define CYTHON_NCP_UNUSED +# else +# define CYTHON_NCP_UNUSED CYTHON_UNUSED +# endif +#endif +#define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None) +#ifdef _MSC_VER + #ifndef _MSC_STDINT_H_ + #if _MSC_VER < 1300 + typedef unsigned char uint8_t; + typedef unsigned int uint32_t; + #else + typedef unsigned __int8 uint8_t; + typedef unsigned __int32 uint32_t; + #endif + #endif +#else + #include +#endif +#ifndef CYTHON_FALLTHROUGH + #if defined(__cplusplus) && __cplusplus >= 201103L + #if __has_cpp_attribute(fallthrough) + #define CYTHON_FALLTHROUGH [[fallthrough]] + #elif __has_cpp_attribute(clang::fallthrough) + #define CYTHON_FALLTHROUGH [[clang::fallthrough]] + #elif __has_cpp_attribute(gnu::fallthrough) + #define CYTHON_FALLTHROUGH [[gnu::fallthrough]] + #endif + #endif + #ifndef CYTHON_FALLTHROUGH + #if __has_attribute(fallthrough) + #define CYTHON_FALLTHROUGH __attribute__((fallthrough)) + #else + #define CYTHON_FALLTHROUGH + #endif + #endif + #if defined(__clang__ ) && defined(__apple_build_version__) + #if __apple_build_version__ < 7000000 + #undef CYTHON_FALLTHROUGH + #define CYTHON_FALLTHROUGH + #endif + #endif +#endif + +#ifndef __cplusplus + #error "Cython files generated with the C++ option must be compiled with a C++ compiler." +#endif +#ifndef CYTHON_INLINE + #if defined(__clang__) + #define CYTHON_INLINE __inline__ __attribute__ ((__unused__)) + #else + #define CYTHON_INLINE inline + #endif +#endif +template +void __Pyx_call_destructor(T& x) { + x.~T(); +} +template +class __Pyx_FakeReference { + public: + __Pyx_FakeReference() : ptr(NULL) { } + __Pyx_FakeReference(const T& ref) : ptr(const_cast(&ref)) { } + T *operator->() { return ptr; } + T *operator&() { return ptr; } + operator T&() { return *ptr; } + template bool operator ==(U other) { return *ptr == other; } + template bool operator !=(U other) { return *ptr != other; } + private: + T *ptr; +}; + +#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag) + #define Py_OptimizeFlag 0 +#endif +#define __PYX_BUILD_PY_SSIZE_T "n" +#define CYTHON_FORMAT_SSIZE_T "z" +#if PY_MAJOR_VERSION < 3 + #define __Pyx_BUILTIN_MODULE_NAME "__builtin__" + #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) + #define __Pyx_DefaultClassType PyClass_Type +#else + #define __Pyx_BUILTIN_MODULE_NAME "builtins" +#if PY_VERSION_HEX >= 0x030800A4 && PY_VERSION_HEX < 0x030800B2 + #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a, 0, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) +#else + #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) +#endif + #define __Pyx_DefaultClassType PyType_Type +#endif +#ifndef Py_TPFLAGS_CHECKTYPES + #define Py_TPFLAGS_CHECKTYPES 0 +#endif +#ifndef Py_TPFLAGS_HAVE_INDEX + #define Py_TPFLAGS_HAVE_INDEX 0 +#endif +#ifndef Py_TPFLAGS_HAVE_NEWBUFFER + #define Py_TPFLAGS_HAVE_NEWBUFFER 0 +#endif +#ifndef Py_TPFLAGS_HAVE_FINALIZE + #define Py_TPFLAGS_HAVE_FINALIZE 0 +#endif +#ifndef METH_STACKLESS + #define METH_STACKLESS 0 +#endif +#if PY_VERSION_HEX <= 0x030700A3 || !defined(METH_FASTCALL) + #ifndef METH_FASTCALL + #define METH_FASTCALL 0x80 + #endif + typedef PyObject *(*__Pyx_PyCFunctionFast) (PyObject *self, PyObject *const *args, Py_ssize_t nargs); + typedef PyObject *(*__Pyx_PyCFunctionFastWithKeywords) (PyObject *self, PyObject *const *args, + Py_ssize_t nargs, PyObject *kwnames); +#else + #define __Pyx_PyCFunctionFast _PyCFunctionFast + #define __Pyx_PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords +#endif +#if CYTHON_FAST_PYCCALL +#define __Pyx_PyFastCFunction_Check(func)\ + ((PyCFunction_Check(func) && (METH_FASTCALL == (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))))) +#else +#define __Pyx_PyFastCFunction_Check(func) 0 +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) + #define PyObject_Malloc(s) PyMem_Malloc(s) + #define PyObject_Free(p) PyMem_Free(p) + #define PyObject_Realloc(p) PyMem_Realloc(p) +#endif +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030400A1 + #define PyMem_RawMalloc(n) PyMem_Malloc(n) + #define PyMem_RawRealloc(p, n) PyMem_Realloc(p, n) + #define PyMem_RawFree(p) PyMem_Free(p) +#endif +#if CYTHON_COMPILING_IN_PYSTON + #define __Pyx_PyCode_HasFreeVars(co) PyCode_HasFreeVars(co) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) PyFrame_SetLineNumber(frame, lineno) +#else + #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) (frame)->f_lineno = (lineno) +#endif +#if !CYTHON_FAST_THREAD_STATE || PY_VERSION_HEX < 0x02070000 + #define __Pyx_PyThreadState_Current PyThreadState_GET() +#elif PY_VERSION_HEX >= 0x03060000 + #define __Pyx_PyThreadState_Current _PyThreadState_UncheckedGet() +#elif PY_VERSION_HEX >= 0x03000000 + #define __Pyx_PyThreadState_Current PyThreadState_GET() +#else + #define __Pyx_PyThreadState_Current _PyThreadState_Current +#endif +#if PY_VERSION_HEX < 0x030700A2 && !defined(PyThread_tss_create) && !defined(Py_tss_NEEDS_INIT) +#include "pythread.h" +#define Py_tss_NEEDS_INIT 0 +typedef int Py_tss_t; +static CYTHON_INLINE int PyThread_tss_create(Py_tss_t *key) { + *key = PyThread_create_key(); + return 0; +} +static CYTHON_INLINE Py_tss_t * PyThread_tss_alloc(void) { + Py_tss_t *key = (Py_tss_t *)PyObject_Malloc(sizeof(Py_tss_t)); + *key = Py_tss_NEEDS_INIT; + return key; +} +static CYTHON_INLINE void PyThread_tss_free(Py_tss_t *key) { + PyObject_Free(key); +} +static CYTHON_INLINE int PyThread_tss_is_created(Py_tss_t *key) { + return *key != Py_tss_NEEDS_INIT; +} +static CYTHON_INLINE void PyThread_tss_delete(Py_tss_t *key) { + PyThread_delete_key(*key); + *key = Py_tss_NEEDS_INIT; +} +static CYTHON_INLINE int PyThread_tss_set(Py_tss_t *key, void *value) { + return PyThread_set_key_value(*key, value); +} +static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { + return PyThread_get_key_value(*key); +} +#endif +#if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized) +#define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n)) +#else +#define __Pyx_PyDict_NewPresized(n) PyDict_New() +#endif +#if PY_MAJOR_VERSION >= 3 || CYTHON_FUTURE_DIVISION + #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) +#else + #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) +#endif +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 && CYTHON_USE_UNICODE_INTERNALS +#define __Pyx_PyDict_GetItemStr(dict, name) _PyDict_GetItem_KnownHash(dict, name, ((PyASCIIObject *) name)->hash) +#else +#define __Pyx_PyDict_GetItemStr(dict, name) PyDict_GetItem(dict, name) +#endif +#if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) + #define CYTHON_PEP393_ENABLED 1 + #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ + 0 : _PyUnicode_Ready((PyObject *)(op))) + #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) + #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) + #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) + #define __Pyx_PyUnicode_KIND(u) PyUnicode_KIND(u) + #define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u) + #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) + #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch) + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) +#else + #define CYTHON_PEP393_ENABLED 0 + #define PyUnicode_1BYTE_KIND 1 + #define PyUnicode_2BYTE_KIND 2 + #define PyUnicode_4BYTE_KIND 4 + #define __Pyx_PyUnicode_READY(op) (0) + #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u) + #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i])) + #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((sizeof(Py_UNICODE) == 2) ? 65535 : 1114111) + #define __Pyx_PyUnicode_KIND(u) (sizeof(Py_UNICODE)) + #define __Pyx_PyUnicode_DATA(u) ((void*)PyUnicode_AS_UNICODE(u)) + #define __Pyx_PyUnicode_READ(k, d, i) ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i])) + #define __Pyx_PyUnicode_WRITE(k, d, i, ch) (((void)(k)), ((Py_UNICODE*)d)[i] = ch) + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_SIZE(u)) +#endif +#if CYTHON_COMPILING_IN_PYPY + #define __Pyx_PyUnicode_Concat(a, b) PyNumber_Add(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) PyNumber_Add(a, b) +#else + #define __Pyx_PyUnicode_Concat(a, b) PyUnicode_Concat(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ?\ + PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b)) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyUnicode_Contains) + #define PyUnicode_Contains(u, s) PySequence_Contains(u, s) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyByteArray_Check) + #define PyByteArray_Check(obj) PyObject_TypeCheck(obj, &PyByteArray_Type) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Format) + #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt) +#endif +#define __Pyx_PyString_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyString_Check(b) && !PyString_CheckExact(b)))) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b)) +#define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyUnicode_Check(b) && !PyUnicode_CheckExact(b)))) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b)) +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyString_Format(a, b) PyUnicode_Format(a, b) +#else + #define __Pyx_PyString_Format(a, b) PyString_Format(a, b) +#endif +#if PY_MAJOR_VERSION < 3 && !defined(PyObject_ASCII) + #define PyObject_ASCII(o) PyObject_Repr(o) +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyBaseString_Type PyUnicode_Type + #define PyStringObject PyUnicodeObject + #define PyString_Type PyUnicode_Type + #define PyString_Check PyUnicode_Check + #define PyString_CheckExact PyUnicode_CheckExact +#ifndef PyObject_Unicode + #define PyObject_Unicode PyObject_Str +#endif +#endif +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj) + #define __Pyx_PyBaseString_CheckExact(obj) PyUnicode_CheckExact(obj) +#else + #define __Pyx_PyBaseString_Check(obj) (PyString_Check(obj) || PyUnicode_Check(obj)) + #define __Pyx_PyBaseString_CheckExact(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj)) +#endif +#ifndef PySet_CheckExact + #define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type) +#endif +#if PY_VERSION_HEX >= 0x030900A4 + #define __Pyx_SET_REFCNT(obj, refcnt) Py_SET_REFCNT(obj, refcnt) + #define __Pyx_SET_SIZE(obj, size) Py_SET_SIZE(obj, size) +#else + #define __Pyx_SET_REFCNT(obj, refcnt) Py_REFCNT(obj) = (refcnt) + #define __Pyx_SET_SIZE(obj, size) Py_SIZE(obj) = (size) +#endif +#if CYTHON_ASSUME_SAFE_MACROS + #define __Pyx_PySequence_SIZE(seq) Py_SIZE(seq) +#else + #define __Pyx_PySequence_SIZE(seq) PySequence_Size(seq) +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyIntObject PyLongObject + #define PyInt_Type PyLong_Type + #define PyInt_Check(op) PyLong_Check(op) + #define PyInt_CheckExact(op) PyLong_CheckExact(op) + #define PyInt_FromString PyLong_FromString + #define PyInt_FromUnicode PyLong_FromUnicode + #define PyInt_FromLong PyLong_FromLong + #define PyInt_FromSize_t PyLong_FromSize_t + #define PyInt_FromSsize_t PyLong_FromSsize_t + #define PyInt_AsLong PyLong_AsLong + #define PyInt_AS_LONG PyLong_AS_LONG + #define PyInt_AsSsize_t PyLong_AsSsize_t + #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask + #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask + #define PyNumber_Int PyNumber_Long +#endif +#if PY_MAJOR_VERSION >= 3 + #define PyBoolObject PyLongObject +#endif +#if PY_MAJOR_VERSION >= 3 && CYTHON_COMPILING_IN_PYPY + #ifndef PyUnicode_InternFromString + #define PyUnicode_InternFromString(s) PyUnicode_FromString(s) + #endif +#endif +#if PY_VERSION_HEX < 0x030200A4 + typedef long Py_hash_t; + #define __Pyx_PyInt_FromHash_t PyInt_FromLong + #define __Pyx_PyInt_AsHash_t PyInt_AsLong +#else + #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t + #define __Pyx_PyInt_AsHash_t PyInt_AsSsize_t +#endif +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyMethod_New(func, self, klass) ((self) ? PyMethod_New(func, self) : (Py_INCREF(func), func)) +#else + #define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass) +#endif +#if CYTHON_USE_ASYNC_SLOTS + #if PY_VERSION_HEX >= 0x030500B1 + #define __Pyx_PyAsyncMethodsStruct PyAsyncMethods + #define __Pyx_PyType_AsAsync(obj) (Py_TYPE(obj)->tp_as_async) + #else + #define __Pyx_PyType_AsAsync(obj) ((__Pyx_PyAsyncMethodsStruct*) (Py_TYPE(obj)->tp_reserved)) + #endif +#else + #define __Pyx_PyType_AsAsync(obj) NULL +#endif +#ifndef __Pyx_PyAsyncMethodsStruct + typedef struct { + unaryfunc am_await; + unaryfunc am_aiter; + unaryfunc am_anext; + } __Pyx_PyAsyncMethodsStruct; +#endif + +#if defined(WIN32) || defined(MS_WINDOWS) + #define _USE_MATH_DEFINES +#endif +#include +#ifdef NAN +#define __PYX_NAN() ((float) NAN) +#else +static CYTHON_INLINE float __PYX_NAN() { + float value; + memset(&value, 0xFF, sizeof(value)); + return value; +} +#endif +#if defined(__CYGWIN__) && defined(_LDBL_EQ_DBL) +#define __Pyx_truncl trunc +#else +#define __Pyx_truncl truncl +#endif + +#define __PYX_MARK_ERR_POS(f_index, lineno) \ + { __pyx_filename = __pyx_f[f_index]; (void)__pyx_filename; __pyx_lineno = lineno; (void)__pyx_lineno; __pyx_clineno = __LINE__; (void)__pyx_clineno; } +#define __PYX_ERR(f_index, lineno, Ln_error) \ + { __PYX_MARK_ERR_POS(f_index, lineno) goto Ln_error; } + +#ifndef __PYX_EXTERN_C + #ifdef __cplusplus + #define __PYX_EXTERN_C extern "C" + #else + #define __PYX_EXTERN_C extern + #endif +#endif + +#define __PYX_HAVE__networkx__algorithms__isomorphism___embedding__balanced_sequence_cython +#define __PYX_HAVE_API__networkx__algorithms__isomorphism___embedding__balanced_sequence_cython +/* Early includes */ +#ifdef _OPENMP +#include +#endif /* _OPENMP */ + +#if defined(PYREX_WITHOUT_ASSERTIONS) && !defined(CYTHON_WITHOUT_ASSERTIONS) +#define CYTHON_WITHOUT_ASSERTIONS +#endif + +typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* encoding; + const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; + +#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0 +#define __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 0 +#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT (PY_MAJOR_VERSION >= 3 && __PYX_DEFAULT_STRING_ENCODING_IS_UTF8) +#define __PYX_DEFAULT_STRING_ENCODING "" +#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString +#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize +#define __Pyx_uchar_cast(c) ((unsigned char)c) +#define __Pyx_long_cast(x) ((long)x) +#define __Pyx_fits_Py_ssize_t(v, type, is_signed) (\ + (sizeof(type) < sizeof(Py_ssize_t)) ||\ + (sizeof(type) > sizeof(Py_ssize_t) &&\ + likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX) &&\ + (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||\ + v == (type)PY_SSIZE_T_MIN))) ||\ + (sizeof(type) == sizeof(Py_ssize_t) &&\ + (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX))) ) +static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) { + return (size_t) i < (size_t) limit; +} +#if defined (__cplusplus) && __cplusplus >= 201103L + #include + #define __Pyx_sst_abs(value) std::abs(value) +#elif SIZEOF_INT >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) abs(value) +#elif SIZEOF_LONG >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) labs(value) +#elif defined (_MSC_VER) + #define __Pyx_sst_abs(value) ((Py_ssize_t)_abs64(value)) +#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define __Pyx_sst_abs(value) llabs(value) +#elif defined (__GNUC__) + #define __Pyx_sst_abs(value) __builtin_llabs(value) +#else + #define __Pyx_sst_abs(value) ((value<0) ? -value : value) +#endif +static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject*); +static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length); +#define __Pyx_PyByteArray_FromString(s) PyByteArray_FromStringAndSize((const char*)s, strlen((const char*)s)) +#define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l) +#define __Pyx_PyBytes_FromString PyBytes_FromString +#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*); +#if PY_MAJOR_VERSION < 3 + #define __Pyx_PyStr_FromString __Pyx_PyBytes_FromString + #define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize +#else + #define __Pyx_PyStr_FromString __Pyx_PyUnicode_FromString + #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize +#endif +#define __Pyx_PyBytes_AsWritableString(s) ((char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsWritableSString(s) ((signed char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsWritableUString(s) ((unsigned char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsString(s) ((const char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsSString(s) ((const signed char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsUString(s) ((const unsigned char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyObject_AsWritableString(s) ((char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsWritableSString(s) ((signed char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsWritableUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsSString(s) ((const signed char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsUString(s) ((const unsigned char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s) +#define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s) +#define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s) +#define __Pyx_PyStr_FromCString(s) __Pyx_PyStr_FromString((const char*)s) +#define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s) +static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) { + const Py_UNICODE *u_end = u; + while (*u_end++) ; + return (size_t)(u_end - u - 1); +} +#define __Pyx_PyUnicode_FromUnicode(u) PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u)) +#define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode +#define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode +#define __Pyx_NewRef(obj) (Py_INCREF(obj), obj) +#define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None) +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b); +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); +static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject*); +static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); +#define __Pyx_PySequence_Tuple(obj)\ + (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); +#if CYTHON_ASSUME_SAFE_MACROS +#define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) +#else +#define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x) +#endif +#define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x)) +#if PY_MAJOR_VERSION >= 3 +#define __Pyx_PyNumber_Int(x) (PyLong_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Long(x)) +#else +#define __Pyx_PyNumber_Int(x) (PyInt_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Int(x)) +#endif +#define __Pyx_PyNumber_Float(x) (PyFloat_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Float(x)) +#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII +static int __Pyx_sys_getdefaultencoding_not_ascii; +static int __Pyx_init_sys_getdefaultencoding_params(void) { + PyObject* sys; + PyObject* default_encoding = NULL; + PyObject* ascii_chars_u = NULL; + PyObject* ascii_chars_b = NULL; + const char* default_encoding_c; + sys = PyImport_ImportModule("sys"); + if (!sys) goto bad; + default_encoding = PyObject_CallMethod(sys, (char*) "getdefaultencoding", NULL); + Py_DECREF(sys); + if (!default_encoding) goto bad; + default_encoding_c = PyBytes_AsString(default_encoding); + if (!default_encoding_c) goto bad; + if (strcmp(default_encoding_c, "ascii") == 0) { + __Pyx_sys_getdefaultencoding_not_ascii = 0; + } else { + char ascii_chars[128]; + int c; + for (c = 0; c < 128; c++) { + ascii_chars[c] = c; + } + __Pyx_sys_getdefaultencoding_not_ascii = 1; + ascii_chars_u = PyUnicode_DecodeASCII(ascii_chars, 128, NULL); + if (!ascii_chars_u) goto bad; + ascii_chars_b = PyUnicode_AsEncodedString(ascii_chars_u, default_encoding_c, NULL); + if (!ascii_chars_b || !PyBytes_Check(ascii_chars_b) || memcmp(ascii_chars, PyBytes_AS_STRING(ascii_chars_b), 128) != 0) { + PyErr_Format( + PyExc_ValueError, + "This module compiled with c_string_encoding=ascii, but default encoding '%.200s' is not a superset of ascii.", + default_encoding_c); + goto bad; + } + Py_DECREF(ascii_chars_u); + Py_DECREF(ascii_chars_b); + } + Py_DECREF(default_encoding); + return 0; +bad: + Py_XDECREF(default_encoding); + Py_XDECREF(ascii_chars_u); + Py_XDECREF(ascii_chars_b); + return -1; +} +#endif +#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3 +#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL) +#else +#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL) +#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT +static char* __PYX_DEFAULT_STRING_ENCODING; +static int __Pyx_init_sys_getdefaultencoding_params(void) { + PyObject* sys; + PyObject* default_encoding = NULL; + char* default_encoding_c; + sys = PyImport_ImportModule("sys"); + if (!sys) goto bad; + default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL); + Py_DECREF(sys); + if (!default_encoding) goto bad; + default_encoding_c = PyBytes_AsString(default_encoding); + if (!default_encoding_c) goto bad; + __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c) + 1); + if (!__PYX_DEFAULT_STRING_ENCODING) goto bad; + strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c); + Py_DECREF(default_encoding); + return 0; +bad: + Py_XDECREF(default_encoding); + return -1; +} +#endif +#endif + + +/* Test for GCC > 2.95 */ +#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))) + #define likely(x) __builtin_expect(!!(x), 1) + #define unlikely(x) __builtin_expect(!!(x), 0) +#else /* !__GNUC__ or GCC < 2.95 */ + #define likely(x) (x) + #define unlikely(x) (x) +#endif /* __GNUC__ */ +static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; } + +static PyObject *__pyx_m = NULL; +static PyObject *__pyx_d; +static PyObject *__pyx_b; +static PyObject *__pyx_cython_runtime = NULL; +static PyObject *__pyx_empty_tuple; +static PyObject *__pyx_empty_bytes; +static PyObject *__pyx_empty_unicode; +static int __pyx_lineno; +static int __pyx_clineno = 0; +static const char * __pyx_cfilenm= __FILE__; +static const char *__pyx_filename; + + +static const char *__pyx_f[] = { + "_embedding/balanced_sequence_cython.pyx", +}; + +/*--- Type declarations ---*/ +struct __pyx_opt_args_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython; + +/* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":280 + * + * + * cdef generate_all_decomp_cython(seq, open_to_close, open_to_node=None): # <<<<<<<<<<<<<< + * """ + * Cython version of :func:`generate_all_decomp`. + */ +struct __pyx_opt_args_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython { + int __pyx_n; + PyObject *open_to_node; +}; + +/* --- Runtime support code (head) --- */ +/* Refnanny.proto */ +#ifndef CYTHON_REFNANNY + #define CYTHON_REFNANNY 0 +#endif +#if CYTHON_REFNANNY + typedef struct { + void (*INCREF)(void*, PyObject*, int); + void (*DECREF)(void*, PyObject*, int); + void (*GOTREF)(void*, PyObject*, int); + void (*GIVEREF)(void*, PyObject*, int); + void* (*SetupContext)(const char*, int, const char*); + void (*FinishContext)(void**); + } __Pyx_RefNannyAPIStruct; + static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; + static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); + #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL; +#ifdef WITH_THREAD + #define __Pyx_RefNannySetupContext(name, acquire_gil)\ + if (acquire_gil) {\ + PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ + PyGILState_Release(__pyx_gilstate_save);\ + } else {\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ + } +#else + #define __Pyx_RefNannySetupContext(name, acquire_gil)\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) +#endif + #define __Pyx_RefNannyFinishContext()\ + __Pyx_RefNanny->FinishContext(&__pyx_refnanny) + #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__) + #define __Pyx_XINCREF(r) do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0) + #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0) + #define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0) + #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0) +#else + #define __Pyx_RefNannyDeclarations + #define __Pyx_RefNannySetupContext(name, acquire_gil) + #define __Pyx_RefNannyFinishContext() + #define __Pyx_INCREF(r) Py_INCREF(r) + #define __Pyx_DECREF(r) Py_DECREF(r) + #define __Pyx_GOTREF(r) + #define __Pyx_GIVEREF(r) + #define __Pyx_XINCREF(r) Py_XINCREF(r) + #define __Pyx_XDECREF(r) Py_XDECREF(r) + #define __Pyx_XGOTREF(r) + #define __Pyx_XGIVEREF(r) +#endif +#define __Pyx_XDECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_XDECREF(tmp);\ + } while (0) +#define __Pyx_DECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_DECREF(tmp);\ + } while (0) +#define __Pyx_CLEAR(r) do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0) +#define __Pyx_XCLEAR(r) do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0) + +/* PyObjectGetAttrStr.proto */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name); +#else +#define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n) +#endif + +/* GetBuiltinName.proto */ +static PyObject *__Pyx_GetBuiltinName(PyObject *name); + +/* RaiseArgTupleInvalid.proto */ +static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, + Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); + +/* RaiseDoubleKeywords.proto */ +static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name); + +/* ParseKeywords.proto */ +static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],\ + PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,\ + const char* function_name); + +/* PyDictVersioning.proto */ +#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS +#define __PYX_DICT_VERSION_INIT ((PY_UINT64_T) -1) +#define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag) +#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\ + (version_var) = __PYX_GET_DICT_VERSION(dict);\ + (cache_var) = (value); +#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\ + static PY_UINT64_T __pyx_dict_version = 0;\ + static PyObject *__pyx_dict_cached_value = NULL;\ + if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\ + (VAR) = __pyx_dict_cached_value;\ + } else {\ + (VAR) = __pyx_dict_cached_value = (LOOKUP);\ + __pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\ + }\ +} +static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj); +static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj); +static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version); +#else +#define __PYX_GET_DICT_VERSION(dict) (0) +#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var) +#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP); +#endif + +/* GetModuleGlobalName.proto */ +#if CYTHON_USE_DICT_VERSIONS +#define __Pyx_GetModuleGlobalName(var, name) {\ + static PY_UINT64_T __pyx_dict_version = 0;\ + static PyObject *__pyx_dict_cached_value = NULL;\ + (var) = (likely(__pyx_dict_version == __PYX_GET_DICT_VERSION(__pyx_d))) ?\ + (likely(__pyx_dict_cached_value) ? __Pyx_NewRef(__pyx_dict_cached_value) : __Pyx_GetBuiltinName(name)) :\ + __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ +} +#define __Pyx_GetModuleGlobalNameUncached(var, name) {\ + PY_UINT64_T __pyx_dict_version;\ + PyObject *__pyx_dict_cached_value;\ + (var) = __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ +} +static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value); +#else +#define __Pyx_GetModuleGlobalName(var, name) (var) = __Pyx__GetModuleGlobalName(name) +#define __Pyx_GetModuleGlobalNameUncached(var, name) (var) = __Pyx__GetModuleGlobalName(name) +static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name); +#endif + +/* PyFunctionFastCall.proto */ +#if CYTHON_FAST_PYCALL +#define __Pyx_PyFunction_FastCall(func, args, nargs)\ + __Pyx_PyFunction_FastCallDict((func), (args), (nargs), NULL) +#if 1 || PY_VERSION_HEX < 0x030600B1 +static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs); +#else +#define __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs) _PyFunction_FastCallDict(func, args, nargs, kwargs) +#endif +#define __Pyx_BUILD_ASSERT_EXPR(cond)\ + (sizeof(char [1 - 2*!(cond)]) - 1) +#ifndef Py_MEMBER_SIZE +#define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) +#endif + static size_t __pyx_pyframe_localsplus_offset = 0; + #include "frameobject.h" + #define __Pxy_PyFrame_Initialize_Offsets()\ + ((void)__Pyx_BUILD_ASSERT_EXPR(sizeof(PyFrameObject) == offsetof(PyFrameObject, f_localsplus) + Py_MEMBER_SIZE(PyFrameObject, f_localsplus)),\ + (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus))) + #define __Pyx_PyFrame_GetLocalsplus(frame)\ + (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset)) +#endif + +/* PyObjectCall.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw); +#else +#define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw) +#endif + +/* PyObjectCallMethO.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg); +#endif + +/* PyObjectCallNoArg.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func); +#else +#define __Pyx_PyObject_CallNoArg(func) __Pyx_PyObject_Call(func, __pyx_empty_tuple, NULL) +#endif + +/* PyCFunctionFastCall.proto */ +#if CYTHON_FAST_PYCCALL +static CYTHON_INLINE PyObject *__Pyx_PyCFunction_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs); +#else +#define __Pyx_PyCFunction_FastCall(func, args, nargs) (assert(0), NULL) +#endif + +/* PyObjectCallOneArg.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg); + +/* PyThreadStateGet.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyThreadState_declare PyThreadState *__pyx_tstate; +#define __Pyx_PyThreadState_assign __pyx_tstate = __Pyx_PyThreadState_Current; +#define __Pyx_PyErr_Occurred() __pyx_tstate->curexc_type +#else +#define __Pyx_PyThreadState_declare +#define __Pyx_PyThreadState_assign +#define __Pyx_PyErr_Occurred() PyErr_Occurred() +#endif + +/* PyErrFetchRestore.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyErr_Clear() __Pyx_ErrRestore(NULL, NULL, NULL) +#define __Pyx_ErrRestoreWithState(type, value, tb) __Pyx_ErrRestoreInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) __Pyx_ErrFetchInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) __Pyx_ErrRestoreInState(__pyx_tstate, type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) __Pyx_ErrFetchInState(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_PyErr_SetNone(exc) (Py_INCREF(exc), __Pyx_ErrRestore((exc), NULL, NULL)) +#else +#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) +#endif +#else +#define __Pyx_PyErr_Clear() PyErr_Clear() +#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) +#define __Pyx_ErrRestoreWithState(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) PyErr_Fetch(type, value, tb) +#define __Pyx_ErrRestoreInState(tstate, type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetchInState(tstate, type, value, tb) PyErr_Fetch(type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) PyErr_Fetch(type, value, tb) +#endif + +/* IterNext.proto */ +#define __Pyx_PyIter_Next(obj) __Pyx_PyIter_Next2(obj, NULL) +static CYTHON_INLINE PyObject *__Pyx_PyIter_Next2(PyObject *, PyObject *); + +/* GetItemInt.proto */ +#define __Pyx_GetItemInt(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ + (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ + __Pyx_GetItemInt_Fast(o, (Py_ssize_t)i, is_list, wraparound, boundscheck) :\ + (is_list ? (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL) :\ + __Pyx_GetItemInt_Generic(o, to_py_func(i)))) +#define __Pyx_GetItemInt_List(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ + (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ + __Pyx_GetItemInt_List_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) :\ + (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL)) +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, + int wraparound, int boundscheck); +#define __Pyx_GetItemInt_Tuple(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ + (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ + __Pyx_GetItemInt_Tuple_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) :\ + (PyErr_SetString(PyExc_IndexError, "tuple index out of range"), (PyObject*)NULL)) +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, + int wraparound, int boundscheck); +static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j); +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, + int is_list, int wraparound, int boundscheck); + +/* ObjectGetItem.proto */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject* key); +#else +#define __Pyx_PyObject_GetItem(obj, key) PyObject_GetItem(obj, key) +#endif + +/* RaiseTooManyValuesToUnpack.proto */ +static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected); + +/* RaiseNeedMoreValuesToUnpack.proto */ +static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index); + +/* IterFinish.proto */ +static CYTHON_INLINE int __Pyx_IterFinish(void); + +/* UnpackItemEndCheck.proto */ +static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected); + +/* PyDictContains.proto */ +static CYTHON_INLINE int __Pyx_PyDict_ContainsTF(PyObject* item, PyObject* dict, int eq) { + int result = PyDict_Contains(dict, item); + return unlikely(result < 0) ? result : (result == (eq == Py_EQ)); +} + +/* DictGetItem.proto */ +#if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY +static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key); +#define __Pyx_PyObject_Dict_GetItem(obj, name)\ + (likely(PyDict_CheckExact(obj)) ?\ + __Pyx_PyDict_GetItem(obj, name) : PyObject_GetItem(obj, name)) +#else +#define __Pyx_PyDict_GetItem(d, key) PyObject_GetItem(d, key) +#define __Pyx_PyObject_Dict_GetItem(obj, name) PyObject_GetItem(obj, name) +#endif + +/* ListAppend.proto */ +#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS +static CYTHON_INLINE int __Pyx_PyList_Append(PyObject* list, PyObject* x) { + PyListObject* L = (PyListObject*) list; + Py_ssize_t len = Py_SIZE(list); + if (likely(L->allocated > len) & likely(len > (L->allocated >> 1))) { + Py_INCREF(x); + PyList_SET_ITEM(list, len, x); + __Pyx_SET_SIZE(list, len + 1); + return 0; + } + return PyList_Append(list, x); +} +#else +#define __Pyx_PyList_Append(L,x) PyList_Append(L,x) +#endif + +/* PyObjectGetMethod.proto */ +static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method); + +/* PyObjectCallMethod0.proto */ +static PyObject* __Pyx_PyObject_CallMethod0(PyObject* obj, PyObject* method_name); + +/* pop.proto */ +static CYTHON_INLINE PyObject* __Pyx__PyObject_Pop(PyObject* L); +#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS +static CYTHON_INLINE PyObject* __Pyx_PyList_Pop(PyObject* L); +#define __Pyx_PyObject_Pop(L) (likely(PyList_CheckExact(L)) ?\ + __Pyx_PyList_Pop(L) : __Pyx__PyObject_Pop(L)) +#else +#define __Pyx_PyList_Pop(L) __Pyx__PyObject_Pop(L) +#define __Pyx_PyObject_Pop(L) __Pyx__PyObject_Pop(L) +#endif + +/* UnpackUnboundCMethod.proto */ +typedef struct { + PyObject *type; + PyObject **method_name; + PyCFunction func; + PyObject *method; + int flag; +} __Pyx_CachedCFunction; + +/* CallUnboundCMethod0.proto */ +static PyObject* __Pyx__CallUnboundCMethod0(__Pyx_CachedCFunction* cfunc, PyObject* self); +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_CallUnboundCMethod0(cfunc, self)\ + (likely((cfunc)->func) ?\ + (likely((cfunc)->flag == METH_NOARGS) ? (*((cfunc)->func))(self, NULL) :\ + (PY_VERSION_HEX >= 0x030600B1 && likely((cfunc)->flag == METH_FASTCALL) ?\ + (PY_VERSION_HEX >= 0x030700A0 ?\ + (*(__Pyx_PyCFunctionFast)(void*)(PyCFunction)(cfunc)->func)(self, &__pyx_empty_tuple, 0) :\ + (*(__Pyx_PyCFunctionFastWithKeywords)(void*)(PyCFunction)(cfunc)->func)(self, &__pyx_empty_tuple, 0, NULL)) :\ + (PY_VERSION_HEX >= 0x030700A0 && (cfunc)->flag == (METH_FASTCALL | METH_KEYWORDS) ?\ + (*(__Pyx_PyCFunctionFastWithKeywords)(void*)(PyCFunction)(cfunc)->func)(self, &__pyx_empty_tuple, 0, NULL) :\ + (likely((cfunc)->flag == (METH_VARARGS | METH_KEYWORDS)) ? ((*(PyCFunctionWithKeywords)(void*)(PyCFunction)(cfunc)->func)(self, __pyx_empty_tuple, NULL)) :\ + ((cfunc)->flag == METH_VARARGS ? (*((cfunc)->func))(self, __pyx_empty_tuple) :\ + __Pyx__CallUnboundCMethod0(cfunc, self)))))) :\ + __Pyx__CallUnboundCMethod0(cfunc, self)) +#else +#define __Pyx_CallUnboundCMethod0(cfunc, self) __Pyx__CallUnboundCMethod0(cfunc, self) +#endif + +/* py_dict_keys.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyDict_Keys(PyObject* d); + +/* py_dict_items.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyDict_Items(PyObject* d); + +/* SliceObject.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetSlice( + PyObject* obj, Py_ssize_t cstart, Py_ssize_t cstop, + PyObject** py_start, PyObject** py_stop, PyObject** py_slice, + int has_cstart, int has_cstop, int wraparound); + +/* RaiseNoneIterError.proto */ +static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void); + +/* None.proto */ +static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname); + +/* SliceTupleAndList.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyList_GetSlice(PyObject* src, Py_ssize_t start, Py_ssize_t stop); +static CYTHON_INLINE PyObject* __Pyx_PyTuple_GetSlice(PyObject* src, Py_ssize_t start, Py_ssize_t stop); +#else +#define __Pyx_PyList_GetSlice(seq, start, stop) PySequence_GetSlice(seq, start, stop) +#define __Pyx_PyTuple_GetSlice(seq, start, stop) PySequence_GetSlice(seq, start, stop) +#endif + +/* FetchCommonType.proto */ +static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type); + +/* CythonFunctionShared.proto */ +#define __Pyx_CyFunction_USED 1 +#define __Pyx_CYFUNCTION_STATICMETHOD 0x01 +#define __Pyx_CYFUNCTION_CLASSMETHOD 0x02 +#define __Pyx_CYFUNCTION_CCLASS 0x04 +#define __Pyx_CyFunction_GetClosure(f)\ + (((__pyx_CyFunctionObject *) (f))->func_closure) +#define __Pyx_CyFunction_GetClassObj(f)\ + (((__pyx_CyFunctionObject *) (f))->func_classobj) +#define __Pyx_CyFunction_Defaults(type, f)\ + ((type *)(((__pyx_CyFunctionObject *) (f))->defaults)) +#define __Pyx_CyFunction_SetDefaultsGetter(f, g)\ + ((__pyx_CyFunctionObject *) (f))->defaults_getter = (g) +typedef struct { + PyCFunctionObject func; +#if PY_VERSION_HEX < 0x030500A0 + PyObject *func_weakreflist; +#endif + PyObject *func_dict; + PyObject *func_name; + PyObject *func_qualname; + PyObject *func_doc; + PyObject *func_globals; + PyObject *func_code; + PyObject *func_closure; + PyObject *func_classobj; + void *defaults; + int defaults_pyobjects; + size_t defaults_size; // used by FusedFunction for copying defaults + int flags; + PyObject *defaults_tuple; + PyObject *defaults_kwdict; + PyObject *(*defaults_getter)(PyObject *); + PyObject *func_annotations; +} __pyx_CyFunctionObject; +static PyTypeObject *__pyx_CyFunctionType = 0; +#define __Pyx_CyFunction_Check(obj) (__Pyx_TypeCheck(obj, __pyx_CyFunctionType)) +static PyObject *__Pyx_CyFunction_Init(__pyx_CyFunctionObject* op, PyMethodDef *ml, + int flags, PyObject* qualname, + PyObject *self, + PyObject *module, PyObject *globals, + PyObject* code); +static CYTHON_INLINE void *__Pyx_CyFunction_InitDefaults(PyObject *m, + size_t size, + int pyobjects); +static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsTuple(PyObject *m, + PyObject *tuple); +static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsKwDict(PyObject *m, + PyObject *dict); +static CYTHON_INLINE void __Pyx_CyFunction_SetAnnotationsDict(PyObject *m, + PyObject *dict); +static int __pyx_CyFunction_init(void); + +/* CythonFunction.proto */ +static PyObject *__Pyx_CyFunction_New(PyMethodDef *ml, + int flags, PyObject* qualname, + PyObject *closure, + PyObject *module, PyObject *globals, + PyObject* code); + +/* SetNameInClass.proto */ +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 +#define __Pyx_SetNameInClass(ns, name, value)\ + (likely(PyDict_CheckExact(ns)) ? _PyDict_SetItem_KnownHash(ns, name, value, ((PyASCIIObject *) name)->hash) : PyObject_SetItem(ns, name, value)) +#elif CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_SetNameInClass(ns, name, value)\ + (likely(PyDict_CheckExact(ns)) ? PyDict_SetItem(ns, name, value) : PyObject_SetItem(ns, name, value)) +#else +#define __Pyx_SetNameInClass(ns, name, value) PyObject_SetItem(ns, name, value) +#endif + +/* CalculateMetaclass.proto */ +static PyObject *__Pyx_CalculateMetaclass(PyTypeObject *metaclass, PyObject *bases); + +/* Py3ClassCreate.proto */ +static PyObject *__Pyx_Py3MetaclassPrepare(PyObject *metaclass, PyObject *bases, PyObject *name, PyObject *qualname, + PyObject *mkw, PyObject *modname, PyObject *doc); +static PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObject *bases, PyObject *dict, + PyObject *mkw, int calculate_metaclass, int allow_py2_metaclass); + +/* CLineInTraceback.proto */ +#ifdef CYTHON_CLINE_IN_TRACEBACK +#define __Pyx_CLineForTraceback(tstate, c_line) (((CYTHON_CLINE_IN_TRACEBACK)) ? c_line : 0) +#else +static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line); +#endif + +/* CodeObjectCache.proto */ +typedef struct { + PyCodeObject* code_object; + int code_line; +} __Pyx_CodeObjectCacheEntry; +struct __Pyx_CodeObjectCache { + int count; + int max_count; + __Pyx_CodeObjectCacheEntry* entries; +}; +static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL}; +static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line); +static PyCodeObject *__pyx_find_code_object(int code_line); +static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object); + +/* AddTraceback.proto */ +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename); + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value); + +/* CIntFromPy.proto */ +static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *); + +/* CIntFromPy.proto */ +static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *); + +/* FastTypeChecks.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type) +static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2); +#else +#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) +#define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type) +#define __Pyx_PyErr_GivenExceptionMatches2(err, type1, type2) (PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2)) +#endif +#define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception) + +/* CheckBinaryVersion.proto */ +static int __Pyx_check_binary_version(void); + +/* InitStrings.proto */ +static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); + + +/* Module declarations from 'networkx.algorithms.isomorphism._embedding.balanced_sequence_cython' */ +static PyObject *__pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_balanced_decomp_unsafe_cython(PyObject *, PyObject *); /*proto*/ +static PyObject *__pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython(PyObject *, PyObject *, struct __pyx_opt_args_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython *__pyx_optional_args); /*proto*/ +static PyObject *__pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_balanced_decomp_prehash_cython(PyObject *, PyObject *, PyObject *); /*proto*/ +static PyObject *__pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_prehash_cython(PyObject *, PyObject *, PyObject *); /*proto*/ +#define __Pyx_MODULE_NAME "networkx.algorithms.isomorphism._embedding.balanced_sequence_cython" +extern int __pyx_module_is_main_networkx__algorithms__isomorphism___embedding__balanced_sequence_cython; +int __pyx_module_is_main_networkx__algorithms__isomorphism___embedding__balanced_sequence_cython = 0; + +/* Implementation of 'networkx.algorithms.isomorphism._embedding.balanced_sequence_cython' */ +static PyObject *__pyx_builtin_range; +static const char __pyx_k_a1[] = "a1"; +static const char __pyx_k_a2[] = "a2"; +static const char __pyx_k_b1[] = "b1"; +static const char __pyx_k_b2[] = "b2"; +static const char __pyx_k_t1[] = "t1"; +static const char __pyx_k_t2[] = "t2"; +static const char __pyx_k_doc[] = "__doc__"; +static const char __pyx_k_key[] = "key"; +static const char __pyx_k_pop[] = "pop"; +static const char __pyx_k_val[] = "val"; +static const char __pyx_k_best[] = "best"; +static const char __pyx_k_key0[] = "key0"; +static const char __pyx_k_key1[] = "key1"; +static const char __pyx_k_key2[] = "key2"; +static const char __pyx_k_keys[] = "keys"; +static const char __pyx_k_main[] = "__main__"; +static const char __pyx_k_name[] = "__name__"; +static const char __pyx_k_res3[] = "res3"; +static const char __pyx_k_self[] = "self"; +static const char __pyx_k_seq1[] = "seq1"; +static const char __pyx_k_seq2[] = "seq2"; +static const char __pyx_k_test[] = "__test__"; +static const char __pyx_k_tok1[] = "tok1"; +static const char __pyx_k_tok2[] = "tok2"; +static const char __pyx_k_val3[] = "val3"; +static const char __pyx_k_cand1[] = "cand1"; +static const char __pyx_k_cand2[] = "cand2"; +static const char __pyx_k_cand3[] = "cand3"; +static const char __pyx_k_found[] = "found"; +static const char __pyx_k_frame[] = "frame"; +static const char __pyx_k_head1[] = "head1"; +static const char __pyx_k_head2[] = "head2"; +static const char __pyx_k_info1[] = "info1"; +static const char __pyx_k_info2[] = "info2"; +static const char __pyx_k_items[] = "items"; +static const char __pyx_k_range[] = "range"; +static const char __pyx_k_stack[] = "stack"; +static const char __pyx_k_tail1[] = "tail1"; +static const char __pyx_k_tail2[] = "tail2"; +static const char __pyx_k_empty1[] = "empty1"; +static const char __pyx_k_empty2[] = "empty2"; +static const char __pyx_k_frame0[] = "frame0"; +static const char __pyx_k_module[] = "__module__"; +static const char __pyx_k_pval_h[] = "pval_h"; +static const char __pyx_k_pval_t[] = "pval_t"; +static const char __pyx_k_getitem[] = "__getitem__"; +static const char __pyx_k_prepare[] = "__prepare__"; +static const char __pyx_k_results[] = "_results"; +static const char __pyx_k_subseq1[] = "subseq1"; +static const char __pyx_k_subseq2[] = "subseq2"; +static const char __pyx_k_try_key[] = "try_key"; +static const char __pyx_k_affinity[] = "affinity"; +static const char __pyx_k_qualname[] = "__qualname__"; +static const char __pyx_k_seq1_key[] = "seq1_key"; +static const char __pyx_k_seq2_key[] = "seq2_key"; +static const char __pyx_k_full_seq1[] = "full_seq1"; +static const char __pyx_k_full_seq2[] = "full_seq2"; +static const char __pyx_k_head1_key[] = "head1_key"; +static const char __pyx_k_head2_key[] = "head2_key"; +static const char __pyx_k_metaclass[] = "__metaclass__"; +static const char __pyx_k_new_head1[] = "new_head1"; +static const char __pyx_k_new_head2[] = "new_head2"; +static const char __pyx_k_new_heads[] = "new_heads"; +static const char __pyx_k_new_tail1[] = "new_tail1"; +static const char __pyx_k_new_tail2[] = "new_tail2"; +static const char __pyx_k_new_tails[] = "new_tails"; +static const char __pyx_k_tail1_key[] = "tail1_key"; +static const char __pyx_k_tail2_key[] = "tail2_key"; +static const char __pyx_k_empty1_key[] = "empty1_key"; +static const char __pyx_k_empty2_key[] = "empty2_key"; +static const char __pyx_k_head_tail1[] = "head_tail1"; +static const char __pyx_k_head_tail2[] = "head_tail2"; +static const char __pyx_k_miss_frame[] = "miss_frame"; +static const char __pyx_k_all_decomp1[] = "all_decomp1"; +static const char __pyx_k_all_decomp2[] = "all_decomp2"; +static const char __pyx_k_base_result[] = "base_result"; +static const char __pyx_k_key_decomp1[] = "key_decomp1"; +static const char __pyx_k_key_decomp2[] = "key_decomp2"; +static const char __pyx_k_IdentityDict[] = "IdentityDict"; +static const char __pyx_k_open_to_node[] = "open_to_node"; +static const char __pyx_k_full_seq1_key[] = "full_seq1_key"; +static const char __pyx_k_full_seq2_key[] = "full_seq2_key"; +static const char __pyx_k_node_affinity[] = "node_affinity"; +static const char __pyx_k_open_to_close[] = "open_to_close"; +static const char __pyx_k_head_tail1_key[] = "head_tail1_key"; +static const char __pyx_k_head_tail2_key[] = "head_tail2_key"; +static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback"; +static const char __pyx_k_IdentityDict___getitem[] = "IdentityDict.__getitem__"; +static const char __pyx_k_lcs_iter_prehash2_cython[] = "_lcs_iter_prehash2_cython"; +static const char __pyx_k_lcs_iter_simple_alt2_cython[] = "_lcs_iter_simple_alt2_cython"; +static const char __pyx_k_This_module_re_implements_funct[] = "\nThis module re-implements functions in :module:`balanced_sequence` in cython\nand obtains 40-50x speedups in common circumstances. There are likely more\nspeed improvements that could be made.\n\nCommandLine\n-----------\n# Explicitly build this cython module\ncythonize -a -i $HOME/code/networkx/networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx\n\n\nExamples\n--------\n>>> from networkx.algorithms.isomorphism._embedding.balanced_sequence_cython import *\n>>> from networkx.algorithms.isomorphism._embedding.demodata import random_balanced_sequence\n>>> seq1, open_to_close1 = random_balanced_sequence(300, mode='paren')\n>>> seq2, open_to_close2 = random_balanced_sequence(300, mode='paren')\n>>> open_to_close = {**open_to_close1, **open_to_close2}\n>>> full_seq1 = seq1\n>>> full_seq2 = seq2\n>>> import operator\n>>> node_affinity = operator.eq\n>>> open_to_node = IdentityDict()\n\nwith ub.Timer('cython'):\n best, value = _lcs_iter_simple_alt2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node)\n\nwith ub.Timer('python'):\n best, value = _lcs_iter_simple_alt2(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node)\n\n"; +static const char __pyx_k_Used_when_open_to_node_is_unspe[] = " Used when ``open_to_node`` is unspecified "; +static const char __pyx_k_embedding_balanced_sequence_cyt[] = "_embedding/balanced_sequence_cython.pyx"; +static const char __pyx_k_networkx_algorithms_isomorphism[] = "networkx.algorithms.isomorphism._embedding.balanced_sequence_cython"; +static PyObject *__pyx_n_s_IdentityDict; +static PyObject *__pyx_n_s_IdentityDict___getitem; +static PyObject *__pyx_kp_s_Used_when_open_to_node_is_unspe; +static PyObject *__pyx_n_s_a1; +static PyObject *__pyx_n_s_a2; +static PyObject *__pyx_n_s_affinity; +static PyObject *__pyx_n_s_all_decomp1; +static PyObject *__pyx_n_s_all_decomp2; +static PyObject *__pyx_n_s_b1; +static PyObject *__pyx_n_s_b2; +static PyObject *__pyx_n_s_base_result; +static PyObject *__pyx_n_s_best; +static PyObject *__pyx_n_s_cand1; +static PyObject *__pyx_n_s_cand2; +static PyObject *__pyx_n_s_cand3; +static PyObject *__pyx_n_s_cline_in_traceback; +static PyObject *__pyx_n_s_doc; +static PyObject *__pyx_kp_s_embedding_balanced_sequence_cyt; +static PyObject *__pyx_n_s_empty1; +static PyObject *__pyx_n_s_empty1_key; +static PyObject *__pyx_n_s_empty2; +static PyObject *__pyx_n_s_empty2_key; +static PyObject *__pyx_n_s_found; +static PyObject *__pyx_n_s_frame; +static PyObject *__pyx_n_s_frame0; +static PyObject *__pyx_n_s_full_seq1; +static PyObject *__pyx_n_s_full_seq1_key; +static PyObject *__pyx_n_s_full_seq2; +static PyObject *__pyx_n_s_full_seq2_key; +static PyObject *__pyx_n_s_getitem; +static PyObject *__pyx_n_s_head1; +static PyObject *__pyx_n_s_head1_key; +static PyObject *__pyx_n_s_head2; +static PyObject *__pyx_n_s_head2_key; +static PyObject *__pyx_n_s_head_tail1; +static PyObject *__pyx_n_s_head_tail1_key; +static PyObject *__pyx_n_s_head_tail2; +static PyObject *__pyx_n_s_head_tail2_key; +static PyObject *__pyx_n_s_info1; +static PyObject *__pyx_n_s_info2; +static PyObject *__pyx_n_s_items; +static PyObject *__pyx_n_s_key; +static PyObject *__pyx_n_s_key0; +static PyObject *__pyx_n_s_key1; +static PyObject *__pyx_n_s_key2; +static PyObject *__pyx_n_s_key_decomp1; +static PyObject *__pyx_n_s_key_decomp2; +static PyObject *__pyx_n_s_keys; +static PyObject *__pyx_n_s_lcs_iter_prehash2_cython; +static PyObject *__pyx_n_s_lcs_iter_simple_alt2_cython; +static PyObject *__pyx_n_s_main; +static PyObject *__pyx_n_s_metaclass; +static PyObject *__pyx_n_s_miss_frame; +static PyObject *__pyx_n_s_module; +static PyObject *__pyx_n_s_name; +static PyObject *__pyx_n_s_networkx_algorithms_isomorphism; +static PyObject *__pyx_n_s_new_head1; +static PyObject *__pyx_n_s_new_head2; +static PyObject *__pyx_n_s_new_heads; +static PyObject *__pyx_n_s_new_tail1; +static PyObject *__pyx_n_s_new_tail2; +static PyObject *__pyx_n_s_new_tails; +static PyObject *__pyx_n_s_node_affinity; +static PyObject *__pyx_n_s_open_to_close; +static PyObject *__pyx_n_s_open_to_node; +static PyObject *__pyx_n_s_pop; +static PyObject *__pyx_n_s_prepare; +static PyObject *__pyx_n_s_pval_h; +static PyObject *__pyx_n_s_pval_t; +static PyObject *__pyx_n_s_qualname; +static PyObject *__pyx_n_s_range; +static PyObject *__pyx_n_s_res3; +static PyObject *__pyx_n_s_results; +static PyObject *__pyx_n_s_self; +static PyObject *__pyx_n_s_seq1; +static PyObject *__pyx_n_s_seq1_key; +static PyObject *__pyx_n_s_seq2; +static PyObject *__pyx_n_s_seq2_key; +static PyObject *__pyx_n_s_stack; +static PyObject *__pyx_n_s_subseq1; +static PyObject *__pyx_n_s_subseq2; +static PyObject *__pyx_n_s_t1; +static PyObject *__pyx_n_s_t2; +static PyObject *__pyx_n_s_tail1; +static PyObject *__pyx_n_s_tail1_key; +static PyObject *__pyx_n_s_tail2; +static PyObject *__pyx_n_s_tail2_key; +static PyObject *__pyx_n_s_test; +static PyObject *__pyx_n_s_tok1; +static PyObject *__pyx_n_s_tok2; +static PyObject *__pyx_n_s_try_key; +static PyObject *__pyx_n_s_val; +static PyObject *__pyx_n_s_val3; +static PyObject *__pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython__lcs_iter_simple_alt2_cython(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_full_seq1, PyObject *__pyx_v_full_seq2, PyObject *__pyx_v_open_to_close, PyObject *__pyx_v_node_affinity, PyObject *__pyx_v_open_to_node); /* proto */ +static PyObject *__pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_2_lcs_iter_prehash2_cython(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_full_seq1, PyObject *__pyx_v_full_seq2, PyObject *__pyx_v_open_to_close, PyObject *__pyx_v_node_affinity, PyObject *__pyx_v_open_to_node); /* proto */ +static PyObject *__pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict___getitem__(CYTHON_UNUSED PyObject *__pyx_self, CYTHON_UNUSED PyObject *__pyx_v_self, PyObject *__pyx_v_key); /* proto */ +static __Pyx_CachedCFunction __pyx_umethod_PyDict_Type_items = {0, &__pyx_n_s_items, 0, 0, 0}; +static __Pyx_CachedCFunction __pyx_umethod_PyDict_Type_keys = {0, &__pyx_n_s_keys, 0, 0, 0}; +static __Pyx_CachedCFunction __pyx_umethod_PyList_Type_pop = {0, &__pyx_n_s_pop, 0, 0, 0}; +static PyObject *__pyx_int_0; +static PyObject *__pyx_int_1; +static PyObject *__pyx_int_5; +static PyObject *__pyx_int_8; +static PyObject *__pyx_int_neg_1; +static PyObject *__pyx_tuple_; +static PyObject *__pyx_slice__2; +static PyObject *__pyx_slice__3; +static PyObject *__pyx_tuple__4; +static PyObject *__pyx_tuple__6; +static PyObject *__pyx_tuple__8; +static PyObject *__pyx_codeobj__5; +static PyObject *__pyx_codeobj__7; +static PyObject *__pyx_codeobj__9; +/* Late includes */ + +/* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":35 + * + * + * def _lcs_iter_simple_alt2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node): # <<<<<<<<<<<<<< + * """ + * Depth first stack trajectory and replace try except statements with ifs + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_1_lcs_iter_simple_alt2_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static char __pyx_doc_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython__lcs_iter_simple_alt2_cython[] = "\n Depth first stack trajectory and replace try except statements with ifs\n "; +static PyMethodDef __pyx_mdef_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_1_lcs_iter_simple_alt2_cython = {"_lcs_iter_simple_alt2_cython", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_1_lcs_iter_simple_alt2_cython, METH_VARARGS|METH_KEYWORDS, __pyx_doc_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython__lcs_iter_simple_alt2_cython}; +static PyObject *__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_1_lcs_iter_simple_alt2_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_full_seq1 = 0; + PyObject *__pyx_v_full_seq2 = 0; + PyObject *__pyx_v_open_to_close = 0; + PyObject *__pyx_v_node_affinity = 0; + PyObject *__pyx_v_open_to_node = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("_lcs_iter_simple_alt2_cython (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_full_seq1,&__pyx_n_s_full_seq2,&__pyx_n_s_open_to_close,&__pyx_n_s_node_affinity,&__pyx_n_s_open_to_node,0}; + PyObject* values[5] = {0,0,0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4); + CYTHON_FALLTHROUGH; + case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); + CYTHON_FALLTHROUGH; + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_full_seq1)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_full_seq2)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("_lcs_iter_simple_alt2_cython", 1, 5, 5, 1); __PYX_ERR(0, 35, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_open_to_close)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("_lcs_iter_simple_alt2_cython", 1, 5, 5, 2); __PYX_ERR(0, 35, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 3: + if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_node_affinity)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("_lcs_iter_simple_alt2_cython", 1, 5, 5, 3); __PYX_ERR(0, 35, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 4: + if (likely((values[4] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_open_to_node)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("_lcs_iter_simple_alt2_cython", 1, 5, 5, 4); __PYX_ERR(0, 35, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "_lcs_iter_simple_alt2_cython") < 0)) __PYX_ERR(0, 35, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 5) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + values[3] = PyTuple_GET_ITEM(__pyx_args, 3); + values[4] = PyTuple_GET_ITEM(__pyx_args, 4); + } + __pyx_v_full_seq1 = values[0]; + __pyx_v_full_seq2 = values[1]; + __pyx_v_open_to_close = values[2]; + __pyx_v_node_affinity = values[3]; + __pyx_v_open_to_node = values[4]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("_lcs_iter_simple_alt2_cython", 1, 5, 5, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 35, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython._lcs_iter_simple_alt2_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython__lcs_iter_simple_alt2_cython(__pyx_self, __pyx_v_full_seq1, __pyx_v_full_seq2, __pyx_v_open_to_close, __pyx_v_node_affinity, __pyx_v_open_to_node); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython__lcs_iter_simple_alt2_cython(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_full_seq1, PyObject *__pyx_v_full_seq2, PyObject *__pyx_v_open_to_close, PyObject *__pyx_v_node_affinity, PyObject *__pyx_v_open_to_node) { + PyObject *__pyx_v_all_decomp1 = NULL; + PyObject *__pyx_v_all_decomp2 = NULL; + PyObject *__pyx_v_key0 = NULL; + PyObject *__pyx_v_frame0 = NULL; + PyObject *__pyx_v_stack = NULL; + PyObject *__pyx_v__results = NULL; + PyObject *__pyx_v_empty1 = NULL; + PyObject *__pyx_v_empty2 = NULL; + PyObject *__pyx_v_best = NULL; + PyObject *__pyx_v_base_result = NULL; + PyObject *__pyx_v_seq1 = NULL; + PyObject *__pyx_v_key1 = NULL; + PyObject *__pyx_v_t1 = NULL; + PyObject *__pyx_v_a1 = NULL; + PyObject *__pyx_v_b1 = NULL; + PyObject *__pyx_v_head1 = NULL; + PyObject *__pyx_v_tail1 = NULL; + PyObject *__pyx_v_head_tail1 = NULL; + PyObject *__pyx_v_seq2 = NULL; + PyObject *__pyx_v_key2 = NULL; + PyObject *__pyx_v_t2 = NULL; + PyObject *__pyx_v_a2 = NULL; + PyObject *__pyx_v_b2 = NULL; + PyObject *__pyx_v_head2 = NULL; + PyObject *__pyx_v_tail2 = NULL; + PyObject *__pyx_v_head_tail2 = NULL; + PyObject *__pyx_v_key = NULL; + PyObject *__pyx_v_try_key = NULL; + PyObject *__pyx_v_cand1 = NULL; + PyObject *__pyx_v_cand2 = NULL; + PyObject *__pyx_v_affinity = NULL; + PyObject *__pyx_v_pval_h = NULL; + PyObject *__pyx_v_new_heads = NULL; + PyObject *__pyx_v_pval_t = NULL; + PyObject *__pyx_v_new_tails = NULL; + PyObject *__pyx_v_new_head1 = NULL; + PyObject *__pyx_v_new_head2 = NULL; + PyObject *__pyx_v_new_tail1 = NULL; + PyObject *__pyx_v_new_tail2 = NULL; + PyObject *__pyx_v_subseq1 = NULL; + PyObject *__pyx_v_subseq2 = NULL; + PyObject *__pyx_v_res3 = NULL; + PyObject *__pyx_v_val3 = NULL; + PyObject *__pyx_v_cand3 = NULL; + PyObject *__pyx_v_val = NULL; + PyObject *__pyx_v_found = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + int __pyx_t_1; + int __pyx_t_2; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + struct __pyx_opt_args_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython __pyx_t_6; + PyObject *__pyx_t_7 = NULL; + Py_ssize_t __pyx_t_8; + PyObject *(*__pyx_t_9)(PyObject *); + PyObject *__pyx_t_10 = NULL; + PyObject *__pyx_t_11 = NULL; + PyObject *__pyx_t_12 = NULL; + PyObject *__pyx_t_13 = NULL; + PyObject *__pyx_t_14 = NULL; + PyObject *(*__pyx_t_15)(PyObject *); + int __pyx_t_16; + int __pyx_t_17; + PyObject *__pyx_t_18 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("_lcs_iter_simple_alt2_cython", 0); + __Pyx_INCREF(__pyx_v_open_to_node); + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":39 + * Depth first stack trajectory and replace try except statements with ifs + * """ + * if open_to_node is None: # <<<<<<<<<<<<<< + * open_to_node = IdentityDict() + * all_decomp1 = generate_all_decomp_cython(full_seq1, open_to_close, open_to_node) + */ + __pyx_t_1 = (__pyx_v_open_to_node == Py_None); + __pyx_t_2 = (__pyx_t_1 != 0); + if (__pyx_t_2) { + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":40 + * """ + * if open_to_node is None: + * open_to_node = IdentityDict() # <<<<<<<<<<<<<< + * all_decomp1 = generate_all_decomp_cython(full_seq1, open_to_close, open_to_node) + * all_decomp2 = generate_all_decomp_cython(full_seq2, open_to_close, open_to_node) + */ + __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_IdentityDict); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 40, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + } + } + __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5) : __Pyx_PyObject_CallNoArg(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 40, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF_SET(__pyx_v_open_to_node, __pyx_t_3); + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":39 + * Depth first stack trajectory and replace try except statements with ifs + * """ + * if open_to_node is None: # <<<<<<<<<<<<<< + * open_to_node = IdentityDict() + * all_decomp1 = generate_all_decomp_cython(full_seq1, open_to_close, open_to_node) + */ + } + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":41 + * if open_to_node is None: + * open_to_node = IdentityDict() + * all_decomp1 = generate_all_decomp_cython(full_seq1, open_to_close, open_to_node) # <<<<<<<<<<<<<< + * all_decomp2 = generate_all_decomp_cython(full_seq2, open_to_close, open_to_node) + * + */ + __pyx_t_6.__pyx_n = 1; + __pyx_t_6.open_to_node = __pyx_v_open_to_node; + __pyx_t_3 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython(__pyx_v_full_seq1, __pyx_v_open_to_close, &__pyx_t_6); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 41, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_v_all_decomp1 = __pyx_t_3; + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":42 + * open_to_node = IdentityDict() + * all_decomp1 = generate_all_decomp_cython(full_seq1, open_to_close, open_to_node) + * all_decomp2 = generate_all_decomp_cython(full_seq2, open_to_close, open_to_node) # <<<<<<<<<<<<<< + * + * key0 = (full_seq1, full_seq2) + */ + __pyx_t_6.__pyx_n = 1; + __pyx_t_6.open_to_node = __pyx_v_open_to_node; + __pyx_t_3 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython(__pyx_v_full_seq2, __pyx_v_open_to_close, &__pyx_t_6); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 42, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_v_all_decomp2 = __pyx_t_3; + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":44 + * all_decomp2 = generate_all_decomp_cython(full_seq2, open_to_close, open_to_node) + * + * key0 = (full_seq1, full_seq2) # <<<<<<<<<<<<<< + * frame0 = key0 + * stack = [frame0] + */ + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 44, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(__pyx_v_full_seq1); + __Pyx_GIVEREF(__pyx_v_full_seq1); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_full_seq1); + __Pyx_INCREF(__pyx_v_full_seq2); + __Pyx_GIVEREF(__pyx_v_full_seq2); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_full_seq2); + __pyx_v_key0 = ((PyObject*)__pyx_t_3); + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":45 + * + * key0 = (full_seq1, full_seq2) + * frame0 = key0 # <<<<<<<<<<<<<< + * stack = [frame0] + * + */ + __Pyx_INCREF(__pyx_v_key0); + __pyx_v_frame0 = __pyx_v_key0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":46 + * key0 = (full_seq1, full_seq2) + * frame0 = key0 + * stack = [frame0] # <<<<<<<<<<<<<< + * + * _results = {} + */ + __pyx_t_3 = PyList_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 46, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(__pyx_v_frame0); + __Pyx_GIVEREF(__pyx_v_frame0); + PyList_SET_ITEM(__pyx_t_3, 0, __pyx_v_frame0); + __pyx_v_stack = ((PyObject*)__pyx_t_3); + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":48 + * stack = [frame0] + * + * _results = {} # <<<<<<<<<<<<<< + * # Populate base cases + * empty1 = type(next(iter(all_decomp1.keys())))() + */ + __pyx_t_3 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 48, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_v__results = ((PyObject*)__pyx_t_3); + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":50 + * _results = {} + * # Populate base cases + * empty1 = type(next(iter(all_decomp1.keys())))() # <<<<<<<<<<<<<< + * empty2 = type(next(iter(all_decomp2.keys())))() + * best = (empty1, empty2) + */ + __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_all_decomp1, __pyx_n_s_keys); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 50, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_7 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_5); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_5, function); + } + } + __pyx_t_4 = (__pyx_t_7) ? __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_7) : __Pyx_PyObject_CallNoArg(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 50, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 50, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = __Pyx_PyIter_Next(__pyx_t_5); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 50, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_INCREF(((PyObject *)Py_TYPE(__pyx_t_4))); + __pyx_t_5 = ((PyObject *)Py_TYPE(__pyx_t_4)); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) { + __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_5); + if (likely(__pyx_t_4)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_5, function); + } + } + __pyx_t_3 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; + if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 50, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_v_empty1 = __pyx_t_3; + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":51 + * # Populate base cases + * empty1 = type(next(iter(all_decomp1.keys())))() + * empty2 = type(next(iter(all_decomp2.keys())))() # <<<<<<<<<<<<<< + * best = (empty1, empty2) + * base_result = (0, best) + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_all_decomp2, __pyx_n_s_keys); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 51, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_7 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_7)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + } + } + __pyx_t_5 = (__pyx_t_7) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_7) : __Pyx_PyObject_CallNoArg(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 51, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = PyObject_GetIter(__pyx_t_5); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 51, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = __Pyx_PyIter_Next(__pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 51, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_INCREF(((PyObject *)Py_TYPE(__pyx_t_5))); + __pyx_t_4 = ((PyObject *)Py_TYPE(__pyx_t_5)); __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + } + } + __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5) : __Pyx_PyObject_CallNoArg(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 51, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_v_empty2 = __pyx_t_3; + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":52 + * empty1 = type(next(iter(all_decomp1.keys())))() + * empty2 = type(next(iter(all_decomp2.keys())))() + * best = (empty1, empty2) # <<<<<<<<<<<<<< + * base_result = (0, best) + * for seq1 in all_decomp1.keys(): + */ + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 52, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(__pyx_v_empty1); + __Pyx_GIVEREF(__pyx_v_empty1); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_empty1); + __Pyx_INCREF(__pyx_v_empty2); + __Pyx_GIVEREF(__pyx_v_empty2); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_empty2); + __pyx_v_best = __pyx_t_3; + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":53 + * empty2 = type(next(iter(all_decomp2.keys())))() + * best = (empty1, empty2) + * base_result = (0, best) # <<<<<<<<<<<<<< + * for seq1 in all_decomp1.keys(): + * key1 = seq1 + */ + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 53, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(__pyx_int_0); + __Pyx_GIVEREF(__pyx_int_0); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_int_0); + __Pyx_INCREF(__pyx_v_best); + __Pyx_GIVEREF(__pyx_v_best); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_best); + __pyx_v_base_result = ((PyObject*)__pyx_t_3); + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":54 + * best = (empty1, empty2) + * base_result = (0, best) + * for seq1 in all_decomp1.keys(): # <<<<<<<<<<<<<< + * key1 = seq1 + * t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[key1] + */ + __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_all_decomp1, __pyx_n_s_keys); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 54, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_4, function); + } + } + __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5) : __Pyx_PyObject_CallNoArg(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 54, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + if (likely(PyList_CheckExact(__pyx_t_3)) || PyTuple_CheckExact(__pyx_t_3)) { + __pyx_t_4 = __pyx_t_3; __Pyx_INCREF(__pyx_t_4); __pyx_t_8 = 0; + __pyx_t_9 = NULL; + } else { + __pyx_t_8 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 54, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_9 = Py_TYPE(__pyx_t_4)->tp_iternext; if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 54, __pyx_L1_error) + } + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + for (;;) { + if (likely(!__pyx_t_9)) { + if (likely(PyList_CheckExact(__pyx_t_4))) { + if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_4)) break; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_3 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_3); __pyx_t_8++; if (unlikely(0 < 0)) __PYX_ERR(0, 54, __pyx_L1_error) + #else + __pyx_t_3 = PySequence_ITEM(__pyx_t_4, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 54, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + #endif + } else { + if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_4)) break; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_3); __pyx_t_8++; if (unlikely(0 < 0)) __PYX_ERR(0, 54, __pyx_L1_error) + #else + __pyx_t_3 = PySequence_ITEM(__pyx_t_4, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 54, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + #endif + } + } else { + __pyx_t_3 = __pyx_t_9(__pyx_t_4); + if (unlikely(!__pyx_t_3)) { + PyObject* exc_type = PyErr_Occurred(); + if (exc_type) { + if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear(); + else __PYX_ERR(0, 54, __pyx_L1_error) + } + break; + } + __Pyx_GOTREF(__pyx_t_3); + } + __Pyx_XDECREF_SET(__pyx_v_seq1, __pyx_t_3); + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":55 + * base_result = (0, best) + * for seq1 in all_decomp1.keys(): + * key1 = seq1 # <<<<<<<<<<<<<< + * t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[key1] + * _results[(seq1, empty2)] = base_result + */ + __Pyx_INCREF(__pyx_v_seq1); + __Pyx_XDECREF_SET(__pyx_v_key1, __pyx_v_seq1); + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":56 + * for seq1 in all_decomp1.keys(): + * key1 = seq1 + * t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[key1] # <<<<<<<<<<<<<< + * _results[(seq1, empty2)] = base_result + * _results[(head1, empty2)] = base_result + */ + __pyx_t_3 = __Pyx_PyObject_GetItem(__pyx_v_all_decomp1, __pyx_v_key1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 56, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) { + PyObject* sequence = __pyx_t_3; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 6)) { + if (size > 6) __Pyx_RaiseTooManyValuesError(6); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 56, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_5 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_7 = PyTuple_GET_ITEM(sequence, 1); + __pyx_t_10 = PyTuple_GET_ITEM(sequence, 2); + __pyx_t_11 = PyTuple_GET_ITEM(sequence, 3); + __pyx_t_12 = PyTuple_GET_ITEM(sequence, 4); + __pyx_t_13 = PyTuple_GET_ITEM(sequence, 5); + } else { + __pyx_t_5 = PyList_GET_ITEM(sequence, 0); + __pyx_t_7 = PyList_GET_ITEM(sequence, 1); + __pyx_t_10 = PyList_GET_ITEM(sequence, 2); + __pyx_t_11 = PyList_GET_ITEM(sequence, 3); + __pyx_t_12 = PyList_GET_ITEM(sequence, 4); + __pyx_t_13 = PyList_GET_ITEM(sequence, 5); + } + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(__pyx_t_10); + __Pyx_INCREF(__pyx_t_11); + __Pyx_INCREF(__pyx_t_12); + __Pyx_INCREF(__pyx_t_13); + #else + { + Py_ssize_t i; + PyObject** temps[6] = {&__pyx_t_5,&__pyx_t_7,&__pyx_t_10,&__pyx_t_11,&__pyx_t_12,&__pyx_t_13}; + for (i=0; i < 6; i++) { + PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 56, __pyx_L1_error) + __Pyx_GOTREF(item); + *(temps[i]) = item; + } + } + #endif + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } else { + Py_ssize_t index = -1; + PyObject** temps[6] = {&__pyx_t_5,&__pyx_t_7,&__pyx_t_10,&__pyx_t_11,&__pyx_t_12,&__pyx_t_13}; + __pyx_t_14 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 56, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_14); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_15 = Py_TYPE(__pyx_t_14)->tp_iternext; + for (index=0; index < 6; index++) { + PyObject* item = __pyx_t_15(__pyx_t_14); if (unlikely(!item)) goto __pyx_L6_unpacking_failed; + __Pyx_GOTREF(item); + *(temps[index]) = item; + } + if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_14), 6) < 0) __PYX_ERR(0, 56, __pyx_L1_error) + __pyx_t_15 = NULL; + __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0; + goto __pyx_L7_unpacking_done; + __pyx_L6_unpacking_failed:; + __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0; + __pyx_t_15 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 56, __pyx_L1_error) + __pyx_L7_unpacking_done:; + } + __Pyx_XDECREF_SET(__pyx_v_t1, __pyx_t_5); + __pyx_t_5 = 0; + __Pyx_XDECREF_SET(__pyx_v_a1, __pyx_t_7); + __pyx_t_7 = 0; + __Pyx_XDECREF_SET(__pyx_v_b1, __pyx_t_10); + __pyx_t_10 = 0; + __Pyx_XDECREF_SET(__pyx_v_head1, __pyx_t_11); + __pyx_t_11 = 0; + __Pyx_XDECREF_SET(__pyx_v_tail1, __pyx_t_12); + __pyx_t_12 = 0; + __Pyx_XDECREF_SET(__pyx_v_head_tail1, __pyx_t_13); + __pyx_t_13 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":57 + * key1 = seq1 + * t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[key1] + * _results[(seq1, empty2)] = base_result # <<<<<<<<<<<<<< + * _results[(head1, empty2)] = base_result + * _results[(tail1, empty2)] = base_result + */ + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 57, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(__pyx_v_seq1); + __Pyx_GIVEREF(__pyx_v_seq1); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_seq1); + __Pyx_INCREF(__pyx_v_empty2); + __Pyx_GIVEREF(__pyx_v_empty2); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_empty2); + if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 57, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":58 + * t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[key1] + * _results[(seq1, empty2)] = base_result + * _results[(head1, empty2)] = base_result # <<<<<<<<<<<<<< + * _results[(tail1, empty2)] = base_result + * _results[(head_tail1, empty2)] = base_result + */ + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 58, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(__pyx_v_head1); + __Pyx_GIVEREF(__pyx_v_head1); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_head1); + __Pyx_INCREF(__pyx_v_empty2); + __Pyx_GIVEREF(__pyx_v_empty2); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_empty2); + if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 58, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":59 + * _results[(seq1, empty2)] = base_result + * _results[(head1, empty2)] = base_result + * _results[(tail1, empty2)] = base_result # <<<<<<<<<<<<<< + * _results[(head_tail1, empty2)] = base_result + * + */ + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 59, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(__pyx_v_tail1); + __Pyx_GIVEREF(__pyx_v_tail1); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_tail1); + __Pyx_INCREF(__pyx_v_empty2); + __Pyx_GIVEREF(__pyx_v_empty2); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_empty2); + if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 59, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":60 + * _results[(head1, empty2)] = base_result + * _results[(tail1, empty2)] = base_result + * _results[(head_tail1, empty2)] = base_result # <<<<<<<<<<<<<< + * + * for seq2 in all_decomp2.keys(): + */ + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 60, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(__pyx_v_head_tail1); + __Pyx_GIVEREF(__pyx_v_head_tail1); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_head_tail1); + __Pyx_INCREF(__pyx_v_empty2); + __Pyx_GIVEREF(__pyx_v_empty2); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_empty2); + if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 60, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":54 + * best = (empty1, empty2) + * base_result = (0, best) + * for seq1 in all_decomp1.keys(): # <<<<<<<<<<<<<< + * key1 = seq1 + * t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[key1] + */ + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":62 + * _results[(head_tail1, empty2)] = base_result + * + * for seq2 in all_decomp2.keys(): # <<<<<<<<<<<<<< + * key2 = seq2 + * t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[key2] + */ + __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_all_decomp2, __pyx_n_s_keys); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 62, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_13 = NULL; + if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_13 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_13)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_13); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + } + } + __pyx_t_4 = (__pyx_t_13) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_13) : __Pyx_PyObject_CallNoArg(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0; + if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 62, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (likely(PyList_CheckExact(__pyx_t_4)) || PyTuple_CheckExact(__pyx_t_4)) { + __pyx_t_3 = __pyx_t_4; __Pyx_INCREF(__pyx_t_3); __pyx_t_8 = 0; + __pyx_t_9 = NULL; + } else { + __pyx_t_8 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 62, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_9 = Py_TYPE(__pyx_t_3)->tp_iternext; if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 62, __pyx_L1_error) + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + for (;;) { + if (likely(!__pyx_t_9)) { + if (likely(PyList_CheckExact(__pyx_t_3))) { + if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_3)) break; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_4 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_8); __Pyx_INCREF(__pyx_t_4); __pyx_t_8++; if (unlikely(0 < 0)) __PYX_ERR(0, 62, __pyx_L1_error) + #else + __pyx_t_4 = PySequence_ITEM(__pyx_t_3, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 62, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + #endif + } else { + if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_3)) break; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_8); __Pyx_INCREF(__pyx_t_4); __pyx_t_8++; if (unlikely(0 < 0)) __PYX_ERR(0, 62, __pyx_L1_error) + #else + __pyx_t_4 = PySequence_ITEM(__pyx_t_3, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 62, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + #endif + } + } else { + __pyx_t_4 = __pyx_t_9(__pyx_t_3); + if (unlikely(!__pyx_t_4)) { + PyObject* exc_type = PyErr_Occurred(); + if (exc_type) { + if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear(); + else __PYX_ERR(0, 62, __pyx_L1_error) + } + break; + } + __Pyx_GOTREF(__pyx_t_4); + } + __Pyx_XDECREF_SET(__pyx_v_seq2, __pyx_t_4); + __pyx_t_4 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":63 + * + * for seq2 in all_decomp2.keys(): + * key2 = seq2 # <<<<<<<<<<<<<< + * t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[key2] + * _results[(empty1, seq2)] = base_result + */ + __Pyx_INCREF(__pyx_v_seq2); + __Pyx_XDECREF_SET(__pyx_v_key2, __pyx_v_seq2); + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":64 + * for seq2 in all_decomp2.keys(): + * key2 = seq2 + * t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[key2] # <<<<<<<<<<<<<< + * _results[(empty1, seq2)] = base_result + * _results[(empty1, head2)] = base_result + */ + __pyx_t_4 = __Pyx_PyObject_GetItem(__pyx_v_all_decomp2, __pyx_v_key2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 64, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) { + PyObject* sequence = __pyx_t_4; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 6)) { + if (size > 6) __Pyx_RaiseTooManyValuesError(6); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 64, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_13 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_12 = PyTuple_GET_ITEM(sequence, 1); + __pyx_t_11 = PyTuple_GET_ITEM(sequence, 2); + __pyx_t_10 = PyTuple_GET_ITEM(sequence, 3); + __pyx_t_7 = PyTuple_GET_ITEM(sequence, 4); + __pyx_t_5 = PyTuple_GET_ITEM(sequence, 5); + } else { + __pyx_t_13 = PyList_GET_ITEM(sequence, 0); + __pyx_t_12 = PyList_GET_ITEM(sequence, 1); + __pyx_t_11 = PyList_GET_ITEM(sequence, 2); + __pyx_t_10 = PyList_GET_ITEM(sequence, 3); + __pyx_t_7 = PyList_GET_ITEM(sequence, 4); + __pyx_t_5 = PyList_GET_ITEM(sequence, 5); + } + __Pyx_INCREF(__pyx_t_13); + __Pyx_INCREF(__pyx_t_12); + __Pyx_INCREF(__pyx_t_11); + __Pyx_INCREF(__pyx_t_10); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(__pyx_t_5); + #else + { + Py_ssize_t i; + PyObject** temps[6] = {&__pyx_t_13,&__pyx_t_12,&__pyx_t_11,&__pyx_t_10,&__pyx_t_7,&__pyx_t_5}; + for (i=0; i < 6; i++) { + PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 64, __pyx_L1_error) + __Pyx_GOTREF(item); + *(temps[i]) = item; + } + } + #endif + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + } else { + Py_ssize_t index = -1; + PyObject** temps[6] = {&__pyx_t_13,&__pyx_t_12,&__pyx_t_11,&__pyx_t_10,&__pyx_t_7,&__pyx_t_5}; + __pyx_t_14 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 64, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_14); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_15 = Py_TYPE(__pyx_t_14)->tp_iternext; + for (index=0; index < 6; index++) { + PyObject* item = __pyx_t_15(__pyx_t_14); if (unlikely(!item)) goto __pyx_L10_unpacking_failed; + __Pyx_GOTREF(item); + *(temps[index]) = item; + } + if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_14), 6) < 0) __PYX_ERR(0, 64, __pyx_L1_error) + __pyx_t_15 = NULL; + __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0; + goto __pyx_L11_unpacking_done; + __pyx_L10_unpacking_failed:; + __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0; + __pyx_t_15 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 64, __pyx_L1_error) + __pyx_L11_unpacking_done:; + } + __Pyx_XDECREF_SET(__pyx_v_t2, __pyx_t_13); + __pyx_t_13 = 0; + __Pyx_XDECREF_SET(__pyx_v_a2, __pyx_t_12); + __pyx_t_12 = 0; + __Pyx_XDECREF_SET(__pyx_v_b2, __pyx_t_11); + __pyx_t_11 = 0; + __Pyx_XDECREF_SET(__pyx_v_head2, __pyx_t_10); + __pyx_t_10 = 0; + __Pyx_XDECREF_SET(__pyx_v_tail2, __pyx_t_7); + __pyx_t_7 = 0; + __Pyx_XDECREF_SET(__pyx_v_head_tail2, __pyx_t_5); + __pyx_t_5 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":65 + * key2 = seq2 + * t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[key2] + * _results[(empty1, seq2)] = base_result # <<<<<<<<<<<<<< + * _results[(empty1, head2)] = base_result + * _results[(empty1, tail2)] = base_result + */ + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 65, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(__pyx_v_empty1); + __Pyx_GIVEREF(__pyx_v_empty1); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_empty1); + __Pyx_INCREF(__pyx_v_seq2); + __Pyx_GIVEREF(__pyx_v_seq2); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_seq2); + if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_4, __pyx_v_base_result) < 0)) __PYX_ERR(0, 65, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":66 + * t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[key2] + * _results[(empty1, seq2)] = base_result + * _results[(empty1, head2)] = base_result # <<<<<<<<<<<<<< + * _results[(empty1, tail2)] = base_result + * _results[(empty1, head_tail2)] = base_result + */ + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 66, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(__pyx_v_empty1); + __Pyx_GIVEREF(__pyx_v_empty1); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_empty1); + __Pyx_INCREF(__pyx_v_head2); + __Pyx_GIVEREF(__pyx_v_head2); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_head2); + if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_4, __pyx_v_base_result) < 0)) __PYX_ERR(0, 66, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":67 + * _results[(empty1, seq2)] = base_result + * _results[(empty1, head2)] = base_result + * _results[(empty1, tail2)] = base_result # <<<<<<<<<<<<<< + * _results[(empty1, head_tail2)] = base_result + * + */ + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 67, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(__pyx_v_empty1); + __Pyx_GIVEREF(__pyx_v_empty1); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_empty1); + __Pyx_INCREF(__pyx_v_tail2); + __Pyx_GIVEREF(__pyx_v_tail2); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_tail2); + if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_4, __pyx_v_base_result) < 0)) __PYX_ERR(0, 67, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":68 + * _results[(empty1, head2)] = base_result + * _results[(empty1, tail2)] = base_result + * _results[(empty1, head_tail2)] = base_result # <<<<<<<<<<<<<< + * + * while stack: + */ + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 68, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(__pyx_v_empty1); + __Pyx_GIVEREF(__pyx_v_empty1); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_empty1); + __Pyx_INCREF(__pyx_v_head_tail2); + __Pyx_GIVEREF(__pyx_v_head_tail2); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_head_tail2); + if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_4, __pyx_v_base_result) < 0)) __PYX_ERR(0, 68, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":62 + * _results[(head_tail1, empty2)] = base_result + * + * for seq2 in all_decomp2.keys(): # <<<<<<<<<<<<<< + * key2 = seq2 + * t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[key2] + */ + } + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":70 + * _results[(empty1, head_tail2)] = base_result + * + * while stack: # <<<<<<<<<<<<<< + * key = stack[-1] + * if key not in _results: + */ + while (1) { + __pyx_t_2 = (PyList_GET_SIZE(__pyx_v_stack) != 0); + if (!__pyx_t_2) break; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":71 + * + * while stack: + * key = stack[-1] # <<<<<<<<<<<<<< + * if key not in _results: + * seq1, seq2 = key + */ + __pyx_t_3 = __Pyx_GetItemInt_List(__pyx_v_stack, -1L, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 71, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_XDECREF_SET(__pyx_v_key, __pyx_t_3); + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":72 + * while stack: + * key = stack[-1] + * if key not in _results: # <<<<<<<<<<<<<< + * seq1, seq2 = key + * + */ + __pyx_t_2 = (__Pyx_PyDict_ContainsTF(__pyx_v_key, __pyx_v__results, Py_NE)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 72, __pyx_L1_error) + __pyx_t_1 = (__pyx_t_2 != 0); + if (__pyx_t_1) { + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":73 + * key = stack[-1] + * if key not in _results: + * seq1, seq2 = key # <<<<<<<<<<<<<< + * + * t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[seq1] + */ + if ((likely(PyTuple_CheckExact(__pyx_v_key))) || (PyList_CheckExact(__pyx_v_key))) { + PyObject* sequence = __pyx_v_key; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 73, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_3 = PyList_GET_ITEM(sequence, 0); + __pyx_t_4 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(__pyx_t_4); + #else + __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 73, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 73, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + #endif + } else { + Py_ssize_t index = -1; + __pyx_t_5 = PyObject_GetIter(__pyx_v_key); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 73, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_15 = Py_TYPE(__pyx_t_5)->tp_iternext; + index = 0; __pyx_t_3 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_3)) goto __pyx_L15_unpacking_failed; + __Pyx_GOTREF(__pyx_t_3); + index = 1; __pyx_t_4 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_4)) goto __pyx_L15_unpacking_failed; + __Pyx_GOTREF(__pyx_t_4); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_5), 2) < 0) __PYX_ERR(0, 73, __pyx_L1_error) + __pyx_t_15 = NULL; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + goto __pyx_L16_unpacking_done; + __pyx_L15_unpacking_failed:; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_15 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 73, __pyx_L1_error) + __pyx_L16_unpacking_done:; + } + __Pyx_XDECREF_SET(__pyx_v_seq1, __pyx_t_3); + __pyx_t_3 = 0; + __Pyx_XDECREF_SET(__pyx_v_seq2, __pyx_t_4); + __pyx_t_4 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":75 + * seq1, seq2 = key + * + * t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[seq1] # <<<<<<<<<<<<<< + * t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[seq2] + * + */ + __pyx_t_4 = __Pyx_PyObject_GetItem(__pyx_v_all_decomp1, __pyx_v_seq1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 75, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) { + PyObject* sequence = __pyx_t_4; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 6)) { + if (size > 6) __Pyx_RaiseTooManyValuesError(6); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 75, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_5 = PyTuple_GET_ITEM(sequence, 1); + __pyx_t_7 = PyTuple_GET_ITEM(sequence, 2); + __pyx_t_10 = PyTuple_GET_ITEM(sequence, 3); + __pyx_t_11 = PyTuple_GET_ITEM(sequence, 4); + __pyx_t_12 = PyTuple_GET_ITEM(sequence, 5); + } else { + __pyx_t_3 = PyList_GET_ITEM(sequence, 0); + __pyx_t_5 = PyList_GET_ITEM(sequence, 1); + __pyx_t_7 = PyList_GET_ITEM(sequence, 2); + __pyx_t_10 = PyList_GET_ITEM(sequence, 3); + __pyx_t_11 = PyList_GET_ITEM(sequence, 4); + __pyx_t_12 = PyList_GET_ITEM(sequence, 5); + } + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(__pyx_t_10); + __Pyx_INCREF(__pyx_t_11); + __Pyx_INCREF(__pyx_t_12); + #else + { + Py_ssize_t i; + PyObject** temps[6] = {&__pyx_t_3,&__pyx_t_5,&__pyx_t_7,&__pyx_t_10,&__pyx_t_11,&__pyx_t_12}; + for (i=0; i < 6; i++) { + PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 75, __pyx_L1_error) + __Pyx_GOTREF(item); + *(temps[i]) = item; + } + } + #endif + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + } else { + Py_ssize_t index = -1; + PyObject** temps[6] = {&__pyx_t_3,&__pyx_t_5,&__pyx_t_7,&__pyx_t_10,&__pyx_t_11,&__pyx_t_12}; + __pyx_t_13 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 75, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_13); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_15 = Py_TYPE(__pyx_t_13)->tp_iternext; + for (index=0; index < 6; index++) { + PyObject* item = __pyx_t_15(__pyx_t_13); if (unlikely(!item)) goto __pyx_L17_unpacking_failed; + __Pyx_GOTREF(item); + *(temps[index]) = item; + } + if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_13), 6) < 0) __PYX_ERR(0, 75, __pyx_L1_error) + __pyx_t_15 = NULL; + __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; + goto __pyx_L18_unpacking_done; + __pyx_L17_unpacking_failed:; + __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; + __pyx_t_15 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 75, __pyx_L1_error) + __pyx_L18_unpacking_done:; + } + __Pyx_XDECREF_SET(__pyx_v_t1, __pyx_t_3); + __pyx_t_3 = 0; + __Pyx_XDECREF_SET(__pyx_v_a1, __pyx_t_5); + __pyx_t_5 = 0; + __Pyx_XDECREF_SET(__pyx_v_b1, __pyx_t_7); + __pyx_t_7 = 0; + __Pyx_XDECREF_SET(__pyx_v_head1, __pyx_t_10); + __pyx_t_10 = 0; + __Pyx_XDECREF_SET(__pyx_v_tail1, __pyx_t_11); + __pyx_t_11 = 0; + __Pyx_XDECREF_SET(__pyx_v_head_tail1, __pyx_t_12); + __pyx_t_12 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":76 + * + * t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[seq1] + * t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[seq2] # <<<<<<<<<<<<<< + * + * # Case 2: The current edge in sequence1 is deleted + */ + __pyx_t_4 = __Pyx_PyObject_GetItem(__pyx_v_all_decomp2, __pyx_v_seq2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 76, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) { + PyObject* sequence = __pyx_t_4; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 6)) { + if (size > 6) __Pyx_RaiseTooManyValuesError(6); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 76, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_12 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_11 = PyTuple_GET_ITEM(sequence, 1); + __pyx_t_10 = PyTuple_GET_ITEM(sequence, 2); + __pyx_t_7 = PyTuple_GET_ITEM(sequence, 3); + __pyx_t_5 = PyTuple_GET_ITEM(sequence, 4); + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 5); + } else { + __pyx_t_12 = PyList_GET_ITEM(sequence, 0); + __pyx_t_11 = PyList_GET_ITEM(sequence, 1); + __pyx_t_10 = PyList_GET_ITEM(sequence, 2); + __pyx_t_7 = PyList_GET_ITEM(sequence, 3); + __pyx_t_5 = PyList_GET_ITEM(sequence, 4); + __pyx_t_3 = PyList_GET_ITEM(sequence, 5); + } + __Pyx_INCREF(__pyx_t_12); + __Pyx_INCREF(__pyx_t_11); + __Pyx_INCREF(__pyx_t_10); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(__pyx_t_3); + #else + { + Py_ssize_t i; + PyObject** temps[6] = {&__pyx_t_12,&__pyx_t_11,&__pyx_t_10,&__pyx_t_7,&__pyx_t_5,&__pyx_t_3}; + for (i=0; i < 6; i++) { + PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 76, __pyx_L1_error) + __Pyx_GOTREF(item); + *(temps[i]) = item; + } + } + #endif + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + } else { + Py_ssize_t index = -1; + PyObject** temps[6] = {&__pyx_t_12,&__pyx_t_11,&__pyx_t_10,&__pyx_t_7,&__pyx_t_5,&__pyx_t_3}; + __pyx_t_13 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 76, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_13); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_15 = Py_TYPE(__pyx_t_13)->tp_iternext; + for (index=0; index < 6; index++) { + PyObject* item = __pyx_t_15(__pyx_t_13); if (unlikely(!item)) goto __pyx_L19_unpacking_failed; + __Pyx_GOTREF(item); + *(temps[index]) = item; + } + if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_13), 6) < 0) __PYX_ERR(0, 76, __pyx_L1_error) + __pyx_t_15 = NULL; + __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; + goto __pyx_L20_unpacking_done; + __pyx_L19_unpacking_failed:; + __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; + __pyx_t_15 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 76, __pyx_L1_error) + __pyx_L20_unpacking_done:; + } + __Pyx_XDECREF_SET(__pyx_v_t2, __pyx_t_12); + __pyx_t_12 = 0; + __Pyx_XDECREF_SET(__pyx_v_a2, __pyx_t_11); + __pyx_t_11 = 0; + __Pyx_XDECREF_SET(__pyx_v_b2, __pyx_t_10); + __pyx_t_10 = 0; + __Pyx_XDECREF_SET(__pyx_v_head2, __pyx_t_7); + __pyx_t_7 = 0; + __Pyx_XDECREF_SET(__pyx_v_tail2, __pyx_t_5); + __pyx_t_5 = 0; + __Pyx_XDECREF_SET(__pyx_v_head_tail2, __pyx_t_3); + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":79 + * + * # Case 2: The current edge in sequence1 is deleted + * try_key = (head_tail1, seq2) # <<<<<<<<<<<<<< + * if try_key in _results: + * cand1 = _results[try_key] + */ + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 79, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(__pyx_v_head_tail1); + __Pyx_GIVEREF(__pyx_v_head_tail1); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_head_tail1); + __Pyx_INCREF(__pyx_v_seq2); + __Pyx_GIVEREF(__pyx_v_seq2); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_seq2); + __Pyx_XDECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_4)); + __pyx_t_4 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":80 + * # Case 2: The current edge in sequence1 is deleted + * try_key = (head_tail1, seq2) + * if try_key in _results: # <<<<<<<<<<<<<< + * cand1 = _results[try_key] + * else: + */ + __pyx_t_1 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 80, __pyx_L1_error) + __pyx_t_2 = (__pyx_t_1 != 0); + if (__pyx_t_2) { + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":81 + * try_key = (head_tail1, seq2) + * if try_key in _results: + * cand1 = _results[try_key] # <<<<<<<<<<<<<< + * else: + * # stack.append(key) + */ + __pyx_t_4 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 81, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_XDECREF_SET(__pyx_v_cand1, __pyx_t_4); + __pyx_t_4 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":80 + * # Case 2: The current edge in sequence1 is deleted + * try_key = (head_tail1, seq2) + * if try_key in _results: # <<<<<<<<<<<<<< + * cand1 = _results[try_key] + * else: + */ + goto __pyx_L21; + } + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":84 + * else: + * # stack.append(key) + * stack.append(try_key) # <<<<<<<<<<<<<< + * continue + * + */ + /*else*/ { + __pyx_t_16 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_try_key); if (unlikely(__pyx_t_16 == ((int)-1))) __PYX_ERR(0, 84, __pyx_L1_error) + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":85 + * # stack.append(key) + * stack.append(try_key) + * continue # <<<<<<<<<<<<<< + * + * # Case 3: The current edge in sequence2 is deleted + */ + goto __pyx_L12_continue; + } + __pyx_L21:; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":88 + * + * # Case 3: The current edge in sequence2 is deleted + * try_key = (seq1, head_tail2) # <<<<<<<<<<<<<< + * if try_key in _results: + * cand2 = _results[try_key] + */ + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 88, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(__pyx_v_seq1); + __Pyx_GIVEREF(__pyx_v_seq1); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_seq1); + __Pyx_INCREF(__pyx_v_head_tail2); + __Pyx_GIVEREF(__pyx_v_head_tail2); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_head_tail2); + __Pyx_DECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_4)); + __pyx_t_4 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":89 + * # Case 3: The current edge in sequence2 is deleted + * try_key = (seq1, head_tail2) + * if try_key in _results: # <<<<<<<<<<<<<< + * cand2 = _results[try_key] + * else: + */ + __pyx_t_2 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 89, __pyx_L1_error) + __pyx_t_1 = (__pyx_t_2 != 0); + if (__pyx_t_1) { + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":90 + * try_key = (seq1, head_tail2) + * if try_key in _results: + * cand2 = _results[try_key] # <<<<<<<<<<<<<< + * else: + * # stack.append(key) + */ + __pyx_t_4 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 90, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_XDECREF_SET(__pyx_v_cand2, __pyx_t_4); + __pyx_t_4 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":89 + * # Case 3: The current edge in sequence2 is deleted + * try_key = (seq1, head_tail2) + * if try_key in _results: # <<<<<<<<<<<<<< + * cand2 = _results[try_key] + * else: + */ + goto __pyx_L22; + } + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":93 + * else: + * # stack.append(key) + * stack.append(try_key) # <<<<<<<<<<<<<< + * continue + * + */ + /*else*/ { + __pyx_t_16 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_try_key); if (unlikely(__pyx_t_16 == ((int)-1))) __PYX_ERR(0, 93, __pyx_L1_error) + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":94 + * # stack.append(key) + * stack.append(try_key) + * continue # <<<<<<<<<<<<<< + * + * # Case 1: The LCS involves this edge + */ + goto __pyx_L12_continue; + } + __pyx_L22:; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":97 + * + * # Case 1: The LCS involves this edge + * affinity = node_affinity(t1, t2) # <<<<<<<<<<<<<< + * if affinity: + * try_key = (head1, head2) + */ + __Pyx_INCREF(__pyx_v_node_affinity); + __pyx_t_3 = __pyx_v_node_affinity; __pyx_t_5 = NULL; + __pyx_t_17 = 0; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_5)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + __pyx_t_17 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_3)) { + PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_v_t1, __pyx_v_t2}; + __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_17, 2+__pyx_t_17); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 97, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_GOTREF(__pyx_t_4); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) { + PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_v_t1, __pyx_v_t2}; + __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_17, 2+__pyx_t_17); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 97, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; + __Pyx_GOTREF(__pyx_t_4); + } else + #endif + { + __pyx_t_7 = PyTuple_New(2+__pyx_t_17); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 97, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + if (__pyx_t_5) { + __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL; + } + __Pyx_INCREF(__pyx_v_t1); + __Pyx_GIVEREF(__pyx_v_t1); + PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_17, __pyx_v_t1); + __Pyx_INCREF(__pyx_v_t2); + __Pyx_GIVEREF(__pyx_v_t2); + PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_17, __pyx_v_t2); + __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_7, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 97, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF_SET(__pyx_v_affinity, __pyx_t_4); + __pyx_t_4 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":98 + * # Case 1: The LCS involves this edge + * affinity = node_affinity(t1, t2) + * if affinity: # <<<<<<<<<<<<<< + * try_key = (head1, head2) + * if try_key in _results: + */ + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_affinity); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 98, __pyx_L1_error) + if (__pyx_t_1) { + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":99 + * affinity = node_affinity(t1, t2) + * if affinity: + * try_key = (head1, head2) # <<<<<<<<<<<<<< + * if try_key in _results: + * pval_h, new_heads = _results[try_key] + */ + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 99, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(__pyx_v_head1); + __Pyx_GIVEREF(__pyx_v_head1); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_head1); + __Pyx_INCREF(__pyx_v_head2); + __Pyx_GIVEREF(__pyx_v_head2); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_head2); + __Pyx_DECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_4)); + __pyx_t_4 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":100 + * if affinity: + * try_key = (head1, head2) + * if try_key in _results: # <<<<<<<<<<<<<< + * pval_h, new_heads = _results[try_key] + * else: + */ + __pyx_t_1 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 100, __pyx_L1_error) + __pyx_t_2 = (__pyx_t_1 != 0); + if (__pyx_t_2) { + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":101 + * try_key = (head1, head2) + * if try_key in _results: + * pval_h, new_heads = _results[try_key] # <<<<<<<<<<<<<< + * else: + * # stack.append(key) + */ + __pyx_t_4 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 101, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) { + PyObject* sequence = __pyx_t_4; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 101, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_7 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_3 = PyList_GET_ITEM(sequence, 0); + __pyx_t_7 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(__pyx_t_7); + #else + __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 101, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_7 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 101, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + #endif + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + } else { + Py_ssize_t index = -1; + __pyx_t_5 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 101, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_15 = Py_TYPE(__pyx_t_5)->tp_iternext; + index = 0; __pyx_t_3 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_3)) goto __pyx_L25_unpacking_failed; + __Pyx_GOTREF(__pyx_t_3); + index = 1; __pyx_t_7 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_7)) goto __pyx_L25_unpacking_failed; + __Pyx_GOTREF(__pyx_t_7); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_5), 2) < 0) __PYX_ERR(0, 101, __pyx_L1_error) + __pyx_t_15 = NULL; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + goto __pyx_L26_unpacking_done; + __pyx_L25_unpacking_failed:; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_15 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 101, __pyx_L1_error) + __pyx_L26_unpacking_done:; + } + __Pyx_XDECREF_SET(__pyx_v_pval_h, __pyx_t_3); + __pyx_t_3 = 0; + __Pyx_XDECREF_SET(__pyx_v_new_heads, __pyx_t_7); + __pyx_t_7 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":100 + * if affinity: + * try_key = (head1, head2) + * if try_key in _results: # <<<<<<<<<<<<<< + * pval_h, new_heads = _results[try_key] + * else: + */ + goto __pyx_L24; + } + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":104 + * else: + * # stack.append(key) + * stack.append(try_key) # <<<<<<<<<<<<<< + * continue + * + */ + /*else*/ { + __pyx_t_16 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_try_key); if (unlikely(__pyx_t_16 == ((int)-1))) __PYX_ERR(0, 104, __pyx_L1_error) + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":105 + * # stack.append(key) + * stack.append(try_key) + * continue # <<<<<<<<<<<<<< + * + * try_key = (tail1, tail2) + */ + goto __pyx_L12_continue; + } + __pyx_L24:; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":107 + * continue + * + * try_key = (tail1, tail2) # <<<<<<<<<<<<<< + * if try_key in _results: + * pval_t, new_tails = _results[try_key] + */ + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 107, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(__pyx_v_tail1); + __Pyx_GIVEREF(__pyx_v_tail1); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_tail1); + __Pyx_INCREF(__pyx_v_tail2); + __Pyx_GIVEREF(__pyx_v_tail2); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_tail2); + __Pyx_DECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_4)); + __pyx_t_4 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":108 + * + * try_key = (tail1, tail2) + * if try_key in _results: # <<<<<<<<<<<<<< + * pval_t, new_tails = _results[try_key] + * else: + */ + __pyx_t_2 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 108, __pyx_L1_error) + __pyx_t_1 = (__pyx_t_2 != 0); + if (__pyx_t_1) { + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":109 + * try_key = (tail1, tail2) + * if try_key in _results: + * pval_t, new_tails = _results[try_key] # <<<<<<<<<<<<<< + * else: + * # stack.append(key) + */ + __pyx_t_4 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 109, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) { + PyObject* sequence = __pyx_t_4; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 109, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_7 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_7 = PyList_GET_ITEM(sequence, 0); + __pyx_t_3 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(__pyx_t_3); + #else + __pyx_t_7 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 109, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 109, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + #endif + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + } else { + Py_ssize_t index = -1; + __pyx_t_5 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 109, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_15 = Py_TYPE(__pyx_t_5)->tp_iternext; + index = 0; __pyx_t_7 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_7)) goto __pyx_L28_unpacking_failed; + __Pyx_GOTREF(__pyx_t_7); + index = 1; __pyx_t_3 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_3)) goto __pyx_L28_unpacking_failed; + __Pyx_GOTREF(__pyx_t_3); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_5), 2) < 0) __PYX_ERR(0, 109, __pyx_L1_error) + __pyx_t_15 = NULL; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + goto __pyx_L29_unpacking_done; + __pyx_L28_unpacking_failed:; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_15 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 109, __pyx_L1_error) + __pyx_L29_unpacking_done:; + } + __Pyx_XDECREF_SET(__pyx_v_pval_t, __pyx_t_7); + __pyx_t_7 = 0; + __Pyx_XDECREF_SET(__pyx_v_new_tails, __pyx_t_3); + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":108 + * + * try_key = (tail1, tail2) + * if try_key in _results: # <<<<<<<<<<<<<< + * pval_t, new_tails = _results[try_key] + * else: + */ + goto __pyx_L27; + } + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":112 + * else: + * # stack.append(key) + * stack.append(try_key) # <<<<<<<<<<<<<< + * continue + * + */ + /*else*/ { + __pyx_t_16 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_try_key); if (unlikely(__pyx_t_16 == ((int)-1))) __PYX_ERR(0, 112, __pyx_L1_error) + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":113 + * # stack.append(key) + * stack.append(try_key) + * continue # <<<<<<<<<<<<<< + * + * new_head1, new_head2 = new_heads + */ + goto __pyx_L12_continue; + } + __pyx_L27:; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":115 + * continue + * + * new_head1, new_head2 = new_heads # <<<<<<<<<<<<<< + * new_tail1, new_tail2 = new_tails + * + */ + if ((likely(PyTuple_CheckExact(__pyx_v_new_heads))) || (PyList_CheckExact(__pyx_v_new_heads))) { + PyObject* sequence = __pyx_v_new_heads; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 115, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_4 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_4 = PyList_GET_ITEM(sequence, 0); + __pyx_t_3 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(__pyx_t_3); + #else + __pyx_t_4 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 115, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 115, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + #endif + } else { + Py_ssize_t index = -1; + __pyx_t_7 = PyObject_GetIter(__pyx_v_new_heads); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 115, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_15 = Py_TYPE(__pyx_t_7)->tp_iternext; + index = 0; __pyx_t_4 = __pyx_t_15(__pyx_t_7); if (unlikely(!__pyx_t_4)) goto __pyx_L30_unpacking_failed; + __Pyx_GOTREF(__pyx_t_4); + index = 1; __pyx_t_3 = __pyx_t_15(__pyx_t_7); if (unlikely(!__pyx_t_3)) goto __pyx_L30_unpacking_failed; + __Pyx_GOTREF(__pyx_t_3); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_7), 2) < 0) __PYX_ERR(0, 115, __pyx_L1_error) + __pyx_t_15 = NULL; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + goto __pyx_L31_unpacking_done; + __pyx_L30_unpacking_failed:; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_15 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 115, __pyx_L1_error) + __pyx_L31_unpacking_done:; + } + __Pyx_XDECREF_SET(__pyx_v_new_head1, __pyx_t_4); + __pyx_t_4 = 0; + __Pyx_XDECREF_SET(__pyx_v_new_head2, __pyx_t_3); + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":116 + * + * new_head1, new_head2 = new_heads + * new_tail1, new_tail2 = new_tails # <<<<<<<<<<<<<< + * + * subseq1 = a1 + new_head1 + b1 + new_tail1 + */ + if ((likely(PyTuple_CheckExact(__pyx_v_new_tails))) || (PyList_CheckExact(__pyx_v_new_tails))) { + PyObject* sequence = __pyx_v_new_tails; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 116, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_3 = PyList_GET_ITEM(sequence, 0); + __pyx_t_4 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(__pyx_t_4); + #else + __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 116, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 116, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + #endif + } else { + Py_ssize_t index = -1; + __pyx_t_7 = PyObject_GetIter(__pyx_v_new_tails); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 116, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_15 = Py_TYPE(__pyx_t_7)->tp_iternext; + index = 0; __pyx_t_3 = __pyx_t_15(__pyx_t_7); if (unlikely(!__pyx_t_3)) goto __pyx_L32_unpacking_failed; + __Pyx_GOTREF(__pyx_t_3); + index = 1; __pyx_t_4 = __pyx_t_15(__pyx_t_7); if (unlikely(!__pyx_t_4)) goto __pyx_L32_unpacking_failed; + __Pyx_GOTREF(__pyx_t_4); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_7), 2) < 0) __PYX_ERR(0, 116, __pyx_L1_error) + __pyx_t_15 = NULL; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + goto __pyx_L33_unpacking_done; + __pyx_L32_unpacking_failed:; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_15 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 116, __pyx_L1_error) + __pyx_L33_unpacking_done:; + } + __Pyx_XDECREF_SET(__pyx_v_new_tail1, __pyx_t_3); + __pyx_t_3 = 0; + __Pyx_XDECREF_SET(__pyx_v_new_tail2, __pyx_t_4); + __pyx_t_4 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":118 + * new_tail1, new_tail2 = new_tails + * + * subseq1 = a1 + new_head1 + b1 + new_tail1 # <<<<<<<<<<<<<< + * subseq2 = a2 + new_head2 + b2 + new_tail2 + * + */ + __pyx_t_4 = PyNumber_Add(__pyx_v_a1, __pyx_v_new_head1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 118, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = PyNumber_Add(__pyx_t_4, __pyx_v_b1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 118, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = PyNumber_Add(__pyx_t_3, __pyx_v_new_tail1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 118, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF_SET(__pyx_v_subseq1, __pyx_t_4); + __pyx_t_4 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":119 + * + * subseq1 = a1 + new_head1 + b1 + new_tail1 + * subseq2 = a2 + new_head2 + b2 + new_tail2 # <<<<<<<<<<<<<< + * + * res3 = (subseq1, subseq2) + */ + __pyx_t_4 = PyNumber_Add(__pyx_v_a2, __pyx_v_new_head2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 119, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = PyNumber_Add(__pyx_t_4, __pyx_v_b2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 119, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __pyx_t_4 = PyNumber_Add(__pyx_t_3, __pyx_v_new_tail2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 119, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF_SET(__pyx_v_subseq2, __pyx_t_4); + __pyx_t_4 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":121 + * subseq2 = a2 + new_head2 + b2 + new_tail2 + * + * res3 = (subseq1, subseq2) # <<<<<<<<<<<<<< + * val3 = pval_h + pval_t + affinity + * cand3 = (val3, res3) + */ + __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 121, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(__pyx_v_subseq1); + __Pyx_GIVEREF(__pyx_v_subseq1); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_subseq1); + __Pyx_INCREF(__pyx_v_subseq2); + __Pyx_GIVEREF(__pyx_v_subseq2); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_subseq2); + __Pyx_XDECREF_SET(__pyx_v_res3, ((PyObject*)__pyx_t_4)); + __pyx_t_4 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":122 + * + * res3 = (subseq1, subseq2) + * val3 = pval_h + pval_t + affinity # <<<<<<<<<<<<<< + * cand3 = (val3, res3) + * else: + */ + __pyx_t_4 = PyNumber_Add(__pyx_v_pval_h, __pyx_v_pval_t); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 122, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_3 = PyNumber_Add(__pyx_t_4, __pyx_v_affinity); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 122, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_XDECREF_SET(__pyx_v_val3, __pyx_t_3); + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":123 + * res3 = (subseq1, subseq2) + * val3 = pval_h + pval_t + affinity + * cand3 = (val3, res3) # <<<<<<<<<<<<<< + * else: + * cand3 = (-1, None) + */ + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 123, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(__pyx_v_val3); + __Pyx_GIVEREF(__pyx_v_val3); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_val3); + __Pyx_INCREF(__pyx_v_res3); + __Pyx_GIVEREF(__pyx_v_res3); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_res3); + __Pyx_XDECREF_SET(__pyx_v_cand3, ((PyObject*)__pyx_t_3)); + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":98 + * # Case 1: The LCS involves this edge + * affinity = node_affinity(t1, t2) + * if affinity: # <<<<<<<<<<<<<< + * try_key = (head1, head2) + * if try_key in _results: + */ + goto __pyx_L23; + } + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":125 + * cand3 = (val3, res3) + * else: + * cand3 = (-1, None) # <<<<<<<<<<<<<< + * + * # We solved the frame + */ + /*else*/ { + __Pyx_INCREF(__pyx_tuple_); + __Pyx_XDECREF_SET(__pyx_v_cand3, __pyx_tuple_); + } + __pyx_L23:; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":128 + * + * # We solved the frame + * _results[key] = max(cand1, cand2, cand3) # <<<<<<<<<<<<<< + * stack.pop() + * + */ + __Pyx_INCREF(__pyx_v_cand2); + __pyx_t_3 = __pyx_v_cand2; + __Pyx_INCREF(__pyx_v_cand3); + __pyx_t_18 = __pyx_v_cand3; + __Pyx_INCREF(__pyx_v_cand1); + __pyx_t_4 = __pyx_v_cand1; + __pyx_t_5 = PyObject_RichCompare(__pyx_t_3, __pyx_t_4, Py_GT); __Pyx_XGOTREF(__pyx_t_5); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 128, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 128, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_1) { + __Pyx_INCREF(__pyx_t_3); + __pyx_t_7 = __pyx_t_3; + } else { + __Pyx_INCREF(__pyx_t_4); + __pyx_t_7 = __pyx_t_4; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_INCREF(__pyx_t_7); + __pyx_t_4 = __pyx_t_7; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_5 = PyObject_RichCompare(__pyx_t_18, __pyx_t_4, Py_GT); __Pyx_XGOTREF(__pyx_t_5); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 128, __pyx_L1_error) + __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 128, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + if (__pyx_t_1) { + __Pyx_INCREF(__pyx_t_18); + __pyx_t_7 = __pyx_t_18; + } else { + __Pyx_INCREF(__pyx_t_4); + __pyx_t_7 = __pyx_t_4; + } + __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; + __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0; + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = __pyx_t_7; + __Pyx_INCREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_v_key, __pyx_t_3) < 0)) __PYX_ERR(0, 128, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":72 + * while stack: + * key = stack[-1] + * if key not in _results: # <<<<<<<<<<<<<< + * seq1, seq2 = key + * + */ + } + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":129 + * # We solved the frame + * _results[key] = max(cand1, cand2, cand3) + * stack.pop() # <<<<<<<<<<<<<< + * + * val, best = _results[key0] + */ + __pyx_t_3 = __Pyx_PyList_Pop(__pyx_v_stack); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 129, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_L12_continue:; + } + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":131 + * stack.pop() + * + * val, best = _results[key0] # <<<<<<<<<<<<<< + * found = (best, val) + * return found + */ + __pyx_t_3 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_key0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 131, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) { + PyObject* sequence = __pyx_t_3; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 131, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_7 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_7 = PyList_GET_ITEM(sequence, 0); + __pyx_t_4 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(__pyx_t_4); + #else + __pyx_t_7 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 131, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 131, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + #endif + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } else { + Py_ssize_t index = -1; + __pyx_t_5 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 131, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_15 = Py_TYPE(__pyx_t_5)->tp_iternext; + index = 0; __pyx_t_7 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_7)) goto __pyx_L34_unpacking_failed; + __Pyx_GOTREF(__pyx_t_7); + index = 1; __pyx_t_4 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_4)) goto __pyx_L34_unpacking_failed; + __Pyx_GOTREF(__pyx_t_4); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_5), 2) < 0) __PYX_ERR(0, 131, __pyx_L1_error) + __pyx_t_15 = NULL; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + goto __pyx_L35_unpacking_done; + __pyx_L34_unpacking_failed:; + __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; + __pyx_t_15 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 131, __pyx_L1_error) + __pyx_L35_unpacking_done:; + } + __pyx_v_val = __pyx_t_7; + __pyx_t_7 = 0; + __Pyx_DECREF_SET(__pyx_v_best, __pyx_t_4); + __pyx_t_4 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":132 + * + * val, best = _results[key0] + * found = (best, val) # <<<<<<<<<<<<<< + * return found + * + */ + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 132, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(__pyx_v_best); + __Pyx_GIVEREF(__pyx_v_best); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_best); + __Pyx_INCREF(__pyx_v_val); + __Pyx_GIVEREF(__pyx_v_val); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_val); + __pyx_v_found = ((PyObject*)__pyx_t_3); + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":133 + * val, best = _results[key0] + * found = (best, val) + * return found # <<<<<<<<<<<<<< + * + * + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_found); + __pyx_r = __pyx_v_found; + goto __pyx_L0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":35 + * + * + * def _lcs_iter_simple_alt2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node): # <<<<<<<<<<<<<< + * """ + * Depth first stack trajectory and replace try except statements with ifs + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_10); + __Pyx_XDECREF(__pyx_t_11); + __Pyx_XDECREF(__pyx_t_12); + __Pyx_XDECREF(__pyx_t_13); + __Pyx_XDECREF(__pyx_t_14); + __Pyx_XDECREF(__pyx_t_18); + __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython._lcs_iter_simple_alt2_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_all_decomp1); + __Pyx_XDECREF(__pyx_v_all_decomp2); + __Pyx_XDECREF(__pyx_v_key0); + __Pyx_XDECREF(__pyx_v_frame0); + __Pyx_XDECREF(__pyx_v_stack); + __Pyx_XDECREF(__pyx_v__results); + __Pyx_XDECREF(__pyx_v_empty1); + __Pyx_XDECREF(__pyx_v_empty2); + __Pyx_XDECREF(__pyx_v_best); + __Pyx_XDECREF(__pyx_v_base_result); + __Pyx_XDECREF(__pyx_v_seq1); + __Pyx_XDECREF(__pyx_v_key1); + __Pyx_XDECREF(__pyx_v_t1); + __Pyx_XDECREF(__pyx_v_a1); + __Pyx_XDECREF(__pyx_v_b1); + __Pyx_XDECREF(__pyx_v_head1); + __Pyx_XDECREF(__pyx_v_tail1); + __Pyx_XDECREF(__pyx_v_head_tail1); + __Pyx_XDECREF(__pyx_v_seq2); + __Pyx_XDECREF(__pyx_v_key2); + __Pyx_XDECREF(__pyx_v_t2); + __Pyx_XDECREF(__pyx_v_a2); + __Pyx_XDECREF(__pyx_v_b2); + __Pyx_XDECREF(__pyx_v_head2); + __Pyx_XDECREF(__pyx_v_tail2); + __Pyx_XDECREF(__pyx_v_head_tail2); + __Pyx_XDECREF(__pyx_v_key); + __Pyx_XDECREF(__pyx_v_try_key); + __Pyx_XDECREF(__pyx_v_cand1); + __Pyx_XDECREF(__pyx_v_cand2); + __Pyx_XDECREF(__pyx_v_affinity); + __Pyx_XDECREF(__pyx_v_pval_h); + __Pyx_XDECREF(__pyx_v_new_heads); + __Pyx_XDECREF(__pyx_v_pval_t); + __Pyx_XDECREF(__pyx_v_new_tails); + __Pyx_XDECREF(__pyx_v_new_head1); + __Pyx_XDECREF(__pyx_v_new_head2); + __Pyx_XDECREF(__pyx_v_new_tail1); + __Pyx_XDECREF(__pyx_v_new_tail2); + __Pyx_XDECREF(__pyx_v_subseq1); + __Pyx_XDECREF(__pyx_v_subseq2); + __Pyx_XDECREF(__pyx_v_res3); + __Pyx_XDECREF(__pyx_v_val3); + __Pyx_XDECREF(__pyx_v_cand3); + __Pyx_XDECREF(__pyx_v_val); + __Pyx_XDECREF(__pyx_v_found); + __Pyx_XDECREF(__pyx_v_open_to_node); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":136 + * + * + * def _lcs_iter_prehash2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node): # <<<<<<<<<<<<<< + * """ + * Version of the lcs iterative algorithm where we precompute hash values + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_3_lcs_iter_prehash2_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static char __pyx_doc_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_2_lcs_iter_prehash2_cython[] = "\n Version of the lcs iterative algorithm where we precompute hash values\n "; +static PyMethodDef __pyx_mdef_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_3_lcs_iter_prehash2_cython = {"_lcs_iter_prehash2_cython", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_3_lcs_iter_prehash2_cython, METH_VARARGS|METH_KEYWORDS, __pyx_doc_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_2_lcs_iter_prehash2_cython}; +static PyObject *__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_3_lcs_iter_prehash2_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + PyObject *__pyx_v_full_seq1 = 0; + PyObject *__pyx_v_full_seq2 = 0; + PyObject *__pyx_v_open_to_close = 0; + PyObject *__pyx_v_node_affinity = 0; + PyObject *__pyx_v_open_to_node = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("_lcs_iter_prehash2_cython (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_full_seq1,&__pyx_n_s_full_seq2,&__pyx_n_s_open_to_close,&__pyx_n_s_node_affinity,&__pyx_n_s_open_to_node,0}; + PyObject* values[5] = {0,0,0,0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4); + CYTHON_FALLTHROUGH; + case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); + CYTHON_FALLTHROUGH; + case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + CYTHON_FALLTHROUGH; + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_full_seq1)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_full_seq2)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("_lcs_iter_prehash2_cython", 1, 5, 5, 1); __PYX_ERR(0, 136, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 2: + if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_open_to_close)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("_lcs_iter_prehash2_cython", 1, 5, 5, 2); __PYX_ERR(0, 136, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 3: + if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_node_affinity)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("_lcs_iter_prehash2_cython", 1, 5, 5, 3); __PYX_ERR(0, 136, __pyx_L3_error) + } + CYTHON_FALLTHROUGH; + case 4: + if (likely((values[4] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_open_to_node)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("_lcs_iter_prehash2_cython", 1, 5, 5, 4); __PYX_ERR(0, 136, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "_lcs_iter_prehash2_cython") < 0)) __PYX_ERR(0, 136, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 5) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + values[2] = PyTuple_GET_ITEM(__pyx_args, 2); + values[3] = PyTuple_GET_ITEM(__pyx_args, 3); + values[4] = PyTuple_GET_ITEM(__pyx_args, 4); + } + __pyx_v_full_seq1 = values[0]; + __pyx_v_full_seq2 = values[1]; + __pyx_v_open_to_close = values[2]; + __pyx_v_node_affinity = values[3]; + __pyx_v_open_to_node = values[4]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("_lcs_iter_prehash2_cython", 1, 5, 5, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 136, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython._lcs_iter_prehash2_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_2_lcs_iter_prehash2_cython(__pyx_self, __pyx_v_full_seq1, __pyx_v_full_seq2, __pyx_v_open_to_close, __pyx_v_node_affinity, __pyx_v_open_to_node); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_2_lcs_iter_prehash2_cython(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_full_seq1, PyObject *__pyx_v_full_seq2, PyObject *__pyx_v_open_to_close, PyObject *__pyx_v_node_affinity, PyObject *__pyx_v_open_to_node) { + PyObject *__pyx_v_all_decomp1 = 0; + PyObject *__pyx_v_all_decomp2 = 0; + PyObject *__pyx_v_key_decomp1 = 0; + PyObject *__pyx_v_key_decomp2 = 0; + PyObject *__pyx_v__results = 0; + PyObject *__pyx_v_empty1 = NULL; + PyObject *__pyx_v_empty2 = NULL; + Py_hash_t __pyx_v_empty1_key; + Py_hash_t __pyx_v_empty2_key; + PyObject *__pyx_v_best = 0; + PyObject *__pyx_v_info1 = 0; + PyObject *__pyx_v_info2 = 0; + PyObject *__pyx_v_try_key = 0; + PyObject *__pyx_v_key = 0; + Py_hash_t __pyx_v_seq1_key; + Py_hash_t __pyx_v_seq2_key; + Py_hash_t __pyx_v_head1_key; + Py_hash_t __pyx_v_tail1_key; + Py_hash_t __pyx_v_head_tail1_key; + Py_hash_t __pyx_v_head2_key; + Py_hash_t __pyx_v_tail2_key; + Py_hash_t __pyx_v_head_tail2_key; + PyObject *__pyx_v_frame = 0; + PyObject *__pyx_v_miss_frame = 0; + PyObject *__pyx_v_base_result = NULL; + PyObject *__pyx_v_seq1 = NULL; + PyObject *__pyx_v_seq2 = NULL; + Py_hash_t __pyx_v_full_seq1_key; + Py_hash_t __pyx_v_full_seq2_key; + PyObject *__pyx_v_key0 = 0; + PyObject *__pyx_v_frame0 = 0; + PyObject *__pyx_v_stack = 0; + PyObject *__pyx_v_tok1 = NULL; + PyObject *__pyx_v_head1 = NULL; + PyObject *__pyx_v_tail1 = NULL; + PyObject *__pyx_v_head_tail1 = NULL; + PyObject *__pyx_v_a1 = NULL; + PyObject *__pyx_v_b1 = NULL; + PyObject *__pyx_v_tok2 = NULL; + PyObject *__pyx_v_head2 = NULL; + PyObject *__pyx_v_tail2 = NULL; + PyObject *__pyx_v_head_tail2 = NULL; + PyObject *__pyx_v_a2 = NULL; + PyObject *__pyx_v_b2 = NULL; + PyObject *__pyx_v_affinity = NULL; + PyObject *__pyx_v_cand1 = NULL; + PyObject *__pyx_v_cand2 = NULL; + PyObject *__pyx_v_pval_h = NULL; + PyObject *__pyx_v_new_heads = NULL; + PyObject *__pyx_v_pval_t = NULL; + PyObject *__pyx_v_new_tails = NULL; + PyObject *__pyx_v_new_head1 = NULL; + PyObject *__pyx_v_new_head2 = NULL; + PyObject *__pyx_v_new_tail1 = NULL; + PyObject *__pyx_v_new_tail2 = NULL; + PyObject *__pyx_v_subseq1 = NULL; + PyObject *__pyx_v_subseq2 = NULL; + PyObject *__pyx_v_res3 = NULL; + PyObject *__pyx_v_val3 = NULL; + PyObject *__pyx_v_cand3 = NULL; + PyObject *__pyx_v_val = NULL; + PyObject *__pyx_v_found = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + Py_hash_t __pyx_t_4; + Py_ssize_t __pyx_t_5; + PyObject *(*__pyx_t_6)(PyObject *); + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + PyObject *(*__pyx_t_9)(PyObject *); + PyObject *__pyx_t_10 = NULL; + Py_hash_t __pyx_t_11; + Py_hash_t __pyx_t_12; + int __pyx_t_13; + int __pyx_t_14; + PyObject *__pyx_t_15 = NULL; + PyObject *__pyx_t_16 = NULL; + PyObject *__pyx_t_17 = NULL; + PyObject *__pyx_t_18 = NULL; + int __pyx_t_19; + int __pyx_t_20; + PyObject *__pyx_t_21 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("_lcs_iter_prehash2_cython", 0); + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":140 + * Version of the lcs iterative algorithm where we precompute hash values + * """ + * cdef dict all_decomp1 = generate_all_decomp_prehash_cython(full_seq1, open_to_close, open_to_node) # <<<<<<<<<<<<<< + * cdef dict all_decomp2 = generate_all_decomp_prehash_cython(full_seq2, open_to_close, open_to_node) + * cdef dict key_decomp1 = {} + */ + if (!(likely(PyDict_CheckExact(__pyx_v_open_to_close))||((__pyx_v_open_to_close) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "dict", Py_TYPE(__pyx_v_open_to_close)->tp_name), 0))) __PYX_ERR(0, 140, __pyx_L1_error) + __pyx_t_1 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_prehash_cython(__pyx_v_full_seq1, ((PyObject*)__pyx_v_open_to_close), __pyx_v_open_to_node); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 140, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_all_decomp1 = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":141 + * """ + * cdef dict all_decomp1 = generate_all_decomp_prehash_cython(full_seq1, open_to_close, open_to_node) + * cdef dict all_decomp2 = generate_all_decomp_prehash_cython(full_seq2, open_to_close, open_to_node) # <<<<<<<<<<<<<< + * cdef dict key_decomp1 = {} + * cdef dict key_decomp2 = {} + */ + if (!(likely(PyDict_CheckExact(__pyx_v_open_to_close))||((__pyx_v_open_to_close) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "dict", Py_TYPE(__pyx_v_open_to_close)->tp_name), 0))) __PYX_ERR(0, 141, __pyx_L1_error) + __pyx_t_1 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_prehash_cython(__pyx_v_full_seq2, ((PyObject*)__pyx_v_open_to_close), __pyx_v_open_to_node); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 141, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_all_decomp2 = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":142 + * cdef dict all_decomp1 = generate_all_decomp_prehash_cython(full_seq1, open_to_close, open_to_node) + * cdef dict all_decomp2 = generate_all_decomp_prehash_cython(full_seq2, open_to_close, open_to_node) + * cdef dict key_decomp1 = {} # <<<<<<<<<<<<<< + * cdef dict key_decomp2 = {} + * + */ + __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 142, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_key_decomp1 = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":143 + * cdef dict all_decomp2 = generate_all_decomp_prehash_cython(full_seq2, open_to_close, open_to_node) + * cdef dict key_decomp1 = {} + * cdef dict key_decomp2 = {} # <<<<<<<<<<<<<< + * + * cdef dict _results = {} + */ + __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 143, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_key_decomp2 = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":145 + * cdef dict key_decomp2 = {} + * + * cdef dict _results = {} # <<<<<<<<<<<<<< + * # Populate base cases + * empty1 = type(next(iter(all_decomp1.keys())))() + */ + __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 145, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v__results = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":147 + * cdef dict _results = {} + * # Populate base cases + * empty1 = type(next(iter(all_decomp1.keys())))() # <<<<<<<<<<<<<< + * empty2 = type(next(iter(all_decomp2.keys())))() + * cdef Py_hash_t empty1_key = hash(empty1) + */ + if (unlikely(__pyx_v_all_decomp1 == Py_None)) { + PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "keys"); + __PYX_ERR(0, 147, __pyx_L1_error) + } + __pyx_t_2 = __Pyx_PyDict_Keys(__pyx_v_all_decomp1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 147, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 147, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = __Pyx_PyIter_Next(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 147, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_INCREF(((PyObject *)Py_TYPE(__pyx_t_2))); + __pyx_t_3 = ((PyObject *)Py_TYPE(__pyx_t_2)); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_2 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_2)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_2); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + } + } + __pyx_t_1 = (__pyx_t_2) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_2) : __Pyx_PyObject_CallNoArg(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 147, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_v_empty1 = __pyx_t_1; + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":148 + * # Populate base cases + * empty1 = type(next(iter(all_decomp1.keys())))() + * empty2 = type(next(iter(all_decomp2.keys())))() # <<<<<<<<<<<<<< + * cdef Py_hash_t empty1_key = hash(empty1) + * cdef Py_hash_t empty2_key = hash(empty2) + */ + if (unlikely(__pyx_v_all_decomp2 == Py_None)) { + PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "keys"); + __PYX_ERR(0, 148, __pyx_L1_error) + } + __pyx_t_3 = __Pyx_PyDict_Keys(__pyx_v_all_decomp2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 148, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_2 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 148, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = __Pyx_PyIter_Next(__pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 148, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_INCREF(((PyObject *)Py_TYPE(__pyx_t_3))); + __pyx_t_2 = ((PyObject *)Py_TYPE(__pyx_t_3)); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = NULL; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) { + __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2); + if (likely(__pyx_t_3)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_2, function); + } + } + __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; + if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 148, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_v_empty2 = __pyx_t_1; + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":149 + * empty1 = type(next(iter(all_decomp1.keys())))() + * empty2 = type(next(iter(all_decomp2.keys())))() + * cdef Py_hash_t empty1_key = hash(empty1) # <<<<<<<<<<<<<< + * cdef Py_hash_t empty2_key = hash(empty2) + * cdef tuple best = (empty1, empty2) + */ + __pyx_t_4 = PyObject_Hash(__pyx_v_empty1); if (unlikely(__pyx_t_4 == ((Py_hash_t)-1))) __PYX_ERR(0, 149, __pyx_L1_error) + __pyx_v_empty1_key = __pyx_t_4; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":150 + * empty2 = type(next(iter(all_decomp2.keys())))() + * cdef Py_hash_t empty1_key = hash(empty1) + * cdef Py_hash_t empty2_key = hash(empty2) # <<<<<<<<<<<<<< + * cdef tuple best = (empty1, empty2) + * + */ + __pyx_t_4 = PyObject_Hash(__pyx_v_empty2); if (unlikely(__pyx_t_4 == ((Py_hash_t)-1))) __PYX_ERR(0, 150, __pyx_L1_error) + __pyx_v_empty2_key = __pyx_t_4; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":151 + * cdef Py_hash_t empty1_key = hash(empty1) + * cdef Py_hash_t empty2_key = hash(empty2) + * cdef tuple best = (empty1, empty2) # <<<<<<<<<<<<<< + * + * cdef tuple info1, info2 + */ + __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 151, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v_empty1); + __Pyx_GIVEREF(__pyx_v_empty1); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_empty1); + __Pyx_INCREF(__pyx_v_empty2); + __Pyx_GIVEREF(__pyx_v_empty2); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_empty2); + __pyx_v_best = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":161 + * cdef tuple miss_frame + * + * base_result = (0, best) # <<<<<<<<<<<<<< + * for seq1, info1 in all_decomp1.items(): + * seq1_key = hash(seq1) + */ + __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 161, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_int_0); + __Pyx_GIVEREF(__pyx_int_0); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_int_0); + __Pyx_INCREF(__pyx_v_best); + __Pyx_GIVEREF(__pyx_v_best); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_best); + __pyx_v_base_result = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":162 + * + * base_result = (0, best) + * for seq1, info1 in all_decomp1.items(): # <<<<<<<<<<<<<< + * seq1_key = hash(seq1) + * head1_key, tail1_key, head_tail1_key = all_decomp1[seq1][5:8] + */ + if (unlikely(__pyx_v_all_decomp1 == Py_None)) { + PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "items"); + __PYX_ERR(0, 162, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_PyDict_Items(__pyx_v_all_decomp1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 162, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (likely(PyList_CheckExact(__pyx_t_1)) || PyTuple_CheckExact(__pyx_t_1)) { + __pyx_t_2 = __pyx_t_1; __Pyx_INCREF(__pyx_t_2); __pyx_t_5 = 0; + __pyx_t_6 = NULL; + } else { + __pyx_t_5 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 162, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_6 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 162, __pyx_L1_error) + } + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + for (;;) { + if (likely(!__pyx_t_6)) { + if (likely(PyList_CheckExact(__pyx_t_2))) { + if (__pyx_t_5 >= PyList_GET_SIZE(__pyx_t_2)) break; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_1 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_5); __Pyx_INCREF(__pyx_t_1); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 162, __pyx_L1_error) + #else + __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 162, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + #endif + } else { + if (__pyx_t_5 >= PyTuple_GET_SIZE(__pyx_t_2)) break; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_5); __Pyx_INCREF(__pyx_t_1); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 162, __pyx_L1_error) + #else + __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 162, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + #endif + } + } else { + __pyx_t_1 = __pyx_t_6(__pyx_t_2); + if (unlikely(!__pyx_t_1)) { + PyObject* exc_type = PyErr_Occurred(); + if (exc_type) { + if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear(); + else __PYX_ERR(0, 162, __pyx_L1_error) + } + break; + } + __Pyx_GOTREF(__pyx_t_1); + } + if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) { + PyObject* sequence = __pyx_t_1; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 162, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_7 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_3 = PyList_GET_ITEM(sequence, 0); + __pyx_t_7 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(__pyx_t_7); + #else + __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 162, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_7 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 162, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + #endif + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + } else { + Py_ssize_t index = -1; + __pyx_t_8 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 162, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_9 = Py_TYPE(__pyx_t_8)->tp_iternext; + index = 0; __pyx_t_3 = __pyx_t_9(__pyx_t_8); if (unlikely(!__pyx_t_3)) goto __pyx_L5_unpacking_failed; + __Pyx_GOTREF(__pyx_t_3); + index = 1; __pyx_t_7 = __pyx_t_9(__pyx_t_8); if (unlikely(!__pyx_t_7)) goto __pyx_L5_unpacking_failed; + __Pyx_GOTREF(__pyx_t_7); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_8), 2) < 0) __PYX_ERR(0, 162, __pyx_L1_error) + __pyx_t_9 = NULL; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + goto __pyx_L6_unpacking_done; + __pyx_L5_unpacking_failed:; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_9 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 162, __pyx_L1_error) + __pyx_L6_unpacking_done:; + } + if (!(likely(PyTuple_CheckExact(__pyx_t_7))||((__pyx_t_7) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_7)->tp_name), 0))) __PYX_ERR(0, 162, __pyx_L1_error) + __Pyx_XDECREF_SET(__pyx_v_seq1, __pyx_t_3); + __pyx_t_3 = 0; + __Pyx_XDECREF_SET(__pyx_v_info1, ((PyObject*)__pyx_t_7)); + __pyx_t_7 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":163 + * base_result = (0, best) + * for seq1, info1 in all_decomp1.items(): + * seq1_key = hash(seq1) # <<<<<<<<<<<<<< + * head1_key, tail1_key, head_tail1_key = all_decomp1[seq1][5:8] + * _results[(seq1_key, empty2_key)] = base_result + */ + __pyx_t_4 = PyObject_Hash(__pyx_v_seq1); if (unlikely(__pyx_t_4 == ((Py_hash_t)-1))) __PYX_ERR(0, 163, __pyx_L1_error) + __pyx_v_seq1_key = __pyx_t_4; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":164 + * for seq1, info1 in all_decomp1.items(): + * seq1_key = hash(seq1) + * head1_key, tail1_key, head_tail1_key = all_decomp1[seq1][5:8] # <<<<<<<<<<<<<< + * _results[(seq1_key, empty2_key)] = base_result + * _results[(head1_key, empty2_key)] = base_result + */ + if (unlikely(__pyx_v_all_decomp1 == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 164, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_PyDict_GetItem(__pyx_v_all_decomp1, __pyx_v_seq1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 164, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_7 = __Pyx_PyObject_GetSlice(__pyx_t_1, 5, 8, NULL, NULL, &__pyx_slice__2, 1, 1, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 164, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if ((likely(PyTuple_CheckExact(__pyx_t_7))) || (PyList_CheckExact(__pyx_t_7))) { + PyObject* sequence = __pyx_t_7; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 3)) { + if (size > 3) __Pyx_RaiseTooManyValuesError(3); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 164, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_1 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); + __pyx_t_8 = PyTuple_GET_ITEM(sequence, 2); + } else { + __pyx_t_1 = PyList_GET_ITEM(sequence, 0); + __pyx_t_3 = PyList_GET_ITEM(sequence, 1); + __pyx_t_8 = PyList_GET_ITEM(sequence, 2); + } + __Pyx_INCREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(__pyx_t_8); + #else + __pyx_t_1 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 164, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 164, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_8 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 164, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + #endif + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + } else { + Py_ssize_t index = -1; + __pyx_t_10 = PyObject_GetIter(__pyx_t_7); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 164, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_10); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_9 = Py_TYPE(__pyx_t_10)->tp_iternext; + index = 0; __pyx_t_1 = __pyx_t_9(__pyx_t_10); if (unlikely(!__pyx_t_1)) goto __pyx_L7_unpacking_failed; + __Pyx_GOTREF(__pyx_t_1); + index = 1; __pyx_t_3 = __pyx_t_9(__pyx_t_10); if (unlikely(!__pyx_t_3)) goto __pyx_L7_unpacking_failed; + __Pyx_GOTREF(__pyx_t_3); + index = 2; __pyx_t_8 = __pyx_t_9(__pyx_t_10); if (unlikely(!__pyx_t_8)) goto __pyx_L7_unpacking_failed; + __Pyx_GOTREF(__pyx_t_8); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_10), 3) < 0) __PYX_ERR(0, 164, __pyx_L1_error) + __pyx_t_9 = NULL; + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + goto __pyx_L8_unpacking_done; + __pyx_L7_unpacking_failed:; + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __pyx_t_9 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 164, __pyx_L1_error) + __pyx_L8_unpacking_done:; + } + __pyx_t_4 = __Pyx_PyInt_AsHash_t(__pyx_t_1); if (unlikely((__pyx_t_4 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 164, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_11 = __Pyx_PyInt_AsHash_t(__pyx_t_3); if (unlikely((__pyx_t_11 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 164, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_12 = __Pyx_PyInt_AsHash_t(__pyx_t_8); if (unlikely((__pyx_t_12 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 164, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_v_head1_key = __pyx_t_4; + __pyx_v_tail1_key = __pyx_t_11; + __pyx_v_head_tail1_key = __pyx_t_12; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":165 + * seq1_key = hash(seq1) + * head1_key, tail1_key, head_tail1_key = all_decomp1[seq1][5:8] + * _results[(seq1_key, empty2_key)] = base_result # <<<<<<<<<<<<<< + * _results[(head1_key, empty2_key)] = base_result + * _results[(tail1_key, empty2_key)] = base_result + */ + __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_seq1_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 165, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_empty2_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 165, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 165, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_GIVEREF(__pyx_t_7); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_7); + __Pyx_GIVEREF(__pyx_t_8); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_8); + __pyx_t_7 = 0; + __pyx_t_8 = 0; + if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 165, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":166 + * head1_key, tail1_key, head_tail1_key = all_decomp1[seq1][5:8] + * _results[(seq1_key, empty2_key)] = base_result + * _results[(head1_key, empty2_key)] = base_result # <<<<<<<<<<<<<< + * _results[(tail1_key, empty2_key)] = base_result + * _results[(head_tail1_key, empty2_key)] = base_result + */ + __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_head1_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 166, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_empty2_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 166, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 166, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_8); + PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_t_8); + __pyx_t_3 = 0; + __pyx_t_8 = 0; + if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_7, __pyx_v_base_result) < 0)) __PYX_ERR(0, 166, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":167 + * _results[(seq1_key, empty2_key)] = base_result + * _results[(head1_key, empty2_key)] = base_result + * _results[(tail1_key, empty2_key)] = base_result # <<<<<<<<<<<<<< + * _results[(head_tail1_key, empty2_key)] = base_result + * key_decomp1[seq1_key] = info1 + */ + __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_tail1_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 167, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_empty2_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 167, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 167, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_GIVEREF(__pyx_t_7); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_7); + __Pyx_GIVEREF(__pyx_t_8); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_8); + __pyx_t_7 = 0; + __pyx_t_8 = 0; + if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 167, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":168 + * _results[(head1_key, empty2_key)] = base_result + * _results[(tail1_key, empty2_key)] = base_result + * _results[(head_tail1_key, empty2_key)] = base_result # <<<<<<<<<<<<<< + * key_decomp1[seq1_key] = info1 + * + */ + __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_head_tail1_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 168, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_empty2_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 168, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 168, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_8); + PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_t_8); + __pyx_t_3 = 0; + __pyx_t_8 = 0; + if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_7, __pyx_v_base_result) < 0)) __PYX_ERR(0, 168, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":169 + * _results[(tail1_key, empty2_key)] = base_result + * _results[(head_tail1_key, empty2_key)] = base_result + * key_decomp1[seq1_key] = info1 # <<<<<<<<<<<<<< + * + * for seq2, info2 in all_decomp2.items(): + */ + __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_seq1_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 169, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + if (unlikely(PyDict_SetItem(__pyx_v_key_decomp1, __pyx_t_7, __pyx_v_info1) < 0)) __PYX_ERR(0, 169, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":162 + * + * base_result = (0, best) + * for seq1, info1 in all_decomp1.items(): # <<<<<<<<<<<<<< + * seq1_key = hash(seq1) + * head1_key, tail1_key, head_tail1_key = all_decomp1[seq1][5:8] + */ + } + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":171 + * key_decomp1[seq1_key] = info1 + * + * for seq2, info2 in all_decomp2.items(): # <<<<<<<<<<<<<< + * seq2_key = hash(seq2) + * head2_key, tail2_key, head_tail2_key = all_decomp2[seq2][5:8] + */ + if (unlikely(__pyx_v_all_decomp2 == Py_None)) { + PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "items"); + __PYX_ERR(0, 171, __pyx_L1_error) + } + __pyx_t_2 = __Pyx_PyDict_Items(__pyx_v_all_decomp2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 171, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (likely(PyList_CheckExact(__pyx_t_2)) || PyTuple_CheckExact(__pyx_t_2)) { + __pyx_t_7 = __pyx_t_2; __Pyx_INCREF(__pyx_t_7); __pyx_t_5 = 0; + __pyx_t_6 = NULL; + } else { + __pyx_t_5 = -1; __pyx_t_7 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 171, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_6 = Py_TYPE(__pyx_t_7)->tp_iternext; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 171, __pyx_L1_error) + } + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + for (;;) { + if (likely(!__pyx_t_6)) { + if (likely(PyList_CheckExact(__pyx_t_7))) { + if (__pyx_t_5 >= PyList_GET_SIZE(__pyx_t_7)) break; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_2 = PyList_GET_ITEM(__pyx_t_7, __pyx_t_5); __Pyx_INCREF(__pyx_t_2); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 171, __pyx_L1_error) + #else + __pyx_t_2 = PySequence_ITEM(__pyx_t_7, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 171, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + #endif + } else { + if (__pyx_t_5 >= PyTuple_GET_SIZE(__pyx_t_7)) break; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_7, __pyx_t_5); __Pyx_INCREF(__pyx_t_2); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 171, __pyx_L1_error) + #else + __pyx_t_2 = PySequence_ITEM(__pyx_t_7, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 171, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + #endif + } + } else { + __pyx_t_2 = __pyx_t_6(__pyx_t_7); + if (unlikely(!__pyx_t_2)) { + PyObject* exc_type = PyErr_Occurred(); + if (exc_type) { + if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear(); + else __PYX_ERR(0, 171, __pyx_L1_error) + } + break; + } + __Pyx_GOTREF(__pyx_t_2); + } + if ((likely(PyTuple_CheckExact(__pyx_t_2))) || (PyList_CheckExact(__pyx_t_2))) { + PyObject* sequence = __pyx_t_2; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 171, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_8 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_8 = PyList_GET_ITEM(sequence, 0); + __pyx_t_3 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(__pyx_t_3); + #else + __pyx_t_8 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 171, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 171, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + #endif + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + } else { + Py_ssize_t index = -1; + __pyx_t_1 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 171, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext; + index = 0; __pyx_t_8 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_8)) goto __pyx_L11_unpacking_failed; + __Pyx_GOTREF(__pyx_t_8); + index = 1; __pyx_t_3 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_3)) goto __pyx_L11_unpacking_failed; + __Pyx_GOTREF(__pyx_t_3); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_1), 2) < 0) __PYX_ERR(0, 171, __pyx_L1_error) + __pyx_t_9 = NULL; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + goto __pyx_L12_unpacking_done; + __pyx_L11_unpacking_failed:; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_9 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 171, __pyx_L1_error) + __pyx_L12_unpacking_done:; + } + if (!(likely(PyTuple_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_3)->tp_name), 0))) __PYX_ERR(0, 171, __pyx_L1_error) + __Pyx_XDECREF_SET(__pyx_v_seq2, __pyx_t_8); + __pyx_t_8 = 0; + __Pyx_XDECREF_SET(__pyx_v_info2, ((PyObject*)__pyx_t_3)); + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":172 + * + * for seq2, info2 in all_decomp2.items(): + * seq2_key = hash(seq2) # <<<<<<<<<<<<<< + * head2_key, tail2_key, head_tail2_key = all_decomp2[seq2][5:8] + * _results[(empty1_key, seq2_key)] = base_result + */ + __pyx_t_12 = PyObject_Hash(__pyx_v_seq2); if (unlikely(__pyx_t_12 == ((Py_hash_t)-1))) __PYX_ERR(0, 172, __pyx_L1_error) + __pyx_v_seq2_key = __pyx_t_12; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":173 + * for seq2, info2 in all_decomp2.items(): + * seq2_key = hash(seq2) + * head2_key, tail2_key, head_tail2_key = all_decomp2[seq2][5:8] # <<<<<<<<<<<<<< + * _results[(empty1_key, seq2_key)] = base_result + * _results[(empty1_key, head2_key)] = base_result + */ + if (unlikely(__pyx_v_all_decomp2 == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 173, __pyx_L1_error) + } + __pyx_t_2 = __Pyx_PyDict_GetItem(__pyx_v_all_decomp2, __pyx_v_seq2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 173, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_3 = __Pyx_PyObject_GetSlice(__pyx_t_2, 5, 8, NULL, NULL, &__pyx_slice__2, 1, 1, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 173, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) { + PyObject* sequence = __pyx_t_3; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 3)) { + if (size > 3) __Pyx_RaiseTooManyValuesError(3); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 173, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_8 = PyTuple_GET_ITEM(sequence, 1); + __pyx_t_1 = PyTuple_GET_ITEM(sequence, 2); + } else { + __pyx_t_2 = PyList_GET_ITEM(sequence, 0); + __pyx_t_8 = PyList_GET_ITEM(sequence, 1); + __pyx_t_1 = PyList_GET_ITEM(sequence, 2); + } + __Pyx_INCREF(__pyx_t_2); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(__pyx_t_1); + #else + __pyx_t_2 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 173, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __pyx_t_8 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 173, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_1 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 173, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + #endif + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } else { + Py_ssize_t index = -1; + __pyx_t_10 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 173, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_10); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_9 = Py_TYPE(__pyx_t_10)->tp_iternext; + index = 0; __pyx_t_2 = __pyx_t_9(__pyx_t_10); if (unlikely(!__pyx_t_2)) goto __pyx_L13_unpacking_failed; + __Pyx_GOTREF(__pyx_t_2); + index = 1; __pyx_t_8 = __pyx_t_9(__pyx_t_10); if (unlikely(!__pyx_t_8)) goto __pyx_L13_unpacking_failed; + __Pyx_GOTREF(__pyx_t_8); + index = 2; __pyx_t_1 = __pyx_t_9(__pyx_t_10); if (unlikely(!__pyx_t_1)) goto __pyx_L13_unpacking_failed; + __Pyx_GOTREF(__pyx_t_1); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_10), 3) < 0) __PYX_ERR(0, 173, __pyx_L1_error) + __pyx_t_9 = NULL; + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + goto __pyx_L14_unpacking_done; + __pyx_L13_unpacking_failed:; + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __pyx_t_9 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 173, __pyx_L1_error) + __pyx_L14_unpacking_done:; + } + __pyx_t_12 = __Pyx_PyInt_AsHash_t(__pyx_t_2); if (unlikely((__pyx_t_12 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 173, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_11 = __Pyx_PyInt_AsHash_t(__pyx_t_8); if (unlikely((__pyx_t_11 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 173, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_4 = __Pyx_PyInt_AsHash_t(__pyx_t_1); if (unlikely((__pyx_t_4 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 173, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_head2_key = __pyx_t_12; + __pyx_v_tail2_key = __pyx_t_11; + __pyx_v_head_tail2_key = __pyx_t_4; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":174 + * seq2_key = hash(seq2) + * head2_key, tail2_key, head_tail2_key = all_decomp2[seq2][5:8] + * _results[(empty1_key, seq2_key)] = base_result # <<<<<<<<<<<<<< + * _results[(empty1_key, head2_key)] = base_result + * _results[(empty1_key, tail2_key)] = base_result + */ + __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_empty1_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 174, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_1 = __Pyx_PyInt_FromHash_t(__pyx_v_seq2_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 174, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 174, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_1); + __pyx_t_3 = 0; + __pyx_t_1 = 0; + if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_8, __pyx_v_base_result) < 0)) __PYX_ERR(0, 174, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":175 + * head2_key, tail2_key, head_tail2_key = all_decomp2[seq2][5:8] + * _results[(empty1_key, seq2_key)] = base_result + * _results[(empty1_key, head2_key)] = base_result # <<<<<<<<<<<<<< + * _results[(empty1_key, tail2_key)] = base_result + * _results[(empty1_key, head_tail2_key)] = base_result + */ + __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_empty1_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 175, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_1 = __Pyx_PyInt_FromHash_t(__pyx_v_head2_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 175, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 175, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_GIVEREF(__pyx_t_8); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_8); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_1); + __pyx_t_8 = 0; + __pyx_t_1 = 0; + if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 175, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":176 + * _results[(empty1_key, seq2_key)] = base_result + * _results[(empty1_key, head2_key)] = base_result + * _results[(empty1_key, tail2_key)] = base_result # <<<<<<<<<<<<<< + * _results[(empty1_key, head_tail2_key)] = base_result + * key_decomp2[seq2_key] = info2 + */ + __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_empty1_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 176, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_1 = __Pyx_PyInt_FromHash_t(__pyx_v_tail2_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 176, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 176, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_3); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_1); + __pyx_t_3 = 0; + __pyx_t_1 = 0; + if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_8, __pyx_v_base_result) < 0)) __PYX_ERR(0, 176, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":177 + * _results[(empty1_key, head2_key)] = base_result + * _results[(empty1_key, tail2_key)] = base_result + * _results[(empty1_key, head_tail2_key)] = base_result # <<<<<<<<<<<<<< + * key_decomp2[seq2_key] = info2 + * + */ + __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_empty1_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 177, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_1 = __Pyx_PyInt_FromHash_t(__pyx_v_head_tail2_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 177, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 177, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_GIVEREF(__pyx_t_8); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_8); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_1); + __pyx_t_8 = 0; + __pyx_t_1 = 0; + if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 177, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":178 + * _results[(empty1_key, tail2_key)] = base_result + * _results[(empty1_key, head_tail2_key)] = base_result + * key_decomp2[seq2_key] = info2 # <<<<<<<<<<<<<< + * + * cdef Py_hash_t full_seq1_key = hash(full_seq1) + */ + __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_seq2_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 178, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + if (unlikely(PyDict_SetItem(__pyx_v_key_decomp2, __pyx_t_3, __pyx_v_info2) < 0)) __PYX_ERR(0, 178, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":171 + * key_decomp1[seq1_key] = info1 + * + * for seq2, info2 in all_decomp2.items(): # <<<<<<<<<<<<<< + * seq2_key = hash(seq2) + * head2_key, tail2_key, head_tail2_key = all_decomp2[seq2][5:8] + */ + } + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":180 + * key_decomp2[seq2_key] = info2 + * + * cdef Py_hash_t full_seq1_key = hash(full_seq1) # <<<<<<<<<<<<<< + * cdef Py_hash_t full_seq2_key = hash(full_seq2) + * + */ + __pyx_t_4 = PyObject_Hash(__pyx_v_full_seq1); if (unlikely(__pyx_t_4 == ((Py_hash_t)-1))) __PYX_ERR(0, 180, __pyx_L1_error) + __pyx_v_full_seq1_key = __pyx_t_4; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":181 + * + * cdef Py_hash_t full_seq1_key = hash(full_seq1) + * cdef Py_hash_t full_seq2_key = hash(full_seq2) # <<<<<<<<<<<<<< + * + * cdef tuple key0 = (full_seq1_key, full_seq2_key) + */ + __pyx_t_4 = PyObject_Hash(__pyx_v_full_seq2); if (unlikely(__pyx_t_4 == ((Py_hash_t)-1))) __PYX_ERR(0, 181, __pyx_L1_error) + __pyx_v_full_seq2_key = __pyx_t_4; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":183 + * cdef Py_hash_t full_seq2_key = hash(full_seq2) + * + * cdef tuple key0 = (full_seq1_key, full_seq2_key) # <<<<<<<<<<<<<< + * cdef tuple frame0 = (key0, full_seq1, full_seq2) + * cdef list stack = [frame0] + */ + __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_full_seq1_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 183, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_full_seq2_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 183, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 183, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_GIVEREF(__pyx_t_7); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_7); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_3); + __pyx_t_7 = 0; + __pyx_t_3 = 0; + __pyx_v_key0 = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":184 + * + * cdef tuple key0 = (full_seq1_key, full_seq2_key) + * cdef tuple frame0 = (key0, full_seq1, full_seq2) # <<<<<<<<<<<<<< + * cdef list stack = [frame0] + * + */ + __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 184, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v_key0); + __Pyx_GIVEREF(__pyx_v_key0); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_key0); + __Pyx_INCREF(__pyx_v_full_seq1); + __Pyx_GIVEREF(__pyx_v_full_seq1); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_full_seq1); + __Pyx_INCREF(__pyx_v_full_seq2); + __Pyx_GIVEREF(__pyx_v_full_seq2); + PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_full_seq2); + __pyx_v_frame0 = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":185 + * cdef tuple key0 = (full_seq1_key, full_seq2_key) + * cdef tuple frame0 = (key0, full_seq1, full_seq2) + * cdef list stack = [frame0] # <<<<<<<<<<<<<< + * + * while stack: + */ + __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 185, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v_frame0); + __Pyx_GIVEREF(__pyx_v_frame0); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_v_frame0); + __pyx_v_stack = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":187 + * cdef list stack = [frame0] + * + * while stack: # <<<<<<<<<<<<<< + * frame = stack[-1] + * key, seq1, seq2 = frame + */ + while (1) { + __pyx_t_13 = (PyList_GET_SIZE(__pyx_v_stack) != 0); + if (!__pyx_t_13) break; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":188 + * + * while stack: + * frame = stack[-1] # <<<<<<<<<<<<<< + * key, seq1, seq2 = frame + * seq1_key, seq2_key = key + */ + __pyx_t_1 = __Pyx_GetItemInt_List(__pyx_v_stack, -1L, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 188, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (!(likely(PyTuple_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(0, 188, __pyx_L1_error) + __Pyx_XDECREF_SET(__pyx_v_frame, ((PyObject*)__pyx_t_1)); + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":189 + * while stack: + * frame = stack[-1] + * key, seq1, seq2 = frame # <<<<<<<<<<<<<< + * seq1_key, seq2_key = key + * if key not in _results: + */ + if (likely(__pyx_v_frame != Py_None)) { + PyObject* sequence = __pyx_v_frame; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 3)) { + if (size > 3) __Pyx_RaiseTooManyValuesError(3); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 189, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_1 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); + __pyx_t_7 = PyTuple_GET_ITEM(sequence, 2); + __Pyx_INCREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(__pyx_t_7); + #else + __pyx_t_1 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 189, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 189, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_7 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 189, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + #endif + } else { + __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 189, __pyx_L1_error) + } + if (!(likely(PyTuple_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(0, 189, __pyx_L1_error) + __Pyx_XDECREF_SET(__pyx_v_key, ((PyObject*)__pyx_t_1)); + __pyx_t_1 = 0; + __Pyx_XDECREF_SET(__pyx_v_seq1, __pyx_t_3); + __pyx_t_3 = 0; + __Pyx_XDECREF_SET(__pyx_v_seq2, __pyx_t_7); + __pyx_t_7 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":190 + * frame = stack[-1] + * key, seq1, seq2 = frame + * seq1_key, seq2_key = key # <<<<<<<<<<<<<< + * if key not in _results: + * info1 = key_decomp1[seq1_key] + */ + if (likely(__pyx_v_key != Py_None)) { + PyObject* sequence = __pyx_v_key; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 190, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_7 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(__pyx_t_3); + #else + __pyx_t_7 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 190, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 190, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + #endif + } else { + __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 190, __pyx_L1_error) + } + __pyx_t_4 = __Pyx_PyInt_AsHash_t(__pyx_t_7); if (unlikely((__pyx_t_4 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 190, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_11 = __Pyx_PyInt_AsHash_t(__pyx_t_3); if (unlikely((__pyx_t_11 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 190, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_v_seq1_key = __pyx_t_4; + __pyx_v_seq2_key = __pyx_t_11; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":191 + * key, seq1, seq2 = frame + * seq1_key, seq2_key = key + * if key not in _results: # <<<<<<<<<<<<<< + * info1 = key_decomp1[seq1_key] + * tok1, seq1, head1, tail1, head_tail1, head1_key, tail1_key, head_tail1_key, a1, b1 = info1 + */ + __pyx_t_13 = (__Pyx_PyDict_ContainsTF(__pyx_v_key, __pyx_v__results, Py_NE)); if (unlikely(__pyx_t_13 < 0)) __PYX_ERR(0, 191, __pyx_L1_error) + __pyx_t_14 = (__pyx_t_13 != 0); + if (__pyx_t_14) { + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":192 + * seq1_key, seq2_key = key + * if key not in _results: + * info1 = key_decomp1[seq1_key] # <<<<<<<<<<<<<< + * tok1, seq1, head1, tail1, head_tail1, head1_key, tail1_key, head_tail1_key, a1, b1 = info1 + * + */ + __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_seq1_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 192, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_7 = __Pyx_PyDict_GetItem(__pyx_v_key_decomp1, __pyx_t_3); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 192, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + if (!(likely(PyTuple_CheckExact(__pyx_t_7))||((__pyx_t_7) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_7)->tp_name), 0))) __PYX_ERR(0, 192, __pyx_L1_error) + __Pyx_XDECREF_SET(__pyx_v_info1, ((PyObject*)__pyx_t_7)); + __pyx_t_7 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":193 + * if key not in _results: + * info1 = key_decomp1[seq1_key] + * tok1, seq1, head1, tail1, head_tail1, head1_key, tail1_key, head_tail1_key, a1, b1 = info1 # <<<<<<<<<<<<<< + * + * info2 = key_decomp2[seq2_key] + */ + if (likely(__pyx_v_info1 != Py_None)) { + PyObject* sequence = __pyx_v_info1; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 10)) { + if (size > 10) __Pyx_RaiseTooManyValuesError(10); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 193, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_7 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); + __pyx_t_1 = PyTuple_GET_ITEM(sequence, 2); + __pyx_t_8 = PyTuple_GET_ITEM(sequence, 3); + __pyx_t_2 = PyTuple_GET_ITEM(sequence, 4); + __pyx_t_10 = PyTuple_GET_ITEM(sequence, 5); + __pyx_t_15 = PyTuple_GET_ITEM(sequence, 6); + __pyx_t_16 = PyTuple_GET_ITEM(sequence, 7); + __pyx_t_17 = PyTuple_GET_ITEM(sequence, 8); + __pyx_t_18 = PyTuple_GET_ITEM(sequence, 9); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(__pyx_t_2); + __Pyx_INCREF(__pyx_t_10); + __Pyx_INCREF(__pyx_t_15); + __Pyx_INCREF(__pyx_t_16); + __Pyx_INCREF(__pyx_t_17); + __Pyx_INCREF(__pyx_t_18); + #else + { + Py_ssize_t i; + PyObject** temps[10] = {&__pyx_t_7,&__pyx_t_3,&__pyx_t_1,&__pyx_t_8,&__pyx_t_2,&__pyx_t_10,&__pyx_t_15,&__pyx_t_16,&__pyx_t_17,&__pyx_t_18}; + for (i=0; i < 10; i++) { + PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 193, __pyx_L1_error) + __Pyx_GOTREF(item); + *(temps[i]) = item; + } + } + #endif + } else { + __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 193, __pyx_L1_error) + } + __pyx_t_11 = __Pyx_PyInt_AsHash_t(__pyx_t_10); if (unlikely((__pyx_t_11 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 193, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; + __pyx_t_4 = __Pyx_PyInt_AsHash_t(__pyx_t_15); if (unlikely((__pyx_t_4 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 193, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0; + __pyx_t_12 = __Pyx_PyInt_AsHash_t(__pyx_t_16); if (unlikely((__pyx_t_12 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 193, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0; + __Pyx_XDECREF_SET(__pyx_v_tok1, __pyx_t_7); + __pyx_t_7 = 0; + __Pyx_DECREF_SET(__pyx_v_seq1, __pyx_t_3); + __pyx_t_3 = 0; + __Pyx_XDECREF_SET(__pyx_v_head1, __pyx_t_1); + __pyx_t_1 = 0; + __Pyx_XDECREF_SET(__pyx_v_tail1, __pyx_t_8); + __pyx_t_8 = 0; + __Pyx_XDECREF_SET(__pyx_v_head_tail1, __pyx_t_2); + __pyx_t_2 = 0; + __pyx_v_head1_key = __pyx_t_11; + __pyx_v_tail1_key = __pyx_t_4; + __pyx_v_head_tail1_key = __pyx_t_12; + __Pyx_XDECREF_SET(__pyx_v_a1, __pyx_t_17); + __pyx_t_17 = 0; + __Pyx_XDECREF_SET(__pyx_v_b1, __pyx_t_18); + __pyx_t_18 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":195 + * tok1, seq1, head1, tail1, head_tail1, head1_key, tail1_key, head_tail1_key, a1, b1 = info1 + * + * info2 = key_decomp2[seq2_key] # <<<<<<<<<<<<<< + * tok2, seq2, head2, tail2, head_tail2, head2_key, tail2_key, head_tail2_key, a2, b2 = info2 + * + */ + __pyx_t_18 = __Pyx_PyInt_FromHash_t(__pyx_v_seq2_key); if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 195, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_18); + __pyx_t_17 = __Pyx_PyDict_GetItem(__pyx_v_key_decomp2, __pyx_t_18); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 195, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_17); + __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0; + if (!(likely(PyTuple_CheckExact(__pyx_t_17))||((__pyx_t_17) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_17)->tp_name), 0))) __PYX_ERR(0, 195, __pyx_L1_error) + __Pyx_XDECREF_SET(__pyx_v_info2, ((PyObject*)__pyx_t_17)); + __pyx_t_17 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":196 + * + * info2 = key_decomp2[seq2_key] + * tok2, seq2, head2, tail2, head_tail2, head2_key, tail2_key, head_tail2_key, a2, b2 = info2 # <<<<<<<<<<<<<< + * + * affinity = node_affinity(tok1, tok2) + */ + if (likely(__pyx_v_info2 != Py_None)) { + PyObject* sequence = __pyx_v_info2; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 10)) { + if (size > 10) __Pyx_RaiseTooManyValuesError(10); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 196, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_17 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_18 = PyTuple_GET_ITEM(sequence, 1); + __pyx_t_16 = PyTuple_GET_ITEM(sequence, 2); + __pyx_t_15 = PyTuple_GET_ITEM(sequence, 3); + __pyx_t_10 = PyTuple_GET_ITEM(sequence, 4); + __pyx_t_2 = PyTuple_GET_ITEM(sequence, 5); + __pyx_t_8 = PyTuple_GET_ITEM(sequence, 6); + __pyx_t_1 = PyTuple_GET_ITEM(sequence, 7); + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 8); + __pyx_t_7 = PyTuple_GET_ITEM(sequence, 9); + __Pyx_INCREF(__pyx_t_17); + __Pyx_INCREF(__pyx_t_18); + __Pyx_INCREF(__pyx_t_16); + __Pyx_INCREF(__pyx_t_15); + __Pyx_INCREF(__pyx_t_10); + __Pyx_INCREF(__pyx_t_2); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(__pyx_t_1); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(__pyx_t_7); + #else + { + Py_ssize_t i; + PyObject** temps[10] = {&__pyx_t_17,&__pyx_t_18,&__pyx_t_16,&__pyx_t_15,&__pyx_t_10,&__pyx_t_2,&__pyx_t_8,&__pyx_t_1,&__pyx_t_3,&__pyx_t_7}; + for (i=0; i < 10; i++) { + PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 196, __pyx_L1_error) + __Pyx_GOTREF(item); + *(temps[i]) = item; + } + } + #endif + } else { + __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 196, __pyx_L1_error) + } + __pyx_t_12 = __Pyx_PyInt_AsHash_t(__pyx_t_2); if (unlikely((__pyx_t_12 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 196, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __pyx_t_4 = __Pyx_PyInt_AsHash_t(__pyx_t_8); if (unlikely((__pyx_t_4 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 196, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_11 = __Pyx_PyInt_AsHash_t(__pyx_t_1); if (unlikely((__pyx_t_11 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 196, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF_SET(__pyx_v_tok2, __pyx_t_17); + __pyx_t_17 = 0; + __Pyx_DECREF_SET(__pyx_v_seq2, __pyx_t_18); + __pyx_t_18 = 0; + __Pyx_XDECREF_SET(__pyx_v_head2, __pyx_t_16); + __pyx_t_16 = 0; + __Pyx_XDECREF_SET(__pyx_v_tail2, __pyx_t_15); + __pyx_t_15 = 0; + __Pyx_XDECREF_SET(__pyx_v_head_tail2, __pyx_t_10); + __pyx_t_10 = 0; + __pyx_v_head2_key = __pyx_t_12; + __pyx_v_tail2_key = __pyx_t_4; + __pyx_v_head_tail2_key = __pyx_t_11; + __Pyx_XDECREF_SET(__pyx_v_a2, __pyx_t_3); + __pyx_t_3 = 0; + __Pyx_XDECREF_SET(__pyx_v_b2, __pyx_t_7); + __pyx_t_7 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":198 + * tok2, seq2, head2, tail2, head_tail2, head2_key, tail2_key, head_tail2_key, a2, b2 = info2 + * + * affinity = node_affinity(tok1, tok2) # <<<<<<<<<<<<<< + * + * # Case 2: The current edge in sequence1 is deleted + */ + __Pyx_INCREF(__pyx_v_node_affinity); + __pyx_t_3 = __pyx_v_node_affinity; __pyx_t_1 = NULL; + __pyx_t_19 = 0; + if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { + __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_3); + if (likely(__pyx_t_1)) { + PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); + __Pyx_INCREF(__pyx_t_1); + __Pyx_INCREF(function); + __Pyx_DECREF_SET(__pyx_t_3, function); + __pyx_t_19 = 1; + } + } + #if CYTHON_FAST_PYCALL + if (PyFunction_Check(__pyx_t_3)) { + PyObject *__pyx_temp[3] = {__pyx_t_1, __pyx_v_tok1, __pyx_v_tok2}; + __pyx_t_7 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_19, 2+__pyx_t_19); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 198, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_GOTREF(__pyx_t_7); + } else + #endif + #if CYTHON_FAST_PYCCALL + if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) { + PyObject *__pyx_temp[3] = {__pyx_t_1, __pyx_v_tok1, __pyx_v_tok2}; + __pyx_t_7 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_19, 2+__pyx_t_19); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 198, __pyx_L1_error) + __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_GOTREF(__pyx_t_7); + } else + #endif + { + __pyx_t_8 = PyTuple_New(2+__pyx_t_19); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 198, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + if (__pyx_t_1) { + __Pyx_GIVEREF(__pyx_t_1); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_1); __pyx_t_1 = NULL; + } + __Pyx_INCREF(__pyx_v_tok1); + __Pyx_GIVEREF(__pyx_v_tok1); + PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_19, __pyx_v_tok1); + __Pyx_INCREF(__pyx_v_tok2); + __Pyx_GIVEREF(__pyx_v_tok2); + PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_19, __pyx_v_tok2); + __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_8, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 198, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + } + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF_SET(__pyx_v_affinity, __pyx_t_7); + __pyx_t_7 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":201 + * + * # Case 2: The current edge in sequence1 is deleted + * try_key = (head_tail1_key, seq2_key) # <<<<<<<<<<<<<< + * if try_key in _results: + * cand1 = _results[try_key] + */ + __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_head_tail1_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 201, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_seq2_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 201, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 201, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_GIVEREF(__pyx_t_7); + PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_7); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_3); + __pyx_t_7 = 0; + __pyx_t_3 = 0; + __Pyx_XDECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_8)); + __pyx_t_8 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":202 + * # Case 2: The current edge in sequence1 is deleted + * try_key = (head_tail1_key, seq2_key) + * if try_key in _results: # <<<<<<<<<<<<<< + * cand1 = _results[try_key] + * else: + */ + __pyx_t_14 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 202, __pyx_L1_error) + __pyx_t_13 = (__pyx_t_14 != 0); + if (__pyx_t_13) { + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":203 + * try_key = (head_tail1_key, seq2_key) + * if try_key in _results: + * cand1 = _results[try_key] # <<<<<<<<<<<<<< + * else: + * miss_frame = try_key, head_tail1, seq2 + */ + __pyx_t_8 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 203, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_XDECREF_SET(__pyx_v_cand1, __pyx_t_8); + __pyx_t_8 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":202 + * # Case 2: The current edge in sequence1 is deleted + * try_key = (head_tail1_key, seq2_key) + * if try_key in _results: # <<<<<<<<<<<<<< + * cand1 = _results[try_key] + * else: + */ + goto __pyx_L18; + } + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":205 + * cand1 = _results[try_key] + * else: + * miss_frame = try_key, head_tail1, seq2 # <<<<<<<<<<<<<< + * stack.append(miss_frame) + * continue + */ + /*else*/ { + __pyx_t_8 = PyTuple_New(3); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 205, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_INCREF(__pyx_v_try_key); + __Pyx_GIVEREF(__pyx_v_try_key); + PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_v_try_key); + __Pyx_INCREF(__pyx_v_head_tail1); + __Pyx_GIVEREF(__pyx_v_head_tail1); + PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_v_head_tail1); + __Pyx_INCREF(__pyx_v_seq2); + __Pyx_GIVEREF(__pyx_v_seq2); + PyTuple_SET_ITEM(__pyx_t_8, 2, __pyx_v_seq2); + __Pyx_XDECREF_SET(__pyx_v_miss_frame, ((PyObject*)__pyx_t_8)); + __pyx_t_8 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":206 + * else: + * miss_frame = try_key, head_tail1, seq2 + * stack.append(miss_frame) # <<<<<<<<<<<<<< + * continue + * + */ + __pyx_t_20 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_miss_frame); if (unlikely(__pyx_t_20 == ((int)-1))) __PYX_ERR(0, 206, __pyx_L1_error) + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":207 + * miss_frame = try_key, head_tail1, seq2 + * stack.append(miss_frame) + * continue # <<<<<<<<<<<<<< + * + * # Case 3: The current edge in sequence2 is deleted + */ + goto __pyx_L15_continue; + } + __pyx_L18:; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":210 + * + * # Case 3: The current edge in sequence2 is deleted + * try_key = (seq1_key, head_tail2_key) # <<<<<<<<<<<<<< + * if try_key in _results: + * cand2 = _results[try_key] + */ + __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_seq1_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 210, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_head_tail2_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 210, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 210, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_GIVEREF(__pyx_t_8); + PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_8); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_t_3); + __pyx_t_8 = 0; + __pyx_t_3 = 0; + __Pyx_DECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_7)); + __pyx_t_7 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":211 + * # Case 3: The current edge in sequence2 is deleted + * try_key = (seq1_key, head_tail2_key) + * if try_key in _results: # <<<<<<<<<<<<<< + * cand2 = _results[try_key] + * else: + */ + __pyx_t_13 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_13 < 0)) __PYX_ERR(0, 211, __pyx_L1_error) + __pyx_t_14 = (__pyx_t_13 != 0); + if (__pyx_t_14) { + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":212 + * try_key = (seq1_key, head_tail2_key) + * if try_key in _results: + * cand2 = _results[try_key] # <<<<<<<<<<<<<< + * else: + * miss_frame = try_key, seq1, head_tail2 + */ + __pyx_t_7 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 212, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_XDECREF_SET(__pyx_v_cand2, __pyx_t_7); + __pyx_t_7 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":211 + * # Case 3: The current edge in sequence2 is deleted + * try_key = (seq1_key, head_tail2_key) + * if try_key in _results: # <<<<<<<<<<<<<< + * cand2 = _results[try_key] + * else: + */ + goto __pyx_L19; + } + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":214 + * cand2 = _results[try_key] + * else: + * miss_frame = try_key, seq1, head_tail2 # <<<<<<<<<<<<<< + * stack.append(miss_frame) + * continue + */ + /*else*/ { + __pyx_t_7 = PyTuple_New(3); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 214, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __Pyx_INCREF(__pyx_v_try_key); + __Pyx_GIVEREF(__pyx_v_try_key); + PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_v_try_key); + __Pyx_INCREF(__pyx_v_seq1); + __Pyx_GIVEREF(__pyx_v_seq1); + PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_v_seq1); + __Pyx_INCREF(__pyx_v_head_tail2); + __Pyx_GIVEREF(__pyx_v_head_tail2); + PyTuple_SET_ITEM(__pyx_t_7, 2, __pyx_v_head_tail2); + __Pyx_XDECREF_SET(__pyx_v_miss_frame, ((PyObject*)__pyx_t_7)); + __pyx_t_7 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":215 + * else: + * miss_frame = try_key, seq1, head_tail2 + * stack.append(miss_frame) # <<<<<<<<<<<<<< + * continue + * + */ + __pyx_t_20 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_miss_frame); if (unlikely(__pyx_t_20 == ((int)-1))) __PYX_ERR(0, 215, __pyx_L1_error) + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":216 + * miss_frame = try_key, seq1, head_tail2 + * stack.append(miss_frame) + * continue # <<<<<<<<<<<<<< + * + * # Case 1: The LCS involves this edge + */ + goto __pyx_L15_continue; + } + __pyx_L19:; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":219 + * + * # Case 1: The LCS involves this edge + * if affinity: # <<<<<<<<<<<<<< + * try_key = (head1_key, head2_key) + * if try_key in _results: + */ + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_v_affinity); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 219, __pyx_L1_error) + if (__pyx_t_14) { + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":220 + * # Case 1: The LCS involves this edge + * if affinity: + * try_key = (head1_key, head2_key) # <<<<<<<<<<<<<< + * if try_key in _results: + * pval_h, new_heads = _results[try_key] + */ + __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_head1_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 220, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_head2_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 220, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 220, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_GIVEREF(__pyx_t_7); + PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_7); + __Pyx_GIVEREF(__pyx_t_3); + PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_3); + __pyx_t_7 = 0; + __pyx_t_3 = 0; + __Pyx_DECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_8)); + __pyx_t_8 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":221 + * if affinity: + * try_key = (head1_key, head2_key) + * if try_key in _results: # <<<<<<<<<<<<<< + * pval_h, new_heads = _results[try_key] + * else: + */ + __pyx_t_14 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 221, __pyx_L1_error) + __pyx_t_13 = (__pyx_t_14 != 0); + if (__pyx_t_13) { + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":222 + * try_key = (head1_key, head2_key) + * if try_key in _results: + * pval_h, new_heads = _results[try_key] # <<<<<<<<<<<<<< + * else: + * miss_frame = try_key, head1, head2 + */ + __pyx_t_8 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 222, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + if ((likely(PyTuple_CheckExact(__pyx_t_8))) || (PyList_CheckExact(__pyx_t_8))) { + PyObject* sequence = __pyx_t_8; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 222, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_7 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_3 = PyList_GET_ITEM(sequence, 0); + __pyx_t_7 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(__pyx_t_7); + #else + __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 222, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_7 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 222, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + #endif + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + } else { + Py_ssize_t index = -1; + __pyx_t_1 = PyObject_GetIter(__pyx_t_8); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 222, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext; + index = 0; __pyx_t_3 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_3)) goto __pyx_L22_unpacking_failed; + __Pyx_GOTREF(__pyx_t_3); + index = 1; __pyx_t_7 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_7)) goto __pyx_L22_unpacking_failed; + __Pyx_GOTREF(__pyx_t_7); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_1), 2) < 0) __PYX_ERR(0, 222, __pyx_L1_error) + __pyx_t_9 = NULL; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + goto __pyx_L23_unpacking_done; + __pyx_L22_unpacking_failed:; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_9 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 222, __pyx_L1_error) + __pyx_L23_unpacking_done:; + } + __Pyx_XDECREF_SET(__pyx_v_pval_h, __pyx_t_3); + __pyx_t_3 = 0; + __Pyx_XDECREF_SET(__pyx_v_new_heads, __pyx_t_7); + __pyx_t_7 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":221 + * if affinity: + * try_key = (head1_key, head2_key) + * if try_key in _results: # <<<<<<<<<<<<<< + * pval_h, new_heads = _results[try_key] + * else: + */ + goto __pyx_L21; + } + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":224 + * pval_h, new_heads = _results[try_key] + * else: + * miss_frame = try_key, head1, head2 # <<<<<<<<<<<<<< + * stack.append(miss_frame) + * continue + */ + /*else*/ { + __pyx_t_8 = PyTuple_New(3); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 224, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_INCREF(__pyx_v_try_key); + __Pyx_GIVEREF(__pyx_v_try_key); + PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_v_try_key); + __Pyx_INCREF(__pyx_v_head1); + __Pyx_GIVEREF(__pyx_v_head1); + PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_v_head1); + __Pyx_INCREF(__pyx_v_head2); + __Pyx_GIVEREF(__pyx_v_head2); + PyTuple_SET_ITEM(__pyx_t_8, 2, __pyx_v_head2); + __Pyx_XDECREF_SET(__pyx_v_miss_frame, ((PyObject*)__pyx_t_8)); + __pyx_t_8 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":225 + * else: + * miss_frame = try_key, head1, head2 + * stack.append(miss_frame) # <<<<<<<<<<<<<< + * continue + * + */ + __pyx_t_20 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_miss_frame); if (unlikely(__pyx_t_20 == ((int)-1))) __PYX_ERR(0, 225, __pyx_L1_error) + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":226 + * miss_frame = try_key, head1, head2 + * stack.append(miss_frame) + * continue # <<<<<<<<<<<<<< + * + * try_key = (tail1_key, tail2_key) + */ + goto __pyx_L15_continue; + } + __pyx_L21:; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":228 + * continue + * + * try_key = (tail1_key, tail2_key) # <<<<<<<<<<<<<< + * if try_key in _results: + * pval_t, new_tails = _results[try_key] + */ + __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_tail1_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 228, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_tail2_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 228, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 228, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_GIVEREF(__pyx_t_8); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_8); + __Pyx_GIVEREF(__pyx_t_7); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_7); + __pyx_t_8 = 0; + __pyx_t_7 = 0; + __Pyx_DECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_3)); + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":229 + * + * try_key = (tail1_key, tail2_key) + * if try_key in _results: # <<<<<<<<<<<<<< + * pval_t, new_tails = _results[try_key] + * else: + */ + __pyx_t_13 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_13 < 0)) __PYX_ERR(0, 229, __pyx_L1_error) + __pyx_t_14 = (__pyx_t_13 != 0); + if (__pyx_t_14) { + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":230 + * try_key = (tail1_key, tail2_key) + * if try_key in _results: + * pval_t, new_tails = _results[try_key] # <<<<<<<<<<<<<< + * else: + * miss_frame = try_key, tail1, tail2 + */ + __pyx_t_3 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 230, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) { + PyObject* sequence = __pyx_t_3; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 230, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_7 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_8 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_7 = PyList_GET_ITEM(sequence, 0); + __pyx_t_8 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(__pyx_t_8); + #else + __pyx_t_7 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 230, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_8 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 230, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + #endif + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + } else { + Py_ssize_t index = -1; + __pyx_t_1 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 230, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext; + index = 0; __pyx_t_7 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_7)) goto __pyx_L25_unpacking_failed; + __Pyx_GOTREF(__pyx_t_7); + index = 1; __pyx_t_8 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_8)) goto __pyx_L25_unpacking_failed; + __Pyx_GOTREF(__pyx_t_8); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_1), 2) < 0) __PYX_ERR(0, 230, __pyx_L1_error) + __pyx_t_9 = NULL; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + goto __pyx_L26_unpacking_done; + __pyx_L25_unpacking_failed:; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_9 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 230, __pyx_L1_error) + __pyx_L26_unpacking_done:; + } + __Pyx_XDECREF_SET(__pyx_v_pval_t, __pyx_t_7); + __pyx_t_7 = 0; + __Pyx_XDECREF_SET(__pyx_v_new_tails, __pyx_t_8); + __pyx_t_8 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":229 + * + * try_key = (tail1_key, tail2_key) + * if try_key in _results: # <<<<<<<<<<<<<< + * pval_t, new_tails = _results[try_key] + * else: + */ + goto __pyx_L24; + } + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":232 + * pval_t, new_tails = _results[try_key] + * else: + * miss_frame = try_key, tail1, tail2 # <<<<<<<<<<<<<< + * stack.append(miss_frame) + * continue + */ + /*else*/ { + __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 232, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(__pyx_v_try_key); + __Pyx_GIVEREF(__pyx_v_try_key); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_try_key); + __Pyx_INCREF(__pyx_v_tail1); + __Pyx_GIVEREF(__pyx_v_tail1); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_tail1); + __Pyx_INCREF(__pyx_v_tail2); + __Pyx_GIVEREF(__pyx_v_tail2); + PyTuple_SET_ITEM(__pyx_t_3, 2, __pyx_v_tail2); + __Pyx_XDECREF_SET(__pyx_v_miss_frame, ((PyObject*)__pyx_t_3)); + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":233 + * else: + * miss_frame = try_key, tail1, tail2 + * stack.append(miss_frame) # <<<<<<<<<<<<<< + * continue + * + */ + __pyx_t_20 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_miss_frame); if (unlikely(__pyx_t_20 == ((int)-1))) __PYX_ERR(0, 233, __pyx_L1_error) + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":234 + * miss_frame = try_key, tail1, tail2 + * stack.append(miss_frame) + * continue # <<<<<<<<<<<<<< + * + * new_head1, new_head2 = new_heads + */ + goto __pyx_L15_continue; + } + __pyx_L24:; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":236 + * continue + * + * new_head1, new_head2 = new_heads # <<<<<<<<<<<<<< + * new_tail1, new_tail2 = new_tails + * + */ + if ((likely(PyTuple_CheckExact(__pyx_v_new_heads))) || (PyList_CheckExact(__pyx_v_new_heads))) { + PyObject* sequence = __pyx_v_new_heads; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 236, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_8 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_3 = PyList_GET_ITEM(sequence, 0); + __pyx_t_8 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(__pyx_t_8); + #else + __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 236, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_8 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 236, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + #endif + } else { + Py_ssize_t index = -1; + __pyx_t_7 = PyObject_GetIter(__pyx_v_new_heads); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 236, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_9 = Py_TYPE(__pyx_t_7)->tp_iternext; + index = 0; __pyx_t_3 = __pyx_t_9(__pyx_t_7); if (unlikely(!__pyx_t_3)) goto __pyx_L27_unpacking_failed; + __Pyx_GOTREF(__pyx_t_3); + index = 1; __pyx_t_8 = __pyx_t_9(__pyx_t_7); if (unlikely(!__pyx_t_8)) goto __pyx_L27_unpacking_failed; + __Pyx_GOTREF(__pyx_t_8); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_7), 2) < 0) __PYX_ERR(0, 236, __pyx_L1_error) + __pyx_t_9 = NULL; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + goto __pyx_L28_unpacking_done; + __pyx_L27_unpacking_failed:; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_9 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 236, __pyx_L1_error) + __pyx_L28_unpacking_done:; + } + __Pyx_XDECREF_SET(__pyx_v_new_head1, __pyx_t_3); + __pyx_t_3 = 0; + __Pyx_XDECREF_SET(__pyx_v_new_head2, __pyx_t_8); + __pyx_t_8 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":237 + * + * new_head1, new_head2 = new_heads + * new_tail1, new_tail2 = new_tails # <<<<<<<<<<<<<< + * + * subseq1 = a1 + new_head1 + b1 + new_tail1 + */ + if ((likely(PyTuple_CheckExact(__pyx_v_new_tails))) || (PyList_CheckExact(__pyx_v_new_tails))) { + PyObject* sequence = __pyx_v_new_tails; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 237, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_8 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_8 = PyList_GET_ITEM(sequence, 0); + __pyx_t_3 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(__pyx_t_3); + #else + __pyx_t_8 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 237, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 237, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + #endif + } else { + Py_ssize_t index = -1; + __pyx_t_7 = PyObject_GetIter(__pyx_v_new_tails); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 237, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_9 = Py_TYPE(__pyx_t_7)->tp_iternext; + index = 0; __pyx_t_8 = __pyx_t_9(__pyx_t_7); if (unlikely(!__pyx_t_8)) goto __pyx_L29_unpacking_failed; + __Pyx_GOTREF(__pyx_t_8); + index = 1; __pyx_t_3 = __pyx_t_9(__pyx_t_7); if (unlikely(!__pyx_t_3)) goto __pyx_L29_unpacking_failed; + __Pyx_GOTREF(__pyx_t_3); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_7), 2) < 0) __PYX_ERR(0, 237, __pyx_L1_error) + __pyx_t_9 = NULL; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + goto __pyx_L30_unpacking_done; + __pyx_L29_unpacking_failed:; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_9 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 237, __pyx_L1_error) + __pyx_L30_unpacking_done:; + } + __Pyx_XDECREF_SET(__pyx_v_new_tail1, __pyx_t_8); + __pyx_t_8 = 0; + __Pyx_XDECREF_SET(__pyx_v_new_tail2, __pyx_t_3); + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":239 + * new_tail1, new_tail2 = new_tails + * + * subseq1 = a1 + new_head1 + b1 + new_tail1 # <<<<<<<<<<<<<< + * subseq2 = a2 + new_head2 + b2 + new_tail2 + * + */ + __pyx_t_3 = PyNumber_Add(__pyx_v_a1, __pyx_v_new_head1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 239, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_8 = PyNumber_Add(__pyx_t_3, __pyx_v_b1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 239, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyNumber_Add(__pyx_t_8, __pyx_v_new_tail1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 239, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF_SET(__pyx_v_subseq1, __pyx_t_3); + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":240 + * + * subseq1 = a1 + new_head1 + b1 + new_tail1 + * subseq2 = a2 + new_head2 + b2 + new_tail2 # <<<<<<<<<<<<<< + * + * res3 = (subseq1, subseq2) + */ + __pyx_t_3 = PyNumber_Add(__pyx_v_a2, __pyx_v_new_head2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 240, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_8 = PyNumber_Add(__pyx_t_3, __pyx_v_b2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 240, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __pyx_t_3 = PyNumber_Add(__pyx_t_8, __pyx_v_new_tail2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 240, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __Pyx_XDECREF_SET(__pyx_v_subseq2, __pyx_t_3); + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":242 + * subseq2 = a2 + new_head2 + b2 + new_tail2 + * + * res3 = (subseq1, subseq2) # <<<<<<<<<<<<<< + * val3 = pval_h + pval_t + affinity + * cand3 = (val3, res3) + */ + __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 242, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __Pyx_INCREF(__pyx_v_subseq1); + __Pyx_GIVEREF(__pyx_v_subseq1); + PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_subseq1); + __Pyx_INCREF(__pyx_v_subseq2); + __Pyx_GIVEREF(__pyx_v_subseq2); + PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_subseq2); + __Pyx_XDECREF_SET(__pyx_v_res3, ((PyObject*)__pyx_t_3)); + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":243 + * + * res3 = (subseq1, subseq2) + * val3 = pval_h + pval_t + affinity # <<<<<<<<<<<<<< + * cand3 = (val3, res3) + * else: + */ + __pyx_t_3 = PyNumber_Add(__pyx_v_pval_h, __pyx_v_pval_t); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 243, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + __pyx_t_8 = PyNumber_Add(__pyx_t_3, __pyx_v_affinity); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 243, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_XDECREF_SET(__pyx_v_val3, __pyx_t_8); + __pyx_t_8 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":244 + * res3 = (subseq1, subseq2) + * val3 = pval_h + pval_t + affinity + * cand3 = (val3, res3) # <<<<<<<<<<<<<< + * else: + * cand3 = (-1, None) + */ + __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 244, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_INCREF(__pyx_v_val3); + __Pyx_GIVEREF(__pyx_v_val3); + PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_v_val3); + __Pyx_INCREF(__pyx_v_res3); + __Pyx_GIVEREF(__pyx_v_res3); + PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_v_res3); + __Pyx_XDECREF_SET(__pyx_v_cand3, ((PyObject*)__pyx_t_8)); + __pyx_t_8 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":219 + * + * # Case 1: The LCS involves this edge + * if affinity: # <<<<<<<<<<<<<< + * try_key = (head1_key, head2_key) + * if try_key in _results: + */ + goto __pyx_L20; + } + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":246 + * cand3 = (val3, res3) + * else: + * cand3 = (-1, None) # <<<<<<<<<<<<<< + * + * # We solved the frame + */ + /*else*/ { + __Pyx_INCREF(__pyx_tuple_); + __Pyx_XDECREF_SET(__pyx_v_cand3, __pyx_tuple_); + } + __pyx_L20:; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":249 + * + * # We solved the frame + * _results[key] = max(cand1, cand2, cand3) # <<<<<<<<<<<<<< + * stack.pop() + * + */ + __Pyx_INCREF(__pyx_v_cand2); + __pyx_t_8 = __pyx_v_cand2; + __Pyx_INCREF(__pyx_v_cand3); + __pyx_t_21 = __pyx_v_cand3; + __Pyx_INCREF(__pyx_v_cand1); + __pyx_t_3 = __pyx_v_cand1; + __pyx_t_1 = PyObject_RichCompare(__pyx_t_8, __pyx_t_3, Py_GT); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 249, __pyx_L1_error) + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 249, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_14) { + __Pyx_INCREF(__pyx_t_8); + __pyx_t_7 = __pyx_t_8; + } else { + __Pyx_INCREF(__pyx_t_3); + __pyx_t_7 = __pyx_t_3; + } + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_INCREF(__pyx_t_7); + __pyx_t_3 = __pyx_t_7; + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + __pyx_t_1 = PyObject_RichCompare(__pyx_t_21, __pyx_t_3, Py_GT); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 249, __pyx_L1_error) + __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 249, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__pyx_t_14) { + __Pyx_INCREF(__pyx_t_21); + __pyx_t_7 = __pyx_t_21; + } else { + __Pyx_INCREF(__pyx_t_3); + __pyx_t_7 = __pyx_t_3; + } + __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; + __Pyx_DECREF(__pyx_t_21); __pyx_t_21 = 0; + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_8 = __pyx_t_7; + __Pyx_INCREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; + if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_v_key, __pyx_t_8) < 0)) __PYX_ERR(0, 249, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":191 + * key, seq1, seq2 = frame + * seq1_key, seq2_key = key + * if key not in _results: # <<<<<<<<<<<<<< + * info1 = key_decomp1[seq1_key] + * tok1, seq1, head1, tail1, head_tail1, head1_key, tail1_key, head_tail1_key, a1, b1 = info1 + */ + } + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":250 + * # We solved the frame + * _results[key] = max(cand1, cand2, cand3) + * stack.pop() # <<<<<<<<<<<<<< + * + * # The stack pop is our solution + */ + __pyx_t_8 = __Pyx_PyList_Pop(__pyx_v_stack); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 250, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_L15_continue:; + } + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":253 + * + * # The stack pop is our solution + * (val, best) = _results[key0] # <<<<<<<<<<<<<< + * found = (best, val) + * return found + */ + __pyx_t_8 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_key0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 253, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + if ((likely(PyTuple_CheckExact(__pyx_t_8))) || (PyList_CheckExact(__pyx_t_8))) { + PyObject* sequence = __pyx_t_8; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 2)) { + if (size > 2) __Pyx_RaiseTooManyValuesError(2); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 253, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + if (likely(PyTuple_CheckExact(sequence))) { + __pyx_t_7 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); + } else { + __pyx_t_7 = PyList_GET_ITEM(sequence, 0); + __pyx_t_3 = PyList_GET_ITEM(sequence, 1); + } + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(__pyx_t_3); + #else + __pyx_t_7 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 253, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_7); + __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 253, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_3); + #endif + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + } else { + Py_ssize_t index = -1; + __pyx_t_1 = PyObject_GetIter(__pyx_t_8); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 253, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; + __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext; + index = 0; __pyx_t_7 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_7)) goto __pyx_L31_unpacking_failed; + __Pyx_GOTREF(__pyx_t_7); + index = 1; __pyx_t_3 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_3)) goto __pyx_L31_unpacking_failed; + __Pyx_GOTREF(__pyx_t_3); + if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_1), 2) < 0) __PYX_ERR(0, 253, __pyx_L1_error) + __pyx_t_9 = NULL; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + goto __pyx_L32_unpacking_done; + __pyx_L31_unpacking_failed:; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_9 = NULL; + if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); + __PYX_ERR(0, 253, __pyx_L1_error) + __pyx_L32_unpacking_done:; + } + if (!(likely(PyTuple_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_3)->tp_name), 0))) __PYX_ERR(0, 253, __pyx_L1_error) + __pyx_v_val = __pyx_t_7; + __pyx_t_7 = 0; + __Pyx_DECREF_SET(__pyx_v_best, ((PyObject*)__pyx_t_3)); + __pyx_t_3 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":254 + * # The stack pop is our solution + * (val, best) = _results[key0] + * found = (best, val) # <<<<<<<<<<<<<< + * return found + * + */ + __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 254, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_8); + __Pyx_INCREF(__pyx_v_best); + __Pyx_GIVEREF(__pyx_v_best); + PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_v_best); + __Pyx_INCREF(__pyx_v_val); + __Pyx_GIVEREF(__pyx_v_val); + PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_v_val); + __pyx_v_found = ((PyObject*)__pyx_t_8); + __pyx_t_8 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":255 + * (val, best) = _results[key0] + * found = (best, val) + * return found # <<<<<<<<<<<<<< + * + * + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_found); + __pyx_r = __pyx_v_found; + goto __pyx_L0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":136 + * + * + * def _lcs_iter_prehash2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node): # <<<<<<<<<<<<<< + * """ + * Version of the lcs iterative algorithm where we precompute hash values + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_10); + __Pyx_XDECREF(__pyx_t_15); + __Pyx_XDECREF(__pyx_t_16); + __Pyx_XDECREF(__pyx_t_17); + __Pyx_XDECREF(__pyx_t_18); + __Pyx_XDECREF(__pyx_t_21); + __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython._lcs_iter_prehash2_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_all_decomp1); + __Pyx_XDECREF(__pyx_v_all_decomp2); + __Pyx_XDECREF(__pyx_v_key_decomp1); + __Pyx_XDECREF(__pyx_v_key_decomp2); + __Pyx_XDECREF(__pyx_v__results); + __Pyx_XDECREF(__pyx_v_empty1); + __Pyx_XDECREF(__pyx_v_empty2); + __Pyx_XDECREF(__pyx_v_best); + __Pyx_XDECREF(__pyx_v_info1); + __Pyx_XDECREF(__pyx_v_info2); + __Pyx_XDECREF(__pyx_v_try_key); + __Pyx_XDECREF(__pyx_v_key); + __Pyx_XDECREF(__pyx_v_frame); + __Pyx_XDECREF(__pyx_v_miss_frame); + __Pyx_XDECREF(__pyx_v_base_result); + __Pyx_XDECREF(__pyx_v_seq1); + __Pyx_XDECREF(__pyx_v_seq2); + __Pyx_XDECREF(__pyx_v_key0); + __Pyx_XDECREF(__pyx_v_frame0); + __Pyx_XDECREF(__pyx_v_stack); + __Pyx_XDECREF(__pyx_v_tok1); + __Pyx_XDECREF(__pyx_v_head1); + __Pyx_XDECREF(__pyx_v_tail1); + __Pyx_XDECREF(__pyx_v_head_tail1); + __Pyx_XDECREF(__pyx_v_a1); + __Pyx_XDECREF(__pyx_v_b1); + __Pyx_XDECREF(__pyx_v_tok2); + __Pyx_XDECREF(__pyx_v_head2); + __Pyx_XDECREF(__pyx_v_tail2); + __Pyx_XDECREF(__pyx_v_head_tail2); + __Pyx_XDECREF(__pyx_v_a2); + __Pyx_XDECREF(__pyx_v_b2); + __Pyx_XDECREF(__pyx_v_affinity); + __Pyx_XDECREF(__pyx_v_cand1); + __Pyx_XDECREF(__pyx_v_cand2); + __Pyx_XDECREF(__pyx_v_pval_h); + __Pyx_XDECREF(__pyx_v_new_heads); + __Pyx_XDECREF(__pyx_v_pval_t); + __Pyx_XDECREF(__pyx_v_new_tails); + __Pyx_XDECREF(__pyx_v_new_head1); + __Pyx_XDECREF(__pyx_v_new_head2); + __Pyx_XDECREF(__pyx_v_new_tail1); + __Pyx_XDECREF(__pyx_v_new_tail2); + __Pyx_XDECREF(__pyx_v_subseq1); + __Pyx_XDECREF(__pyx_v_subseq2); + __Pyx_XDECREF(__pyx_v_res3); + __Pyx_XDECREF(__pyx_v_val3); + __Pyx_XDECREF(__pyx_v_cand3); + __Pyx_XDECREF(__pyx_v_val); + __Pyx_XDECREF(__pyx_v_found); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":258 + * + * + * cdef tuple balanced_decomp_unsafe_cython(sequence, dict open_to_close): # <<<<<<<<<<<<<< + * cdef int stacklen = 1 # always +1 in the first iteration + * cdef int head_stop = 1 + */ + +static PyObject *__pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_balanced_decomp_unsafe_cython(PyObject *__pyx_v_sequence, PyObject *__pyx_v_open_to_close) { + int __pyx_v_stacklen; + int __pyx_v_head_stop; + PyObject *__pyx_v_tok_curr = NULL; + PyObject *__pyx_v_want_close = NULL; + PyObject *__pyx_v_pop_close = NULL; + PyObject *__pyx_v_pop_open = NULL; + PyObject *__pyx_v_head = NULL; + PyObject *__pyx_v_tail = NULL; + PyObject *__pyx_v_head_tail = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + Py_ssize_t __pyx_t_2; + Py_ssize_t __pyx_t_3; + int __pyx_t_4; + long __pyx_t_5; + int __pyx_t_6; + int __pyx_t_7; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("balanced_decomp_unsafe_cython", 0); + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":259 + * + * cdef tuple balanced_decomp_unsafe_cython(sequence, dict open_to_close): + * cdef int stacklen = 1 # always +1 in the first iteration # <<<<<<<<<<<<<< + * cdef int head_stop = 1 + * + */ + __pyx_v_stacklen = 1; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":260 + * cdef tuple balanced_decomp_unsafe_cython(sequence, dict open_to_close): + * cdef int stacklen = 1 # always +1 in the first iteration + * cdef int head_stop = 1 # <<<<<<<<<<<<<< + * + * tok_curr = sequence[0] + */ + __pyx_v_head_stop = 1; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":262 + * cdef int head_stop = 1 + * + * tok_curr = sequence[0] # <<<<<<<<<<<<<< + * want_close = open_to_close[tok_curr] + * + */ + __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_sequence, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 262, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_tok_curr = __pyx_t_1; + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":263 + * + * tok_curr = sequence[0] + * want_close = open_to_close[tok_curr] # <<<<<<<<<<<<<< + * + * # for tok_curr in sequence[1:]: + */ + if (unlikely(__pyx_v_open_to_close == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 263, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_PyDict_GetItem(__pyx_v_open_to_close, __pyx_v_tok_curr); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 263, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_want_close = __pyx_t_1; + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":266 + * + * # for tok_curr in sequence[1:]: + * for head_stop in range(1, len(sequence)): # <<<<<<<<<<<<<< + * tok_curr = sequence[head_stop] + * stacklen += 1 if tok_curr in open_to_close else -1 + */ + __pyx_t_2 = PyObject_Length(__pyx_v_sequence); if (unlikely(__pyx_t_2 == ((Py_ssize_t)-1))) __PYX_ERR(0, 266, __pyx_L1_error) + __pyx_t_3 = __pyx_t_2; + for (__pyx_t_4 = 1; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { + __pyx_v_head_stop = __pyx_t_4; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":267 + * # for tok_curr in sequence[1:]: + * for head_stop in range(1, len(sequence)): + * tok_curr = sequence[head_stop] # <<<<<<<<<<<<<< + * stacklen += 1 if tok_curr in open_to_close else -1 + * if stacklen == 0 and tok_curr == want_close: + */ + __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_sequence, __pyx_v_head_stop, int, 1, __Pyx_PyInt_From_int, 0, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 267, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF_SET(__pyx_v_tok_curr, __pyx_t_1); + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":268 + * for head_stop in range(1, len(sequence)): + * tok_curr = sequence[head_stop] + * stacklen += 1 if tok_curr in open_to_close else -1 # <<<<<<<<<<<<<< + * if stacklen == 0 and tok_curr == want_close: + * pop_close = sequence[head_stop:head_stop + 1] + */ + if (unlikely(__pyx_v_open_to_close == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); + __PYX_ERR(0, 268, __pyx_L1_error) + } + __pyx_t_6 = (__Pyx_PyDict_ContainsTF(__pyx_v_tok_curr, __pyx_v_open_to_close, Py_EQ)); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(0, 268, __pyx_L1_error) + if ((__pyx_t_6 != 0)) { + __pyx_t_5 = 1; + } else { + __pyx_t_5 = -1L; + } + __pyx_v_stacklen = (__pyx_v_stacklen + __pyx_t_5); + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":269 + * tok_curr = sequence[head_stop] + * stacklen += 1 if tok_curr in open_to_close else -1 + * if stacklen == 0 and tok_curr == want_close: # <<<<<<<<<<<<<< + * pop_close = sequence[head_stop:head_stop + 1] + * break + */ + __pyx_t_7 = ((__pyx_v_stacklen == 0) != 0); + if (__pyx_t_7) { + } else { + __pyx_t_6 = __pyx_t_7; + goto __pyx_L6_bool_binop_done; + } + __pyx_t_1 = PyObject_RichCompare(__pyx_v_tok_curr, __pyx_v_want_close, Py_EQ); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 269, __pyx_L1_error) + __pyx_t_7 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 269, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_t_6 = __pyx_t_7; + __pyx_L6_bool_binop_done:; + if (__pyx_t_6) { + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":270 + * stacklen += 1 if tok_curr in open_to_close else -1 + * if stacklen == 0 and tok_curr == want_close: + * pop_close = sequence[head_stop:head_stop + 1] # <<<<<<<<<<<<<< + * break + * + */ + __pyx_t_1 = __Pyx_PyObject_GetSlice(__pyx_v_sequence, __pyx_v_head_stop, (__pyx_v_head_stop + 1), NULL, NULL, NULL, 1, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 270, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_pop_close = __pyx_t_1; + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":271 + * if stacklen == 0 and tok_curr == want_close: + * pop_close = sequence[head_stop:head_stop + 1] + * break # <<<<<<<<<<<<<< + * + * pop_open = sequence[0:1] + */ + goto __pyx_L4_break; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":269 + * tok_curr = sequence[head_stop] + * stacklen += 1 if tok_curr in open_to_close else -1 + * if stacklen == 0 and tok_curr == want_close: # <<<<<<<<<<<<<< + * pop_close = sequence[head_stop:head_stop + 1] + * break + */ + } + } + __pyx_L4_break:; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":273 + * break + * + * pop_open = sequence[0:1] # <<<<<<<<<<<<<< + * head = sequence[1:head_stop] + * tail = sequence[head_stop + 1:] + */ + __pyx_t_1 = __Pyx_PyObject_GetSlice(__pyx_v_sequence, 0, 1, NULL, NULL, &__pyx_slice__3, 1, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 273, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_pop_open = __pyx_t_1; + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":274 + * + * pop_open = sequence[0:1] + * head = sequence[1:head_stop] # <<<<<<<<<<<<<< + * tail = sequence[head_stop + 1:] + * head_tail = head + tail + */ + __pyx_t_1 = __Pyx_PyObject_GetSlice(__pyx_v_sequence, 1, __pyx_v_head_stop, NULL, NULL, NULL, 1, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 274, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_head = __pyx_t_1; + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":275 + * pop_open = sequence[0:1] + * head = sequence[1:head_stop] + * tail = sequence[head_stop + 1:] # <<<<<<<<<<<<<< + * head_tail = head + tail + * return pop_open, pop_close, head, tail, head_tail + */ + __pyx_t_1 = __Pyx_PyObject_GetSlice(__pyx_v_sequence, (__pyx_v_head_stop + 1), 0, NULL, NULL, NULL, 1, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 275, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_tail = __pyx_t_1; + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":276 + * head = sequence[1:head_stop] + * tail = sequence[head_stop + 1:] + * head_tail = head + tail # <<<<<<<<<<<<<< + * return pop_open, pop_close, head, tail, head_tail + * + */ + __pyx_t_1 = PyNumber_Add(__pyx_v_head, __pyx_v_tail); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 276, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_head_tail = __pyx_t_1; + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":277 + * tail = sequence[head_stop + 1:] + * head_tail = head + tail + * return pop_open, pop_close, head, tail, head_tail # <<<<<<<<<<<<<< + * + * + */ + __Pyx_XDECREF(__pyx_r); + if (unlikely(!__pyx_v_pop_close)) { __Pyx_RaiseUnboundLocalError("pop_close"); __PYX_ERR(0, 277, __pyx_L1_error) } + __pyx_t_1 = PyTuple_New(5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 277, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v_pop_open); + __Pyx_GIVEREF(__pyx_v_pop_open); + PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_pop_open); + __Pyx_INCREF(__pyx_v_pop_close); + __Pyx_GIVEREF(__pyx_v_pop_close); + PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_pop_close); + __Pyx_INCREF(__pyx_v_head); + __Pyx_GIVEREF(__pyx_v_head); + PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_head); + __Pyx_INCREF(__pyx_v_tail); + __Pyx_GIVEREF(__pyx_v_tail); + PyTuple_SET_ITEM(__pyx_t_1, 3, __pyx_v_tail); + __Pyx_INCREF(__pyx_v_head_tail); + __Pyx_GIVEREF(__pyx_v_head_tail); + PyTuple_SET_ITEM(__pyx_t_1, 4, __pyx_v_head_tail); + __pyx_r = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + goto __pyx_L0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":258 + * + * + * cdef tuple balanced_decomp_unsafe_cython(sequence, dict open_to_close): # <<<<<<<<<<<<<< + * cdef int stacklen = 1 # always +1 in the first iteration + * cdef int head_stop = 1 + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython.balanced_decomp_unsafe_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_tok_curr); + __Pyx_XDECREF(__pyx_v_want_close); + __Pyx_XDECREF(__pyx_v_pop_close); + __Pyx_XDECREF(__pyx_v_pop_open); + __Pyx_XDECREF(__pyx_v_head); + __Pyx_XDECREF(__pyx_v_tail); + __Pyx_XDECREF(__pyx_v_head_tail); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":280 + * + * + * cdef generate_all_decomp_cython(seq, open_to_close, open_to_node=None): # <<<<<<<<<<<<<< + * """ + * Cython version of :func:`generate_all_decomp`. + */ + +static PyObject *__pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython(PyObject *__pyx_v_seq, PyObject *__pyx_v_open_to_close, struct __pyx_opt_args_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython *__pyx_optional_args) { + PyObject *__pyx_v_open_to_node = ((PyObject *)Py_None); + PyObject *__pyx_v_all_decomp = NULL; + PyObject *__pyx_v_stack = NULL; + PyObject *__pyx_v_pop_open = NULL; + PyObject *__pyx_v_pop_close = NULL; + PyObject *__pyx_v_head = NULL; + PyObject *__pyx_v_tail = NULL; + PyObject *__pyx_v_head_tail = NULL; + PyObject *__pyx_v_node = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + int __pyx_t_4; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + PyObject *__pyx_t_7 = NULL; + PyObject *__pyx_t_8 = NULL; + PyObject *__pyx_t_9 = NULL; + int __pyx_t_10; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("generate_all_decomp_cython", 0); + if (__pyx_optional_args) { + if (__pyx_optional_args->__pyx_n > 0) { + __pyx_v_open_to_node = __pyx_optional_args->open_to_node; + } + } + __Pyx_INCREF(__pyx_v_seq); + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":288 + * >>> all_decomp = generate_all_decomp_cython(seq, open_to_close) + * """ + * all_decomp = {} # <<<<<<<<<<<<<< + * stack = [seq] + * while stack: + */ + __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 288, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_all_decomp = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":289 + * """ + * all_decomp = {} + * stack = [seq] # <<<<<<<<<<<<<< + * while stack: + * seq = stack.pop() + */ + __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 289, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v_seq); + __Pyx_GIVEREF(__pyx_v_seq); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_v_seq); + __pyx_v_stack = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":290 + * all_decomp = {} + * stack = [seq] + * while stack: # <<<<<<<<<<<<<< + * seq = stack.pop() + * if seq not in all_decomp and seq: + */ + while (1) { + __pyx_t_2 = (PyList_GET_SIZE(__pyx_v_stack) != 0); + if (!__pyx_t_2) break; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":291 + * stack = [seq] + * while stack: + * seq = stack.pop() # <<<<<<<<<<<<<< + * if seq not in all_decomp and seq: + * pop_open, pop_close, head, tail, head_tail = balanced_decomp_unsafe_cython(seq, open_to_close) + */ + __pyx_t_1 = __Pyx_PyList_Pop(__pyx_v_stack); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 291, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF_SET(__pyx_v_seq, __pyx_t_1); + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":292 + * while stack: + * seq = stack.pop() + * if seq not in all_decomp and seq: # <<<<<<<<<<<<<< + * pop_open, pop_close, head, tail, head_tail = balanced_decomp_unsafe_cython(seq, open_to_close) + * node = open_to_node[pop_open[0]] + */ + __pyx_t_3 = (__Pyx_PyDict_ContainsTF(__pyx_v_seq, __pyx_v_all_decomp, Py_NE)); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 292, __pyx_L1_error) + __pyx_t_4 = (__pyx_t_3 != 0); + if (__pyx_t_4) { + } else { + __pyx_t_2 = __pyx_t_4; + goto __pyx_L6_bool_binop_done; + } + __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_v_seq); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 292, __pyx_L1_error) + __pyx_t_2 = __pyx_t_4; + __pyx_L6_bool_binop_done:; + if (__pyx_t_2) { + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":293 + * seq = stack.pop() + * if seq not in all_decomp and seq: + * pop_open, pop_close, head, tail, head_tail = balanced_decomp_unsafe_cython(seq, open_to_close) # <<<<<<<<<<<<<< + * node = open_to_node[pop_open[0]] + * all_decomp[seq] = (node, pop_open, pop_close, head, tail, head_tail) + */ + if (!(likely(PyDict_CheckExact(__pyx_v_open_to_close))||((__pyx_v_open_to_close) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "dict", Py_TYPE(__pyx_v_open_to_close)->tp_name), 0))) __PYX_ERR(0, 293, __pyx_L1_error) + __pyx_t_1 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_balanced_decomp_unsafe_cython(__pyx_v_seq, ((PyObject*)__pyx_v_open_to_close)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 293, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (likely(__pyx_t_1 != Py_None)) { + PyObject* sequence = __pyx_t_1; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 5)) { + if (size > 5) __Pyx_RaiseTooManyValuesError(5); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 293, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_5 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_6 = PyTuple_GET_ITEM(sequence, 1); + __pyx_t_7 = PyTuple_GET_ITEM(sequence, 2); + __pyx_t_8 = PyTuple_GET_ITEM(sequence, 3); + __pyx_t_9 = PyTuple_GET_ITEM(sequence, 4); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(__pyx_t_6); + __Pyx_INCREF(__pyx_t_7); + __Pyx_INCREF(__pyx_t_8); + __Pyx_INCREF(__pyx_t_9); + #else + { + Py_ssize_t i; + PyObject** temps[5] = {&__pyx_t_5,&__pyx_t_6,&__pyx_t_7,&__pyx_t_8,&__pyx_t_9}; + for (i=0; i < 5; i++) { + PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 293, __pyx_L1_error) + __Pyx_GOTREF(item); + *(temps[i]) = item; + } + } + #endif + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + } else { + __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 293, __pyx_L1_error) + } + __Pyx_XDECREF_SET(__pyx_v_pop_open, __pyx_t_5); + __pyx_t_5 = 0; + __Pyx_XDECREF_SET(__pyx_v_pop_close, __pyx_t_6); + __pyx_t_6 = 0; + __Pyx_XDECREF_SET(__pyx_v_head, __pyx_t_7); + __pyx_t_7 = 0; + __Pyx_XDECREF_SET(__pyx_v_tail, __pyx_t_8); + __pyx_t_8 = 0; + __Pyx_XDECREF_SET(__pyx_v_head_tail, __pyx_t_9); + __pyx_t_9 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":294 + * if seq not in all_decomp and seq: + * pop_open, pop_close, head, tail, head_tail = balanced_decomp_unsafe_cython(seq, open_to_close) + * node = open_to_node[pop_open[0]] # <<<<<<<<<<<<<< + * all_decomp[seq] = (node, pop_open, pop_close, head, tail, head_tail) + * stack.append(head_tail) + */ + __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_pop_open, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 294, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_9 = __Pyx_PyObject_GetItem(__pyx_v_open_to_node, __pyx_t_1); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 294, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_9); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __Pyx_XDECREF_SET(__pyx_v_node, __pyx_t_9); + __pyx_t_9 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":295 + * pop_open, pop_close, head, tail, head_tail = balanced_decomp_unsafe_cython(seq, open_to_close) + * node = open_to_node[pop_open[0]] + * all_decomp[seq] = (node, pop_open, pop_close, head, tail, head_tail) # <<<<<<<<<<<<<< + * stack.append(head_tail) + * stack.append(head) + */ + __pyx_t_9 = PyTuple_New(6); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 295, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_9); + __Pyx_INCREF(__pyx_v_node); + __Pyx_GIVEREF(__pyx_v_node); + PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_v_node); + __Pyx_INCREF(__pyx_v_pop_open); + __Pyx_GIVEREF(__pyx_v_pop_open); + PyTuple_SET_ITEM(__pyx_t_9, 1, __pyx_v_pop_open); + __Pyx_INCREF(__pyx_v_pop_close); + __Pyx_GIVEREF(__pyx_v_pop_close); + PyTuple_SET_ITEM(__pyx_t_9, 2, __pyx_v_pop_close); + __Pyx_INCREF(__pyx_v_head); + __Pyx_GIVEREF(__pyx_v_head); + PyTuple_SET_ITEM(__pyx_t_9, 3, __pyx_v_head); + __Pyx_INCREF(__pyx_v_tail); + __Pyx_GIVEREF(__pyx_v_tail); + PyTuple_SET_ITEM(__pyx_t_9, 4, __pyx_v_tail); + __Pyx_INCREF(__pyx_v_head_tail); + __Pyx_GIVEREF(__pyx_v_head_tail); + PyTuple_SET_ITEM(__pyx_t_9, 5, __pyx_v_head_tail); + if (unlikely(PyDict_SetItem(__pyx_v_all_decomp, __pyx_v_seq, __pyx_t_9) < 0)) __PYX_ERR(0, 295, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":296 + * node = open_to_node[pop_open[0]] + * all_decomp[seq] = (node, pop_open, pop_close, head, tail, head_tail) + * stack.append(head_tail) # <<<<<<<<<<<<<< + * stack.append(head) + * stack.append(tail) + */ + __pyx_t_10 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_head_tail); if (unlikely(__pyx_t_10 == ((int)-1))) __PYX_ERR(0, 296, __pyx_L1_error) + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":297 + * all_decomp[seq] = (node, pop_open, pop_close, head, tail, head_tail) + * stack.append(head_tail) + * stack.append(head) # <<<<<<<<<<<<<< + * stack.append(tail) + * return all_decomp + */ + __pyx_t_10 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_head); if (unlikely(__pyx_t_10 == ((int)-1))) __PYX_ERR(0, 297, __pyx_L1_error) + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":298 + * stack.append(head_tail) + * stack.append(head) + * stack.append(tail) # <<<<<<<<<<<<<< + * return all_decomp + * + */ + __pyx_t_10 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_tail); if (unlikely(__pyx_t_10 == ((int)-1))) __PYX_ERR(0, 298, __pyx_L1_error) + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":292 + * while stack: + * seq = stack.pop() + * if seq not in all_decomp and seq: # <<<<<<<<<<<<<< + * pop_open, pop_close, head, tail, head_tail = balanced_decomp_unsafe_cython(seq, open_to_close) + * node = open_to_node[pop_open[0]] + */ + } + } + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":299 + * stack.append(head) + * stack.append(tail) + * return all_decomp # <<<<<<<<<<<<<< + * + * + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_all_decomp); + __pyx_r = __pyx_v_all_decomp; + goto __pyx_L0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":280 + * + * + * cdef generate_all_decomp_cython(seq, open_to_close, open_to_node=None): # <<<<<<<<<<<<<< + * """ + * Cython version of :func:`generate_all_decomp`. + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_XDECREF(__pyx_t_7); + __Pyx_XDECREF(__pyx_t_8); + __Pyx_XDECREF(__pyx_t_9); + __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython.generate_all_decomp_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_all_decomp); + __Pyx_XDECREF(__pyx_v_stack); + __Pyx_XDECREF(__pyx_v_pop_open); + __Pyx_XDECREF(__pyx_v_pop_close); + __Pyx_XDECREF(__pyx_v_head); + __Pyx_XDECREF(__pyx_v_tail); + __Pyx_XDECREF(__pyx_v_head_tail); + __Pyx_XDECREF(__pyx_v_node); + __Pyx_XDECREF(__pyx_v_seq); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":302 + * + * + * cdef tuple balanced_decomp_prehash_cython(seq, dict open_to_close, open_to_node): # <<<<<<<<<<<<<< + * """ + * Cython version of :func:`balanced_decomp_unsafe`. + */ + +static PyObject *__pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_balanced_decomp_prehash_cython(PyObject *__pyx_v_seq, PyObject *__pyx_v_open_to_close, PyObject *__pyx_v_open_to_node) { + PyObject *__pyx_v_info = 0; + PyObject *__pyx_v_pop_open = NULL; + PyObject *__pyx_v_pop_close = NULL; + PyObject *__pyx_v_head = NULL; + PyObject *__pyx_v_tail = NULL; + PyObject *__pyx_v_head_tail = NULL; + Py_hash_t __pyx_v_head_key; + Py_hash_t __pyx_v_tail_key; + Py_hash_t __pyx_v_head_tail_key; + PyObject *__pyx_v_node = NULL; + PyObject *__pyx_v_a = NULL; + PyObject *__pyx_v_b = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + PyObject *__pyx_t_3 = NULL; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + Py_hash_t __pyx_t_7; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("balanced_decomp_prehash_cython", 0); + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":307 + * """ + * cdef tuple info + * pop_open, pop_close, head, tail, head_tail = balanced_decomp_unsafe_cython(seq, open_to_close) # <<<<<<<<<<<<<< + * cdef Py_hash_t head_key = hash(head) + * cdef Py_hash_t tail_key = hash(tail) + */ + __pyx_t_1 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_balanced_decomp_unsafe_cython(__pyx_v_seq, __pyx_v_open_to_close); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 307, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (likely(__pyx_t_1 != Py_None)) { + PyObject* sequence = __pyx_t_1; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 5)) { + if (size > 5) __Pyx_RaiseTooManyValuesError(5); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 307, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); + __pyx_t_4 = PyTuple_GET_ITEM(sequence, 2); + __pyx_t_5 = PyTuple_GET_ITEM(sequence, 3); + __pyx_t_6 = PyTuple_GET_ITEM(sequence, 4); + __Pyx_INCREF(__pyx_t_2); + __Pyx_INCREF(__pyx_t_3); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(__pyx_t_6); + #else + { + Py_ssize_t i; + PyObject** temps[5] = {&__pyx_t_2,&__pyx_t_3,&__pyx_t_4,&__pyx_t_5,&__pyx_t_6}; + for (i=0; i < 5; i++) { + PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 307, __pyx_L1_error) + __Pyx_GOTREF(item); + *(temps[i]) = item; + } + } + #endif + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + } else { + __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 307, __pyx_L1_error) + } + __pyx_v_pop_open = __pyx_t_2; + __pyx_t_2 = 0; + __pyx_v_pop_close = __pyx_t_3; + __pyx_t_3 = 0; + __pyx_v_head = __pyx_t_4; + __pyx_t_4 = 0; + __pyx_v_tail = __pyx_t_5; + __pyx_t_5 = 0; + __pyx_v_head_tail = __pyx_t_6; + __pyx_t_6 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":308 + * cdef tuple info + * pop_open, pop_close, head, tail, head_tail = balanced_decomp_unsafe_cython(seq, open_to_close) + * cdef Py_hash_t head_key = hash(head) # <<<<<<<<<<<<<< + * cdef Py_hash_t tail_key = hash(tail) + * cdef Py_hash_t head_tail_key = hash(head_tail) + */ + __pyx_t_7 = PyObject_Hash(__pyx_v_head); if (unlikely(__pyx_t_7 == ((Py_hash_t)-1))) __PYX_ERR(0, 308, __pyx_L1_error) + __pyx_v_head_key = __pyx_t_7; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":309 + * pop_open, pop_close, head, tail, head_tail = balanced_decomp_unsafe_cython(seq, open_to_close) + * cdef Py_hash_t head_key = hash(head) + * cdef Py_hash_t tail_key = hash(tail) # <<<<<<<<<<<<<< + * cdef Py_hash_t head_tail_key = hash(head_tail) + * node = open_to_node[pop_open[0]] + */ + __pyx_t_7 = PyObject_Hash(__pyx_v_tail); if (unlikely(__pyx_t_7 == ((Py_hash_t)-1))) __PYX_ERR(0, 309, __pyx_L1_error) + __pyx_v_tail_key = __pyx_t_7; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":310 + * cdef Py_hash_t head_key = hash(head) + * cdef Py_hash_t tail_key = hash(tail) + * cdef Py_hash_t head_tail_key = hash(head_tail) # <<<<<<<<<<<<<< + * node = open_to_node[pop_open[0]] + * a = pop_open + */ + __pyx_t_7 = PyObject_Hash(__pyx_v_head_tail); if (unlikely(__pyx_t_7 == ((Py_hash_t)-1))) __PYX_ERR(0, 310, __pyx_L1_error) + __pyx_v_head_tail_key = __pyx_t_7; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":311 + * cdef Py_hash_t tail_key = hash(tail) + * cdef Py_hash_t head_tail_key = hash(head_tail) + * node = open_to_node[pop_open[0]] # <<<<<<<<<<<<<< + * a = pop_open + * b = pop_close + */ + __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_pop_open, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 311, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_6 = __Pyx_PyObject_GetItem(__pyx_v_open_to_node, __pyx_t_1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 311, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + __pyx_v_node = __pyx_t_6; + __pyx_t_6 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":312 + * cdef Py_hash_t head_tail_key = hash(head_tail) + * node = open_to_node[pop_open[0]] + * a = pop_open # <<<<<<<<<<<<<< + * b = pop_close + * info = (node, seq, head, tail, head_tail, head_key, tail_key, head_tail_key, a, b) + */ + __Pyx_INCREF(__pyx_v_pop_open); + __pyx_v_a = __pyx_v_pop_open; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":313 + * node = open_to_node[pop_open[0]] + * a = pop_open + * b = pop_close # <<<<<<<<<<<<<< + * info = (node, seq, head, tail, head_tail, head_key, tail_key, head_tail_key, a, b) + * return info + */ + __Pyx_INCREF(__pyx_v_pop_close); + __pyx_v_b = __pyx_v_pop_close; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":314 + * a = pop_open + * b = pop_close + * info = (node, seq, head, tail, head_tail, head_key, tail_key, head_tail_key, a, b) # <<<<<<<<<<<<<< + * return info + * + */ + __pyx_t_6 = __Pyx_PyInt_FromHash_t(__pyx_v_head_key); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 314, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + __pyx_t_1 = __Pyx_PyInt_FromHash_t(__pyx_v_tail_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 314, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_5 = __Pyx_PyInt_FromHash_t(__pyx_v_head_tail_key); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 314, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_4 = PyTuple_New(10); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 314, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __Pyx_INCREF(__pyx_v_node); + __Pyx_GIVEREF(__pyx_v_node); + PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_node); + __Pyx_INCREF(__pyx_v_seq); + __Pyx_GIVEREF(__pyx_v_seq); + PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_seq); + __Pyx_INCREF(__pyx_v_head); + __Pyx_GIVEREF(__pyx_v_head); + PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_v_head); + __Pyx_INCREF(__pyx_v_tail); + __Pyx_GIVEREF(__pyx_v_tail); + PyTuple_SET_ITEM(__pyx_t_4, 3, __pyx_v_tail); + __Pyx_INCREF(__pyx_v_head_tail); + __Pyx_GIVEREF(__pyx_v_head_tail); + PyTuple_SET_ITEM(__pyx_t_4, 4, __pyx_v_head_tail); + __Pyx_GIVEREF(__pyx_t_6); + PyTuple_SET_ITEM(__pyx_t_4, 5, __pyx_t_6); + __Pyx_GIVEREF(__pyx_t_1); + PyTuple_SET_ITEM(__pyx_t_4, 6, __pyx_t_1); + __Pyx_GIVEREF(__pyx_t_5); + PyTuple_SET_ITEM(__pyx_t_4, 7, __pyx_t_5); + __Pyx_INCREF(__pyx_v_a); + __Pyx_GIVEREF(__pyx_v_a); + PyTuple_SET_ITEM(__pyx_t_4, 8, __pyx_v_a); + __Pyx_INCREF(__pyx_v_b); + __Pyx_GIVEREF(__pyx_v_b); + PyTuple_SET_ITEM(__pyx_t_4, 9, __pyx_v_b); + __pyx_t_6 = 0; + __pyx_t_1 = 0; + __pyx_t_5 = 0; + __pyx_v_info = ((PyObject*)__pyx_t_4); + __pyx_t_4 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":315 + * b = pop_close + * info = (node, seq, head, tail, head_tail, head_key, tail_key, head_tail_key, a, b) + * return info # <<<<<<<<<<<<<< + * + * + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_info); + __pyx_r = __pyx_v_info; + goto __pyx_L0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":302 + * + * + * cdef tuple balanced_decomp_prehash_cython(seq, dict open_to_close, open_to_node): # <<<<<<<<<<<<<< + * """ + * Cython version of :func:`balanced_decomp_unsafe`. + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_XDECREF(__pyx_t_3); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython.balanced_decomp_prehash_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_info); + __Pyx_XDECREF(__pyx_v_pop_open); + __Pyx_XDECREF(__pyx_v_pop_close); + __Pyx_XDECREF(__pyx_v_head); + __Pyx_XDECREF(__pyx_v_tail); + __Pyx_XDECREF(__pyx_v_head_tail); + __Pyx_XDECREF(__pyx_v_node); + __Pyx_XDECREF(__pyx_v_a); + __Pyx_XDECREF(__pyx_v_b); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":318 + * + * + * cdef dict generate_all_decomp_prehash_cython(seq, dict open_to_close, open_to_node): # <<<<<<<<<<<<<< + * """ + * Cython version of :func:`generate_all_decomp_prehash`. + */ + +static PyObject *__pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_prehash_cython(PyObject *__pyx_v_seq, PyObject *__pyx_v_open_to_close, PyObject *__pyx_v_open_to_node) { + PyObject *__pyx_v_all_decomp = 0; + PyObject *__pyx_v_stack = 0; + PyObject *__pyx_v_info = 0; + PyObject *__pyx_v_key = NULL; + PyObject *__pyx_v_head = NULL; + PyObject *__pyx_v_tail = NULL; + PyObject *__pyx_v_head_tail = NULL; + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + int __pyx_t_2; + int __pyx_t_3; + PyObject *__pyx_t_4 = NULL; + PyObject *__pyx_t_5 = NULL; + PyObject *__pyx_t_6 = NULL; + int __pyx_t_7; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannySetupContext("generate_all_decomp_prehash_cython", 0); + __Pyx_INCREF(__pyx_v_seq); + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":322 + * Cython version of :func:`generate_all_decomp_prehash`. + * """ + * cdef dict all_decomp = {} # <<<<<<<<<<<<<< + * cdef list stack = [seq] + * cdef tuple info + */ + __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 322, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_v_all_decomp = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":323 + * """ + * cdef dict all_decomp = {} + * cdef list stack = [seq] # <<<<<<<<<<<<<< + * cdef tuple info + * while stack: + */ + __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 323, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_INCREF(__pyx_v_seq); + __Pyx_GIVEREF(__pyx_v_seq); + PyList_SET_ITEM(__pyx_t_1, 0, __pyx_v_seq); + __pyx_v_stack = ((PyObject*)__pyx_t_1); + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":325 + * cdef list stack = [seq] + * cdef tuple info + * while stack: # <<<<<<<<<<<<<< + * seq = stack.pop() + * if seq: + */ + while (1) { + __pyx_t_2 = (PyList_GET_SIZE(__pyx_v_stack) != 0); + if (!__pyx_t_2) break; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":326 + * cdef tuple info + * while stack: + * seq = stack.pop() # <<<<<<<<<<<<<< + * if seq: + * # key = hash(seq) + */ + __pyx_t_1 = __Pyx_PyList_Pop(__pyx_v_stack); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 326, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_DECREF_SET(__pyx_v_seq, __pyx_t_1); + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":327 + * while stack: + * seq = stack.pop() + * if seq: # <<<<<<<<<<<<<< + * # key = hash(seq) + * key = seq + */ + __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_seq); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 327, __pyx_L1_error) + if (__pyx_t_2) { + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":329 + * if seq: + * # key = hash(seq) + * key = seq # <<<<<<<<<<<<<< + * if key not in all_decomp: + * info = balanced_decomp_prehash_cython(seq, open_to_close, open_to_node) + */ + __Pyx_INCREF(__pyx_v_seq); + __Pyx_XDECREF_SET(__pyx_v_key, __pyx_v_seq); + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":330 + * # key = hash(seq) + * key = seq + * if key not in all_decomp: # <<<<<<<<<<<<<< + * info = balanced_decomp_prehash_cython(seq, open_to_close, open_to_node) + * head, tail, head_tail = info[2:5] + */ + __pyx_t_2 = (__Pyx_PyDict_ContainsTF(__pyx_v_key, __pyx_v_all_decomp, Py_NE)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 330, __pyx_L1_error) + __pyx_t_3 = (__pyx_t_2 != 0); + if (__pyx_t_3) { + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":331 + * key = seq + * if key not in all_decomp: + * info = balanced_decomp_prehash_cython(seq, open_to_close, open_to_node) # <<<<<<<<<<<<<< + * head, tail, head_tail = info[2:5] + * all_decomp[key] = info + */ + __pyx_t_1 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_balanced_decomp_prehash_cython(__pyx_v_seq, __pyx_v_open_to_close, __pyx_v_open_to_node); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 331, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __Pyx_XDECREF_SET(__pyx_v_info, ((PyObject*)__pyx_t_1)); + __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":332 + * if key not in all_decomp: + * info = balanced_decomp_prehash_cython(seq, open_to_close, open_to_node) + * head, tail, head_tail = info[2:5] # <<<<<<<<<<<<<< + * all_decomp[key] = info + * stack.append(head_tail) + */ + if (unlikely(__pyx_v_info == Py_None)) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); + __PYX_ERR(0, 332, __pyx_L1_error) + } + __pyx_t_1 = __Pyx_PyTuple_GetSlice(__pyx_v_info, 2, 5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 332, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (1) { + PyObject* sequence = __pyx_t_1; + Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); + if (unlikely(size != 3)) { + if (size > 3) __Pyx_RaiseTooManyValuesError(3); + else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); + __PYX_ERR(0, 332, __pyx_L1_error) + } + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + __pyx_t_4 = PyTuple_GET_ITEM(sequence, 0); + __pyx_t_5 = PyTuple_GET_ITEM(sequence, 1); + __pyx_t_6 = PyTuple_GET_ITEM(sequence, 2); + __Pyx_INCREF(__pyx_t_4); + __Pyx_INCREF(__pyx_t_5); + __Pyx_INCREF(__pyx_t_6); + #else + __pyx_t_4 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 332, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_4); + __pyx_t_5 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 332, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_5); + __pyx_t_6 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 332, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_6); + #endif + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + } + __Pyx_XDECREF_SET(__pyx_v_head, __pyx_t_4); + __pyx_t_4 = 0; + __Pyx_XDECREF_SET(__pyx_v_tail, __pyx_t_5); + __pyx_t_5 = 0; + __Pyx_XDECREF_SET(__pyx_v_head_tail, __pyx_t_6); + __pyx_t_6 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":333 + * info = balanced_decomp_prehash_cython(seq, open_to_close, open_to_node) + * head, tail, head_tail = info[2:5] + * all_decomp[key] = info # <<<<<<<<<<<<<< + * stack.append(head_tail) + * stack.append(head) + */ + if (unlikely(PyDict_SetItem(__pyx_v_all_decomp, __pyx_v_key, __pyx_v_info) < 0)) __PYX_ERR(0, 333, __pyx_L1_error) + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":334 + * head, tail, head_tail = info[2:5] + * all_decomp[key] = info + * stack.append(head_tail) # <<<<<<<<<<<<<< + * stack.append(head) + * stack.append(tail) + */ + __pyx_t_7 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_head_tail); if (unlikely(__pyx_t_7 == ((int)-1))) __PYX_ERR(0, 334, __pyx_L1_error) + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":335 + * all_decomp[key] = info + * stack.append(head_tail) + * stack.append(head) # <<<<<<<<<<<<<< + * stack.append(tail) + * return all_decomp + */ + __pyx_t_7 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_head); if (unlikely(__pyx_t_7 == ((int)-1))) __PYX_ERR(0, 335, __pyx_L1_error) + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":336 + * stack.append(head_tail) + * stack.append(head) + * stack.append(tail) # <<<<<<<<<<<<<< + * return all_decomp + * + */ + __pyx_t_7 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_tail); if (unlikely(__pyx_t_7 == ((int)-1))) __PYX_ERR(0, 336, __pyx_L1_error) + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":330 + * # key = hash(seq) + * key = seq + * if key not in all_decomp: # <<<<<<<<<<<<<< + * info = balanced_decomp_prehash_cython(seq, open_to_close, open_to_node) + * head, tail, head_tail = info[2:5] + */ + } + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":327 + * while stack: + * seq = stack.pop() + * if seq: # <<<<<<<<<<<<<< + * # key = hash(seq) + * key = seq + */ + } + } + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":337 + * stack.append(head) + * stack.append(tail) + * return all_decomp # <<<<<<<<<<<<<< + * + * + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_all_decomp); + __pyx_r = __pyx_v_all_decomp; + goto __pyx_L0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":318 + * + * + * cdef dict generate_all_decomp_prehash_cython(seq, dict open_to_close, open_to_node): # <<<<<<<<<<<<<< + * """ + * Cython version of :func:`generate_all_decomp_prehash`. + */ + + /* function exit code */ + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_4); + __Pyx_XDECREF(__pyx_t_5); + __Pyx_XDECREF(__pyx_t_6); + __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython.generate_all_decomp_prehash_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = 0; + __pyx_L0:; + __Pyx_XDECREF(__pyx_v_all_decomp); + __Pyx_XDECREF(__pyx_v_stack); + __Pyx_XDECREF(__pyx_v_info); + __Pyx_XDECREF(__pyx_v_key); + __Pyx_XDECREF(__pyx_v_head); + __Pyx_XDECREF(__pyx_v_tail); + __Pyx_XDECREF(__pyx_v_head_tail); + __Pyx_XDECREF(__pyx_v_seq); + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +/* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":342 + * class IdentityDict: + * """ Used when ``open_to_node`` is unspecified """ + * def __getitem__(self, key): # <<<<<<<<<<<<<< + * return key + */ + +/* Python wrapper */ +static PyObject *__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict_1__getitem__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ +static PyMethodDef __pyx_mdef_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict_1__getitem__ = {"__getitem__", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict_1__getitem__, METH_VARARGS|METH_KEYWORDS, 0}; +static PyObject *__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict_1__getitem__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { + CYTHON_UNUSED PyObject *__pyx_v_self = 0; + PyObject *__pyx_v_key = 0; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + PyObject *__pyx_r = 0; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__getitem__ (wrapper)", 0); + { + static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_self,&__pyx_n_s_key,0}; + PyObject* values[2] = {0,0}; + if (unlikely(__pyx_kwds)) { + Py_ssize_t kw_args; + const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); + switch (pos_args) { + case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + CYTHON_FALLTHROUGH; + case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + CYTHON_FALLTHROUGH; + case 0: break; + default: goto __pyx_L5_argtuple_error; + } + kw_args = PyDict_Size(__pyx_kwds); + switch (pos_args) { + case 0: + if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_self)) != 0)) kw_args--; + else goto __pyx_L5_argtuple_error; + CYTHON_FALLTHROUGH; + case 1: + if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_key)) != 0)) kw_args--; + else { + __Pyx_RaiseArgtupleInvalid("__getitem__", 1, 2, 2, 1); __PYX_ERR(0, 342, __pyx_L3_error) + } + } + if (unlikely(kw_args > 0)) { + if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__getitem__") < 0)) __PYX_ERR(0, 342, __pyx_L3_error) + } + } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { + goto __pyx_L5_argtuple_error; + } else { + values[0] = PyTuple_GET_ITEM(__pyx_args, 0); + values[1] = PyTuple_GET_ITEM(__pyx_args, 1); + } + __pyx_v_self = values[0]; + __pyx_v_key = values[1]; + } + goto __pyx_L4_argument_unpacking_done; + __pyx_L5_argtuple_error:; + __Pyx_RaiseArgtupleInvalid("__getitem__", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 342, __pyx_L3_error) + __pyx_L3_error:; + __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython.IdentityDict.__getitem__", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_RefNannyFinishContext(); + return NULL; + __pyx_L4_argument_unpacking_done:; + __pyx_r = __pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict___getitem__(__pyx_self, __pyx_v_self, __pyx_v_key); + + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict___getitem__(CYTHON_UNUSED PyObject *__pyx_self, CYTHON_UNUSED PyObject *__pyx_v_self, PyObject *__pyx_v_key) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__getitem__", 0); + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":343 + * """ Used when ``open_to_node`` is unspecified """ + * def __getitem__(self, key): + * return key # <<<<<<<<<<<<<< + */ + __Pyx_XDECREF(__pyx_r); + __Pyx_INCREF(__pyx_v_key); + __pyx_r = __pyx_v_key; + goto __pyx_L0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":342 + * class IdentityDict: + * """ Used when ``open_to_node`` is unspecified """ + * def __getitem__(self, key): # <<<<<<<<<<<<<< + * return key + */ + + /* function exit code */ + __pyx_L0:; + __Pyx_XGIVEREF(__pyx_r); + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyMethodDef __pyx_methods[] = { + {0, 0, 0, 0} +}; + +#if PY_MAJOR_VERSION >= 3 +#if CYTHON_PEP489_MULTI_PHASE_INIT +static PyObject* __pyx_pymod_create(PyObject *spec, PyModuleDef *def); /*proto*/ +static int __pyx_pymod_exec_balanced_sequence_cython(PyObject* module); /*proto*/ +static PyModuleDef_Slot __pyx_moduledef_slots[] = { + {Py_mod_create, (void*)__pyx_pymod_create}, + {Py_mod_exec, (void*)__pyx_pymod_exec_balanced_sequence_cython}, + {0, NULL} +}; +#endif + +static struct PyModuleDef __pyx_moduledef = { + PyModuleDef_HEAD_INIT, + "balanced_sequence_cython", + __pyx_k_This_module_re_implements_funct, /* m_doc */ + #if CYTHON_PEP489_MULTI_PHASE_INIT + 0, /* m_size */ + #else + -1, /* m_size */ + #endif + __pyx_methods /* m_methods */, + #if CYTHON_PEP489_MULTI_PHASE_INIT + __pyx_moduledef_slots, /* m_slots */ + #else + NULL, /* m_reload */ + #endif + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL /* m_free */ +}; +#endif +#ifndef CYTHON_SMALL_CODE +#if defined(__clang__) + #define CYTHON_SMALL_CODE +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) + #define CYTHON_SMALL_CODE __attribute__((cold)) +#else + #define CYTHON_SMALL_CODE +#endif +#endif + +static __Pyx_StringTabEntry __pyx_string_tab[] = { + {&__pyx_n_s_IdentityDict, __pyx_k_IdentityDict, sizeof(__pyx_k_IdentityDict), 0, 0, 1, 1}, + {&__pyx_n_s_IdentityDict___getitem, __pyx_k_IdentityDict___getitem, sizeof(__pyx_k_IdentityDict___getitem), 0, 0, 1, 1}, + {&__pyx_kp_s_Used_when_open_to_node_is_unspe, __pyx_k_Used_when_open_to_node_is_unspe, sizeof(__pyx_k_Used_when_open_to_node_is_unspe), 0, 0, 1, 0}, + {&__pyx_n_s_a1, __pyx_k_a1, sizeof(__pyx_k_a1), 0, 0, 1, 1}, + {&__pyx_n_s_a2, __pyx_k_a2, sizeof(__pyx_k_a2), 0, 0, 1, 1}, + {&__pyx_n_s_affinity, __pyx_k_affinity, sizeof(__pyx_k_affinity), 0, 0, 1, 1}, + {&__pyx_n_s_all_decomp1, __pyx_k_all_decomp1, sizeof(__pyx_k_all_decomp1), 0, 0, 1, 1}, + {&__pyx_n_s_all_decomp2, __pyx_k_all_decomp2, sizeof(__pyx_k_all_decomp2), 0, 0, 1, 1}, + {&__pyx_n_s_b1, __pyx_k_b1, sizeof(__pyx_k_b1), 0, 0, 1, 1}, + {&__pyx_n_s_b2, __pyx_k_b2, sizeof(__pyx_k_b2), 0, 0, 1, 1}, + {&__pyx_n_s_base_result, __pyx_k_base_result, sizeof(__pyx_k_base_result), 0, 0, 1, 1}, + {&__pyx_n_s_best, __pyx_k_best, sizeof(__pyx_k_best), 0, 0, 1, 1}, + {&__pyx_n_s_cand1, __pyx_k_cand1, sizeof(__pyx_k_cand1), 0, 0, 1, 1}, + {&__pyx_n_s_cand2, __pyx_k_cand2, sizeof(__pyx_k_cand2), 0, 0, 1, 1}, + {&__pyx_n_s_cand3, __pyx_k_cand3, sizeof(__pyx_k_cand3), 0, 0, 1, 1}, + {&__pyx_n_s_cline_in_traceback, __pyx_k_cline_in_traceback, sizeof(__pyx_k_cline_in_traceback), 0, 0, 1, 1}, + {&__pyx_n_s_doc, __pyx_k_doc, sizeof(__pyx_k_doc), 0, 0, 1, 1}, + {&__pyx_kp_s_embedding_balanced_sequence_cyt, __pyx_k_embedding_balanced_sequence_cyt, sizeof(__pyx_k_embedding_balanced_sequence_cyt), 0, 0, 1, 0}, + {&__pyx_n_s_empty1, __pyx_k_empty1, sizeof(__pyx_k_empty1), 0, 0, 1, 1}, + {&__pyx_n_s_empty1_key, __pyx_k_empty1_key, sizeof(__pyx_k_empty1_key), 0, 0, 1, 1}, + {&__pyx_n_s_empty2, __pyx_k_empty2, sizeof(__pyx_k_empty2), 0, 0, 1, 1}, + {&__pyx_n_s_empty2_key, __pyx_k_empty2_key, sizeof(__pyx_k_empty2_key), 0, 0, 1, 1}, + {&__pyx_n_s_found, __pyx_k_found, sizeof(__pyx_k_found), 0, 0, 1, 1}, + {&__pyx_n_s_frame, __pyx_k_frame, sizeof(__pyx_k_frame), 0, 0, 1, 1}, + {&__pyx_n_s_frame0, __pyx_k_frame0, sizeof(__pyx_k_frame0), 0, 0, 1, 1}, + {&__pyx_n_s_full_seq1, __pyx_k_full_seq1, sizeof(__pyx_k_full_seq1), 0, 0, 1, 1}, + {&__pyx_n_s_full_seq1_key, __pyx_k_full_seq1_key, sizeof(__pyx_k_full_seq1_key), 0, 0, 1, 1}, + {&__pyx_n_s_full_seq2, __pyx_k_full_seq2, sizeof(__pyx_k_full_seq2), 0, 0, 1, 1}, + {&__pyx_n_s_full_seq2_key, __pyx_k_full_seq2_key, sizeof(__pyx_k_full_seq2_key), 0, 0, 1, 1}, + {&__pyx_n_s_getitem, __pyx_k_getitem, sizeof(__pyx_k_getitem), 0, 0, 1, 1}, + {&__pyx_n_s_head1, __pyx_k_head1, sizeof(__pyx_k_head1), 0, 0, 1, 1}, + {&__pyx_n_s_head1_key, __pyx_k_head1_key, sizeof(__pyx_k_head1_key), 0, 0, 1, 1}, + {&__pyx_n_s_head2, __pyx_k_head2, sizeof(__pyx_k_head2), 0, 0, 1, 1}, + {&__pyx_n_s_head2_key, __pyx_k_head2_key, sizeof(__pyx_k_head2_key), 0, 0, 1, 1}, + {&__pyx_n_s_head_tail1, __pyx_k_head_tail1, sizeof(__pyx_k_head_tail1), 0, 0, 1, 1}, + {&__pyx_n_s_head_tail1_key, __pyx_k_head_tail1_key, sizeof(__pyx_k_head_tail1_key), 0, 0, 1, 1}, + {&__pyx_n_s_head_tail2, __pyx_k_head_tail2, sizeof(__pyx_k_head_tail2), 0, 0, 1, 1}, + {&__pyx_n_s_head_tail2_key, __pyx_k_head_tail2_key, sizeof(__pyx_k_head_tail2_key), 0, 0, 1, 1}, + {&__pyx_n_s_info1, __pyx_k_info1, sizeof(__pyx_k_info1), 0, 0, 1, 1}, + {&__pyx_n_s_info2, __pyx_k_info2, sizeof(__pyx_k_info2), 0, 0, 1, 1}, + {&__pyx_n_s_items, __pyx_k_items, sizeof(__pyx_k_items), 0, 0, 1, 1}, + {&__pyx_n_s_key, __pyx_k_key, sizeof(__pyx_k_key), 0, 0, 1, 1}, + {&__pyx_n_s_key0, __pyx_k_key0, sizeof(__pyx_k_key0), 0, 0, 1, 1}, + {&__pyx_n_s_key1, __pyx_k_key1, sizeof(__pyx_k_key1), 0, 0, 1, 1}, + {&__pyx_n_s_key2, __pyx_k_key2, sizeof(__pyx_k_key2), 0, 0, 1, 1}, + {&__pyx_n_s_key_decomp1, __pyx_k_key_decomp1, sizeof(__pyx_k_key_decomp1), 0, 0, 1, 1}, + {&__pyx_n_s_key_decomp2, __pyx_k_key_decomp2, sizeof(__pyx_k_key_decomp2), 0, 0, 1, 1}, + {&__pyx_n_s_keys, __pyx_k_keys, sizeof(__pyx_k_keys), 0, 0, 1, 1}, + {&__pyx_n_s_lcs_iter_prehash2_cython, __pyx_k_lcs_iter_prehash2_cython, sizeof(__pyx_k_lcs_iter_prehash2_cython), 0, 0, 1, 1}, + {&__pyx_n_s_lcs_iter_simple_alt2_cython, __pyx_k_lcs_iter_simple_alt2_cython, sizeof(__pyx_k_lcs_iter_simple_alt2_cython), 0, 0, 1, 1}, + {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1}, + {&__pyx_n_s_metaclass, __pyx_k_metaclass, sizeof(__pyx_k_metaclass), 0, 0, 1, 1}, + {&__pyx_n_s_miss_frame, __pyx_k_miss_frame, sizeof(__pyx_k_miss_frame), 0, 0, 1, 1}, + {&__pyx_n_s_module, __pyx_k_module, sizeof(__pyx_k_module), 0, 0, 1, 1}, + {&__pyx_n_s_name, __pyx_k_name, sizeof(__pyx_k_name), 0, 0, 1, 1}, + {&__pyx_n_s_networkx_algorithms_isomorphism, __pyx_k_networkx_algorithms_isomorphism, sizeof(__pyx_k_networkx_algorithms_isomorphism), 0, 0, 1, 1}, + {&__pyx_n_s_new_head1, __pyx_k_new_head1, sizeof(__pyx_k_new_head1), 0, 0, 1, 1}, + {&__pyx_n_s_new_head2, __pyx_k_new_head2, sizeof(__pyx_k_new_head2), 0, 0, 1, 1}, + {&__pyx_n_s_new_heads, __pyx_k_new_heads, sizeof(__pyx_k_new_heads), 0, 0, 1, 1}, + {&__pyx_n_s_new_tail1, __pyx_k_new_tail1, sizeof(__pyx_k_new_tail1), 0, 0, 1, 1}, + {&__pyx_n_s_new_tail2, __pyx_k_new_tail2, sizeof(__pyx_k_new_tail2), 0, 0, 1, 1}, + {&__pyx_n_s_new_tails, __pyx_k_new_tails, sizeof(__pyx_k_new_tails), 0, 0, 1, 1}, + {&__pyx_n_s_node_affinity, __pyx_k_node_affinity, sizeof(__pyx_k_node_affinity), 0, 0, 1, 1}, + {&__pyx_n_s_open_to_close, __pyx_k_open_to_close, sizeof(__pyx_k_open_to_close), 0, 0, 1, 1}, + {&__pyx_n_s_open_to_node, __pyx_k_open_to_node, sizeof(__pyx_k_open_to_node), 0, 0, 1, 1}, + {&__pyx_n_s_pop, __pyx_k_pop, sizeof(__pyx_k_pop), 0, 0, 1, 1}, + {&__pyx_n_s_prepare, __pyx_k_prepare, sizeof(__pyx_k_prepare), 0, 0, 1, 1}, + {&__pyx_n_s_pval_h, __pyx_k_pval_h, sizeof(__pyx_k_pval_h), 0, 0, 1, 1}, + {&__pyx_n_s_pval_t, __pyx_k_pval_t, sizeof(__pyx_k_pval_t), 0, 0, 1, 1}, + {&__pyx_n_s_qualname, __pyx_k_qualname, sizeof(__pyx_k_qualname), 0, 0, 1, 1}, + {&__pyx_n_s_range, __pyx_k_range, sizeof(__pyx_k_range), 0, 0, 1, 1}, + {&__pyx_n_s_res3, __pyx_k_res3, sizeof(__pyx_k_res3), 0, 0, 1, 1}, + {&__pyx_n_s_results, __pyx_k_results, sizeof(__pyx_k_results), 0, 0, 1, 1}, + {&__pyx_n_s_self, __pyx_k_self, sizeof(__pyx_k_self), 0, 0, 1, 1}, + {&__pyx_n_s_seq1, __pyx_k_seq1, sizeof(__pyx_k_seq1), 0, 0, 1, 1}, + {&__pyx_n_s_seq1_key, __pyx_k_seq1_key, sizeof(__pyx_k_seq1_key), 0, 0, 1, 1}, + {&__pyx_n_s_seq2, __pyx_k_seq2, sizeof(__pyx_k_seq2), 0, 0, 1, 1}, + {&__pyx_n_s_seq2_key, __pyx_k_seq2_key, sizeof(__pyx_k_seq2_key), 0, 0, 1, 1}, + {&__pyx_n_s_stack, __pyx_k_stack, sizeof(__pyx_k_stack), 0, 0, 1, 1}, + {&__pyx_n_s_subseq1, __pyx_k_subseq1, sizeof(__pyx_k_subseq1), 0, 0, 1, 1}, + {&__pyx_n_s_subseq2, __pyx_k_subseq2, sizeof(__pyx_k_subseq2), 0, 0, 1, 1}, + {&__pyx_n_s_t1, __pyx_k_t1, sizeof(__pyx_k_t1), 0, 0, 1, 1}, + {&__pyx_n_s_t2, __pyx_k_t2, sizeof(__pyx_k_t2), 0, 0, 1, 1}, + {&__pyx_n_s_tail1, __pyx_k_tail1, sizeof(__pyx_k_tail1), 0, 0, 1, 1}, + {&__pyx_n_s_tail1_key, __pyx_k_tail1_key, sizeof(__pyx_k_tail1_key), 0, 0, 1, 1}, + {&__pyx_n_s_tail2, __pyx_k_tail2, sizeof(__pyx_k_tail2), 0, 0, 1, 1}, + {&__pyx_n_s_tail2_key, __pyx_k_tail2_key, sizeof(__pyx_k_tail2_key), 0, 0, 1, 1}, + {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1}, + {&__pyx_n_s_tok1, __pyx_k_tok1, sizeof(__pyx_k_tok1), 0, 0, 1, 1}, + {&__pyx_n_s_tok2, __pyx_k_tok2, sizeof(__pyx_k_tok2), 0, 0, 1, 1}, + {&__pyx_n_s_try_key, __pyx_k_try_key, sizeof(__pyx_k_try_key), 0, 0, 1, 1}, + {&__pyx_n_s_val, __pyx_k_val, sizeof(__pyx_k_val), 0, 0, 1, 1}, + {&__pyx_n_s_val3, __pyx_k_val3, sizeof(__pyx_k_val3), 0, 0, 1, 1}, + {0, 0, 0, 0, 0, 0, 0} +}; +static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) { + __pyx_builtin_range = __Pyx_GetBuiltinName(__pyx_n_s_range); if (!__pyx_builtin_range) __PYX_ERR(0, 266, __pyx_L1_error) + return 0; + __pyx_L1_error:; + return -1; +} + +static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":125 + * cand3 = (val3, res3) + * else: + * cand3 = (-1, None) # <<<<<<<<<<<<<< + * + * # We solved the frame + */ + __pyx_tuple_ = PyTuple_Pack(2, __pyx_int_neg_1, Py_None); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 125, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple_); + __Pyx_GIVEREF(__pyx_tuple_); + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":164 + * for seq1, info1 in all_decomp1.items(): + * seq1_key = hash(seq1) + * head1_key, tail1_key, head_tail1_key = all_decomp1[seq1][5:8] # <<<<<<<<<<<<<< + * _results[(seq1_key, empty2_key)] = base_result + * _results[(head1_key, empty2_key)] = base_result + */ + __pyx_slice__2 = PySlice_New(__pyx_int_5, __pyx_int_8, Py_None); if (unlikely(!__pyx_slice__2)) __PYX_ERR(0, 164, __pyx_L1_error) + __Pyx_GOTREF(__pyx_slice__2); + __Pyx_GIVEREF(__pyx_slice__2); + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":273 + * break + * + * pop_open = sequence[0:1] # <<<<<<<<<<<<<< + * head = sequence[1:head_stop] + * tail = sequence[head_stop + 1:] + */ + __pyx_slice__3 = PySlice_New(__pyx_int_0, __pyx_int_1, Py_None); if (unlikely(!__pyx_slice__3)) __PYX_ERR(0, 273, __pyx_L1_error) + __Pyx_GOTREF(__pyx_slice__3); + __Pyx_GIVEREF(__pyx_slice__3); + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":35 + * + * + * def _lcs_iter_simple_alt2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node): # <<<<<<<<<<<<<< + * """ + * Depth first stack trajectory and replace try except statements with ifs + */ + __pyx_tuple__4 = PyTuple_Pack(51, __pyx_n_s_full_seq1, __pyx_n_s_full_seq2, __pyx_n_s_open_to_close, __pyx_n_s_node_affinity, __pyx_n_s_open_to_node, __pyx_n_s_all_decomp1, __pyx_n_s_all_decomp2, __pyx_n_s_key0, __pyx_n_s_frame0, __pyx_n_s_stack, __pyx_n_s_results, __pyx_n_s_empty1, __pyx_n_s_empty2, __pyx_n_s_best, __pyx_n_s_base_result, __pyx_n_s_seq1, __pyx_n_s_key1, __pyx_n_s_t1, __pyx_n_s_a1, __pyx_n_s_b1, __pyx_n_s_head1, __pyx_n_s_tail1, __pyx_n_s_head_tail1, __pyx_n_s_seq2, __pyx_n_s_key2, __pyx_n_s_t2, __pyx_n_s_a2, __pyx_n_s_b2, __pyx_n_s_head2, __pyx_n_s_tail2, __pyx_n_s_head_tail2, __pyx_n_s_key, __pyx_n_s_try_key, __pyx_n_s_cand1, __pyx_n_s_cand2, __pyx_n_s_affinity, __pyx_n_s_pval_h, __pyx_n_s_new_heads, __pyx_n_s_pval_t, __pyx_n_s_new_tails, __pyx_n_s_new_head1, __pyx_n_s_new_head2, __pyx_n_s_new_tail1, __pyx_n_s_new_tail2, __pyx_n_s_subseq1, __pyx_n_s_subseq2, __pyx_n_s_res3, __pyx_n_s_val3, __pyx_n_s_cand3, __pyx_n_s_val, __pyx_n_s_found); if (unlikely(!__pyx_tuple__4)) __PYX_ERR(0, 35, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__4); + __Pyx_GIVEREF(__pyx_tuple__4); + __pyx_codeobj__5 = (PyObject*)__Pyx_PyCode_New(5, 0, 51, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__4, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_embedding_balanced_sequence_cyt, __pyx_n_s_lcs_iter_simple_alt2_cython, 35, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__5)) __PYX_ERR(0, 35, __pyx_L1_error) + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":136 + * + * + * def _lcs_iter_prehash2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node): # <<<<<<<<<<<<<< + * """ + * Version of the lcs iterative algorithm where we precompute hash values + */ + __pyx_tuple__6 = PyTuple_Pack(67, __pyx_n_s_full_seq1, __pyx_n_s_full_seq2, __pyx_n_s_open_to_close, __pyx_n_s_node_affinity, __pyx_n_s_open_to_node, __pyx_n_s_all_decomp1, __pyx_n_s_all_decomp2, __pyx_n_s_key_decomp1, __pyx_n_s_key_decomp2, __pyx_n_s_results, __pyx_n_s_empty1, __pyx_n_s_empty2, __pyx_n_s_empty1_key, __pyx_n_s_empty2_key, __pyx_n_s_best, __pyx_n_s_info1, __pyx_n_s_info2, __pyx_n_s_try_key, __pyx_n_s_key, __pyx_n_s_seq1_key, __pyx_n_s_seq2_key, __pyx_n_s_head1_key, __pyx_n_s_tail1_key, __pyx_n_s_head_tail1_key, __pyx_n_s_head2_key, __pyx_n_s_tail2_key, __pyx_n_s_head_tail2_key, __pyx_n_s_frame, __pyx_n_s_miss_frame, __pyx_n_s_base_result, __pyx_n_s_seq1, __pyx_n_s_seq2, __pyx_n_s_full_seq1_key, __pyx_n_s_full_seq2_key, __pyx_n_s_key0, __pyx_n_s_frame0, __pyx_n_s_stack, __pyx_n_s_tok1, __pyx_n_s_head1, __pyx_n_s_tail1, __pyx_n_s_head_tail1, __pyx_n_s_a1, __pyx_n_s_b1, __pyx_n_s_tok2, __pyx_n_s_head2, __pyx_n_s_tail2, __pyx_n_s_head_tail2, __pyx_n_s_a2, __pyx_n_s_b2, __pyx_n_s_affinity, __pyx_n_s_cand1, __pyx_n_s_cand2, __pyx_n_s_pval_h, __pyx_n_s_new_heads, __pyx_n_s_pval_t, __pyx_n_s_new_tails, __pyx_n_s_new_head1, __pyx_n_s_new_head2, __pyx_n_s_new_tail1, __pyx_n_s_new_tail2, __pyx_n_s_subseq1, __pyx_n_s_subseq2, __pyx_n_s_res3, __pyx_n_s_val3, __pyx_n_s_cand3, __pyx_n_s_val, __pyx_n_s_found); if (unlikely(!__pyx_tuple__6)) __PYX_ERR(0, 136, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__6); + __Pyx_GIVEREF(__pyx_tuple__6); + __pyx_codeobj__7 = (PyObject*)__Pyx_PyCode_New(5, 0, 67, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__6, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_embedding_balanced_sequence_cyt, __pyx_n_s_lcs_iter_prehash2_cython, 136, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__7)) __PYX_ERR(0, 136, __pyx_L1_error) + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":342 + * class IdentityDict: + * """ Used when ``open_to_node`` is unspecified """ + * def __getitem__(self, key): # <<<<<<<<<<<<<< + * return key + */ + __pyx_tuple__8 = PyTuple_Pack(2, __pyx_n_s_self, __pyx_n_s_key); if (unlikely(!__pyx_tuple__8)) __PYX_ERR(0, 342, __pyx_L1_error) + __Pyx_GOTREF(__pyx_tuple__8); + __Pyx_GIVEREF(__pyx_tuple__8); + __pyx_codeobj__9 = (PyObject*)__Pyx_PyCode_New(2, 0, 2, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__8, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_embedding_balanced_sequence_cyt, __pyx_n_s_getitem, 342, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__9)) __PYX_ERR(0, 342, __pyx_L1_error) + __Pyx_RefNannyFinishContext(); + return 0; + __pyx_L1_error:; + __Pyx_RefNannyFinishContext(); + return -1; +} + +static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) { + __pyx_umethod_PyDict_Type_items.type = (PyObject*)&PyDict_Type; + __pyx_umethod_PyDict_Type_keys.type = (PyObject*)&PyDict_Type; + __pyx_umethod_PyList_Type_pop.type = (PyObject*)&PyList_Type; + if (__Pyx_InitStrings(__pyx_string_tab) < 0) __PYX_ERR(0, 1, __pyx_L1_error); + __pyx_int_0 = PyInt_FromLong(0); if (unlikely(!__pyx_int_0)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_1 = PyInt_FromLong(1); if (unlikely(!__pyx_int_1)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_5 = PyInt_FromLong(5); if (unlikely(!__pyx_int_5)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_8 = PyInt_FromLong(8); if (unlikely(!__pyx_int_8)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_int_neg_1 = PyInt_FromLong(-1); if (unlikely(!__pyx_int_neg_1)) __PYX_ERR(0, 1, __pyx_L1_error) + return 0; + __pyx_L1_error:; + return -1; +} + +static CYTHON_SMALL_CODE int __Pyx_modinit_global_init_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_variable_export_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_function_export_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_type_init_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_type_import_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_variable_import_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_function_import_code(void); /*proto*/ + +static int __Pyx_modinit_global_init_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_global_init_code", 0); + /*--- Global init code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_variable_export_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_variable_export_code", 0); + /*--- Variable export code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_function_export_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_function_export_code", 0); + /*--- Function export code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_type_init_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_type_init_code", 0); + /*--- Type init code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_type_import_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_type_import_code", 0); + /*--- Type import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_variable_import_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_variable_import_code", 0); + /*--- Variable import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_function_import_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_function_import_code", 0); + /*--- Function import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + + +#ifndef CYTHON_NO_PYINIT_EXPORT +#define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC +#elif PY_MAJOR_VERSION < 3 +#ifdef __cplusplus +#define __Pyx_PyMODINIT_FUNC extern "C" void +#else +#define __Pyx_PyMODINIT_FUNC void +#endif +#else +#ifdef __cplusplus +#define __Pyx_PyMODINIT_FUNC extern "C" PyObject * +#else +#define __Pyx_PyMODINIT_FUNC PyObject * +#endif +#endif + + +#if PY_MAJOR_VERSION < 3 +__Pyx_PyMODINIT_FUNC initbalanced_sequence_cython(void) CYTHON_SMALL_CODE; /*proto*/ +__Pyx_PyMODINIT_FUNC initbalanced_sequence_cython(void) +#else +__Pyx_PyMODINIT_FUNC PyInit_balanced_sequence_cython(void) CYTHON_SMALL_CODE; /*proto*/ +__Pyx_PyMODINIT_FUNC PyInit_balanced_sequence_cython(void) +#if CYTHON_PEP489_MULTI_PHASE_INIT +{ + return PyModuleDef_Init(&__pyx_moduledef); +} +static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) { + #if PY_VERSION_HEX >= 0x030700A1 + static PY_INT64_T main_interpreter_id = -1; + PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()->interp); + if (main_interpreter_id == -1) { + main_interpreter_id = current_id; + return (unlikely(current_id == -1)) ? -1 : 0; + } else if (unlikely(main_interpreter_id != current_id)) + #else + static PyInterpreterState *main_interpreter = NULL; + PyInterpreterState *current_interpreter = PyThreadState_Get()->interp; + if (!main_interpreter) { + main_interpreter = current_interpreter; + } else if (unlikely(main_interpreter != current_interpreter)) + #endif + { + PyErr_SetString( + PyExc_ImportError, + "Interpreter change detected - this module can only be loaded into one interpreter per process."); + return -1; + } + return 0; +} +static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name, int allow_none) { + PyObject *value = PyObject_GetAttrString(spec, from_name); + int result = 0; + if (likely(value)) { + if (allow_none || value != Py_None) { + result = PyDict_SetItemString(moddict, to_name, value); + } + Py_DECREF(value); + } else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + } else { + result = -1; + } + return result; +} +static CYTHON_SMALL_CODE PyObject* __pyx_pymod_create(PyObject *spec, CYTHON_UNUSED PyModuleDef *def) { + PyObject *module = NULL, *moddict, *modname; + if (__Pyx_check_single_interpreter()) + return NULL; + if (__pyx_m) + return __Pyx_NewRef(__pyx_m); + modname = PyObject_GetAttrString(spec, "name"); + if (unlikely(!modname)) goto bad; + module = PyModule_NewObject(modname); + Py_DECREF(modname); + if (unlikely(!module)) goto bad; + moddict = PyModule_GetDict(module); + if (unlikely(!moddict)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "loader", "__loader__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "origin", "__file__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "parent", "__package__", 1) < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "submodule_search_locations", "__path__", 0) < 0)) goto bad; + return module; +bad: + Py_XDECREF(module); + return NULL; +} + + +static CYTHON_SMALL_CODE int __pyx_pymod_exec_balanced_sequence_cython(PyObject *__pyx_pyinit_module) +#endif +#endif +{ + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; + int __pyx_lineno = 0; + const char *__pyx_filename = NULL; + int __pyx_clineno = 0; + __Pyx_RefNannyDeclarations + #if CYTHON_PEP489_MULTI_PHASE_INIT + if (__pyx_m) { + if (__pyx_m == __pyx_pyinit_module) return 0; + PyErr_SetString(PyExc_RuntimeError, "Module 'balanced_sequence_cython' has already been imported. Re-initialisation is not supported."); + return -1; + } + #elif PY_MAJOR_VERSION >= 3 + if (__pyx_m) return __Pyx_NewRef(__pyx_m); + #endif + #if CYTHON_REFNANNY +__Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); +if (!__Pyx_RefNanny) { + PyErr_Clear(); + __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); + if (!__Pyx_RefNanny) + Py_FatalError("failed to import 'refnanny' module"); +} +#endif + __Pyx_RefNannySetupContext("__Pyx_PyMODINIT_FUNC PyInit_balanced_sequence_cython(void)", 0); + if (__Pyx_check_binary_version() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #ifdef __Pxy_PyFrame_Initialize_Offsets + __Pxy_PyFrame_Initialize_Offsets(); + #endif + __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_empty_unicode = PyUnicode_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_unicode)) __PYX_ERR(0, 1, __pyx_L1_error) + #ifdef __Pyx_CyFunction_USED + if (__pyx_CyFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_FusedFunction_USED + if (__pyx_FusedFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_Coroutine_USED + if (__pyx_Coroutine_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_Generator_USED + if (__pyx_Generator_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_AsyncGen_USED + if (__pyx_AsyncGen_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_StopAsyncIteration_USED + if (__pyx_StopAsyncIteration_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + /*--- Library function declarations ---*/ + /*--- Threads initialization code ---*/ + #if defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS + #ifdef WITH_THREAD /* Python build with threading support? */ + PyEval_InitThreads(); + #endif + #endif + /*--- Module creation code ---*/ + #if CYTHON_PEP489_MULTI_PHASE_INIT + __pyx_m = __pyx_pyinit_module; + Py_INCREF(__pyx_m); + #else + #if PY_MAJOR_VERSION < 3 + __pyx_m = Py_InitModule4("balanced_sequence_cython", __pyx_methods, __pyx_k_This_module_re_implements_funct, 0, PYTHON_API_VERSION); Py_XINCREF(__pyx_m); + #else + __pyx_m = PyModule_Create(&__pyx_moduledef); + #endif + if (unlikely(!__pyx_m)) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + __pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_d); + __pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_b)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_b); + __pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_cython_runtime); + if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) __PYX_ERR(0, 1, __pyx_L1_error); + /*--- Initialize various global constants etc. ---*/ + if (__Pyx_InitGlobals() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #if PY_MAJOR_VERSION < 3 && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT) + if (__Pyx_init_sys_getdefaultencoding_params() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + if (__pyx_module_is_main_networkx__algorithms__isomorphism___embedding__balanced_sequence_cython) { + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_name, __pyx_n_s_main) < 0) __PYX_ERR(0, 1, __pyx_L1_error) + } + #if PY_MAJOR_VERSION >= 3 + { + PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) __PYX_ERR(0, 1, __pyx_L1_error) + if (!PyDict_GetItemString(modules, "networkx.algorithms.isomorphism._embedding.balanced_sequence_cython")) { + if (unlikely(PyDict_SetItemString(modules, "networkx.algorithms.isomorphism._embedding.balanced_sequence_cython", __pyx_m) < 0)) __PYX_ERR(0, 1, __pyx_L1_error) + } + } + #endif + /*--- Builtin init code ---*/ + if (__Pyx_InitCachedBuiltins() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + /*--- Constants init code ---*/ + if (__Pyx_InitCachedConstants() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + /*--- Global type/function init code ---*/ + (void)__Pyx_modinit_global_init_code(); + (void)__Pyx_modinit_variable_export_code(); + (void)__Pyx_modinit_function_export_code(); + (void)__Pyx_modinit_type_init_code(); + (void)__Pyx_modinit_type_import_code(); + (void)__Pyx_modinit_variable_import_code(); + (void)__Pyx_modinit_function_import_code(); + /*--- Execution code ---*/ + #if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED) + if (__Pyx_patch_abc() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":35 + * + * + * def _lcs_iter_simple_alt2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node): # <<<<<<<<<<<<<< + * """ + * Depth first stack trajectory and replace try except statements with ifs + */ + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_1_lcs_iter_simple_alt2_cython, NULL, __pyx_n_s_networkx_algorithms_isomorphism); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 35, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_lcs_iter_simple_alt2_cython, __pyx_t_1) < 0) __PYX_ERR(0, 35, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":136 + * + * + * def _lcs_iter_prehash2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node): # <<<<<<<<<<<<<< + * """ + * Version of the lcs iterative algorithm where we precompute hash values + */ + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_3_lcs_iter_prehash2_cython, NULL, __pyx_n_s_networkx_algorithms_isomorphism); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 136, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_lcs_iter_prehash2_cython, __pyx_t_1) < 0) __PYX_ERR(0, 136, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":340 + * + * + * class IdentityDict: # <<<<<<<<<<<<<< + * """ Used when ``open_to_node`` is unspecified """ + * def __getitem__(self, key): + */ + __pyx_t_1 = __Pyx_Py3MetaclassPrepare((PyObject *) NULL, __pyx_empty_tuple, __pyx_n_s_IdentityDict, __pyx_n_s_IdentityDict, (PyObject *) NULL, __pyx_n_s_networkx_algorithms_isomorphism, __pyx_kp_s_Used_when_open_to_node_is_unspe); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 340, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":342 + * class IdentityDict: + * """ Used when ``open_to_node`` is unspecified """ + * def __getitem__(self, key): # <<<<<<<<<<<<<< + * return key + */ + __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict_1__getitem__, 0, __pyx_n_s_IdentityDict___getitem, NULL, __pyx_n_s_networkx_algorithms_isomorphism, __pyx_d, ((PyObject *)__pyx_codeobj__9)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 342, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (__Pyx_SetNameInClass(__pyx_t_1, __pyx_n_s_getitem, __pyx_t_2) < 0) __PYX_ERR(0, 342, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":340 + * + * + * class IdentityDict: # <<<<<<<<<<<<<< + * """ Used when ``open_to_node`` is unspecified """ + * def __getitem__(self, key): + */ + __pyx_t_2 = __Pyx_Py3ClassCreate(((PyObject*)&__Pyx_DefaultClassType), __pyx_n_s_IdentityDict, __pyx_empty_tuple, __pyx_t_1, NULL, 0, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 340, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_IdentityDict, __pyx_t_2) < 0) __PYX_ERR(0, 340, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":1 + * # distutils: language = c++ # <<<<<<<<<<<<<< + * """ + * This module re-implements functions in :module:`balanced_sequence` in cython + */ + __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /*--- Wrapped vars code ---*/ + + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + if (__pyx_m) { + if (__pyx_d) { + __Pyx_AddTraceback("init networkx.algorithms.isomorphism._embedding.balanced_sequence_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); + } + Py_CLEAR(__pyx_m); + } else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_ImportError, "init networkx.algorithms.isomorphism._embedding.balanced_sequence_cython"); + } + __pyx_L0:; + __Pyx_RefNannyFinishContext(); + #if CYTHON_PEP489_MULTI_PHASE_INIT + return (__pyx_m != NULL) ? 0 : -1; + #elif PY_MAJOR_VERSION >= 3 + return __pyx_m; + #else + return; + #endif +} + +/* --- Runtime support code --- */ +/* Refnanny */ +#if CYTHON_REFNANNY +static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { + PyObject *m = NULL, *p = NULL; + void *r = NULL; + m = PyImport_ImportModule(modname); + if (!m) goto end; + p = PyObject_GetAttrString(m, "RefNannyAPI"); + if (!p) goto end; + r = PyLong_AsVoidPtr(p); +end: + Py_XDECREF(p); + Py_XDECREF(m); + return (__Pyx_RefNannyAPIStruct *)r; +} +#endif + +/* PyObjectGetAttrStr */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) { + PyTypeObject* tp = Py_TYPE(obj); + if (likely(tp->tp_getattro)) + return tp->tp_getattro(obj, attr_name); +#if PY_MAJOR_VERSION < 3 + if (likely(tp->tp_getattr)) + return tp->tp_getattr(obj, PyString_AS_STRING(attr_name)); +#endif + return PyObject_GetAttr(obj, attr_name); +} +#endif + +/* GetBuiltinName */ +static PyObject *__Pyx_GetBuiltinName(PyObject *name) { + PyObject* result = __Pyx_PyObject_GetAttrStr(__pyx_b, name); + if (unlikely(!result)) { + PyErr_Format(PyExc_NameError, +#if PY_MAJOR_VERSION >= 3 + "name '%U' is not defined", name); +#else + "name '%.200s' is not defined", PyString_AS_STRING(name)); +#endif + } + return result; +} + +/* RaiseArgTupleInvalid */ +static void __Pyx_RaiseArgtupleInvalid( + const char* func_name, + int exact, + Py_ssize_t num_min, + Py_ssize_t num_max, + Py_ssize_t num_found) +{ + Py_ssize_t num_expected; + const char *more_or_less; + if (num_found < num_min) { + num_expected = num_min; + more_or_less = "at least"; + } else { + num_expected = num_max; + more_or_less = "at most"; + } + if (exact) { + more_or_less = "exactly"; + } + PyErr_Format(PyExc_TypeError, + "%.200s() takes %.8s %" CYTHON_FORMAT_SSIZE_T "d positional argument%.1s (%" CYTHON_FORMAT_SSIZE_T "d given)", + func_name, more_or_less, num_expected, + (num_expected == 1) ? "" : "s", num_found); +} + +/* RaiseDoubleKeywords */ +static void __Pyx_RaiseDoubleKeywordsError( + const char* func_name, + PyObject* kw_name) +{ + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION >= 3 + "%s() got multiple values for keyword argument '%U'", func_name, kw_name); + #else + "%s() got multiple values for keyword argument '%s'", func_name, + PyString_AsString(kw_name)); + #endif +} + +/* ParseKeywords */ +static int __Pyx_ParseOptionalKeywords( + PyObject *kwds, + PyObject **argnames[], + PyObject *kwds2, + PyObject *values[], + Py_ssize_t num_pos_args, + const char* function_name) +{ + PyObject *key = 0, *value = 0; + Py_ssize_t pos = 0; + PyObject*** name; + PyObject*** first_kw_arg = argnames + num_pos_args; + while (PyDict_Next(kwds, &pos, &key, &value)) { + name = first_kw_arg; + while (*name && (**name != key)) name++; + if (*name) { + values[name-argnames] = value; + continue; + } + name = first_kw_arg; + #if PY_MAJOR_VERSION < 3 + if (likely(PyString_Check(key))) { + while (*name) { + if ((CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**name) == PyString_GET_SIZE(key)) + && _PyString_Eq(**name, key)) { + values[name-argnames] = value; + break; + } + name++; + } + if (*name) continue; + else { + PyObject*** argname = argnames; + while (argname != first_kw_arg) { + if ((**argname == key) || ( + (CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**argname) == PyString_GET_SIZE(key)) + && _PyString_Eq(**argname, key))) { + goto arg_passed_twice; + } + argname++; + } + } + } else + #endif + if (likely(PyUnicode_Check(key))) { + while (*name) { + int cmp = (**name == key) ? 0 : + #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 + (__Pyx_PyUnicode_GET_LENGTH(**name) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 : + #endif + PyUnicode_Compare(**name, key); + if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; + if (cmp == 0) { + values[name-argnames] = value; + break; + } + name++; + } + if (*name) continue; + else { + PyObject*** argname = argnames; + while (argname != first_kw_arg) { + int cmp = (**argname == key) ? 0 : + #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 + (__Pyx_PyUnicode_GET_LENGTH(**argname) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 : + #endif + PyUnicode_Compare(**argname, key); + if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; + if (cmp == 0) goto arg_passed_twice; + argname++; + } + } + } else + goto invalid_keyword_type; + if (kwds2) { + if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; + } else { + goto invalid_keyword; + } + } + return 0; +arg_passed_twice: + __Pyx_RaiseDoubleKeywordsError(function_name, key); + goto bad; +invalid_keyword_type: + PyErr_Format(PyExc_TypeError, + "%.200s() keywords must be strings", function_name); + goto bad; +invalid_keyword: + PyErr_Format(PyExc_TypeError, + #if PY_MAJOR_VERSION < 3 + "%.200s() got an unexpected keyword argument '%.200s'", + function_name, PyString_AsString(key)); + #else + "%s() got an unexpected keyword argument '%U'", + function_name, key); + #endif +bad: + return -1; +} + +/* PyDictVersioning */ +#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) { + PyObject *dict = Py_TYPE(obj)->tp_dict; + return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0; +} +static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) { + PyObject **dictptr = NULL; + Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset; + if (offset) { +#if CYTHON_COMPILING_IN_CPYTHON + dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj); +#else + dictptr = _PyObject_GetDictPtr(obj); +#endif + } + return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0; +} +static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) { + PyObject *dict = Py_TYPE(obj)->tp_dict; + if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict))) + return 0; + return obj_dict_version == __Pyx_get_object_dict_version(obj); +} +#endif + +/* GetModuleGlobalName */ +#if CYTHON_USE_DICT_VERSIONS +static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value) +#else +static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name) +#endif +{ + PyObject *result; +#if !CYTHON_AVOID_BORROWED_REFS +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 + result = _PyDict_GetItem_KnownHash(__pyx_d, name, ((PyASCIIObject *) name)->hash); + __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return __Pyx_NewRef(result); + } else if (unlikely(PyErr_Occurred())) { + return NULL; + } +#else + result = PyDict_GetItem(__pyx_d, name); + __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return __Pyx_NewRef(result); + } +#endif +#else + result = PyObject_GetItem(__pyx_d, name); + __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) + if (likely(result)) { + return __Pyx_NewRef(result); + } + PyErr_Clear(); +#endif + return __Pyx_GetBuiltinName(name); +} + +/* PyFunctionFastCall */ +#if CYTHON_FAST_PYCALL +static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args, Py_ssize_t na, + PyObject *globals) { + PyFrameObject *f; + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject **fastlocals; + Py_ssize_t i; + PyObject *result; + assert(globals != NULL); + /* XXX Perhaps we should create a specialized + PyFrame_New() that doesn't take locals, but does + take builtins without sanity checking them. + */ + assert(tstate != NULL); + f = PyFrame_New(tstate, co, globals, NULL); + if (f == NULL) { + return NULL; + } + fastlocals = __Pyx_PyFrame_GetLocalsplus(f); + for (i = 0; i < na; i++) { + Py_INCREF(*args); + fastlocals[i] = *args++; + } + result = PyEval_EvalFrameEx(f,0); + ++tstate->recursion_depth; + Py_DECREF(f); + --tstate->recursion_depth; + return result; +} +#if 1 || PY_VERSION_HEX < 0x030600B1 +static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) { + PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); + PyObject *globals = PyFunction_GET_GLOBALS(func); + PyObject *argdefs = PyFunction_GET_DEFAULTS(func); + PyObject *closure; +#if PY_MAJOR_VERSION >= 3 + PyObject *kwdefs; +#endif + PyObject *kwtuple, **k; + PyObject **d; + Py_ssize_t nd; + Py_ssize_t nk; + PyObject *result; + assert(kwargs == NULL || PyDict_Check(kwargs)); + nk = kwargs ? PyDict_Size(kwargs) : 0; + if (Py_EnterRecursiveCall((char*)" while calling a Python object")) { + return NULL; + } + if ( +#if PY_MAJOR_VERSION >= 3 + co->co_kwonlyargcount == 0 && +#endif + likely(kwargs == NULL || nk == 0) && + co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { + if (argdefs == NULL && co->co_argcount == nargs) { + result = __Pyx_PyFunction_FastCallNoKw(co, args, nargs, globals); + goto done; + } + else if (nargs == 0 && argdefs != NULL + && co->co_argcount == Py_SIZE(argdefs)) { + /* function called with no arguments, but all parameters have + a default value: use default values as arguments .*/ + args = &PyTuple_GET_ITEM(argdefs, 0); + result =__Pyx_PyFunction_FastCallNoKw(co, args, Py_SIZE(argdefs), globals); + goto done; + } + } + if (kwargs != NULL) { + Py_ssize_t pos, i; + kwtuple = PyTuple_New(2 * nk); + if (kwtuple == NULL) { + result = NULL; + goto done; + } + k = &PyTuple_GET_ITEM(kwtuple, 0); + pos = i = 0; + while (PyDict_Next(kwargs, &pos, &k[i], &k[i+1])) { + Py_INCREF(k[i]); + Py_INCREF(k[i+1]); + i += 2; + } + nk = i / 2; + } + else { + kwtuple = NULL; + k = NULL; + } + closure = PyFunction_GET_CLOSURE(func); +#if PY_MAJOR_VERSION >= 3 + kwdefs = PyFunction_GET_KW_DEFAULTS(func); +#endif + if (argdefs != NULL) { + d = &PyTuple_GET_ITEM(argdefs, 0); + nd = Py_SIZE(argdefs); + } + else { + d = NULL; + nd = 0; + } +#if PY_MAJOR_VERSION >= 3 + result = PyEval_EvalCodeEx((PyObject*)co, globals, (PyObject *)NULL, + args, (int)nargs, + k, (int)nk, + d, (int)nd, kwdefs, closure); +#else + result = PyEval_EvalCodeEx(co, globals, (PyObject *)NULL, + args, (int)nargs, + k, (int)nk, + d, (int)nd, closure); +#endif + Py_XDECREF(kwtuple); +done: + Py_LeaveRecursiveCall(); + return result; +} +#endif +#endif + +/* PyObjectCall */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { + PyObject *result; + ternaryfunc call = func->ob_type->tp_call; + if (unlikely(!call)) + return PyObject_Call(func, arg, kw); + if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) + return NULL; + result = (*call)(func, arg, kw); + Py_LeaveRecursiveCall(); + if (unlikely(!result) && unlikely(!PyErr_Occurred())) { + PyErr_SetString( + PyExc_SystemError, + "NULL result without error in PyObject_Call"); + } + return result; +} +#endif + +/* PyObjectCallMethO */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg) { + PyObject *self, *result; + PyCFunction cfunc; + cfunc = PyCFunction_GET_FUNCTION(func); + self = PyCFunction_GET_SELF(func); + if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) + return NULL; + result = cfunc(self, arg); + Py_LeaveRecursiveCall(); + if (unlikely(!result) && unlikely(!PyErr_Occurred())) { + PyErr_SetString( + PyExc_SystemError, + "NULL result without error in PyObject_Call"); + } + return result; +} +#endif + +/* PyObjectCallNoArg */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func) { +#if CYTHON_FAST_PYCALL + if (PyFunction_Check(func)) { + return __Pyx_PyFunction_FastCall(func, NULL, 0); + } +#endif +#ifdef __Pyx_CyFunction_USED + if (likely(PyCFunction_Check(func) || __Pyx_CyFunction_Check(func))) +#else + if (likely(PyCFunction_Check(func))) +#endif + { + if (likely(PyCFunction_GET_FLAGS(func) & METH_NOARGS)) { + return __Pyx_PyObject_CallMethO(func, NULL); + } + } + return __Pyx_PyObject_Call(func, __pyx_empty_tuple, NULL); +} +#endif + +/* PyCFunctionFastCall */ +#if CYTHON_FAST_PYCCALL +static CYTHON_INLINE PyObject * __Pyx_PyCFunction_FastCall(PyObject *func_obj, PyObject **args, Py_ssize_t nargs) { + PyCFunctionObject *func = (PyCFunctionObject*)func_obj; + PyCFunction meth = PyCFunction_GET_FUNCTION(func); + PyObject *self = PyCFunction_GET_SELF(func); + int flags = PyCFunction_GET_FLAGS(func); + assert(PyCFunction_Check(func)); + assert(METH_FASTCALL == (flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))); + assert(nargs >= 0); + assert(nargs == 0 || args != NULL); + /* _PyCFunction_FastCallDict() must not be called with an exception set, + because it may clear it (directly or indirectly) and so the + caller loses its exception */ + assert(!PyErr_Occurred()); + if ((PY_VERSION_HEX < 0x030700A0) || unlikely(flags & METH_KEYWORDS)) { + return (*((__Pyx_PyCFunctionFastWithKeywords)(void*)meth)) (self, args, nargs, NULL); + } else { + return (*((__Pyx_PyCFunctionFast)(void*)meth)) (self, args, nargs); + } +} +#endif + +/* PyObjectCallOneArg */ +#if CYTHON_COMPILING_IN_CPYTHON +static PyObject* __Pyx__PyObject_CallOneArg(PyObject *func, PyObject *arg) { + PyObject *result; + PyObject *args = PyTuple_New(1); + if (unlikely(!args)) return NULL; + Py_INCREF(arg); + PyTuple_SET_ITEM(args, 0, arg); + result = __Pyx_PyObject_Call(func, args, NULL); + Py_DECREF(args); + return result; +} +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { +#if CYTHON_FAST_PYCALL + if (PyFunction_Check(func)) { + return __Pyx_PyFunction_FastCall(func, &arg, 1); + } +#endif + if (likely(PyCFunction_Check(func))) { + if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) { + return __Pyx_PyObject_CallMethO(func, arg); +#if CYTHON_FAST_PYCCALL + } else if (PyCFunction_GET_FLAGS(func) & METH_FASTCALL) { + return __Pyx_PyCFunction_FastCall(func, &arg, 1); +#endif + } + } + return __Pyx__PyObject_CallOneArg(func, arg); +} +#else +static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { + PyObject *result; + PyObject *args = PyTuple_Pack(1, arg); + if (unlikely(!args)) return NULL; + result = __Pyx_PyObject_Call(func, args, NULL); + Py_DECREF(args); + return result; +} +#endif + +/* PyErrFetchRestore */ +#if CYTHON_FAST_THREAD_STATE +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + tmp_type = tstate->curexc_type; + tmp_value = tstate->curexc_value; + tmp_tb = tstate->curexc_traceback; + tstate->curexc_type = type; + tstate->curexc_value = value; + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +} +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { + *type = tstate->curexc_type; + *value = tstate->curexc_value; + *tb = tstate->curexc_traceback; + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; +} +#endif + +/* IterNext */ +static PyObject *__Pyx_PyIter_Next2Default(PyObject* defval) { + PyObject* exc_type; + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + exc_type = __Pyx_PyErr_Occurred(); + if (unlikely(exc_type)) { + if (!defval || unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) + return NULL; + __Pyx_PyErr_Clear(); + Py_INCREF(defval); + return defval; + } + if (defval) { + Py_INCREF(defval); + return defval; + } + __Pyx_PyErr_SetNone(PyExc_StopIteration); + return NULL; +} +static void __Pyx_PyIter_Next_ErrorNoIterator(PyObject *iterator) { + PyErr_Format(PyExc_TypeError, + "%.200s object is not an iterator", Py_TYPE(iterator)->tp_name); +} +static CYTHON_INLINE PyObject *__Pyx_PyIter_Next2(PyObject* iterator, PyObject* defval) { + PyObject* next; + iternextfunc iternext = Py_TYPE(iterator)->tp_iternext; + if (likely(iternext)) { +#if CYTHON_USE_TYPE_SLOTS + next = iternext(iterator); + if (likely(next)) + return next; + #if PY_VERSION_HEX >= 0x02070000 + if (unlikely(iternext == &_PyObject_NextNotImplemented)) + return NULL; + #endif +#else + next = PyIter_Next(iterator); + if (likely(next)) + return next; +#endif + } else if (CYTHON_USE_TYPE_SLOTS || unlikely(!PyIter_Check(iterator))) { + __Pyx_PyIter_Next_ErrorNoIterator(iterator); + return NULL; + } +#if !CYTHON_USE_TYPE_SLOTS + else { + next = PyIter_Next(iterator); + if (likely(next)) + return next; + } +#endif + return __Pyx_PyIter_Next2Default(defval); +} + +/* GetItemInt */ +static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) { + PyObject *r; + if (!j) return NULL; + r = PyObject_GetItem(o, j); + Py_DECREF(j); + return r; +} +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, + CYTHON_NCP_UNUSED int wraparound, + CYTHON_NCP_UNUSED int boundscheck) { +#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + Py_ssize_t wrapped_i = i; + if (wraparound & unlikely(i < 0)) { + wrapped_i += PyList_GET_SIZE(o); + } + if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyList_GET_SIZE(o)))) { + PyObject *r = PyList_GET_ITEM(o, wrapped_i); + Py_INCREF(r); + return r; + } + return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); +#else + return PySequence_GetItem(o, i); +#endif +} +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, + CYTHON_NCP_UNUSED int wraparound, + CYTHON_NCP_UNUSED int boundscheck) { +#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + Py_ssize_t wrapped_i = i; + if (wraparound & unlikely(i < 0)) { + wrapped_i += PyTuple_GET_SIZE(o); + } + if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyTuple_GET_SIZE(o)))) { + PyObject *r = PyTuple_GET_ITEM(o, wrapped_i); + Py_INCREF(r); + return r; + } + return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); +#else + return PySequence_GetItem(o, i); +#endif +} +static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int is_list, + CYTHON_NCP_UNUSED int wraparound, + CYTHON_NCP_UNUSED int boundscheck) { +#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS && CYTHON_USE_TYPE_SLOTS + if (is_list || PyList_CheckExact(o)) { + Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyList_GET_SIZE(o); + if ((!boundscheck) || (likely(__Pyx_is_valid_index(n, PyList_GET_SIZE(o))))) { + PyObject *r = PyList_GET_ITEM(o, n); + Py_INCREF(r); + return r; + } + } + else if (PyTuple_CheckExact(o)) { + Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyTuple_GET_SIZE(o); + if ((!boundscheck) || likely(__Pyx_is_valid_index(n, PyTuple_GET_SIZE(o)))) { + PyObject *r = PyTuple_GET_ITEM(o, n); + Py_INCREF(r); + return r; + } + } else { + PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence; + if (likely(m && m->sq_item)) { + if (wraparound && unlikely(i < 0) && likely(m->sq_length)) { + Py_ssize_t l = m->sq_length(o); + if (likely(l >= 0)) { + i += l; + } else { + if (!PyErr_ExceptionMatches(PyExc_OverflowError)) + return NULL; + PyErr_Clear(); + } + } + return m->sq_item(o, i); + } + } +#else + if (is_list || PySequence_Check(o)) { + return PySequence_GetItem(o, i); + } +#endif + return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); +} + +/* ObjectGetItem */ +#if CYTHON_USE_TYPE_SLOTS +static PyObject *__Pyx_PyObject_GetIndex(PyObject *obj, PyObject* index) { + PyObject *runerr; + Py_ssize_t key_value; + PySequenceMethods *m = Py_TYPE(obj)->tp_as_sequence; + if (unlikely(!(m && m->sq_item))) { + PyErr_Format(PyExc_TypeError, "'%.200s' object is not subscriptable", Py_TYPE(obj)->tp_name); + return NULL; + } + key_value = __Pyx_PyIndex_AsSsize_t(index); + if (likely(key_value != -1 || !(runerr = PyErr_Occurred()))) { + return __Pyx_GetItemInt_Fast(obj, key_value, 0, 1, 1); + } + if (PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError)) { + PyErr_Clear(); + PyErr_Format(PyExc_IndexError, "cannot fit '%.200s' into an index-sized integer", Py_TYPE(index)->tp_name); + } + return NULL; +} +static PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject* key) { + PyMappingMethods *m = Py_TYPE(obj)->tp_as_mapping; + if (likely(m && m->mp_subscript)) { + return m->mp_subscript(obj, key); + } + return __Pyx_PyObject_GetIndex(obj, key); +} +#endif + +/* RaiseTooManyValuesToUnpack */ +static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected) { + PyErr_Format(PyExc_ValueError, + "too many values to unpack (expected %" CYTHON_FORMAT_SSIZE_T "d)", expected); +} + +/* RaiseNeedMoreValuesToUnpack */ +static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) { + PyErr_Format(PyExc_ValueError, + "need more than %" CYTHON_FORMAT_SSIZE_T "d value%.1s to unpack", + index, (index == 1) ? "" : "s"); +} + +/* IterFinish */ +static CYTHON_INLINE int __Pyx_IterFinish(void) { +#if CYTHON_FAST_THREAD_STATE + PyThreadState *tstate = __Pyx_PyThreadState_Current; + PyObject* exc_type = tstate->curexc_type; + if (unlikely(exc_type)) { + if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) { + PyObject *exc_value, *exc_tb; + exc_value = tstate->curexc_value; + exc_tb = tstate->curexc_traceback; + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; + Py_DECREF(exc_type); + Py_XDECREF(exc_value); + Py_XDECREF(exc_tb); + return 0; + } else { + return -1; + } + } + return 0; +#else + if (unlikely(PyErr_Occurred())) { + if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) { + PyErr_Clear(); + return 0; + } else { + return -1; + } + } + return 0; +#endif +} + +/* UnpackItemEndCheck */ +static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected) { + if (unlikely(retval)) { + Py_DECREF(retval); + __Pyx_RaiseTooManyValuesError(expected); + return -1; + } else { + return __Pyx_IterFinish(); + } + return 0; +} + +/* DictGetItem */ +#if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY +static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key) { + PyObject *value; + value = PyDict_GetItemWithError(d, key); + if (unlikely(!value)) { + if (!PyErr_Occurred()) { + if (unlikely(PyTuple_Check(key))) { + PyObject* args = PyTuple_Pack(1, key); + if (likely(args)) { + PyErr_SetObject(PyExc_KeyError, args); + Py_DECREF(args); + } + } else { + PyErr_SetObject(PyExc_KeyError, key); + } + } + return NULL; + } + Py_INCREF(value); + return value; +} +#endif + +/* PyObjectGetMethod */ +static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) { + PyObject *attr; +#if CYTHON_UNPACK_METHODS && CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_PYTYPE_LOOKUP + PyTypeObject *tp = Py_TYPE(obj); + PyObject *descr; + descrgetfunc f = NULL; + PyObject **dictptr, *dict; + int meth_found = 0; + assert (*method == NULL); + if (unlikely(tp->tp_getattro != PyObject_GenericGetAttr)) { + attr = __Pyx_PyObject_GetAttrStr(obj, name); + goto try_unpack; + } + if (unlikely(tp->tp_dict == NULL) && unlikely(PyType_Ready(tp) < 0)) { + return 0; + } + descr = _PyType_Lookup(tp, name); + if (likely(descr != NULL)) { + Py_INCREF(descr); +#if PY_MAJOR_VERSION >= 3 + #ifdef __Pyx_CyFunction_USED + if (likely(PyFunction_Check(descr) || (Py_TYPE(descr) == &PyMethodDescr_Type) || __Pyx_CyFunction_Check(descr))) + #else + if (likely(PyFunction_Check(descr) || (Py_TYPE(descr) == &PyMethodDescr_Type))) + #endif +#else + #ifdef __Pyx_CyFunction_USED + if (likely(PyFunction_Check(descr) || __Pyx_CyFunction_Check(descr))) + #else + if (likely(PyFunction_Check(descr))) + #endif +#endif + { + meth_found = 1; + } else { + f = Py_TYPE(descr)->tp_descr_get; + if (f != NULL && PyDescr_IsData(descr)) { + attr = f(descr, obj, (PyObject *)Py_TYPE(obj)); + Py_DECREF(descr); + goto try_unpack; + } + } + } + dictptr = _PyObject_GetDictPtr(obj); + if (dictptr != NULL && (dict = *dictptr) != NULL) { + Py_INCREF(dict); + attr = __Pyx_PyDict_GetItemStr(dict, name); + if (attr != NULL) { + Py_INCREF(attr); + Py_DECREF(dict); + Py_XDECREF(descr); + goto try_unpack; + } + Py_DECREF(dict); + } + if (meth_found) { + *method = descr; + return 1; + } + if (f != NULL) { + attr = f(descr, obj, (PyObject *)Py_TYPE(obj)); + Py_DECREF(descr); + goto try_unpack; + } + if (descr != NULL) { + *method = descr; + return 0; + } + PyErr_Format(PyExc_AttributeError, +#if PY_MAJOR_VERSION >= 3 + "'%.50s' object has no attribute '%U'", + tp->tp_name, name); +#else + "'%.50s' object has no attribute '%.400s'", + tp->tp_name, PyString_AS_STRING(name)); +#endif + return 0; +#else + attr = __Pyx_PyObject_GetAttrStr(obj, name); + goto try_unpack; +#endif +try_unpack: +#if CYTHON_UNPACK_METHODS + if (likely(attr) && PyMethod_Check(attr) && likely(PyMethod_GET_SELF(attr) == obj)) { + PyObject *function = PyMethod_GET_FUNCTION(attr); + Py_INCREF(function); + Py_DECREF(attr); + *method = function; + return 1; + } +#endif + *method = attr; + return 0; +} + +/* PyObjectCallMethod0 */ +static PyObject* __Pyx_PyObject_CallMethod0(PyObject* obj, PyObject* method_name) { + PyObject *method = NULL, *result = NULL; + int is_method = __Pyx_PyObject_GetMethod(obj, method_name, &method); + if (likely(is_method)) { + result = __Pyx_PyObject_CallOneArg(method, obj); + Py_DECREF(method); + return result; + } + if (unlikely(!method)) goto bad; + result = __Pyx_PyObject_CallNoArg(method); + Py_DECREF(method); +bad: + return result; +} + +/* UnpackUnboundCMethod */ +static int __Pyx_TryUnpackUnboundCMethod(__Pyx_CachedCFunction* target) { + PyObject *method; + method = __Pyx_PyObject_GetAttrStr(target->type, *target->method_name); + if (unlikely(!method)) + return -1; + target->method = method; +#if CYTHON_COMPILING_IN_CPYTHON + #if PY_MAJOR_VERSION >= 3 + if (likely(__Pyx_TypeCheck(method, &PyMethodDescr_Type))) + #endif + { + PyMethodDescrObject *descr = (PyMethodDescrObject*) method; + target->func = descr->d_method->ml_meth; + target->flag = descr->d_method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_STACKLESS); + } +#endif + return 0; +} + +/* CallUnboundCMethod0 */ +static PyObject* __Pyx__CallUnboundCMethod0(__Pyx_CachedCFunction* cfunc, PyObject* self) { + PyObject *args, *result = NULL; + if (unlikely(!cfunc->method) && unlikely(__Pyx_TryUnpackUnboundCMethod(cfunc) < 0)) return NULL; +#if CYTHON_ASSUME_SAFE_MACROS + args = PyTuple_New(1); + if (unlikely(!args)) goto bad; + Py_INCREF(self); + PyTuple_SET_ITEM(args, 0, self); +#else + args = PyTuple_Pack(1, self); + if (unlikely(!args)) goto bad; +#endif + result = __Pyx_PyObject_Call(cfunc->method, args, NULL); + Py_DECREF(args); +bad: + return result; +} + +/* pop */ +static CYTHON_INLINE PyObject* __Pyx__PyObject_Pop(PyObject* L) { + if (Py_TYPE(L) == &PySet_Type) { + return PySet_Pop(L); + } + return __Pyx_PyObject_CallMethod0(L, __pyx_n_s_pop); +} +#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS +static CYTHON_INLINE PyObject* __Pyx_PyList_Pop(PyObject* L) { + if (likely(PyList_GET_SIZE(L) > (((PyListObject*)L)->allocated >> 1))) { + __Pyx_SET_SIZE(L, Py_SIZE(L) - 1); + return PyList_GET_ITEM(L, PyList_GET_SIZE(L)); + } + return __Pyx_CallUnboundCMethod0(&__pyx_umethod_PyList_Type_pop, L); +} +#endif + +/* py_dict_keys */ +static CYTHON_INLINE PyObject* __Pyx_PyDict_Keys(PyObject* d) { + if (PY_MAJOR_VERSION >= 3) + return __Pyx_CallUnboundCMethod0(&__pyx_umethod_PyDict_Type_keys, d); + else + return PyDict_Keys(d); +} + +/* py_dict_items */ +static CYTHON_INLINE PyObject* __Pyx_PyDict_Items(PyObject* d) { + if (PY_MAJOR_VERSION >= 3) + return __Pyx_CallUnboundCMethod0(&__pyx_umethod_PyDict_Type_items, d); + else + return PyDict_Items(d); +} + +/* SliceObject */ +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetSlice(PyObject* obj, + Py_ssize_t cstart, Py_ssize_t cstop, + PyObject** _py_start, PyObject** _py_stop, PyObject** _py_slice, + int has_cstart, int has_cstop, CYTHON_UNUSED int wraparound) { +#if CYTHON_USE_TYPE_SLOTS + PyMappingMethods* mp; +#if PY_MAJOR_VERSION < 3 + PySequenceMethods* ms = Py_TYPE(obj)->tp_as_sequence; + if (likely(ms && ms->sq_slice)) { + if (!has_cstart) { + if (_py_start && (*_py_start != Py_None)) { + cstart = __Pyx_PyIndex_AsSsize_t(*_py_start); + if ((cstart == (Py_ssize_t)-1) && PyErr_Occurred()) goto bad; + } else + cstart = 0; + } + if (!has_cstop) { + if (_py_stop && (*_py_stop != Py_None)) { + cstop = __Pyx_PyIndex_AsSsize_t(*_py_stop); + if ((cstop == (Py_ssize_t)-1) && PyErr_Occurred()) goto bad; + } else + cstop = PY_SSIZE_T_MAX; + } + if (wraparound && unlikely((cstart < 0) | (cstop < 0)) && likely(ms->sq_length)) { + Py_ssize_t l = ms->sq_length(obj); + if (likely(l >= 0)) { + if (cstop < 0) { + cstop += l; + if (cstop < 0) cstop = 0; + } + if (cstart < 0) { + cstart += l; + if (cstart < 0) cstart = 0; + } + } else { + if (!PyErr_ExceptionMatches(PyExc_OverflowError)) + goto bad; + PyErr_Clear(); + } + } + return ms->sq_slice(obj, cstart, cstop); + } +#endif + mp = Py_TYPE(obj)->tp_as_mapping; + if (likely(mp && mp->mp_subscript)) +#endif + { + PyObject* result; + PyObject *py_slice, *py_start, *py_stop; + if (_py_slice) { + py_slice = *_py_slice; + } else { + PyObject* owned_start = NULL; + PyObject* owned_stop = NULL; + if (_py_start) { + py_start = *_py_start; + } else { + if (has_cstart) { + owned_start = py_start = PyInt_FromSsize_t(cstart); + if (unlikely(!py_start)) goto bad; + } else + py_start = Py_None; + } + if (_py_stop) { + py_stop = *_py_stop; + } else { + if (has_cstop) { + owned_stop = py_stop = PyInt_FromSsize_t(cstop); + if (unlikely(!py_stop)) { + Py_XDECREF(owned_start); + goto bad; + } + } else + py_stop = Py_None; + } + py_slice = PySlice_New(py_start, py_stop, Py_None); + Py_XDECREF(owned_start); + Py_XDECREF(owned_stop); + if (unlikely(!py_slice)) goto bad; + } +#if CYTHON_USE_TYPE_SLOTS + result = mp->mp_subscript(obj, py_slice); +#else + result = PyObject_GetItem(obj, py_slice); +#endif + if (!_py_slice) { + Py_DECREF(py_slice); + } + return result; + } + PyErr_Format(PyExc_TypeError, + "'%.200s' object is unsliceable", Py_TYPE(obj)->tp_name); +bad: + return NULL; +} + +/* RaiseNoneIterError */ +static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void) { + PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); +} + +/* None */ +static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname) { + PyErr_Format(PyExc_UnboundLocalError, "local variable '%s' referenced before assignment", varname); +} + +/* SliceTupleAndList */ +#if CYTHON_COMPILING_IN_CPYTHON +static CYTHON_INLINE void __Pyx_crop_slice(Py_ssize_t* _start, Py_ssize_t* _stop, Py_ssize_t* _length) { + Py_ssize_t start = *_start, stop = *_stop, length = *_length; + if (start < 0) { + start += length; + if (start < 0) + start = 0; + } + if (stop < 0) + stop += length; + else if (stop > length) + stop = length; + *_length = stop - start; + *_start = start; + *_stop = stop; +} +static CYTHON_INLINE void __Pyx_copy_object_array(PyObject** CYTHON_RESTRICT src, PyObject** CYTHON_RESTRICT dest, Py_ssize_t length) { + PyObject *v; + Py_ssize_t i; + for (i = 0; i < length; i++) { + v = dest[i] = src[i]; + Py_INCREF(v); + } +} +static CYTHON_INLINE PyObject* __Pyx_PyList_GetSlice( + PyObject* src, Py_ssize_t start, Py_ssize_t stop) { + PyObject* dest; + Py_ssize_t length = PyList_GET_SIZE(src); + __Pyx_crop_slice(&start, &stop, &length); + if (unlikely(length <= 0)) + return PyList_New(0); + dest = PyList_New(length); + if (unlikely(!dest)) + return NULL; + __Pyx_copy_object_array( + ((PyListObject*)src)->ob_item + start, + ((PyListObject*)dest)->ob_item, + length); + return dest; +} +static CYTHON_INLINE PyObject* __Pyx_PyTuple_GetSlice( + PyObject* src, Py_ssize_t start, Py_ssize_t stop) { + PyObject* dest; + Py_ssize_t length = PyTuple_GET_SIZE(src); + __Pyx_crop_slice(&start, &stop, &length); + if (unlikely(length <= 0)) + return PyTuple_New(0); + dest = PyTuple_New(length); + if (unlikely(!dest)) + return NULL; + __Pyx_copy_object_array( + ((PyTupleObject*)src)->ob_item + start, + ((PyTupleObject*)dest)->ob_item, + length); + return dest; +} +#endif + +/* FetchCommonType */ +static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type) { + PyObject* fake_module; + PyTypeObject* cached_type = NULL; + fake_module = PyImport_AddModule((char*) "_cython_" CYTHON_ABI); + if (!fake_module) return NULL; + Py_INCREF(fake_module); + cached_type = (PyTypeObject*) PyObject_GetAttrString(fake_module, type->tp_name); + if (cached_type) { + if (!PyType_Check((PyObject*)cached_type)) { + PyErr_Format(PyExc_TypeError, + "Shared Cython type %.200s is not a type object", + type->tp_name); + goto bad; + } + if (cached_type->tp_basicsize != type->tp_basicsize) { + PyErr_Format(PyExc_TypeError, + "Shared Cython type %.200s has the wrong size, try recompiling", + type->tp_name); + goto bad; + } + } else { + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto bad; + PyErr_Clear(); + if (PyType_Ready(type) < 0) goto bad; + if (PyObject_SetAttrString(fake_module, type->tp_name, (PyObject*) type) < 0) + goto bad; + Py_INCREF(type); + cached_type = type; + } +done: + Py_DECREF(fake_module); + return cached_type; +bad: + Py_XDECREF(cached_type); + cached_type = NULL; + goto done; +} + +/* CythonFunctionShared */ +#include +static PyObject * +__Pyx_CyFunction_get_doc(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *closure) +{ + if (unlikely(op->func_doc == NULL)) { + if (op->func.m_ml->ml_doc) { +#if PY_MAJOR_VERSION >= 3 + op->func_doc = PyUnicode_FromString(op->func.m_ml->ml_doc); +#else + op->func_doc = PyString_FromString(op->func.m_ml->ml_doc); +#endif + if (unlikely(op->func_doc == NULL)) + return NULL; + } else { + Py_INCREF(Py_None); + return Py_None; + } + } + Py_INCREF(op->func_doc); + return op->func_doc; +} +static int +__Pyx_CyFunction_set_doc(__pyx_CyFunctionObject *op, PyObject *value, CYTHON_UNUSED void *context) +{ + PyObject *tmp = op->func_doc; + if (value == NULL) { + value = Py_None; + } + Py_INCREF(value); + op->func_doc = value; + Py_XDECREF(tmp); + return 0; +} +static PyObject * +__Pyx_CyFunction_get_name(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) +{ + if (unlikely(op->func_name == NULL)) { +#if PY_MAJOR_VERSION >= 3 + op->func_name = PyUnicode_InternFromString(op->func.m_ml->ml_name); +#else + op->func_name = PyString_InternFromString(op->func.m_ml->ml_name); +#endif + if (unlikely(op->func_name == NULL)) + return NULL; + } + Py_INCREF(op->func_name); + return op->func_name; +} +static int +__Pyx_CyFunction_set_name(__pyx_CyFunctionObject *op, PyObject *value, CYTHON_UNUSED void *context) +{ + PyObject *tmp; +#if PY_MAJOR_VERSION >= 3 + if (unlikely(value == NULL || !PyUnicode_Check(value))) +#else + if (unlikely(value == NULL || !PyString_Check(value))) +#endif + { + PyErr_SetString(PyExc_TypeError, + "__name__ must be set to a string object"); + return -1; + } + tmp = op->func_name; + Py_INCREF(value); + op->func_name = value; + Py_XDECREF(tmp); + return 0; +} +static PyObject * +__Pyx_CyFunction_get_qualname(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) +{ + Py_INCREF(op->func_qualname); + return op->func_qualname; +} +static int +__Pyx_CyFunction_set_qualname(__pyx_CyFunctionObject *op, PyObject *value, CYTHON_UNUSED void *context) +{ + PyObject *tmp; +#if PY_MAJOR_VERSION >= 3 + if (unlikely(value == NULL || !PyUnicode_Check(value))) +#else + if (unlikely(value == NULL || !PyString_Check(value))) +#endif + { + PyErr_SetString(PyExc_TypeError, + "__qualname__ must be set to a string object"); + return -1; + } + tmp = op->func_qualname; + Py_INCREF(value); + op->func_qualname = value; + Py_XDECREF(tmp); + return 0; +} +static PyObject * +__Pyx_CyFunction_get_self(__pyx_CyFunctionObject *m, CYTHON_UNUSED void *closure) +{ + PyObject *self; + self = m->func_closure; + if (self == NULL) + self = Py_None; + Py_INCREF(self); + return self; +} +static PyObject * +__Pyx_CyFunction_get_dict(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) +{ + if (unlikely(op->func_dict == NULL)) { + op->func_dict = PyDict_New(); + if (unlikely(op->func_dict == NULL)) + return NULL; + } + Py_INCREF(op->func_dict); + return op->func_dict; +} +static int +__Pyx_CyFunction_set_dict(__pyx_CyFunctionObject *op, PyObject *value, CYTHON_UNUSED void *context) +{ + PyObject *tmp; + if (unlikely(value == NULL)) { + PyErr_SetString(PyExc_TypeError, + "function's dictionary may not be deleted"); + return -1; + } + if (unlikely(!PyDict_Check(value))) { + PyErr_SetString(PyExc_TypeError, + "setting function's dictionary to a non-dict"); + return -1; + } + tmp = op->func_dict; + Py_INCREF(value); + op->func_dict = value; + Py_XDECREF(tmp); + return 0; +} +static PyObject * +__Pyx_CyFunction_get_globals(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) +{ + Py_INCREF(op->func_globals); + return op->func_globals; +} +static PyObject * +__Pyx_CyFunction_get_closure(CYTHON_UNUSED __pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) +{ + Py_INCREF(Py_None); + return Py_None; +} +static PyObject * +__Pyx_CyFunction_get_code(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) +{ + PyObject* result = (op->func_code) ? op->func_code : Py_None; + Py_INCREF(result); + return result; +} +static int +__Pyx_CyFunction_init_defaults(__pyx_CyFunctionObject *op) { + int result = 0; + PyObject *res = op->defaults_getter((PyObject *) op); + if (unlikely(!res)) + return -1; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + op->defaults_tuple = PyTuple_GET_ITEM(res, 0); + Py_INCREF(op->defaults_tuple); + op->defaults_kwdict = PyTuple_GET_ITEM(res, 1); + Py_INCREF(op->defaults_kwdict); + #else + op->defaults_tuple = PySequence_ITEM(res, 0); + if (unlikely(!op->defaults_tuple)) result = -1; + else { + op->defaults_kwdict = PySequence_ITEM(res, 1); + if (unlikely(!op->defaults_kwdict)) result = -1; + } + #endif + Py_DECREF(res); + return result; +} +static int +__Pyx_CyFunction_set_defaults(__pyx_CyFunctionObject *op, PyObject* value, CYTHON_UNUSED void *context) { + PyObject* tmp; + if (!value) { + value = Py_None; + } else if (value != Py_None && !PyTuple_Check(value)) { + PyErr_SetString(PyExc_TypeError, + "__defaults__ must be set to a tuple object"); + return -1; + } + Py_INCREF(value); + tmp = op->defaults_tuple; + op->defaults_tuple = value; + Py_XDECREF(tmp); + return 0; +} +static PyObject * +__Pyx_CyFunction_get_defaults(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) { + PyObject* result = op->defaults_tuple; + if (unlikely(!result)) { + if (op->defaults_getter) { + if (__Pyx_CyFunction_init_defaults(op) < 0) return NULL; + result = op->defaults_tuple; + } else { + result = Py_None; + } + } + Py_INCREF(result); + return result; +} +static int +__Pyx_CyFunction_set_kwdefaults(__pyx_CyFunctionObject *op, PyObject* value, CYTHON_UNUSED void *context) { + PyObject* tmp; + if (!value) { + value = Py_None; + } else if (value != Py_None && !PyDict_Check(value)) { + PyErr_SetString(PyExc_TypeError, + "__kwdefaults__ must be set to a dict object"); + return -1; + } + Py_INCREF(value); + tmp = op->defaults_kwdict; + op->defaults_kwdict = value; + Py_XDECREF(tmp); + return 0; +} +static PyObject * +__Pyx_CyFunction_get_kwdefaults(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) { + PyObject* result = op->defaults_kwdict; + if (unlikely(!result)) { + if (op->defaults_getter) { + if (__Pyx_CyFunction_init_defaults(op) < 0) return NULL; + result = op->defaults_kwdict; + } else { + result = Py_None; + } + } + Py_INCREF(result); + return result; +} +static int +__Pyx_CyFunction_set_annotations(__pyx_CyFunctionObject *op, PyObject* value, CYTHON_UNUSED void *context) { + PyObject* tmp; + if (!value || value == Py_None) { + value = NULL; + } else if (!PyDict_Check(value)) { + PyErr_SetString(PyExc_TypeError, + "__annotations__ must be set to a dict object"); + return -1; + } + Py_XINCREF(value); + tmp = op->func_annotations; + op->func_annotations = value; + Py_XDECREF(tmp); + return 0; +} +static PyObject * +__Pyx_CyFunction_get_annotations(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) { + PyObject* result = op->func_annotations; + if (unlikely(!result)) { + result = PyDict_New(); + if (unlikely(!result)) return NULL; + op->func_annotations = result; + } + Py_INCREF(result); + return result; +} +static PyGetSetDef __pyx_CyFunction_getsets[] = { + {(char *) "func_doc", (getter)__Pyx_CyFunction_get_doc, (setter)__Pyx_CyFunction_set_doc, 0, 0}, + {(char *) "__doc__", (getter)__Pyx_CyFunction_get_doc, (setter)__Pyx_CyFunction_set_doc, 0, 0}, + {(char *) "func_name", (getter)__Pyx_CyFunction_get_name, (setter)__Pyx_CyFunction_set_name, 0, 0}, + {(char *) "__name__", (getter)__Pyx_CyFunction_get_name, (setter)__Pyx_CyFunction_set_name, 0, 0}, + {(char *) "__qualname__", (getter)__Pyx_CyFunction_get_qualname, (setter)__Pyx_CyFunction_set_qualname, 0, 0}, + {(char *) "__self__", (getter)__Pyx_CyFunction_get_self, 0, 0, 0}, + {(char *) "func_dict", (getter)__Pyx_CyFunction_get_dict, (setter)__Pyx_CyFunction_set_dict, 0, 0}, + {(char *) "__dict__", (getter)__Pyx_CyFunction_get_dict, (setter)__Pyx_CyFunction_set_dict, 0, 0}, + {(char *) "func_globals", (getter)__Pyx_CyFunction_get_globals, 0, 0, 0}, + {(char *) "__globals__", (getter)__Pyx_CyFunction_get_globals, 0, 0, 0}, + {(char *) "func_closure", (getter)__Pyx_CyFunction_get_closure, 0, 0, 0}, + {(char *) "__closure__", (getter)__Pyx_CyFunction_get_closure, 0, 0, 0}, + {(char *) "func_code", (getter)__Pyx_CyFunction_get_code, 0, 0, 0}, + {(char *) "__code__", (getter)__Pyx_CyFunction_get_code, 0, 0, 0}, + {(char *) "func_defaults", (getter)__Pyx_CyFunction_get_defaults, (setter)__Pyx_CyFunction_set_defaults, 0, 0}, + {(char *) "__defaults__", (getter)__Pyx_CyFunction_get_defaults, (setter)__Pyx_CyFunction_set_defaults, 0, 0}, + {(char *) "__kwdefaults__", (getter)__Pyx_CyFunction_get_kwdefaults, (setter)__Pyx_CyFunction_set_kwdefaults, 0, 0}, + {(char *) "__annotations__", (getter)__Pyx_CyFunction_get_annotations, (setter)__Pyx_CyFunction_set_annotations, 0, 0}, + {0, 0, 0, 0, 0} +}; +static PyMemberDef __pyx_CyFunction_members[] = { + {(char *) "__module__", T_OBJECT, offsetof(PyCFunctionObject, m_module), PY_WRITE_RESTRICTED, 0}, + {0, 0, 0, 0, 0} +}; +static PyObject * +__Pyx_CyFunction_reduce(__pyx_CyFunctionObject *m, CYTHON_UNUSED PyObject *args) +{ +#if PY_MAJOR_VERSION >= 3 + return PyUnicode_FromString(m->func.m_ml->ml_name); +#else + return PyString_FromString(m->func.m_ml->ml_name); +#endif +} +static PyMethodDef __pyx_CyFunction_methods[] = { + {"__reduce__", (PyCFunction)__Pyx_CyFunction_reduce, METH_VARARGS, 0}, + {0, 0, 0, 0} +}; +#if PY_VERSION_HEX < 0x030500A0 +#define __Pyx_CyFunction_weakreflist(cyfunc) ((cyfunc)->func_weakreflist) +#else +#define __Pyx_CyFunction_weakreflist(cyfunc) ((cyfunc)->func.m_weakreflist) +#endif +static PyObject *__Pyx_CyFunction_Init(__pyx_CyFunctionObject *op, PyMethodDef *ml, int flags, PyObject* qualname, + PyObject *closure, PyObject *module, PyObject* globals, PyObject* code) { + if (unlikely(op == NULL)) + return NULL; + op->flags = flags; + __Pyx_CyFunction_weakreflist(op) = NULL; + op->func.m_ml = ml; + op->func.m_self = (PyObject *) op; + Py_XINCREF(closure); + op->func_closure = closure; + Py_XINCREF(module); + op->func.m_module = module; + op->func_dict = NULL; + op->func_name = NULL; + Py_INCREF(qualname); + op->func_qualname = qualname; + op->func_doc = NULL; + op->func_classobj = NULL; + op->func_globals = globals; + Py_INCREF(op->func_globals); + Py_XINCREF(code); + op->func_code = code; + op->defaults_pyobjects = 0; + op->defaults_size = 0; + op->defaults = NULL; + op->defaults_tuple = NULL; + op->defaults_kwdict = NULL; + op->defaults_getter = NULL; + op->func_annotations = NULL; + return (PyObject *) op; +} +static int +__Pyx_CyFunction_clear(__pyx_CyFunctionObject *m) +{ + Py_CLEAR(m->func_closure); + Py_CLEAR(m->func.m_module); + Py_CLEAR(m->func_dict); + Py_CLEAR(m->func_name); + Py_CLEAR(m->func_qualname); + Py_CLEAR(m->func_doc); + Py_CLEAR(m->func_globals); + Py_CLEAR(m->func_code); + Py_CLEAR(m->func_classobj); + Py_CLEAR(m->defaults_tuple); + Py_CLEAR(m->defaults_kwdict); + Py_CLEAR(m->func_annotations); + if (m->defaults) { + PyObject **pydefaults = __Pyx_CyFunction_Defaults(PyObject *, m); + int i; + for (i = 0; i < m->defaults_pyobjects; i++) + Py_XDECREF(pydefaults[i]); + PyObject_Free(m->defaults); + m->defaults = NULL; + } + return 0; +} +static void __Pyx__CyFunction_dealloc(__pyx_CyFunctionObject *m) +{ + if (__Pyx_CyFunction_weakreflist(m) != NULL) + PyObject_ClearWeakRefs((PyObject *) m); + __Pyx_CyFunction_clear(m); + PyObject_GC_Del(m); +} +static void __Pyx_CyFunction_dealloc(__pyx_CyFunctionObject *m) +{ + PyObject_GC_UnTrack(m); + __Pyx__CyFunction_dealloc(m); +} +static int __Pyx_CyFunction_traverse(__pyx_CyFunctionObject *m, visitproc visit, void *arg) +{ + Py_VISIT(m->func_closure); + Py_VISIT(m->func.m_module); + Py_VISIT(m->func_dict); + Py_VISIT(m->func_name); + Py_VISIT(m->func_qualname); + Py_VISIT(m->func_doc); + Py_VISIT(m->func_globals); + Py_VISIT(m->func_code); + Py_VISIT(m->func_classobj); + Py_VISIT(m->defaults_tuple); + Py_VISIT(m->defaults_kwdict); + if (m->defaults) { + PyObject **pydefaults = __Pyx_CyFunction_Defaults(PyObject *, m); + int i; + for (i = 0; i < m->defaults_pyobjects; i++) + Py_VISIT(pydefaults[i]); + } + return 0; +} +static PyObject *__Pyx_CyFunction_descr_get(PyObject *func, PyObject *obj, PyObject *type) +{ + __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func; + if (m->flags & __Pyx_CYFUNCTION_STATICMETHOD) { + Py_INCREF(func); + return func; + } + if (m->flags & __Pyx_CYFUNCTION_CLASSMETHOD) { + if (type == NULL) + type = (PyObject *)(Py_TYPE(obj)); + return __Pyx_PyMethod_New(func, type, (PyObject *)(Py_TYPE(type))); + } + if (obj == Py_None) + obj = NULL; + return __Pyx_PyMethod_New(func, obj, type); +} +static PyObject* +__Pyx_CyFunction_repr(__pyx_CyFunctionObject *op) +{ +#if PY_MAJOR_VERSION >= 3 + return PyUnicode_FromFormat("", + op->func_qualname, (void *)op); +#else + return PyString_FromFormat("", + PyString_AsString(op->func_qualname), (void *)op); +#endif +} +static PyObject * __Pyx_CyFunction_CallMethod(PyObject *func, PyObject *self, PyObject *arg, PyObject *kw) { + PyCFunctionObject* f = (PyCFunctionObject*)func; + PyCFunction meth = f->m_ml->ml_meth; + Py_ssize_t size; + switch (f->m_ml->ml_flags & (METH_VARARGS | METH_KEYWORDS | METH_NOARGS | METH_O)) { + case METH_VARARGS: + if (likely(kw == NULL || PyDict_Size(kw) == 0)) + return (*meth)(self, arg); + break; + case METH_VARARGS | METH_KEYWORDS: + return (*(PyCFunctionWithKeywords)(void*)meth)(self, arg, kw); + case METH_NOARGS: + if (likely(kw == NULL || PyDict_Size(kw) == 0)) { + size = PyTuple_GET_SIZE(arg); + if (likely(size == 0)) + return (*meth)(self, NULL); + PyErr_Format(PyExc_TypeError, + "%.200s() takes no arguments (%" CYTHON_FORMAT_SSIZE_T "d given)", + f->m_ml->ml_name, size); + return NULL; + } + break; + case METH_O: + if (likely(kw == NULL || PyDict_Size(kw) == 0)) { + size = PyTuple_GET_SIZE(arg); + if (likely(size == 1)) { + PyObject *result, *arg0; + #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS + arg0 = PyTuple_GET_ITEM(arg, 0); + #else + arg0 = PySequence_ITEM(arg, 0); if (unlikely(!arg0)) return NULL; + #endif + result = (*meth)(self, arg0); + #if !(CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS) + Py_DECREF(arg0); + #endif + return result; + } + PyErr_Format(PyExc_TypeError, + "%.200s() takes exactly one argument (%" CYTHON_FORMAT_SSIZE_T "d given)", + f->m_ml->ml_name, size); + return NULL; + } + break; + default: + PyErr_SetString(PyExc_SystemError, "Bad call flags in " + "__Pyx_CyFunction_Call. METH_OLDARGS is no " + "longer supported!"); + return NULL; + } + PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", + f->m_ml->ml_name); + return NULL; +} +static CYTHON_INLINE PyObject *__Pyx_CyFunction_Call(PyObject *func, PyObject *arg, PyObject *kw) { + return __Pyx_CyFunction_CallMethod(func, ((PyCFunctionObject*)func)->m_self, arg, kw); +} +static PyObject *__Pyx_CyFunction_CallAsMethod(PyObject *func, PyObject *args, PyObject *kw) { + PyObject *result; + __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *) func; + if ((cyfunc->flags & __Pyx_CYFUNCTION_CCLASS) && !(cyfunc->flags & __Pyx_CYFUNCTION_STATICMETHOD)) { + Py_ssize_t argc; + PyObject *new_args; + PyObject *self; + argc = PyTuple_GET_SIZE(args); + new_args = PyTuple_GetSlice(args, 1, argc); + if (unlikely(!new_args)) + return NULL; + self = PyTuple_GetItem(args, 0); + if (unlikely(!self)) { + Py_DECREF(new_args); + return NULL; + } + result = __Pyx_CyFunction_CallMethod(func, self, new_args, kw); + Py_DECREF(new_args); + } else { + result = __Pyx_CyFunction_Call(func, args, kw); + } + return result; +} +static PyTypeObject __pyx_CyFunctionType_type = { + PyVarObject_HEAD_INIT(0, 0) + "cython_function_or_method", + sizeof(__pyx_CyFunctionObject), + 0, + (destructor) __Pyx_CyFunction_dealloc, + 0, + 0, + 0, +#if PY_MAJOR_VERSION < 3 + 0, +#else + 0, +#endif + (reprfunc) __Pyx_CyFunction_repr, + 0, + 0, + 0, + 0, + __Pyx_CyFunction_CallAsMethod, + 0, + 0, + 0, + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, + 0, + (traverseproc) __Pyx_CyFunction_traverse, + (inquiry) __Pyx_CyFunction_clear, + 0, +#if PY_VERSION_HEX < 0x030500A0 + offsetof(__pyx_CyFunctionObject, func_weakreflist), +#else + offsetof(PyCFunctionObject, m_weakreflist), +#endif + 0, + 0, + __pyx_CyFunction_methods, + __pyx_CyFunction_members, + __pyx_CyFunction_getsets, + 0, + 0, + __Pyx_CyFunction_descr_get, + 0, + offsetof(__pyx_CyFunctionObject, func_dict), + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, +#if PY_VERSION_HEX >= 0x030400a1 + 0, +#endif +#if PY_VERSION_HEX >= 0x030800b1 + 0, +#endif +#if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 + 0, +#endif +}; +static int __pyx_CyFunction_init(void) { + __pyx_CyFunctionType = __Pyx_FetchCommonType(&__pyx_CyFunctionType_type); + if (unlikely(__pyx_CyFunctionType == NULL)) { + return -1; + } + return 0; +} +static CYTHON_INLINE void *__Pyx_CyFunction_InitDefaults(PyObject *func, size_t size, int pyobjects) { + __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func; + m->defaults = PyObject_Malloc(size); + if (unlikely(!m->defaults)) + return PyErr_NoMemory(); + memset(m->defaults, 0, size); + m->defaults_pyobjects = pyobjects; + m->defaults_size = size; + return m->defaults; +} +static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsTuple(PyObject *func, PyObject *tuple) { + __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func; + m->defaults_tuple = tuple; + Py_INCREF(tuple); +} +static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsKwDict(PyObject *func, PyObject *dict) { + __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func; + m->defaults_kwdict = dict; + Py_INCREF(dict); +} +static CYTHON_INLINE void __Pyx_CyFunction_SetAnnotationsDict(PyObject *func, PyObject *dict) { + __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func; + m->func_annotations = dict; + Py_INCREF(dict); +} + +/* CythonFunction */ +static PyObject *__Pyx_CyFunction_New(PyMethodDef *ml, int flags, PyObject* qualname, + PyObject *closure, PyObject *module, PyObject* globals, PyObject* code) { + PyObject *op = __Pyx_CyFunction_Init( + PyObject_GC_New(__pyx_CyFunctionObject, __pyx_CyFunctionType), + ml, flags, qualname, closure, module, globals, code + ); + if (likely(op)) { + PyObject_GC_Track(op); + } + return op; +} + +/* CalculateMetaclass */ +static PyObject *__Pyx_CalculateMetaclass(PyTypeObject *metaclass, PyObject *bases) { + Py_ssize_t i, nbases = PyTuple_GET_SIZE(bases); + for (i=0; i < nbases; i++) { + PyTypeObject *tmptype; + PyObject *tmp = PyTuple_GET_ITEM(bases, i); + tmptype = Py_TYPE(tmp); +#if PY_MAJOR_VERSION < 3 + if (tmptype == &PyClass_Type) + continue; +#endif + if (!metaclass) { + metaclass = tmptype; + continue; + } + if (PyType_IsSubtype(metaclass, tmptype)) + continue; + if (PyType_IsSubtype(tmptype, metaclass)) { + metaclass = tmptype; + continue; + } + PyErr_SetString(PyExc_TypeError, + "metaclass conflict: " + "the metaclass of a derived class " + "must be a (non-strict) subclass " + "of the metaclasses of all its bases"); + return NULL; + } + if (!metaclass) { +#if PY_MAJOR_VERSION < 3 + metaclass = &PyClass_Type; +#else + metaclass = &PyType_Type; +#endif + } + Py_INCREF((PyObject*) metaclass); + return (PyObject*) metaclass; +} + +/* Py3ClassCreate */ +static PyObject *__Pyx_Py3MetaclassPrepare(PyObject *metaclass, PyObject *bases, PyObject *name, + PyObject *qualname, PyObject *mkw, PyObject *modname, PyObject *doc) { + PyObject *ns; + if (metaclass) { + PyObject *prep = __Pyx_PyObject_GetAttrStr(metaclass, __pyx_n_s_prepare); + if (prep) { + PyObject *pargs = PyTuple_Pack(2, name, bases); + if (unlikely(!pargs)) { + Py_DECREF(prep); + return NULL; + } + ns = PyObject_Call(prep, pargs, mkw); + Py_DECREF(prep); + Py_DECREF(pargs); + } else { + if (unlikely(!PyErr_ExceptionMatches(PyExc_AttributeError))) + return NULL; + PyErr_Clear(); + ns = PyDict_New(); + } + } else { + ns = PyDict_New(); + } + if (unlikely(!ns)) + return NULL; + if (unlikely(PyObject_SetItem(ns, __pyx_n_s_module, modname) < 0)) goto bad; + if (unlikely(PyObject_SetItem(ns, __pyx_n_s_qualname, qualname) < 0)) goto bad; + if (unlikely(doc && PyObject_SetItem(ns, __pyx_n_s_doc, doc) < 0)) goto bad; + return ns; +bad: + Py_DECREF(ns); + return NULL; +} +static PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObject *bases, + PyObject *dict, PyObject *mkw, + int calculate_metaclass, int allow_py2_metaclass) { + PyObject *result, *margs; + PyObject *owned_metaclass = NULL; + if (allow_py2_metaclass) { + owned_metaclass = PyObject_GetItem(dict, __pyx_n_s_metaclass); + if (owned_metaclass) { + metaclass = owned_metaclass; + } else if (likely(PyErr_ExceptionMatches(PyExc_KeyError))) { + PyErr_Clear(); + } else { + return NULL; + } + } + if (calculate_metaclass && (!metaclass || PyType_Check(metaclass))) { + metaclass = __Pyx_CalculateMetaclass((PyTypeObject*) metaclass, bases); + Py_XDECREF(owned_metaclass); + if (unlikely(!metaclass)) + return NULL; + owned_metaclass = metaclass; + } + margs = PyTuple_Pack(3, name, bases, dict); + if (unlikely(!margs)) { + result = NULL; + } else { + result = PyObject_Call(metaclass, margs, mkw); + Py_DECREF(margs); + } + Py_XDECREF(owned_metaclass); + return result; +} + +/* CLineInTraceback */ +#ifndef CYTHON_CLINE_IN_TRACEBACK +static int __Pyx_CLineForTraceback(CYTHON_NCP_UNUSED PyThreadState *tstate, int c_line) { + PyObject *use_cline; + PyObject *ptype, *pvalue, *ptraceback; +#if CYTHON_COMPILING_IN_CPYTHON + PyObject **cython_runtime_dict; +#endif + if (unlikely(!__pyx_cython_runtime)) { + return c_line; + } + __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); +#if CYTHON_COMPILING_IN_CPYTHON + cython_runtime_dict = _PyObject_GetDictPtr(__pyx_cython_runtime); + if (likely(cython_runtime_dict)) { + __PYX_PY_DICT_LOOKUP_IF_MODIFIED( + use_cline, *cython_runtime_dict, + __Pyx_PyDict_GetItemStr(*cython_runtime_dict, __pyx_n_s_cline_in_traceback)) + } else +#endif + { + PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback); + if (use_cline_obj) { + use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True; + Py_DECREF(use_cline_obj); + } else { + PyErr_Clear(); + use_cline = NULL; + } + } + if (!use_cline) { + c_line = 0; + PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); + } + else if (use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { + c_line = 0; + } + __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); + return c_line; +} +#endif + +/* CodeObjectCache */ +static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) { + int start = 0, mid = 0, end = count - 1; + if (end >= 0 && code_line > entries[end].code_line) { + return count; + } + while (start < end) { + mid = start + (end - start) / 2; + if (code_line < entries[mid].code_line) { + end = mid; + } else if (code_line > entries[mid].code_line) { + start = mid + 1; + } else { + return mid; + } + } + if (code_line <= entries[mid].code_line) { + return mid; + } else { + return mid + 1; + } +} +static PyCodeObject *__pyx_find_code_object(int code_line) { + PyCodeObject* code_object; + int pos; + if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) { + return NULL; + } + pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); + if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) { + return NULL; + } + code_object = __pyx_code_cache.entries[pos].code_object; + Py_INCREF(code_object); + return code_object; +} +static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) { + int pos, i; + __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries; + if (unlikely(!code_line)) { + return; + } + if (unlikely(!entries)) { + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry)); + if (likely(entries)) { + __pyx_code_cache.entries = entries; + __pyx_code_cache.max_count = 64; + __pyx_code_cache.count = 1; + entries[0].code_line = code_line; + entries[0].code_object = code_object; + Py_INCREF(code_object); + } + return; + } + pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); + if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) { + PyCodeObject* tmp = entries[pos].code_object; + entries[pos].code_object = code_object; + Py_DECREF(tmp); + return; + } + if (__pyx_code_cache.count == __pyx_code_cache.max_count) { + int new_max = __pyx_code_cache.max_count + 64; + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc( + __pyx_code_cache.entries, ((size_t)new_max) * sizeof(__Pyx_CodeObjectCacheEntry)); + if (unlikely(!entries)) { + return; + } + __pyx_code_cache.entries = entries; + __pyx_code_cache.max_count = new_max; + } + for (i=__pyx_code_cache.count; i>pos; i--) { + entries[i] = entries[i-1]; + } + entries[pos].code_line = code_line; + entries[pos].code_object = code_object; + __pyx_code_cache.count++; + Py_INCREF(code_object); +} + +/* AddTraceback */ +#include "compile.h" +#include "frameobject.h" +#include "traceback.h" +static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( + const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = 0; + PyObject *py_srcfile = 0; + PyObject *py_funcname = 0; + #if PY_MAJOR_VERSION < 3 + py_srcfile = PyString_FromString(filename); + #else + py_srcfile = PyUnicode_FromString(filename); + #endif + if (!py_srcfile) goto bad; + if (c_line) { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + #else + py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + #endif + } + else { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromString(funcname); + #else + py_funcname = PyUnicode_FromString(funcname); + #endif + } + if (!py_funcname) goto bad; + py_code = __Pyx_PyCode_New( + 0, + 0, + 0, + 0, + 0, + __pyx_empty_bytes, /*PyObject *code,*/ + __pyx_empty_tuple, /*PyObject *consts,*/ + __pyx_empty_tuple, /*PyObject *names,*/ + __pyx_empty_tuple, /*PyObject *varnames,*/ + __pyx_empty_tuple, /*PyObject *freevars,*/ + __pyx_empty_tuple, /*PyObject *cellvars,*/ + py_srcfile, /*PyObject *filename,*/ + py_funcname, /*PyObject *name,*/ + py_line, + __pyx_empty_bytes /*PyObject *lnotab*/ + ); + Py_DECREF(py_srcfile); + Py_DECREF(py_funcname); + return py_code; +bad: + Py_XDECREF(py_srcfile); + Py_XDECREF(py_funcname); + return NULL; +} +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = 0; + PyFrameObject *py_frame = 0; + PyThreadState *tstate = __Pyx_PyThreadState_Current; + if (c_line) { + c_line = __Pyx_CLineForTraceback(tstate, c_line); + } + py_code = __pyx_find_code_object(c_line ? -c_line : py_line); + if (!py_code) { + py_code = __Pyx_CreateCodeObjectForTraceback( + funcname, c_line, py_line, filename); + if (!py_code) goto bad; + __pyx_insert_code_object(c_line ? -c_line : py_line, py_code); + } + py_frame = PyFrame_New( + tstate, /*PyThreadState *tstate,*/ + py_code, /*PyCodeObject *code,*/ + __pyx_d, /*PyObject *globals,*/ + 0 /*PyObject *locals*/ + ); + if (!py_frame) goto bad; + __Pyx_PyFrame_SetLineNumber(py_frame, py_line); + PyTraceBack_Here(py_frame); +bad: + Py_XDECREF(py_code); + Py_XDECREF(py_frame); +} + +/* CIntToPy */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { + const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(long) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(long) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); +#endif + } + } else { + if (sizeof(long) <= sizeof(long)) { + return PyInt_FromLong((long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); +#endif + } + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(long), + little, !is_unsigned); + } +} + +/* CIntFromPyVerify */ +#define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0) +#define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1) +#define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc)\ + {\ + func_type value = func_value;\ + if (sizeof(target_type) < sizeof(func_type)) {\ + if (unlikely(value != (func_type) (target_type) value)) {\ + func_type zero = 0;\ + if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred()))\ + return (target_type) -1;\ + if (is_unsigned && unlikely(value < zero))\ + goto raise_neg_overflow;\ + else\ + goto raise_overflow;\ + }\ + }\ + return (target_type) value;\ + } + +/* CIntToPy */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value) { + const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; + const int is_unsigned = neg_one > const_zero; + if (is_unsigned) { + if (sizeof(int) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(int) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); +#endif + } + } else { + if (sizeof(int) <= sizeof(long)) { + return PyInt_FromLong((long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); +#endif + } + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(int), + little, !is_unsigned); + } +} + +/* CIntFromPy */ +static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { + const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; + const int is_unsigned = neg_one > const_zero; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x))) { + if (sizeof(int) < sizeof(long)) { + __PYX_VERIFY_RETURN_INT(int, long, PyInt_AS_LONG(x)) + } else { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + goto raise_neg_overflow; + } + return (int) val; + } + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (int) 0; + case 1: __PYX_VERIFY_RETURN_INT(int, digit, digits[0]) + case 2: + if (8 * sizeof(int) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 2 * PyLong_SHIFT) { + return (int) (((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 3: + if (8 * sizeof(int) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 3 * PyLong_SHIFT) { + return (int) (((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 4: + if (8 * sizeof(int) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 4 * PyLong_SHIFT) { + return (int) (((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON + if (unlikely(Py_SIZE(x) < 0)) { + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (int) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if (sizeof(int) <= sizeof(unsigned long)) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned long, PyLong_AsUnsignedLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) +#endif + } + } else { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (int) 0; + case -1: __PYX_VERIFY_RETURN_INT(int, sdigit, (sdigit) (-(sdigit)digits[0])) + case 1: __PYX_VERIFY_RETURN_INT(int, digit, +digits[0]) + case -2: + if (8 * sizeof(int) - 1 > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 2: + if (8 * sizeof(int) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + return (int) ((((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -3: + if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 3: + if (8 * sizeof(int) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + return (int) ((((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -4: + if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 4: + if (8 * sizeof(int) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { + return (int) ((((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + } +#endif + if (sizeof(int) <= sizeof(long)) { + __PYX_VERIFY_RETURN_INT_EXC(int, long, PyLong_AsLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(int, PY_LONG_LONG, PyLong_AsLongLong(x)) +#endif + } + } + { +#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) + PyErr_SetString(PyExc_RuntimeError, + "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); +#else + int val; + PyObject *v = __Pyx_PyNumber_IntOrLong(x); + #if PY_MAJOR_VERSION < 3 + if (likely(v) && !PyLong_Check(v)) { + PyObject *tmp = v; + v = PyNumber_Long(tmp); + Py_DECREF(tmp); + } + #endif + if (likely(v)) { + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + int ret = _PyLong_AsByteArray((PyLongObject *)v, + bytes, sizeof(val), + is_little, !is_unsigned); + Py_DECREF(v); + if (likely(!ret)) + return val; + } +#endif + return (int) -1; + } + } else { + int val; + PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); + if (!tmp) return (int) -1; + val = __Pyx_PyInt_As_int(tmp); + Py_DECREF(tmp); + return val; + } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to int"); + return (int) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to int"); + return (int) -1; +} + +/* CIntFromPy */ +static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { + const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; + const int is_unsigned = neg_one > const_zero; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x))) { + if (sizeof(long) < sizeof(long)) { + __PYX_VERIFY_RETURN_INT(long, long, PyInt_AS_LONG(x)) + } else { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + goto raise_neg_overflow; + } + return (long) val; + } + } else +#endif + if (likely(PyLong_Check(x))) { + if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (long) 0; + case 1: __PYX_VERIFY_RETURN_INT(long, digit, digits[0]) + case 2: + if (8 * sizeof(long) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 2 * PyLong_SHIFT) { + return (long) (((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 3: + if (8 * sizeof(long) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 3 * PyLong_SHIFT) { + return (long) (((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 4: + if (8 * sizeof(long) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 4 * PyLong_SHIFT) { + return (long) (((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON + if (unlikely(Py_SIZE(x) < 0)) { + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (long) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if (sizeof(long) <= sizeof(unsigned long)) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned long, PyLong_AsUnsignedLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) +#endif + } + } else { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (long) 0; + case -1: __PYX_VERIFY_RETURN_INT(long, sdigit, (sdigit) (-(sdigit)digits[0])) + case 1: __PYX_VERIFY_RETURN_INT(long, digit, +digits[0]) + case -2: + if (8 * sizeof(long) - 1 > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 2: + if (8 * sizeof(long) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + return (long) ((((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -3: + if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 3: + if (8 * sizeof(long) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + return (long) ((((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -4: + if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 4: + if (8 * sizeof(long) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + return (long) ((((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + } +#endif + if (sizeof(long) <= sizeof(long)) { + __PYX_VERIFY_RETURN_INT_EXC(long, long, PyLong_AsLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(long, PY_LONG_LONG, PyLong_AsLongLong(x)) +#endif + } + } + { +#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) + PyErr_SetString(PyExc_RuntimeError, + "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); +#else + long val; + PyObject *v = __Pyx_PyNumber_IntOrLong(x); + #if PY_MAJOR_VERSION < 3 + if (likely(v) && !PyLong_Check(v)) { + PyObject *tmp = v; + v = PyNumber_Long(tmp); + Py_DECREF(tmp); + } + #endif + if (likely(v)) { + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + int ret = _PyLong_AsByteArray((PyLongObject *)v, + bytes, sizeof(val), + is_little, !is_unsigned); + Py_DECREF(v); + if (likely(!ret)) + return val; + } +#endif + return (long) -1; + } + } else { + long val; + PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); + if (!tmp) return (long) -1; + val = __Pyx_PyInt_As_long(tmp); + Py_DECREF(tmp); + return val; + } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to long"); + return (long) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to long"); + return (long) -1; +} + +/* FastTypeChecks */ +#if CYTHON_COMPILING_IN_CPYTHON +static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) { + while (a) { + a = a->tp_base; + if (a == b) + return 1; + } + return b == &PyBaseObject_Type; +} +static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) { + PyObject *mro; + if (a == b) return 1; + mro = a->tp_mro; + if (likely(mro)) { + Py_ssize_t i, n; + n = PyTuple_GET_SIZE(mro); + for (i = 0; i < n; i++) { + if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b) + return 1; + } + return 0; + } + return __Pyx_InBases(a, b); +} +#if PY_MAJOR_VERSION == 2 +static int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject* exc_type2) { + PyObject *exception, *value, *tb; + int res; + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ErrFetch(&exception, &value, &tb); + res = exc_type1 ? PyObject_IsSubclass(err, exc_type1) : 0; + if (unlikely(res == -1)) { + PyErr_WriteUnraisable(err); + res = 0; + } + if (!res) { + res = PyObject_IsSubclass(err, exc_type2); + if (unlikely(res == -1)) { + PyErr_WriteUnraisable(err); + res = 0; + } + } + __Pyx_ErrRestore(exception, value, tb); + return res; +} +#else +static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject *exc_type2) { + int res = exc_type1 ? __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type1) : 0; + if (!res) { + res = __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2); + } + return res; +} +#endif +static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { + Py_ssize_t i, n; + assert(PyExceptionClass_Check(exc_type)); + n = PyTuple_GET_SIZE(tuple); +#if PY_MAJOR_VERSION >= 3 + for (i=0; ip) { + #if PY_MAJOR_VERSION < 3 + if (t->is_unicode) { + *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL); + } else if (t->intern) { + *t->p = PyString_InternFromString(t->s); + } else { + *t->p = PyString_FromStringAndSize(t->s, t->n - 1); + } + #else + if (t->is_unicode | t->is_str) { + if (t->intern) { + *t->p = PyUnicode_InternFromString(t->s); + } else if (t->encoding) { + *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL); + } else { + *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1); + } + } else { + *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1); + } + #endif + if (!*t->p) + return -1; + if (PyObject_Hash(*t->p) == -1) + return -1; + ++t; + } + return 0; +} + +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) { + return __Pyx_PyUnicode_FromStringAndSize(c_str, (Py_ssize_t)strlen(c_str)); +} +static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject* o) { + Py_ssize_t ignore; + return __Pyx_PyObject_AsStringAndSize(o, &ignore); +} +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT +#if !CYTHON_PEP393_ENABLED +static const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { + char* defenc_c; + PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL); + if (!defenc) return NULL; + defenc_c = PyBytes_AS_STRING(defenc); +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + { + char* end = defenc_c + PyBytes_GET_SIZE(defenc); + char* c; + for (c = defenc_c; c < end; c++) { + if ((unsigned char) (*c) >= 128) { + PyUnicode_AsASCIIString(o); + return NULL; + } + } + } +#endif + *length = PyBytes_GET_SIZE(defenc); + return defenc_c; +} +#else +static CYTHON_INLINE const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { + if (unlikely(__Pyx_PyUnicode_READY(o) == -1)) return NULL; +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + if (likely(PyUnicode_IS_ASCII(o))) { + *length = PyUnicode_GET_LENGTH(o); + return PyUnicode_AsUTF8(o); + } else { + PyUnicode_AsASCIIString(o); + return NULL; + } +#else + return PyUnicode_AsUTF8AndSize(o, length); +#endif +} +#endif +#endif +static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) { +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT + if ( +#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + __Pyx_sys_getdefaultencoding_not_ascii && +#endif + PyUnicode_Check(o)) { + return __Pyx_PyUnicode_AsStringAndSize(o, length); + } else +#endif +#if (!CYTHON_COMPILING_IN_PYPY) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE)) + if (PyByteArray_Check(o)) { + *length = PyByteArray_GET_SIZE(o); + return PyByteArray_AS_STRING(o); + } else +#endif + { + char* result; + int r = PyBytes_AsStringAndSize(o, &result, length); + if (unlikely(r < 0)) { + return NULL; + } else { + return result; + } + } +} +static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { + int is_true = x == Py_True; + if (is_true | (x == Py_False) | (x == Py_None)) return is_true; + else return PyObject_IsTrue(x); +} +static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject* x) { + int retval; + if (unlikely(!x)) return -1; + retval = __Pyx_PyObject_IsTrue(x); + Py_DECREF(x); + return retval; +} +static PyObject* __Pyx_PyNumber_IntOrLongWrongResultType(PyObject* result, const char* type_name) { +#if PY_MAJOR_VERSION >= 3 + if (PyLong_Check(result)) { + if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "__int__ returned non-int (type %.200s). " + "The ability to return an instance of a strict subclass of int " + "is deprecated, and may be removed in a future version of Python.", + Py_TYPE(result)->tp_name)) { + Py_DECREF(result); + return NULL; + } + return result; + } +#endif + PyErr_Format(PyExc_TypeError, + "__%.4s__ returned non-%.4s (type %.200s)", + type_name, type_name, Py_TYPE(result)->tp_name); + Py_DECREF(result); + return NULL; +} +static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x) { +#if CYTHON_USE_TYPE_SLOTS + PyNumberMethods *m; +#endif + const char *name = NULL; + PyObject *res = NULL; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x) || PyLong_Check(x))) +#else + if (likely(PyLong_Check(x))) +#endif + return __Pyx_NewRef(x); +#if CYTHON_USE_TYPE_SLOTS + m = Py_TYPE(x)->tp_as_number; + #if PY_MAJOR_VERSION < 3 + if (m && m->nb_int) { + name = "int"; + res = m->nb_int(x); + } + else if (m && m->nb_long) { + name = "long"; + res = m->nb_long(x); + } + #else + if (likely(m && m->nb_int)) { + name = "int"; + res = m->nb_int(x); + } + #endif +#else + if (!PyBytes_CheckExact(x) && !PyUnicode_CheckExact(x)) { + res = PyNumber_Int(x); + } +#endif + if (likely(res)) { +#if PY_MAJOR_VERSION < 3 + if (unlikely(!PyInt_Check(res) && !PyLong_Check(res))) { +#else + if (unlikely(!PyLong_CheckExact(res))) { +#endif + return __Pyx_PyNumber_IntOrLongWrongResultType(res, name); + } + } + else if (!PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, + "an integer is required"); + } + return res; +} +static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { + Py_ssize_t ival; + PyObject *x; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_CheckExact(b))) { + if (sizeof(Py_ssize_t) >= sizeof(long)) + return PyInt_AS_LONG(b); + else + return PyInt_AsSsize_t(b); + } +#endif + if (likely(PyLong_CheckExact(b))) { + #if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)b)->ob_digit; + const Py_ssize_t size = Py_SIZE(b); + if (likely(__Pyx_sst_abs(size) <= 1)) { + ival = likely(size) ? digits[0] : 0; + if (size == -1) ival = -ival; + return ival; + } else { + switch (size) { + case 2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return (Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + } + } + #endif + return PyLong_AsSsize_t(b); + } + x = PyNumber_Index(b); + if (!x) return -1; + ival = PyInt_AsSsize_t(x); + Py_DECREF(x); + return ival; +} +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { + return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False); +} +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { + return PyInt_FromSize_t(ival); +} + + +#endif /* Py_PYTHON_H */ diff --git a/netharn/initializers/_nx_ext/balanced_sequence_cython.html b/netharn/initializers/_nx_ext/balanced_sequence_cython.html new file mode 100644 index 0000000..3bf259f --- /dev/null +++ b/netharn/initializers/_nx_ext/balanced_sequence_cython.html @@ -0,0 +1,4497 @@ + + + + + + Cython: balanced_sequence_cython.pyx + + + +

Generated by Cython 0.29.20

+

+ Yellow lines hint at Python interaction.
+ Click on a line that starts with a "+" to see the C code that Cython generated for it. +

+

Raw output: balanced_sequence_cython.cpp

+
 001: # distutils: language = c++
+
 002: """
+
 003: This module re-implements functions in :module:`balanced_sequence` in cython
+
 004: and obtains 40-50x speedups in common circumstances. There are likely more
+
 005: speed improvements that could be made.
+
 006: 
+
 007: CommandLine
+
 008: -----------
+
 009: # Explicitly build this cython module
+
 010: cythonize -a -i $HOME/code/networkx/networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx
+
 011: 
+
 012: 
+
 013: Examples
+
 014: --------
+
 015: >>> from networkx.algorithms.isomorphism._embedding.balanced_sequence_cython import *
+
 016: >>> from networkx.algorithms.isomorphism._embedding.demodata import random_balanced_sequence
+
 017: >>> seq1, open_to_close1 = random_balanced_sequence(300, mode='paren')
+
 018: >>> seq2, open_to_close2 = random_balanced_sequence(300, mode='paren')
+
 019: >>> open_to_close = {**open_to_close1, **open_to_close2}
+
 020: >>> full_seq1 = seq1
+
 021: >>> full_seq2 = seq2
+
 022: >>> import operator
+
 023: >>> node_affinity = operator.eq
+
 024: >>> open_to_node = IdentityDict()
+
 025: 
+
 026: with ub.Timer('cython'):
+
 027:     best, value = _lcs_iter_simple_alt2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node)
+
 028: 
+
 029: with ub.Timer('python'):
+
 030:     best, value = _lcs_iter_simple_alt2(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node)
+
 031: 
+
 032: """
+
 033: 
+
 034: 
+
+035: def _lcs_iter_simple_alt2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node):
+
/* Python wrapper */
+static PyObject *__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_1_lcs_iter_simple_alt2_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython__lcs_iter_simple_alt2_cython[] = "\n    Depth first stack trajectory and replace try except statements with ifs\n    ";
+static PyMethodDef __pyx_mdef_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_1_lcs_iter_simple_alt2_cython = {"_lcs_iter_simple_alt2_cython", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_1_lcs_iter_simple_alt2_cython, METH_VARARGS|METH_KEYWORDS, __pyx_doc_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython__lcs_iter_simple_alt2_cython};
+static PyObject *__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_1_lcs_iter_simple_alt2_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_full_seq1 = 0;
+  PyObject *__pyx_v_full_seq2 = 0;
+  PyObject *__pyx_v_open_to_close = 0;
+  PyObject *__pyx_v_node_affinity = 0;
+  PyObject *__pyx_v_open_to_node = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("_lcs_iter_simple_alt2_cython (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_full_seq1,&__pyx_n_s_full_seq2,&__pyx_n_s_open_to_close,&__pyx_n_s_node_affinity,&__pyx_n_s_open_to_node,0};
+    PyObject* values[5] = {0,0,0,0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
+        CYTHON_FALLTHROUGH;
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+        CYTHON_FALLTHROUGH;
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        CYTHON_FALLTHROUGH;
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        CYTHON_FALLTHROUGH;
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        CYTHON_FALLTHROUGH;
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_full_seq1)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        CYTHON_FALLTHROUGH;
+        case  1:
+        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_full_seq2)) != 0)) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("_lcs_iter_simple_alt2_cython", 1, 5, 5, 1); __PYX_ERR(0, 35, __pyx_L3_error)
+        }
+        CYTHON_FALLTHROUGH;
+        case  2:
+        if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_open_to_close)) != 0)) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("_lcs_iter_simple_alt2_cython", 1, 5, 5, 2); __PYX_ERR(0, 35, __pyx_L3_error)
+        }
+        CYTHON_FALLTHROUGH;
+        case  3:
+        if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_node_affinity)) != 0)) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("_lcs_iter_simple_alt2_cython", 1, 5, 5, 3); __PYX_ERR(0, 35, __pyx_L3_error)
+        }
+        CYTHON_FALLTHROUGH;
+        case  4:
+        if (likely((values[4] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_open_to_node)) != 0)) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("_lcs_iter_simple_alt2_cython", 1, 5, 5, 4); __PYX_ERR(0, 35, __pyx_L3_error)
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "_lcs_iter_simple_alt2_cython") < 0)) __PYX_ERR(0, 35, __pyx_L3_error)
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 5) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+      values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+      values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
+    }
+    __pyx_v_full_seq1 = values[0];
+    __pyx_v_full_seq2 = values[1];
+    __pyx_v_open_to_close = values[2];
+    __pyx_v_node_affinity = values[3];
+    __pyx_v_open_to_node = values[4];
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("_lcs_iter_simple_alt2_cython", 1, 5, 5, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 35, __pyx_L3_error)
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython._lcs_iter_simple_alt2_cython", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython__lcs_iter_simple_alt2_cython(__pyx_self, __pyx_v_full_seq1, __pyx_v_full_seq2, __pyx_v_open_to_close, __pyx_v_node_affinity, __pyx_v_open_to_node);
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython__lcs_iter_simple_alt2_cython(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_full_seq1, PyObject *__pyx_v_full_seq2, PyObject *__pyx_v_open_to_close, PyObject *__pyx_v_node_affinity, PyObject *__pyx_v_open_to_node) {
+  PyObject *__pyx_v_all_decomp1 = NULL;
+  PyObject *__pyx_v_all_decomp2 = NULL;
+  PyObject *__pyx_v_key0 = NULL;
+  PyObject *__pyx_v_frame0 = NULL;
+  PyObject *__pyx_v_stack = NULL;
+  PyObject *__pyx_v__results = NULL;
+  PyObject *__pyx_v_empty1 = NULL;
+  PyObject *__pyx_v_empty2 = NULL;
+  PyObject *__pyx_v_best = NULL;
+  PyObject *__pyx_v_base_result = NULL;
+  PyObject *__pyx_v_seq1 = NULL;
+  PyObject *__pyx_v_key1 = NULL;
+  PyObject *__pyx_v_t1 = NULL;
+  PyObject *__pyx_v_a1 = NULL;
+  PyObject *__pyx_v_b1 = NULL;
+  PyObject *__pyx_v_head1 = NULL;
+  PyObject *__pyx_v_tail1 = NULL;
+  PyObject *__pyx_v_head_tail1 = NULL;
+  PyObject *__pyx_v_seq2 = NULL;
+  PyObject *__pyx_v_key2 = NULL;
+  PyObject *__pyx_v_t2 = NULL;
+  PyObject *__pyx_v_a2 = NULL;
+  PyObject *__pyx_v_b2 = NULL;
+  PyObject *__pyx_v_head2 = NULL;
+  PyObject *__pyx_v_tail2 = NULL;
+  PyObject *__pyx_v_head_tail2 = NULL;
+  PyObject *__pyx_v_key = NULL;
+  PyObject *__pyx_v_try_key = NULL;
+  PyObject *__pyx_v_cand1 = NULL;
+  PyObject *__pyx_v_cand2 = NULL;
+  PyObject *__pyx_v_affinity = NULL;
+  PyObject *__pyx_v_pval_h = NULL;
+  PyObject *__pyx_v_new_heads = NULL;
+  PyObject *__pyx_v_pval_t = NULL;
+  PyObject *__pyx_v_new_tails = NULL;
+  PyObject *__pyx_v_new_head1 = NULL;
+  PyObject *__pyx_v_new_head2 = NULL;
+  PyObject *__pyx_v_new_tail1 = NULL;
+  PyObject *__pyx_v_new_tail2 = NULL;
+  PyObject *__pyx_v_subseq1 = NULL;
+  PyObject *__pyx_v_subseq2 = NULL;
+  PyObject *__pyx_v_res3 = NULL;
+  PyObject *__pyx_v_val3 = NULL;
+  PyObject *__pyx_v_cand3 = NULL;
+  PyObject *__pyx_v_val = NULL;
+  PyObject *__pyx_v_found = NULL;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("_lcs_iter_simple_alt2_cython", 0);
+  __Pyx_INCREF(__pyx_v_open_to_node);
+/* … */
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_7);
+  __Pyx_XDECREF(__pyx_t_10);
+  __Pyx_XDECREF(__pyx_t_11);
+  __Pyx_XDECREF(__pyx_t_12);
+  __Pyx_XDECREF(__pyx_t_13);
+  __Pyx_XDECREF(__pyx_t_14);
+  __Pyx_XDECREF(__pyx_t_18);
+  __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython._lcs_iter_simple_alt2_cython", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_all_decomp1);
+  __Pyx_XDECREF(__pyx_v_all_decomp2);
+  __Pyx_XDECREF(__pyx_v_key0);
+  __Pyx_XDECREF(__pyx_v_frame0);
+  __Pyx_XDECREF(__pyx_v_stack);
+  __Pyx_XDECREF(__pyx_v__results);
+  __Pyx_XDECREF(__pyx_v_empty1);
+  __Pyx_XDECREF(__pyx_v_empty2);
+  __Pyx_XDECREF(__pyx_v_best);
+  __Pyx_XDECREF(__pyx_v_base_result);
+  __Pyx_XDECREF(__pyx_v_seq1);
+  __Pyx_XDECREF(__pyx_v_key1);
+  __Pyx_XDECREF(__pyx_v_t1);
+  __Pyx_XDECREF(__pyx_v_a1);
+  __Pyx_XDECREF(__pyx_v_b1);
+  __Pyx_XDECREF(__pyx_v_head1);
+  __Pyx_XDECREF(__pyx_v_tail1);
+  __Pyx_XDECREF(__pyx_v_head_tail1);
+  __Pyx_XDECREF(__pyx_v_seq2);
+  __Pyx_XDECREF(__pyx_v_key2);
+  __Pyx_XDECREF(__pyx_v_t2);
+  __Pyx_XDECREF(__pyx_v_a2);
+  __Pyx_XDECREF(__pyx_v_b2);
+  __Pyx_XDECREF(__pyx_v_head2);
+  __Pyx_XDECREF(__pyx_v_tail2);
+  __Pyx_XDECREF(__pyx_v_head_tail2);
+  __Pyx_XDECREF(__pyx_v_key);
+  __Pyx_XDECREF(__pyx_v_try_key);
+  __Pyx_XDECREF(__pyx_v_cand1);
+  __Pyx_XDECREF(__pyx_v_cand2);
+  __Pyx_XDECREF(__pyx_v_affinity);
+  __Pyx_XDECREF(__pyx_v_pval_h);
+  __Pyx_XDECREF(__pyx_v_new_heads);
+  __Pyx_XDECREF(__pyx_v_pval_t);
+  __Pyx_XDECREF(__pyx_v_new_tails);
+  __Pyx_XDECREF(__pyx_v_new_head1);
+  __Pyx_XDECREF(__pyx_v_new_head2);
+  __Pyx_XDECREF(__pyx_v_new_tail1);
+  __Pyx_XDECREF(__pyx_v_new_tail2);
+  __Pyx_XDECREF(__pyx_v_subseq1);
+  __Pyx_XDECREF(__pyx_v_subseq2);
+  __Pyx_XDECREF(__pyx_v_res3);
+  __Pyx_XDECREF(__pyx_v_val3);
+  __Pyx_XDECREF(__pyx_v_cand3);
+  __Pyx_XDECREF(__pyx_v_val);
+  __Pyx_XDECREF(__pyx_v_found);
+  __Pyx_XDECREF(__pyx_v_open_to_node);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+/* … */
+  __pyx_tuple__4 = PyTuple_Pack(51, __pyx_n_s_full_seq1, __pyx_n_s_full_seq2, __pyx_n_s_open_to_close, __pyx_n_s_node_affinity, __pyx_n_s_open_to_node, __pyx_n_s_all_decomp1, __pyx_n_s_all_decomp2, __pyx_n_s_key0, __pyx_n_s_frame0, __pyx_n_s_stack, __pyx_n_s_results, __pyx_n_s_empty1, __pyx_n_s_empty2, __pyx_n_s_best, __pyx_n_s_base_result, __pyx_n_s_seq1, __pyx_n_s_key1, __pyx_n_s_t1, __pyx_n_s_a1, __pyx_n_s_b1, __pyx_n_s_head1, __pyx_n_s_tail1, __pyx_n_s_head_tail1, __pyx_n_s_seq2, __pyx_n_s_key2, __pyx_n_s_t2, __pyx_n_s_a2, __pyx_n_s_b2, __pyx_n_s_head2, __pyx_n_s_tail2, __pyx_n_s_head_tail2, __pyx_n_s_key, __pyx_n_s_try_key, __pyx_n_s_cand1, __pyx_n_s_cand2, __pyx_n_s_affinity, __pyx_n_s_pval_h, __pyx_n_s_new_heads, __pyx_n_s_pval_t, __pyx_n_s_new_tails, __pyx_n_s_new_head1, __pyx_n_s_new_head2, __pyx_n_s_new_tail1, __pyx_n_s_new_tail2, __pyx_n_s_subseq1, __pyx_n_s_subseq2, __pyx_n_s_res3, __pyx_n_s_val3, __pyx_n_s_cand3, __pyx_n_s_val, __pyx_n_s_found); if (unlikely(!__pyx_tuple__4)) __PYX_ERR(0, 35, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__4);
+  __Pyx_GIVEREF(__pyx_tuple__4);
+/* … */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_1_lcs_iter_simple_alt2_cython, NULL, __pyx_n_s_networkx_algorithms_isomorphism); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 35, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_lcs_iter_simple_alt2_cython, __pyx_t_1) < 0) __PYX_ERR(0, 35, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_codeobj__5 = (PyObject*)__Pyx_PyCode_New(5, 0, 51, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__4, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_embedding_balanced_sequence_cyt, __pyx_n_s_lcs_iter_simple_alt2_cython, 35, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__5)) __PYX_ERR(0, 35, __pyx_L1_error)
+
 036:     """
+
 037:     Depth first stack trajectory and replace try except statements with ifs
+
 038:     """
+
+039:     if open_to_node is None:
+
  __pyx_t_1 = (__pyx_v_open_to_node == Py_None);
+  __pyx_t_2 = (__pyx_t_1 != 0);
+  if (__pyx_t_2) {
+/* … */
+  }
+
+040:         open_to_node = IdentityDict()
+
    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_IdentityDict); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 40, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_5 = NULL;
+    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
+      __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+      if (likely(__pyx_t_5)) {
+        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+        __Pyx_INCREF(__pyx_t_5);
+        __Pyx_INCREF(function);
+        __Pyx_DECREF_SET(__pyx_t_4, function);
+      }
+    }
+    __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5) : __Pyx_PyObject_CallNoArg(__pyx_t_4);
+    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 40, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    __Pyx_DECREF_SET(__pyx_v_open_to_node, __pyx_t_3);
+    __pyx_t_3 = 0;
+
+041:     all_decomp1 = generate_all_decomp_cython(full_seq1, open_to_close, open_to_node)
+
  __pyx_t_6.__pyx_n = 1;
+  __pyx_t_6.open_to_node = __pyx_v_open_to_node;
+  __pyx_t_3 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython(__pyx_v_full_seq1, __pyx_v_open_to_close, &__pyx_t_6); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 41, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_v_all_decomp1 = __pyx_t_3;
+  __pyx_t_3 = 0;
+
+042:     all_decomp2 = generate_all_decomp_cython(full_seq2, open_to_close, open_to_node)
+
  __pyx_t_6.__pyx_n = 1;
+  __pyx_t_6.open_to_node = __pyx_v_open_to_node;
+  __pyx_t_3 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython(__pyx_v_full_seq2, __pyx_v_open_to_close, &__pyx_t_6); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 42, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_v_all_decomp2 = __pyx_t_3;
+  __pyx_t_3 = 0;
+
 043: 
+
+044:     key0 = (full_seq1, full_seq2)
+
  __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 44, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_INCREF(__pyx_v_full_seq1);
+  __Pyx_GIVEREF(__pyx_v_full_seq1);
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_full_seq1);
+  __Pyx_INCREF(__pyx_v_full_seq2);
+  __Pyx_GIVEREF(__pyx_v_full_seq2);
+  PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_full_seq2);
+  __pyx_v_key0 = ((PyObject*)__pyx_t_3);
+  __pyx_t_3 = 0;
+
+045:     frame0 = key0
+
  __Pyx_INCREF(__pyx_v_key0);
+  __pyx_v_frame0 = __pyx_v_key0;
+
+046:     stack = [frame0]
+
  __pyx_t_3 = PyList_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 46, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_INCREF(__pyx_v_frame0);
+  __Pyx_GIVEREF(__pyx_v_frame0);
+  PyList_SET_ITEM(__pyx_t_3, 0, __pyx_v_frame0);
+  __pyx_v_stack = ((PyObject*)__pyx_t_3);
+  __pyx_t_3 = 0;
+
 047: 
+
+048:     _results = {}
+
  __pyx_t_3 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 48, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_v__results = ((PyObject*)__pyx_t_3);
+  __pyx_t_3 = 0;
+
 049:     # Populate base cases
+
+050:     empty1 = type(next(iter(all_decomp1.keys())))()
+
  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_all_decomp1, __pyx_n_s_keys); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 50, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_7 = NULL;
+  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) {
+    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_5);
+    if (likely(__pyx_t_7)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
+      __Pyx_INCREF(__pyx_t_7);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_5, function);
+    }
+  }
+  __pyx_t_4 = (__pyx_t_7) ? __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_7) : __Pyx_PyObject_CallNoArg(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+  if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 50, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 50, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __pyx_t_4 = __Pyx_PyIter_Next(__pyx_t_5); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 50, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __Pyx_INCREF(((PyObject *)Py_TYPE(__pyx_t_4)));
+  __pyx_t_5 = ((PyObject *)Py_TYPE(__pyx_t_4)); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __pyx_t_4 = NULL;
+  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
+    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_5);
+    if (likely(__pyx_t_4)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
+      __Pyx_INCREF(__pyx_t_4);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_5, function);
+    }
+  }
+  __pyx_t_3 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
+  if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 50, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_v_empty1 = __pyx_t_3;
+  __pyx_t_3 = 0;
+
+051:     empty2 = type(next(iter(all_decomp2.keys())))()
+
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_all_decomp2, __pyx_n_s_keys); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 51, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_7 = NULL;
+  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) {
+    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_4);
+    if (likely(__pyx_t_7)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+      __Pyx_INCREF(__pyx_t_7);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_4, function);
+    }
+  }
+  __pyx_t_5 = (__pyx_t_7) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_7) : __Pyx_PyObject_CallNoArg(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
+  if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 51, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __pyx_t_4 = PyObject_GetIter(__pyx_t_5); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 51, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = __Pyx_PyIter_Next(__pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 51, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_5);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __Pyx_INCREF(((PyObject *)Py_TYPE(__pyx_t_5)));
+  __pyx_t_4 = ((PyObject *)Py_TYPE(__pyx_t_5)); __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+  __pyx_t_5 = NULL;
+  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
+    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+    if (likely(__pyx_t_5)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+      __Pyx_INCREF(__pyx_t_5);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_4, function);
+    }
+  }
+  __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5) : __Pyx_PyObject_CallNoArg(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+  if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 51, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  __pyx_v_empty2 = __pyx_t_3;
+  __pyx_t_3 = 0;
+
+052:     best = (empty1, empty2)
+
  __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 52, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_INCREF(__pyx_v_empty1);
+  __Pyx_GIVEREF(__pyx_v_empty1);
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_empty1);
+  __Pyx_INCREF(__pyx_v_empty2);
+  __Pyx_GIVEREF(__pyx_v_empty2);
+  PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_empty2);
+  __pyx_v_best = __pyx_t_3;
+  __pyx_t_3 = 0;
+
+053:     base_result = (0, best)
+
  __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 53, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_INCREF(__pyx_int_0);
+  __Pyx_GIVEREF(__pyx_int_0);
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_int_0);
+  __Pyx_INCREF(__pyx_v_best);
+  __Pyx_GIVEREF(__pyx_v_best);
+  PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_best);
+  __pyx_v_base_result = ((PyObject*)__pyx_t_3);
+  __pyx_t_3 = 0;
+
+054:     for seq1 in all_decomp1.keys():
+
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_all_decomp1, __pyx_n_s_keys); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 54, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_4);
+  __pyx_t_5 = NULL;
+  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) {
+    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
+    if (likely(__pyx_t_5)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
+      __Pyx_INCREF(__pyx_t_5);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_4, function);
+    }
+  }
+  __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5) : __Pyx_PyObject_CallNoArg(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+  if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 54, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  if (likely(PyList_CheckExact(__pyx_t_3)) || PyTuple_CheckExact(__pyx_t_3)) {
+    __pyx_t_4 = __pyx_t_3; __Pyx_INCREF(__pyx_t_4); __pyx_t_8 = 0;
+    __pyx_t_9 = NULL;
+  } else {
+    __pyx_t_8 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 54, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
+    __pyx_t_9 = Py_TYPE(__pyx_t_4)->tp_iternext; if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 54, __pyx_L1_error)
+  }
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  for (;;) {
+    if (likely(!__pyx_t_9)) {
+      if (likely(PyList_CheckExact(__pyx_t_4))) {
+        if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_4)) break;
+        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+        __pyx_t_3 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_3); __pyx_t_8++; if (unlikely(0 < 0)) __PYX_ERR(0, 54, __pyx_L1_error)
+        #else
+        __pyx_t_3 = PySequence_ITEM(__pyx_t_4, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 54, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        #endif
+      } else {
+        if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_4)) break;
+        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+        __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_3); __pyx_t_8++; if (unlikely(0 < 0)) __PYX_ERR(0, 54, __pyx_L1_error)
+        #else
+        __pyx_t_3 = PySequence_ITEM(__pyx_t_4, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 54, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        #endif
+      }
+    } else {
+      __pyx_t_3 = __pyx_t_9(__pyx_t_4);
+      if (unlikely(!__pyx_t_3)) {
+        PyObject* exc_type = PyErr_Occurred();
+        if (exc_type) {
+          if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
+          else __PYX_ERR(0, 54, __pyx_L1_error)
+        }
+        break;
+      }
+      __Pyx_GOTREF(__pyx_t_3);
+    }
+    __Pyx_XDECREF_SET(__pyx_v_seq1, __pyx_t_3);
+    __pyx_t_3 = 0;
+/* … */
+  }
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+
+055:         key1 = seq1
+
    __Pyx_INCREF(__pyx_v_seq1);
+    __Pyx_XDECREF_SET(__pyx_v_key1, __pyx_v_seq1);
+
+056:         t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[key1]
+
    __pyx_t_3 = __Pyx_PyObject_GetItem(__pyx_v_all_decomp1, __pyx_v_key1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 56, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) {
+      PyObject* sequence = __pyx_t_3;
+      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+      if (unlikely(size != 6)) {
+        if (size > 6) __Pyx_RaiseTooManyValuesError(6);
+        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+        __PYX_ERR(0, 56, __pyx_L1_error)
+      }
+      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+      if (likely(PyTuple_CheckExact(sequence))) {
+        __pyx_t_5 = PyTuple_GET_ITEM(sequence, 0); 
+        __pyx_t_7 = PyTuple_GET_ITEM(sequence, 1); 
+        __pyx_t_10 = PyTuple_GET_ITEM(sequence, 2); 
+        __pyx_t_11 = PyTuple_GET_ITEM(sequence, 3); 
+        __pyx_t_12 = PyTuple_GET_ITEM(sequence, 4); 
+        __pyx_t_13 = PyTuple_GET_ITEM(sequence, 5); 
+      } else {
+        __pyx_t_5 = PyList_GET_ITEM(sequence, 0); 
+        __pyx_t_7 = PyList_GET_ITEM(sequence, 1); 
+        __pyx_t_10 = PyList_GET_ITEM(sequence, 2); 
+        __pyx_t_11 = PyList_GET_ITEM(sequence, 3); 
+        __pyx_t_12 = PyList_GET_ITEM(sequence, 4); 
+        __pyx_t_13 = PyList_GET_ITEM(sequence, 5); 
+      }
+      __Pyx_INCREF(__pyx_t_5);
+      __Pyx_INCREF(__pyx_t_7);
+      __Pyx_INCREF(__pyx_t_10);
+      __Pyx_INCREF(__pyx_t_11);
+      __Pyx_INCREF(__pyx_t_12);
+      __Pyx_INCREF(__pyx_t_13);
+      #else
+      {
+        Py_ssize_t i;
+        PyObject** temps[6] = {&__pyx_t_5,&__pyx_t_7,&__pyx_t_10,&__pyx_t_11,&__pyx_t_12,&__pyx_t_13};
+        for (i=0; i < 6; i++) {
+          PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 56, __pyx_L1_error)
+          __Pyx_GOTREF(item);
+          *(temps[i]) = item;
+        }
+      }
+      #endif
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    } else {
+      Py_ssize_t index = -1;
+      PyObject** temps[6] = {&__pyx_t_5,&__pyx_t_7,&__pyx_t_10,&__pyx_t_11,&__pyx_t_12,&__pyx_t_13};
+      __pyx_t_14 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 56, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_14);
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __pyx_t_15 = Py_TYPE(__pyx_t_14)->tp_iternext;
+      for (index=0; index < 6; index++) {
+        PyObject* item = __pyx_t_15(__pyx_t_14); if (unlikely(!item)) goto __pyx_L6_unpacking_failed;
+        __Pyx_GOTREF(item);
+        *(temps[index]) = item;
+      }
+      if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_14), 6) < 0) __PYX_ERR(0, 56, __pyx_L1_error)
+      __pyx_t_15 = NULL;
+      __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
+      goto __pyx_L7_unpacking_done;
+      __pyx_L6_unpacking_failed:;
+      __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
+      __pyx_t_15 = NULL;
+      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
+      __PYX_ERR(0, 56, __pyx_L1_error)
+      __pyx_L7_unpacking_done:;
+    }
+    __Pyx_XDECREF_SET(__pyx_v_t1, __pyx_t_5);
+    __pyx_t_5 = 0;
+    __Pyx_XDECREF_SET(__pyx_v_a1, __pyx_t_7);
+    __pyx_t_7 = 0;
+    __Pyx_XDECREF_SET(__pyx_v_b1, __pyx_t_10);
+    __pyx_t_10 = 0;
+    __Pyx_XDECREF_SET(__pyx_v_head1, __pyx_t_11);
+    __pyx_t_11 = 0;
+    __Pyx_XDECREF_SET(__pyx_v_tail1, __pyx_t_12);
+    __pyx_t_12 = 0;
+    __Pyx_XDECREF_SET(__pyx_v_head_tail1, __pyx_t_13);
+    __pyx_t_13 = 0;
+
+057:         _results[(seq1, empty2)] = base_result
+
    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 57, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_INCREF(__pyx_v_seq1);
+    __Pyx_GIVEREF(__pyx_v_seq1);
+    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_seq1);
+    __Pyx_INCREF(__pyx_v_empty2);
+    __Pyx_GIVEREF(__pyx_v_empty2);
+    PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_empty2);
+    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 57, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+058:         _results[(head1, empty2)] = base_result
+
    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 58, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_INCREF(__pyx_v_head1);
+    __Pyx_GIVEREF(__pyx_v_head1);
+    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_head1);
+    __Pyx_INCREF(__pyx_v_empty2);
+    __Pyx_GIVEREF(__pyx_v_empty2);
+    PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_empty2);
+    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 58, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+059:         _results[(tail1, empty2)] = base_result
+
    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 59, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_INCREF(__pyx_v_tail1);
+    __Pyx_GIVEREF(__pyx_v_tail1);
+    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_tail1);
+    __Pyx_INCREF(__pyx_v_empty2);
+    __Pyx_GIVEREF(__pyx_v_empty2);
+    PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_empty2);
+    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 59, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+060:         _results[(head_tail1, empty2)] = base_result
+
    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 60, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_INCREF(__pyx_v_head_tail1);
+    __Pyx_GIVEREF(__pyx_v_head_tail1);
+    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_head_tail1);
+    __Pyx_INCREF(__pyx_v_empty2);
+    __Pyx_GIVEREF(__pyx_v_empty2);
+    PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_empty2);
+    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 60, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
 061: 
+
+062:     for seq2 in all_decomp2.keys():
+
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_all_decomp2, __pyx_n_s_keys); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 62, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_13 = NULL;
+  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) {
+    __pyx_t_13 = PyMethod_GET_SELF(__pyx_t_3);
+    if (likely(__pyx_t_13)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+      __Pyx_INCREF(__pyx_t_13);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_3, function);
+    }
+  }
+  __pyx_t_4 = (__pyx_t_13) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_13) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0;
+  if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 62, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (likely(PyList_CheckExact(__pyx_t_4)) || PyTuple_CheckExact(__pyx_t_4)) {
+    __pyx_t_3 = __pyx_t_4; __Pyx_INCREF(__pyx_t_3); __pyx_t_8 = 0;
+    __pyx_t_9 = NULL;
+  } else {
+    __pyx_t_8 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 62, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_9 = Py_TYPE(__pyx_t_3)->tp_iternext; if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 62, __pyx_L1_error)
+  }
+  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+  for (;;) {
+    if (likely(!__pyx_t_9)) {
+      if (likely(PyList_CheckExact(__pyx_t_3))) {
+        if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_3)) break;
+        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+        __pyx_t_4 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_8); __Pyx_INCREF(__pyx_t_4); __pyx_t_8++; if (unlikely(0 < 0)) __PYX_ERR(0, 62, __pyx_L1_error)
+        #else
+        __pyx_t_4 = PySequence_ITEM(__pyx_t_3, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 62, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_4);
+        #endif
+      } else {
+        if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_3)) break;
+        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+        __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_8); __Pyx_INCREF(__pyx_t_4); __pyx_t_8++; if (unlikely(0 < 0)) __PYX_ERR(0, 62, __pyx_L1_error)
+        #else
+        __pyx_t_4 = PySequence_ITEM(__pyx_t_3, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 62, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_4);
+        #endif
+      }
+    } else {
+      __pyx_t_4 = __pyx_t_9(__pyx_t_3);
+      if (unlikely(!__pyx_t_4)) {
+        PyObject* exc_type = PyErr_Occurred();
+        if (exc_type) {
+          if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
+          else __PYX_ERR(0, 62, __pyx_L1_error)
+        }
+        break;
+      }
+      __Pyx_GOTREF(__pyx_t_4);
+    }
+    __Pyx_XDECREF_SET(__pyx_v_seq2, __pyx_t_4);
+    __pyx_t_4 = 0;
+/* … */
+  }
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+063:         key2 = seq2
+
    __Pyx_INCREF(__pyx_v_seq2);
+    __Pyx_XDECREF_SET(__pyx_v_key2, __pyx_v_seq2);
+
+064:         t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[key2]
+
    __pyx_t_4 = __Pyx_PyObject_GetItem(__pyx_v_all_decomp2, __pyx_v_key2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 64, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
+    if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) {
+      PyObject* sequence = __pyx_t_4;
+      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+      if (unlikely(size != 6)) {
+        if (size > 6) __Pyx_RaiseTooManyValuesError(6);
+        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+        __PYX_ERR(0, 64, __pyx_L1_error)
+      }
+      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+      if (likely(PyTuple_CheckExact(sequence))) {
+        __pyx_t_13 = PyTuple_GET_ITEM(sequence, 0); 
+        __pyx_t_12 = PyTuple_GET_ITEM(sequence, 1); 
+        __pyx_t_11 = PyTuple_GET_ITEM(sequence, 2); 
+        __pyx_t_10 = PyTuple_GET_ITEM(sequence, 3); 
+        __pyx_t_7 = PyTuple_GET_ITEM(sequence, 4); 
+        __pyx_t_5 = PyTuple_GET_ITEM(sequence, 5); 
+      } else {
+        __pyx_t_13 = PyList_GET_ITEM(sequence, 0); 
+        __pyx_t_12 = PyList_GET_ITEM(sequence, 1); 
+        __pyx_t_11 = PyList_GET_ITEM(sequence, 2); 
+        __pyx_t_10 = PyList_GET_ITEM(sequence, 3); 
+        __pyx_t_7 = PyList_GET_ITEM(sequence, 4); 
+        __pyx_t_5 = PyList_GET_ITEM(sequence, 5); 
+      }
+      __Pyx_INCREF(__pyx_t_13);
+      __Pyx_INCREF(__pyx_t_12);
+      __Pyx_INCREF(__pyx_t_11);
+      __Pyx_INCREF(__pyx_t_10);
+      __Pyx_INCREF(__pyx_t_7);
+      __Pyx_INCREF(__pyx_t_5);
+      #else
+      {
+        Py_ssize_t i;
+        PyObject** temps[6] = {&__pyx_t_13,&__pyx_t_12,&__pyx_t_11,&__pyx_t_10,&__pyx_t_7,&__pyx_t_5};
+        for (i=0; i < 6; i++) {
+          PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 64, __pyx_L1_error)
+          __Pyx_GOTREF(item);
+          *(temps[i]) = item;
+        }
+      }
+      #endif
+      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+    } else {
+      Py_ssize_t index = -1;
+      PyObject** temps[6] = {&__pyx_t_13,&__pyx_t_12,&__pyx_t_11,&__pyx_t_10,&__pyx_t_7,&__pyx_t_5};
+      __pyx_t_14 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 64, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_14);
+      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+      __pyx_t_15 = Py_TYPE(__pyx_t_14)->tp_iternext;
+      for (index=0; index < 6; index++) {
+        PyObject* item = __pyx_t_15(__pyx_t_14); if (unlikely(!item)) goto __pyx_L10_unpacking_failed;
+        __Pyx_GOTREF(item);
+        *(temps[index]) = item;
+      }
+      if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_14), 6) < 0) __PYX_ERR(0, 64, __pyx_L1_error)
+      __pyx_t_15 = NULL;
+      __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
+      goto __pyx_L11_unpacking_done;
+      __pyx_L10_unpacking_failed:;
+      __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
+      __pyx_t_15 = NULL;
+      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
+      __PYX_ERR(0, 64, __pyx_L1_error)
+      __pyx_L11_unpacking_done:;
+    }
+    __Pyx_XDECREF_SET(__pyx_v_t2, __pyx_t_13);
+    __pyx_t_13 = 0;
+    __Pyx_XDECREF_SET(__pyx_v_a2, __pyx_t_12);
+    __pyx_t_12 = 0;
+    __Pyx_XDECREF_SET(__pyx_v_b2, __pyx_t_11);
+    __pyx_t_11 = 0;
+    __Pyx_XDECREF_SET(__pyx_v_head2, __pyx_t_10);
+    __pyx_t_10 = 0;
+    __Pyx_XDECREF_SET(__pyx_v_tail2, __pyx_t_7);
+    __pyx_t_7 = 0;
+    __Pyx_XDECREF_SET(__pyx_v_head_tail2, __pyx_t_5);
+    __pyx_t_5 = 0;
+
+065:         _results[(empty1, seq2)] = base_result
+
    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 65, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
+    __Pyx_INCREF(__pyx_v_empty1);
+    __Pyx_GIVEREF(__pyx_v_empty1);
+    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_empty1);
+    __Pyx_INCREF(__pyx_v_seq2);
+    __Pyx_GIVEREF(__pyx_v_seq2);
+    PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_seq2);
+    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_4, __pyx_v_base_result) < 0)) __PYX_ERR(0, 65, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+
+066:         _results[(empty1, head2)] = base_result
+
    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 66, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
+    __Pyx_INCREF(__pyx_v_empty1);
+    __Pyx_GIVEREF(__pyx_v_empty1);
+    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_empty1);
+    __Pyx_INCREF(__pyx_v_head2);
+    __Pyx_GIVEREF(__pyx_v_head2);
+    PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_head2);
+    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_4, __pyx_v_base_result) < 0)) __PYX_ERR(0, 66, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+
+067:         _results[(empty1, tail2)] = base_result
+
    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 67, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
+    __Pyx_INCREF(__pyx_v_empty1);
+    __Pyx_GIVEREF(__pyx_v_empty1);
+    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_empty1);
+    __Pyx_INCREF(__pyx_v_tail2);
+    __Pyx_GIVEREF(__pyx_v_tail2);
+    PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_tail2);
+    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_4, __pyx_v_base_result) < 0)) __PYX_ERR(0, 67, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+
+068:         _results[(empty1, head_tail2)] = base_result
+
    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 68, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
+    __Pyx_INCREF(__pyx_v_empty1);
+    __Pyx_GIVEREF(__pyx_v_empty1);
+    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_empty1);
+    __Pyx_INCREF(__pyx_v_head_tail2);
+    __Pyx_GIVEREF(__pyx_v_head_tail2);
+    PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_head_tail2);
+    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_4, __pyx_v_base_result) < 0)) __PYX_ERR(0, 68, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+
 069: 
+
+070:     while stack:
+
  while (1) {
+    __pyx_t_2 = (PyList_GET_SIZE(__pyx_v_stack) != 0);
+    if (!__pyx_t_2) break;
+
+071:         key = stack[-1]
+
    __pyx_t_3 = __Pyx_GetItemInt_List(__pyx_v_stack, -1L, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 71, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_XDECREF_SET(__pyx_v_key, __pyx_t_3);
+    __pyx_t_3 = 0;
+
+072:         if key not in _results:
+
    __pyx_t_2 = (__Pyx_PyDict_ContainsTF(__pyx_v_key, __pyx_v__results, Py_NE)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 72, __pyx_L1_error)
+    __pyx_t_1 = (__pyx_t_2 != 0);
+    if (__pyx_t_1) {
+/* … */
+    }
+
+073:             seq1, seq2 = key
+
      if ((likely(PyTuple_CheckExact(__pyx_v_key))) || (PyList_CheckExact(__pyx_v_key))) {
+        PyObject* sequence = __pyx_v_key;
+        Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+        if (unlikely(size != 2)) {
+          if (size > 2) __Pyx_RaiseTooManyValuesError(2);
+          else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+          __PYX_ERR(0, 73, __pyx_L1_error)
+        }
+        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+        if (likely(PyTuple_CheckExact(sequence))) {
+          __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); 
+          __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); 
+        } else {
+          __pyx_t_3 = PyList_GET_ITEM(sequence, 0); 
+          __pyx_t_4 = PyList_GET_ITEM(sequence, 1); 
+        }
+        __Pyx_INCREF(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_4);
+        #else
+        __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 73, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 73, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_4);
+        #endif
+      } else {
+        Py_ssize_t index = -1;
+        __pyx_t_5 = PyObject_GetIter(__pyx_v_key); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 73, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_5);
+        __pyx_t_15 = Py_TYPE(__pyx_t_5)->tp_iternext;
+        index = 0; __pyx_t_3 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_3)) goto __pyx_L15_unpacking_failed;
+        __Pyx_GOTREF(__pyx_t_3);
+        index = 1; __pyx_t_4 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_4)) goto __pyx_L15_unpacking_failed;
+        __Pyx_GOTREF(__pyx_t_4);
+        if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_5), 2) < 0) __PYX_ERR(0, 73, __pyx_L1_error)
+        __pyx_t_15 = NULL;
+        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+        goto __pyx_L16_unpacking_done;
+        __pyx_L15_unpacking_failed:;
+        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+        __pyx_t_15 = NULL;
+        if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
+        __PYX_ERR(0, 73, __pyx_L1_error)
+        __pyx_L16_unpacking_done:;
+      }
+      __Pyx_XDECREF_SET(__pyx_v_seq1, __pyx_t_3);
+      __pyx_t_3 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_seq2, __pyx_t_4);
+      __pyx_t_4 = 0;
+
 074: 
+
+075:             t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[seq1]
+
      __pyx_t_4 = __Pyx_PyObject_GetItem(__pyx_v_all_decomp1, __pyx_v_seq1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 75, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_4);
+      if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) {
+        PyObject* sequence = __pyx_t_4;
+        Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+        if (unlikely(size != 6)) {
+          if (size > 6) __Pyx_RaiseTooManyValuesError(6);
+          else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+          __PYX_ERR(0, 75, __pyx_L1_error)
+        }
+        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+        if (likely(PyTuple_CheckExact(sequence))) {
+          __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); 
+          __pyx_t_5 = PyTuple_GET_ITEM(sequence, 1); 
+          __pyx_t_7 = PyTuple_GET_ITEM(sequence, 2); 
+          __pyx_t_10 = PyTuple_GET_ITEM(sequence, 3); 
+          __pyx_t_11 = PyTuple_GET_ITEM(sequence, 4); 
+          __pyx_t_12 = PyTuple_GET_ITEM(sequence, 5); 
+        } else {
+          __pyx_t_3 = PyList_GET_ITEM(sequence, 0); 
+          __pyx_t_5 = PyList_GET_ITEM(sequence, 1); 
+          __pyx_t_7 = PyList_GET_ITEM(sequence, 2); 
+          __pyx_t_10 = PyList_GET_ITEM(sequence, 3); 
+          __pyx_t_11 = PyList_GET_ITEM(sequence, 4); 
+          __pyx_t_12 = PyList_GET_ITEM(sequence, 5); 
+        }
+        __Pyx_INCREF(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_5);
+        __Pyx_INCREF(__pyx_t_7);
+        __Pyx_INCREF(__pyx_t_10);
+        __Pyx_INCREF(__pyx_t_11);
+        __Pyx_INCREF(__pyx_t_12);
+        #else
+        {
+          Py_ssize_t i;
+          PyObject** temps[6] = {&__pyx_t_3,&__pyx_t_5,&__pyx_t_7,&__pyx_t_10,&__pyx_t_11,&__pyx_t_12};
+          for (i=0; i < 6; i++) {
+            PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 75, __pyx_L1_error)
+            __Pyx_GOTREF(item);
+            *(temps[i]) = item;
+          }
+        }
+        #endif
+        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+      } else {
+        Py_ssize_t index = -1;
+        PyObject** temps[6] = {&__pyx_t_3,&__pyx_t_5,&__pyx_t_7,&__pyx_t_10,&__pyx_t_11,&__pyx_t_12};
+        __pyx_t_13 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 75, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_13);
+        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        __pyx_t_15 = Py_TYPE(__pyx_t_13)->tp_iternext;
+        for (index=0; index < 6; index++) {
+          PyObject* item = __pyx_t_15(__pyx_t_13); if (unlikely(!item)) goto __pyx_L17_unpacking_failed;
+          __Pyx_GOTREF(item);
+          *(temps[index]) = item;
+        }
+        if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_13), 6) < 0) __PYX_ERR(0, 75, __pyx_L1_error)
+        __pyx_t_15 = NULL;
+        __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
+        goto __pyx_L18_unpacking_done;
+        __pyx_L17_unpacking_failed:;
+        __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
+        __pyx_t_15 = NULL;
+        if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
+        __PYX_ERR(0, 75, __pyx_L1_error)
+        __pyx_L18_unpacking_done:;
+      }
+      __Pyx_XDECREF_SET(__pyx_v_t1, __pyx_t_3);
+      __pyx_t_3 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_a1, __pyx_t_5);
+      __pyx_t_5 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_b1, __pyx_t_7);
+      __pyx_t_7 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_head1, __pyx_t_10);
+      __pyx_t_10 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_tail1, __pyx_t_11);
+      __pyx_t_11 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_head_tail1, __pyx_t_12);
+      __pyx_t_12 = 0;
+
+076:             t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[seq2]
+
      __pyx_t_4 = __Pyx_PyObject_GetItem(__pyx_v_all_decomp2, __pyx_v_seq2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 76, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_4);
+      if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) {
+        PyObject* sequence = __pyx_t_4;
+        Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+        if (unlikely(size != 6)) {
+          if (size > 6) __Pyx_RaiseTooManyValuesError(6);
+          else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+          __PYX_ERR(0, 76, __pyx_L1_error)
+        }
+        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+        if (likely(PyTuple_CheckExact(sequence))) {
+          __pyx_t_12 = PyTuple_GET_ITEM(sequence, 0); 
+          __pyx_t_11 = PyTuple_GET_ITEM(sequence, 1); 
+          __pyx_t_10 = PyTuple_GET_ITEM(sequence, 2); 
+          __pyx_t_7 = PyTuple_GET_ITEM(sequence, 3); 
+          __pyx_t_5 = PyTuple_GET_ITEM(sequence, 4); 
+          __pyx_t_3 = PyTuple_GET_ITEM(sequence, 5); 
+        } else {
+          __pyx_t_12 = PyList_GET_ITEM(sequence, 0); 
+          __pyx_t_11 = PyList_GET_ITEM(sequence, 1); 
+          __pyx_t_10 = PyList_GET_ITEM(sequence, 2); 
+          __pyx_t_7 = PyList_GET_ITEM(sequence, 3); 
+          __pyx_t_5 = PyList_GET_ITEM(sequence, 4); 
+          __pyx_t_3 = PyList_GET_ITEM(sequence, 5); 
+        }
+        __Pyx_INCREF(__pyx_t_12);
+        __Pyx_INCREF(__pyx_t_11);
+        __Pyx_INCREF(__pyx_t_10);
+        __Pyx_INCREF(__pyx_t_7);
+        __Pyx_INCREF(__pyx_t_5);
+        __Pyx_INCREF(__pyx_t_3);
+        #else
+        {
+          Py_ssize_t i;
+          PyObject** temps[6] = {&__pyx_t_12,&__pyx_t_11,&__pyx_t_10,&__pyx_t_7,&__pyx_t_5,&__pyx_t_3};
+          for (i=0; i < 6; i++) {
+            PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 76, __pyx_L1_error)
+            __Pyx_GOTREF(item);
+            *(temps[i]) = item;
+          }
+        }
+        #endif
+        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+      } else {
+        Py_ssize_t index = -1;
+        PyObject** temps[6] = {&__pyx_t_12,&__pyx_t_11,&__pyx_t_10,&__pyx_t_7,&__pyx_t_5,&__pyx_t_3};
+        __pyx_t_13 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 76, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_13);
+        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        __pyx_t_15 = Py_TYPE(__pyx_t_13)->tp_iternext;
+        for (index=0; index < 6; index++) {
+          PyObject* item = __pyx_t_15(__pyx_t_13); if (unlikely(!item)) goto __pyx_L19_unpacking_failed;
+          __Pyx_GOTREF(item);
+          *(temps[index]) = item;
+        }
+        if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_13), 6) < 0) __PYX_ERR(0, 76, __pyx_L1_error)
+        __pyx_t_15 = NULL;
+        __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
+        goto __pyx_L20_unpacking_done;
+        __pyx_L19_unpacking_failed:;
+        __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
+        __pyx_t_15 = NULL;
+        if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
+        __PYX_ERR(0, 76, __pyx_L1_error)
+        __pyx_L20_unpacking_done:;
+      }
+      __Pyx_XDECREF_SET(__pyx_v_t2, __pyx_t_12);
+      __pyx_t_12 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_a2, __pyx_t_11);
+      __pyx_t_11 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_b2, __pyx_t_10);
+      __pyx_t_10 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_head2, __pyx_t_7);
+      __pyx_t_7 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_tail2, __pyx_t_5);
+      __pyx_t_5 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_head_tail2, __pyx_t_3);
+      __pyx_t_3 = 0;
+
 077: 
+
 078:             # Case 2: The current edge in sequence1 is deleted
+
+079:             try_key = (head_tail1, seq2)
+
      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 79, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_4);
+      __Pyx_INCREF(__pyx_v_head_tail1);
+      __Pyx_GIVEREF(__pyx_v_head_tail1);
+      PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_head_tail1);
+      __Pyx_INCREF(__pyx_v_seq2);
+      __Pyx_GIVEREF(__pyx_v_seq2);
+      PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_seq2);
+      __Pyx_XDECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_4));
+      __pyx_t_4 = 0;
+
+080:             if try_key in _results:
+
      __pyx_t_1 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 80, __pyx_L1_error)
+      __pyx_t_2 = (__pyx_t_1 != 0);
+      if (__pyx_t_2) {
+/* … */
+        goto __pyx_L21;
+      }
+
+081:                 cand1 = _results[try_key]
+
        __pyx_t_4 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 81, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_4);
+        __Pyx_XDECREF_SET(__pyx_v_cand1, __pyx_t_4);
+        __pyx_t_4 = 0;
+
 082:             else:
+
 083:                 # stack.append(key)
+
+084:                 stack.append(try_key)
+
      /*else*/ {
+        __pyx_t_16 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_try_key); if (unlikely(__pyx_t_16 == ((int)-1))) __PYX_ERR(0, 84, __pyx_L1_error)
+
+085:                 continue
+
        goto __pyx_L12_continue;
+      }
+      __pyx_L21:;
+
 086: 
+
 087:             # Case 3: The current edge in sequence2 is deleted
+
+088:             try_key = (seq1, head_tail2)
+
      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 88, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_4);
+      __Pyx_INCREF(__pyx_v_seq1);
+      __Pyx_GIVEREF(__pyx_v_seq1);
+      PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_seq1);
+      __Pyx_INCREF(__pyx_v_head_tail2);
+      __Pyx_GIVEREF(__pyx_v_head_tail2);
+      PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_head_tail2);
+      __Pyx_DECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_4));
+      __pyx_t_4 = 0;
+
+089:             if try_key in _results:
+
      __pyx_t_2 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 89, __pyx_L1_error)
+      __pyx_t_1 = (__pyx_t_2 != 0);
+      if (__pyx_t_1) {
+/* … */
+        goto __pyx_L22;
+      }
+
+090:                 cand2 = _results[try_key]
+
        __pyx_t_4 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 90, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_4);
+        __Pyx_XDECREF_SET(__pyx_v_cand2, __pyx_t_4);
+        __pyx_t_4 = 0;
+
 091:             else:
+
 092:                 # stack.append(key)
+
+093:                 stack.append(try_key)
+
      /*else*/ {
+        __pyx_t_16 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_try_key); if (unlikely(__pyx_t_16 == ((int)-1))) __PYX_ERR(0, 93, __pyx_L1_error)
+
+094:                 continue
+
        goto __pyx_L12_continue;
+      }
+      __pyx_L22:;
+
 095: 
+
 096:             # Case 1: The LCS involves this edge
+
+097:             affinity = node_affinity(t1, t2)
+
      __Pyx_INCREF(__pyx_v_node_affinity);
+      __pyx_t_3 = __pyx_v_node_affinity; __pyx_t_5 = NULL;
+      __pyx_t_17 = 0;
+      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+        __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_3);
+        if (likely(__pyx_t_5)) {
+          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+          __Pyx_INCREF(__pyx_t_5);
+          __Pyx_INCREF(function);
+          __Pyx_DECREF_SET(__pyx_t_3, function);
+          __pyx_t_17 = 1;
+        }
+      }
+      #if CYTHON_FAST_PYCALL
+      if (PyFunction_Check(__pyx_t_3)) {
+        PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_v_t1, __pyx_v_t2};
+        __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_17, 2+__pyx_t_17); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 97, __pyx_L1_error)
+        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+        __Pyx_GOTREF(__pyx_t_4);
+      } else
+      #endif
+      #if CYTHON_FAST_PYCCALL
+      if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
+        PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_v_t1, __pyx_v_t2};
+        __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_17, 2+__pyx_t_17); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 97, __pyx_L1_error)
+        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
+        __Pyx_GOTREF(__pyx_t_4);
+      } else
+      #endif
+      {
+        __pyx_t_7 = PyTuple_New(2+__pyx_t_17); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 97, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_7);
+        if (__pyx_t_5) {
+          __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL;
+        }
+        __Pyx_INCREF(__pyx_v_t1);
+        __Pyx_GIVEREF(__pyx_v_t1);
+        PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_17, __pyx_v_t1);
+        __Pyx_INCREF(__pyx_v_t2);
+        __Pyx_GIVEREF(__pyx_v_t2);
+        PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_17, __pyx_v_t2);
+        __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_7, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 97, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_4);
+        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+      }
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_affinity, __pyx_t_4);
+      __pyx_t_4 = 0;
+
+098:             if affinity:
+
      __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_affinity); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 98, __pyx_L1_error)
+      if (__pyx_t_1) {
+/* … */
+        goto __pyx_L23;
+      }
+
+099:                 try_key = (head1, head2)
+
        __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 99, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_4);
+        __Pyx_INCREF(__pyx_v_head1);
+        __Pyx_GIVEREF(__pyx_v_head1);
+        PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_head1);
+        __Pyx_INCREF(__pyx_v_head2);
+        __Pyx_GIVEREF(__pyx_v_head2);
+        PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_head2);
+        __Pyx_DECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_4));
+        __pyx_t_4 = 0;
+
+100:                 if try_key in _results:
+
        __pyx_t_1 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 100, __pyx_L1_error)
+        __pyx_t_2 = (__pyx_t_1 != 0);
+        if (__pyx_t_2) {
+/* … */
+          goto __pyx_L24;
+        }
+
+101:                     pval_h, new_heads = _results[try_key]
+
          __pyx_t_4 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 101, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_4);
+          if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) {
+            PyObject* sequence = __pyx_t_4;
+            Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+            if (unlikely(size != 2)) {
+              if (size > 2) __Pyx_RaiseTooManyValuesError(2);
+              else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+              __PYX_ERR(0, 101, __pyx_L1_error)
+            }
+            #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+            if (likely(PyTuple_CheckExact(sequence))) {
+              __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); 
+              __pyx_t_7 = PyTuple_GET_ITEM(sequence, 1); 
+            } else {
+              __pyx_t_3 = PyList_GET_ITEM(sequence, 0); 
+              __pyx_t_7 = PyList_GET_ITEM(sequence, 1); 
+            }
+            __Pyx_INCREF(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_7);
+            #else
+            __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 101, __pyx_L1_error)
+            __Pyx_GOTREF(__pyx_t_3);
+            __pyx_t_7 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 101, __pyx_L1_error)
+            __Pyx_GOTREF(__pyx_t_7);
+            #endif
+            __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+          } else {
+            Py_ssize_t index = -1;
+            __pyx_t_5 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 101, __pyx_L1_error)
+            __Pyx_GOTREF(__pyx_t_5);
+            __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+            __pyx_t_15 = Py_TYPE(__pyx_t_5)->tp_iternext;
+            index = 0; __pyx_t_3 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_3)) goto __pyx_L25_unpacking_failed;
+            __Pyx_GOTREF(__pyx_t_3);
+            index = 1; __pyx_t_7 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_7)) goto __pyx_L25_unpacking_failed;
+            __Pyx_GOTREF(__pyx_t_7);
+            if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_5), 2) < 0) __PYX_ERR(0, 101, __pyx_L1_error)
+            __pyx_t_15 = NULL;
+            __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+            goto __pyx_L26_unpacking_done;
+            __pyx_L25_unpacking_failed:;
+            __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+            __pyx_t_15 = NULL;
+            if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
+            __PYX_ERR(0, 101, __pyx_L1_error)
+            __pyx_L26_unpacking_done:;
+          }
+          __Pyx_XDECREF_SET(__pyx_v_pval_h, __pyx_t_3);
+          __pyx_t_3 = 0;
+          __Pyx_XDECREF_SET(__pyx_v_new_heads, __pyx_t_7);
+          __pyx_t_7 = 0;
+
 102:                 else:
+
 103:                     # stack.append(key)
+
+104:                     stack.append(try_key)
+
        /*else*/ {
+          __pyx_t_16 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_try_key); if (unlikely(__pyx_t_16 == ((int)-1))) __PYX_ERR(0, 104, __pyx_L1_error)
+
+105:                     continue
+
          goto __pyx_L12_continue;
+        }
+        __pyx_L24:;
+
 106: 
+
+107:                 try_key = (tail1, tail2)
+
        __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 107, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_4);
+        __Pyx_INCREF(__pyx_v_tail1);
+        __Pyx_GIVEREF(__pyx_v_tail1);
+        PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_tail1);
+        __Pyx_INCREF(__pyx_v_tail2);
+        __Pyx_GIVEREF(__pyx_v_tail2);
+        PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_tail2);
+        __Pyx_DECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_4));
+        __pyx_t_4 = 0;
+
+108:                 if try_key in _results:
+
        __pyx_t_2 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 108, __pyx_L1_error)
+        __pyx_t_1 = (__pyx_t_2 != 0);
+        if (__pyx_t_1) {
+/* … */
+          goto __pyx_L27;
+        }
+
+109:                     pval_t, new_tails = _results[try_key]
+
          __pyx_t_4 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 109, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_4);
+          if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) {
+            PyObject* sequence = __pyx_t_4;
+            Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+            if (unlikely(size != 2)) {
+              if (size > 2) __Pyx_RaiseTooManyValuesError(2);
+              else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+              __PYX_ERR(0, 109, __pyx_L1_error)
+            }
+            #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+            if (likely(PyTuple_CheckExact(sequence))) {
+              __pyx_t_7 = PyTuple_GET_ITEM(sequence, 0); 
+              __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); 
+            } else {
+              __pyx_t_7 = PyList_GET_ITEM(sequence, 0); 
+              __pyx_t_3 = PyList_GET_ITEM(sequence, 1); 
+            }
+            __Pyx_INCREF(__pyx_t_7);
+            __Pyx_INCREF(__pyx_t_3);
+            #else
+            __pyx_t_7 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 109, __pyx_L1_error)
+            __Pyx_GOTREF(__pyx_t_7);
+            __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 109, __pyx_L1_error)
+            __Pyx_GOTREF(__pyx_t_3);
+            #endif
+            __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+          } else {
+            Py_ssize_t index = -1;
+            __pyx_t_5 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 109, __pyx_L1_error)
+            __Pyx_GOTREF(__pyx_t_5);
+            __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+            __pyx_t_15 = Py_TYPE(__pyx_t_5)->tp_iternext;
+            index = 0; __pyx_t_7 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_7)) goto __pyx_L28_unpacking_failed;
+            __Pyx_GOTREF(__pyx_t_7);
+            index = 1; __pyx_t_3 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_3)) goto __pyx_L28_unpacking_failed;
+            __Pyx_GOTREF(__pyx_t_3);
+            if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_5), 2) < 0) __PYX_ERR(0, 109, __pyx_L1_error)
+            __pyx_t_15 = NULL;
+            __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+            goto __pyx_L29_unpacking_done;
+            __pyx_L28_unpacking_failed:;
+            __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+            __pyx_t_15 = NULL;
+            if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
+            __PYX_ERR(0, 109, __pyx_L1_error)
+            __pyx_L29_unpacking_done:;
+          }
+          __Pyx_XDECREF_SET(__pyx_v_pval_t, __pyx_t_7);
+          __pyx_t_7 = 0;
+          __Pyx_XDECREF_SET(__pyx_v_new_tails, __pyx_t_3);
+          __pyx_t_3 = 0;
+
 110:                 else:
+
 111:                     # stack.append(key)
+
+112:                     stack.append(try_key)
+
        /*else*/ {
+          __pyx_t_16 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_try_key); if (unlikely(__pyx_t_16 == ((int)-1))) __PYX_ERR(0, 112, __pyx_L1_error)
+
+113:                     continue
+
          goto __pyx_L12_continue;
+        }
+        __pyx_L27:;
+
 114: 
+
+115:                 new_head1, new_head2 = new_heads
+
        if ((likely(PyTuple_CheckExact(__pyx_v_new_heads))) || (PyList_CheckExact(__pyx_v_new_heads))) {
+          PyObject* sequence = __pyx_v_new_heads;
+          Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+          if (unlikely(size != 2)) {
+            if (size > 2) __Pyx_RaiseTooManyValuesError(2);
+            else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+            __PYX_ERR(0, 115, __pyx_L1_error)
+          }
+          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+          if (likely(PyTuple_CheckExact(sequence))) {
+            __pyx_t_4 = PyTuple_GET_ITEM(sequence, 0); 
+            __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); 
+          } else {
+            __pyx_t_4 = PyList_GET_ITEM(sequence, 0); 
+            __pyx_t_3 = PyList_GET_ITEM(sequence, 1); 
+          }
+          __Pyx_INCREF(__pyx_t_4);
+          __Pyx_INCREF(__pyx_t_3);
+          #else
+          __pyx_t_4 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 115, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_4);
+          __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 115, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_3);
+          #endif
+        } else {
+          Py_ssize_t index = -1;
+          __pyx_t_7 = PyObject_GetIter(__pyx_v_new_heads); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 115, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_7);
+          __pyx_t_15 = Py_TYPE(__pyx_t_7)->tp_iternext;
+          index = 0; __pyx_t_4 = __pyx_t_15(__pyx_t_7); if (unlikely(!__pyx_t_4)) goto __pyx_L30_unpacking_failed;
+          __Pyx_GOTREF(__pyx_t_4);
+          index = 1; __pyx_t_3 = __pyx_t_15(__pyx_t_7); if (unlikely(!__pyx_t_3)) goto __pyx_L30_unpacking_failed;
+          __Pyx_GOTREF(__pyx_t_3);
+          if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_7), 2) < 0) __PYX_ERR(0, 115, __pyx_L1_error)
+          __pyx_t_15 = NULL;
+          __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+          goto __pyx_L31_unpacking_done;
+          __pyx_L30_unpacking_failed:;
+          __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+          __pyx_t_15 = NULL;
+          if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
+          __PYX_ERR(0, 115, __pyx_L1_error)
+          __pyx_L31_unpacking_done:;
+        }
+        __Pyx_XDECREF_SET(__pyx_v_new_head1, __pyx_t_4);
+        __pyx_t_4 = 0;
+        __Pyx_XDECREF_SET(__pyx_v_new_head2, __pyx_t_3);
+        __pyx_t_3 = 0;
+
+116:                 new_tail1, new_tail2 = new_tails
+
        if ((likely(PyTuple_CheckExact(__pyx_v_new_tails))) || (PyList_CheckExact(__pyx_v_new_tails))) {
+          PyObject* sequence = __pyx_v_new_tails;
+          Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+          if (unlikely(size != 2)) {
+            if (size > 2) __Pyx_RaiseTooManyValuesError(2);
+            else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+            __PYX_ERR(0, 116, __pyx_L1_error)
+          }
+          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+          if (likely(PyTuple_CheckExact(sequence))) {
+            __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); 
+            __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); 
+          } else {
+            __pyx_t_3 = PyList_GET_ITEM(sequence, 0); 
+            __pyx_t_4 = PyList_GET_ITEM(sequence, 1); 
+          }
+          __Pyx_INCREF(__pyx_t_3);
+          __Pyx_INCREF(__pyx_t_4);
+          #else
+          __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 116, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_3);
+          __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 116, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_4);
+          #endif
+        } else {
+          Py_ssize_t index = -1;
+          __pyx_t_7 = PyObject_GetIter(__pyx_v_new_tails); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 116, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_7);
+          __pyx_t_15 = Py_TYPE(__pyx_t_7)->tp_iternext;
+          index = 0; __pyx_t_3 = __pyx_t_15(__pyx_t_7); if (unlikely(!__pyx_t_3)) goto __pyx_L32_unpacking_failed;
+          __Pyx_GOTREF(__pyx_t_3);
+          index = 1; __pyx_t_4 = __pyx_t_15(__pyx_t_7); if (unlikely(!__pyx_t_4)) goto __pyx_L32_unpacking_failed;
+          __Pyx_GOTREF(__pyx_t_4);
+          if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_7), 2) < 0) __PYX_ERR(0, 116, __pyx_L1_error)
+          __pyx_t_15 = NULL;
+          __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+          goto __pyx_L33_unpacking_done;
+          __pyx_L32_unpacking_failed:;
+          __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+          __pyx_t_15 = NULL;
+          if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
+          __PYX_ERR(0, 116, __pyx_L1_error)
+          __pyx_L33_unpacking_done:;
+        }
+        __Pyx_XDECREF_SET(__pyx_v_new_tail1, __pyx_t_3);
+        __pyx_t_3 = 0;
+        __Pyx_XDECREF_SET(__pyx_v_new_tail2, __pyx_t_4);
+        __pyx_t_4 = 0;
+
 117: 
+
+118:                 subseq1 = a1 + new_head1 + b1 + new_tail1
+
        __pyx_t_4 = PyNumber_Add(__pyx_v_a1, __pyx_v_new_head1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 118, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_4);
+        __pyx_t_3 = PyNumber_Add(__pyx_t_4, __pyx_v_b1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 118, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        __pyx_t_4 = PyNumber_Add(__pyx_t_3, __pyx_v_new_tail1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 118, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_4);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_XDECREF_SET(__pyx_v_subseq1, __pyx_t_4);
+        __pyx_t_4 = 0;
+
+119:                 subseq2 = a2 + new_head2 + b2 + new_tail2
+
        __pyx_t_4 = PyNumber_Add(__pyx_v_a2, __pyx_v_new_head2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 119, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_4);
+        __pyx_t_3 = PyNumber_Add(__pyx_t_4, __pyx_v_b2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 119, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        __pyx_t_4 = PyNumber_Add(__pyx_t_3, __pyx_v_new_tail2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 119, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_4);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_XDECREF_SET(__pyx_v_subseq2, __pyx_t_4);
+        __pyx_t_4 = 0;
+
 120: 
+
+121:                 res3 = (subseq1, subseq2)
+
        __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 121, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_4);
+        __Pyx_INCREF(__pyx_v_subseq1);
+        __Pyx_GIVEREF(__pyx_v_subseq1);
+        PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_subseq1);
+        __Pyx_INCREF(__pyx_v_subseq2);
+        __Pyx_GIVEREF(__pyx_v_subseq2);
+        PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_subseq2);
+        __Pyx_XDECREF_SET(__pyx_v_res3, ((PyObject*)__pyx_t_4));
+        __pyx_t_4 = 0;
+
+122:                 val3 = pval_h + pval_t + affinity
+
        __pyx_t_4 = PyNumber_Add(__pyx_v_pval_h, __pyx_v_pval_t); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 122, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_4);
+        __pyx_t_3 = PyNumber_Add(__pyx_t_4, __pyx_v_affinity); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 122, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+        __Pyx_XDECREF_SET(__pyx_v_val3, __pyx_t_3);
+        __pyx_t_3 = 0;
+
+123:                 cand3 = (val3, res3)
+
        __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 123, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __Pyx_INCREF(__pyx_v_val3);
+        __Pyx_GIVEREF(__pyx_v_val3);
+        PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_val3);
+        __Pyx_INCREF(__pyx_v_res3);
+        __Pyx_GIVEREF(__pyx_v_res3);
+        PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_res3);
+        __Pyx_XDECREF_SET(__pyx_v_cand3, ((PyObject*)__pyx_t_3));
+        __pyx_t_3 = 0;
+
 124:             else:
+
+125:                 cand3 = (-1, None)
+
      /*else*/ {
+        __Pyx_INCREF(__pyx_tuple_);
+        __Pyx_XDECREF_SET(__pyx_v_cand3, __pyx_tuple_);
+      }
+      __pyx_L23:;
+/* … */
+  __pyx_tuple_ = PyTuple_Pack(2, __pyx_int_neg_1, Py_None); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 125, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple_);
+  __Pyx_GIVEREF(__pyx_tuple_);
+
 126: 
+
 127:             # We solved the frame
+
+128:             _results[key] = max(cand1, cand2, cand3)
+
      __Pyx_INCREF(__pyx_v_cand2);
+      __pyx_t_3 = __pyx_v_cand2;
+      __Pyx_INCREF(__pyx_v_cand3);
+      __pyx_t_18 = __pyx_v_cand3;
+      __Pyx_INCREF(__pyx_v_cand1);
+      __pyx_t_4 = __pyx_v_cand1;
+      __pyx_t_5 = PyObject_RichCompare(__pyx_t_3, __pyx_t_4, Py_GT); __Pyx_XGOTREF(__pyx_t_5); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 128, __pyx_L1_error)
+      __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 128, __pyx_L1_error)
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      if (__pyx_t_1) {
+        __Pyx_INCREF(__pyx_t_3);
+        __pyx_t_7 = __pyx_t_3;
+      } else {
+        __Pyx_INCREF(__pyx_t_4);
+        __pyx_t_7 = __pyx_t_4;
+      }
+      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+      __Pyx_INCREF(__pyx_t_7);
+      __pyx_t_4 = __pyx_t_7;
+      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+      __pyx_t_5 = PyObject_RichCompare(__pyx_t_18, __pyx_t_4, Py_GT); __Pyx_XGOTREF(__pyx_t_5); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 128, __pyx_L1_error)
+      __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 128, __pyx_L1_error)
+      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+      if (__pyx_t_1) {
+        __Pyx_INCREF(__pyx_t_18);
+        __pyx_t_7 = __pyx_t_18;
+      } else {
+        __Pyx_INCREF(__pyx_t_4);
+        __pyx_t_7 = __pyx_t_4;
+      }
+      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
+      __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __pyx_t_3 = __pyx_t_7;
+      __Pyx_INCREF(__pyx_t_3);
+      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+      if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_v_key, __pyx_t_3) < 0)) __PYX_ERR(0, 128, __pyx_L1_error)
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+129:         stack.pop()
+
    __pyx_t_3 = __Pyx_PyList_Pop(__pyx_v_stack); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 129, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __pyx_L12_continue:;
+  }
+
 130: 
+
+131:     val, best = _results[key0]
+
  __pyx_t_3 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_key0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 131, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) {
+    PyObject* sequence = __pyx_t_3;
+    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+    if (unlikely(size != 2)) {
+      if (size > 2) __Pyx_RaiseTooManyValuesError(2);
+      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+      __PYX_ERR(0, 131, __pyx_L1_error)
+    }
+    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+    if (likely(PyTuple_CheckExact(sequence))) {
+      __pyx_t_7 = PyTuple_GET_ITEM(sequence, 0); 
+      __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); 
+    } else {
+      __pyx_t_7 = PyList_GET_ITEM(sequence, 0); 
+      __pyx_t_4 = PyList_GET_ITEM(sequence, 1); 
+    }
+    __Pyx_INCREF(__pyx_t_7);
+    __Pyx_INCREF(__pyx_t_4);
+    #else
+    __pyx_t_7 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 131, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_7);
+    __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 131, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_4);
+    #endif
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  } else {
+    Py_ssize_t index = -1;
+    __pyx_t_5 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 131, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_5);
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __pyx_t_15 = Py_TYPE(__pyx_t_5)->tp_iternext;
+    index = 0; __pyx_t_7 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_7)) goto __pyx_L34_unpacking_failed;
+    __Pyx_GOTREF(__pyx_t_7);
+    index = 1; __pyx_t_4 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_4)) goto __pyx_L34_unpacking_failed;
+    __Pyx_GOTREF(__pyx_t_4);
+    if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_5), 2) < 0) __PYX_ERR(0, 131, __pyx_L1_error)
+    __pyx_t_15 = NULL;
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    goto __pyx_L35_unpacking_done;
+    __pyx_L34_unpacking_failed:;
+    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+    __pyx_t_15 = NULL;
+    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
+    __PYX_ERR(0, 131, __pyx_L1_error)
+    __pyx_L35_unpacking_done:;
+  }
+  __pyx_v_val = __pyx_t_7;
+  __pyx_t_7 = 0;
+  __Pyx_DECREF_SET(__pyx_v_best, __pyx_t_4);
+  __pyx_t_4 = 0;
+
+132:     found = (best, val)
+
  __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 132, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_INCREF(__pyx_v_best);
+  __Pyx_GIVEREF(__pyx_v_best);
+  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_best);
+  __Pyx_INCREF(__pyx_v_val);
+  __Pyx_GIVEREF(__pyx_v_val);
+  PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_val);
+  __pyx_v_found = ((PyObject*)__pyx_t_3);
+  __pyx_t_3 = 0;
+
+133:     return found
+
  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(__pyx_v_found);
+  __pyx_r = __pyx_v_found;
+  goto __pyx_L0;
+
 134: 
+
 135: 
+
+136: def _lcs_iter_prehash2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node):
+
/* Python wrapper */
+static PyObject *__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_3_lcs_iter_prehash2_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static char __pyx_doc_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_2_lcs_iter_prehash2_cython[] = "\n    Version of the lcs iterative algorithm where we precompute hash values\n    ";
+static PyMethodDef __pyx_mdef_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_3_lcs_iter_prehash2_cython = {"_lcs_iter_prehash2_cython", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_3_lcs_iter_prehash2_cython, METH_VARARGS|METH_KEYWORDS, __pyx_doc_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_2_lcs_iter_prehash2_cython};
+static PyObject *__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_3_lcs_iter_prehash2_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  PyObject *__pyx_v_full_seq1 = 0;
+  PyObject *__pyx_v_full_seq2 = 0;
+  PyObject *__pyx_v_open_to_close = 0;
+  PyObject *__pyx_v_node_affinity = 0;
+  PyObject *__pyx_v_open_to_node = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("_lcs_iter_prehash2_cython (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_full_seq1,&__pyx_n_s_full_seq2,&__pyx_n_s_open_to_close,&__pyx_n_s_node_affinity,&__pyx_n_s_open_to_node,0};
+    PyObject* values[5] = {0,0,0,0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
+        CYTHON_FALLTHROUGH;
+        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+        CYTHON_FALLTHROUGH;
+        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+        CYTHON_FALLTHROUGH;
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        CYTHON_FALLTHROUGH;
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        CYTHON_FALLTHROUGH;
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_full_seq1)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        CYTHON_FALLTHROUGH;
+        case  1:
+        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_full_seq2)) != 0)) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("_lcs_iter_prehash2_cython", 1, 5, 5, 1); __PYX_ERR(0, 136, __pyx_L3_error)
+        }
+        CYTHON_FALLTHROUGH;
+        case  2:
+        if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_open_to_close)) != 0)) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("_lcs_iter_prehash2_cython", 1, 5, 5, 2); __PYX_ERR(0, 136, __pyx_L3_error)
+        }
+        CYTHON_FALLTHROUGH;
+        case  3:
+        if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_node_affinity)) != 0)) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("_lcs_iter_prehash2_cython", 1, 5, 5, 3); __PYX_ERR(0, 136, __pyx_L3_error)
+        }
+        CYTHON_FALLTHROUGH;
+        case  4:
+        if (likely((values[4] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_open_to_node)) != 0)) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("_lcs_iter_prehash2_cython", 1, 5, 5, 4); __PYX_ERR(0, 136, __pyx_L3_error)
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "_lcs_iter_prehash2_cython") < 0)) __PYX_ERR(0, 136, __pyx_L3_error)
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 5) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
+      values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
+      values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
+    }
+    __pyx_v_full_seq1 = values[0];
+    __pyx_v_full_seq2 = values[1];
+    __pyx_v_open_to_close = values[2];
+    __pyx_v_node_affinity = values[3];
+    __pyx_v_open_to_node = values[4];
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("_lcs_iter_prehash2_cython", 1, 5, 5, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 136, __pyx_L3_error)
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython._lcs_iter_prehash2_cython", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_2_lcs_iter_prehash2_cython(__pyx_self, __pyx_v_full_seq1, __pyx_v_full_seq2, __pyx_v_open_to_close, __pyx_v_node_affinity, __pyx_v_open_to_node);
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_2_lcs_iter_prehash2_cython(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_full_seq1, PyObject *__pyx_v_full_seq2, PyObject *__pyx_v_open_to_close, PyObject *__pyx_v_node_affinity, PyObject *__pyx_v_open_to_node) {
+  PyObject *__pyx_v_all_decomp1 = 0;
+  PyObject *__pyx_v_all_decomp2 = 0;
+  PyObject *__pyx_v_key_decomp1 = 0;
+  PyObject *__pyx_v_key_decomp2 = 0;
+  PyObject *__pyx_v__results = 0;
+  PyObject *__pyx_v_empty1 = NULL;
+  PyObject *__pyx_v_empty2 = NULL;
+  Py_hash_t __pyx_v_empty1_key;
+  Py_hash_t __pyx_v_empty2_key;
+  PyObject *__pyx_v_best = 0;
+  PyObject *__pyx_v_info1 = 0;
+  PyObject *__pyx_v_info2 = 0;
+  PyObject *__pyx_v_try_key = 0;
+  PyObject *__pyx_v_key = 0;
+  Py_hash_t __pyx_v_seq1_key;
+  Py_hash_t __pyx_v_seq2_key;
+  Py_hash_t __pyx_v_head1_key;
+  Py_hash_t __pyx_v_tail1_key;
+  Py_hash_t __pyx_v_head_tail1_key;
+  Py_hash_t __pyx_v_head2_key;
+  Py_hash_t __pyx_v_tail2_key;
+  Py_hash_t __pyx_v_head_tail2_key;
+  PyObject *__pyx_v_frame = 0;
+  PyObject *__pyx_v_miss_frame = 0;
+  PyObject *__pyx_v_base_result = NULL;
+  PyObject *__pyx_v_seq1 = NULL;
+  PyObject *__pyx_v_seq2 = NULL;
+  Py_hash_t __pyx_v_full_seq1_key;
+  Py_hash_t __pyx_v_full_seq2_key;
+  PyObject *__pyx_v_key0 = 0;
+  PyObject *__pyx_v_frame0 = 0;
+  PyObject *__pyx_v_stack = 0;
+  PyObject *__pyx_v_tok1 = NULL;
+  PyObject *__pyx_v_head1 = NULL;
+  PyObject *__pyx_v_tail1 = NULL;
+  PyObject *__pyx_v_head_tail1 = NULL;
+  PyObject *__pyx_v_a1 = NULL;
+  PyObject *__pyx_v_b1 = NULL;
+  PyObject *__pyx_v_tok2 = NULL;
+  PyObject *__pyx_v_head2 = NULL;
+  PyObject *__pyx_v_tail2 = NULL;
+  PyObject *__pyx_v_head_tail2 = NULL;
+  PyObject *__pyx_v_a2 = NULL;
+  PyObject *__pyx_v_b2 = NULL;
+  PyObject *__pyx_v_affinity = NULL;
+  PyObject *__pyx_v_cand1 = NULL;
+  PyObject *__pyx_v_cand2 = NULL;
+  PyObject *__pyx_v_pval_h = NULL;
+  PyObject *__pyx_v_new_heads = NULL;
+  PyObject *__pyx_v_pval_t = NULL;
+  PyObject *__pyx_v_new_tails = NULL;
+  PyObject *__pyx_v_new_head1 = NULL;
+  PyObject *__pyx_v_new_head2 = NULL;
+  PyObject *__pyx_v_new_tail1 = NULL;
+  PyObject *__pyx_v_new_tail2 = NULL;
+  PyObject *__pyx_v_subseq1 = NULL;
+  PyObject *__pyx_v_subseq2 = NULL;
+  PyObject *__pyx_v_res3 = NULL;
+  PyObject *__pyx_v_val3 = NULL;
+  PyObject *__pyx_v_cand3 = NULL;
+  PyObject *__pyx_v_val = NULL;
+  PyObject *__pyx_v_found = NULL;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("_lcs_iter_prehash2_cython", 0);
+/* … */
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_7);
+  __Pyx_XDECREF(__pyx_t_8);
+  __Pyx_XDECREF(__pyx_t_10);
+  __Pyx_XDECREF(__pyx_t_15);
+  __Pyx_XDECREF(__pyx_t_16);
+  __Pyx_XDECREF(__pyx_t_17);
+  __Pyx_XDECREF(__pyx_t_18);
+  __Pyx_XDECREF(__pyx_t_21);
+  __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython._lcs_iter_prehash2_cython", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = NULL;
+  __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_all_decomp1);
+  __Pyx_XDECREF(__pyx_v_all_decomp2);
+  __Pyx_XDECREF(__pyx_v_key_decomp1);
+  __Pyx_XDECREF(__pyx_v_key_decomp2);
+  __Pyx_XDECREF(__pyx_v__results);
+  __Pyx_XDECREF(__pyx_v_empty1);
+  __Pyx_XDECREF(__pyx_v_empty2);
+  __Pyx_XDECREF(__pyx_v_best);
+  __Pyx_XDECREF(__pyx_v_info1);
+  __Pyx_XDECREF(__pyx_v_info2);
+  __Pyx_XDECREF(__pyx_v_try_key);
+  __Pyx_XDECREF(__pyx_v_key);
+  __Pyx_XDECREF(__pyx_v_frame);
+  __Pyx_XDECREF(__pyx_v_miss_frame);
+  __Pyx_XDECREF(__pyx_v_base_result);
+  __Pyx_XDECREF(__pyx_v_seq1);
+  __Pyx_XDECREF(__pyx_v_seq2);
+  __Pyx_XDECREF(__pyx_v_key0);
+  __Pyx_XDECREF(__pyx_v_frame0);
+  __Pyx_XDECREF(__pyx_v_stack);
+  __Pyx_XDECREF(__pyx_v_tok1);
+  __Pyx_XDECREF(__pyx_v_head1);
+  __Pyx_XDECREF(__pyx_v_tail1);
+  __Pyx_XDECREF(__pyx_v_head_tail1);
+  __Pyx_XDECREF(__pyx_v_a1);
+  __Pyx_XDECREF(__pyx_v_b1);
+  __Pyx_XDECREF(__pyx_v_tok2);
+  __Pyx_XDECREF(__pyx_v_head2);
+  __Pyx_XDECREF(__pyx_v_tail2);
+  __Pyx_XDECREF(__pyx_v_head_tail2);
+  __Pyx_XDECREF(__pyx_v_a2);
+  __Pyx_XDECREF(__pyx_v_b2);
+  __Pyx_XDECREF(__pyx_v_affinity);
+  __Pyx_XDECREF(__pyx_v_cand1);
+  __Pyx_XDECREF(__pyx_v_cand2);
+  __Pyx_XDECREF(__pyx_v_pval_h);
+  __Pyx_XDECREF(__pyx_v_new_heads);
+  __Pyx_XDECREF(__pyx_v_pval_t);
+  __Pyx_XDECREF(__pyx_v_new_tails);
+  __Pyx_XDECREF(__pyx_v_new_head1);
+  __Pyx_XDECREF(__pyx_v_new_head2);
+  __Pyx_XDECREF(__pyx_v_new_tail1);
+  __Pyx_XDECREF(__pyx_v_new_tail2);
+  __Pyx_XDECREF(__pyx_v_subseq1);
+  __Pyx_XDECREF(__pyx_v_subseq2);
+  __Pyx_XDECREF(__pyx_v_res3);
+  __Pyx_XDECREF(__pyx_v_val3);
+  __Pyx_XDECREF(__pyx_v_cand3);
+  __Pyx_XDECREF(__pyx_v_val);
+  __Pyx_XDECREF(__pyx_v_found);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+/* … */
+  __pyx_tuple__6 = PyTuple_Pack(67, __pyx_n_s_full_seq1, __pyx_n_s_full_seq2, __pyx_n_s_open_to_close, __pyx_n_s_node_affinity, __pyx_n_s_open_to_node, __pyx_n_s_all_decomp1, __pyx_n_s_all_decomp2, __pyx_n_s_key_decomp1, __pyx_n_s_key_decomp2, __pyx_n_s_results, __pyx_n_s_empty1, __pyx_n_s_empty2, __pyx_n_s_empty1_key, __pyx_n_s_empty2_key, __pyx_n_s_best, __pyx_n_s_info1, __pyx_n_s_info2, __pyx_n_s_try_key, __pyx_n_s_key, __pyx_n_s_seq1_key, __pyx_n_s_seq2_key, __pyx_n_s_head1_key, __pyx_n_s_tail1_key, __pyx_n_s_head_tail1_key, __pyx_n_s_head2_key, __pyx_n_s_tail2_key, __pyx_n_s_head_tail2_key, __pyx_n_s_frame, __pyx_n_s_miss_frame, __pyx_n_s_base_result, __pyx_n_s_seq1, __pyx_n_s_seq2, __pyx_n_s_full_seq1_key, __pyx_n_s_full_seq2_key, __pyx_n_s_key0, __pyx_n_s_frame0, __pyx_n_s_stack, __pyx_n_s_tok1, __pyx_n_s_head1, __pyx_n_s_tail1, __pyx_n_s_head_tail1, __pyx_n_s_a1, __pyx_n_s_b1, __pyx_n_s_tok2, __pyx_n_s_head2, __pyx_n_s_tail2, __pyx_n_s_head_tail2, __pyx_n_s_a2, __pyx_n_s_b2, __pyx_n_s_affinity, __pyx_n_s_cand1, __pyx_n_s_cand2, __pyx_n_s_pval_h, __pyx_n_s_new_heads, __pyx_n_s_pval_t, __pyx_n_s_new_tails, __pyx_n_s_new_head1, __pyx_n_s_new_head2, __pyx_n_s_new_tail1, __pyx_n_s_new_tail2, __pyx_n_s_subseq1, __pyx_n_s_subseq2, __pyx_n_s_res3, __pyx_n_s_val3, __pyx_n_s_cand3, __pyx_n_s_val, __pyx_n_s_found); if (unlikely(!__pyx_tuple__6)) __PYX_ERR(0, 136, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__6);
+  __Pyx_GIVEREF(__pyx_tuple__6);
+/* … */
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_3_lcs_iter_prehash2_cython, NULL, __pyx_n_s_networkx_algorithms_isomorphism); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 136, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_lcs_iter_prehash2_cython, __pyx_t_1) < 0) __PYX_ERR(0, 136, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_codeobj__7 = (PyObject*)__Pyx_PyCode_New(5, 0, 67, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__6, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_embedding_balanced_sequence_cyt, __pyx_n_s_lcs_iter_prehash2_cython, 136, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__7)) __PYX_ERR(0, 136, __pyx_L1_error)
+
 137:     """
+
 138:     Version of the lcs iterative algorithm where we precompute hash values
+
 139:     """
+
+140:     cdef dict all_decomp1 = generate_all_decomp_prehash_cython(full_seq1, open_to_close, open_to_node)
+
  if (!(likely(PyDict_CheckExact(__pyx_v_open_to_close))||((__pyx_v_open_to_close) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "dict", Py_TYPE(__pyx_v_open_to_close)->tp_name), 0))) __PYX_ERR(0, 140, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_prehash_cython(__pyx_v_full_seq1, ((PyObject*)__pyx_v_open_to_close), __pyx_v_open_to_node); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 140, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_all_decomp1 = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+141:     cdef dict all_decomp2 = generate_all_decomp_prehash_cython(full_seq2, open_to_close, open_to_node)
+
  if (!(likely(PyDict_CheckExact(__pyx_v_open_to_close))||((__pyx_v_open_to_close) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "dict", Py_TYPE(__pyx_v_open_to_close)->tp_name), 0))) __PYX_ERR(0, 141, __pyx_L1_error)
+  __pyx_t_1 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_prehash_cython(__pyx_v_full_seq2, ((PyObject*)__pyx_v_open_to_close), __pyx_v_open_to_node); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 141, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_all_decomp2 = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+142:     cdef dict key_decomp1 = {}
+
  __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 142, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_key_decomp1 = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+143:     cdef dict key_decomp2 = {}
+
  __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 143, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_key_decomp2 = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
+
 144: 
+
+145:     cdef dict _results = {}
+
  __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 145, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v__results = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
+
 146:     # Populate base cases
+
+147:     empty1 = type(next(iter(all_decomp1.keys())))()
+
  if (unlikely(__pyx_v_all_decomp1 == Py_None)) {
+    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "keys");
+    __PYX_ERR(0, 147, __pyx_L1_error)
+  }
+  __pyx_t_2 = __Pyx_PyDict_Keys(__pyx_v_all_decomp1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 147, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __pyx_t_3 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 147, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_t_2 = __Pyx_PyIter_Next(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 147, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __Pyx_INCREF(((PyObject *)Py_TYPE(__pyx_t_2)));
+  __pyx_t_3 = ((PyObject *)Py_TYPE(__pyx_t_2)); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_t_2 = NULL;
+  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3);
+    if (likely(__pyx_t_2)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+      __Pyx_INCREF(__pyx_t_2);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_3, function);
+    }
+  }
+  __pyx_t_1 = (__pyx_t_2) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_2) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 147, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __pyx_v_empty1 = __pyx_t_1;
+  __pyx_t_1 = 0;
+
+148:     empty2 = type(next(iter(all_decomp2.keys())))()
+
  if (unlikely(__pyx_v_all_decomp2 == Py_None)) {
+    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "keys");
+    __PYX_ERR(0, 148, __pyx_L1_error)
+  }
+  __pyx_t_3 = __Pyx_PyDict_Keys(__pyx_v_all_decomp2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 148, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_2 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 148, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __pyx_t_3 = __Pyx_PyIter_Next(__pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 148, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_INCREF(((PyObject *)Py_TYPE(__pyx_t_3)));
+  __pyx_t_2 = ((PyObject *)Py_TYPE(__pyx_t_3)); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+  __pyx_t_3 = NULL;
+  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
+    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
+    if (likely(__pyx_t_3)) {
+      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
+      __Pyx_INCREF(__pyx_t_3);
+      __Pyx_INCREF(function);
+      __Pyx_DECREF_SET(__pyx_t_2, function);
+    }
+  }
+  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
+  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 148, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __pyx_v_empty2 = __pyx_t_1;
+  __pyx_t_1 = 0;
+
+149:     cdef Py_hash_t empty1_key = hash(empty1)
+
  __pyx_t_4 = PyObject_Hash(__pyx_v_empty1); if (unlikely(__pyx_t_4 == ((Py_hash_t)-1))) __PYX_ERR(0, 149, __pyx_L1_error)
+  __pyx_v_empty1_key = __pyx_t_4;
+
+150:     cdef Py_hash_t empty2_key = hash(empty2)
+
  __pyx_t_4 = PyObject_Hash(__pyx_v_empty2); if (unlikely(__pyx_t_4 == ((Py_hash_t)-1))) __PYX_ERR(0, 150, __pyx_L1_error)
+  __pyx_v_empty2_key = __pyx_t_4;
+
+151:     cdef tuple best = (empty1, empty2)
+
  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 151, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_INCREF(__pyx_v_empty1);
+  __Pyx_GIVEREF(__pyx_v_empty1);
+  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_empty1);
+  __Pyx_INCREF(__pyx_v_empty2);
+  __Pyx_GIVEREF(__pyx_v_empty2);
+  PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_empty2);
+  __pyx_v_best = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
+
 152: 
+
 153:     cdef tuple info1, info2
+
 154:     cdef tuple try_key, key
+
 155:     cdef Py_hash_t seq1_key, seq2_key
+
 156:     cdef Py_hash_t head1_key, tail1_key, head_tail1_key
+
 157:     cdef Py_hash_t head2_key, tail2_key, head_tail2_key
+
 158:     cdef tuple frame
+
 159:     cdef tuple miss_frame
+
 160: 
+
+161:     base_result = (0, best)
+
  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 161, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_INCREF(__pyx_int_0);
+  __Pyx_GIVEREF(__pyx_int_0);
+  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_int_0);
+  __Pyx_INCREF(__pyx_v_best);
+  __Pyx_GIVEREF(__pyx_v_best);
+  PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_best);
+  __pyx_v_base_result = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+162:     for seq1, info1 in all_decomp1.items():
+
  if (unlikely(__pyx_v_all_decomp1 == Py_None)) {
+    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "items");
+    __PYX_ERR(0, 162, __pyx_L1_error)
+  }
+  __pyx_t_1 = __Pyx_PyDict_Items(__pyx_v_all_decomp1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 162, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  if (likely(PyList_CheckExact(__pyx_t_1)) || PyTuple_CheckExact(__pyx_t_1)) {
+    __pyx_t_2 = __pyx_t_1; __Pyx_INCREF(__pyx_t_2); __pyx_t_5 = 0;
+    __pyx_t_6 = NULL;
+  } else {
+    __pyx_t_5 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 162, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_6 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 162, __pyx_L1_error)
+  }
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  for (;;) {
+    if (likely(!__pyx_t_6)) {
+      if (likely(PyList_CheckExact(__pyx_t_2))) {
+        if (__pyx_t_5 >= PyList_GET_SIZE(__pyx_t_2)) break;
+        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+        __pyx_t_1 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_5); __Pyx_INCREF(__pyx_t_1); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 162, __pyx_L1_error)
+        #else
+        __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 162, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_1);
+        #endif
+      } else {
+        if (__pyx_t_5 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
+        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+        __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_5); __Pyx_INCREF(__pyx_t_1); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 162, __pyx_L1_error)
+        #else
+        __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 162, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_1);
+        #endif
+      }
+    } else {
+      __pyx_t_1 = __pyx_t_6(__pyx_t_2);
+      if (unlikely(!__pyx_t_1)) {
+        PyObject* exc_type = PyErr_Occurred();
+        if (exc_type) {
+          if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
+          else __PYX_ERR(0, 162, __pyx_L1_error)
+        }
+        break;
+      }
+      __Pyx_GOTREF(__pyx_t_1);
+    }
+    if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) {
+      PyObject* sequence = __pyx_t_1;
+      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+      if (unlikely(size != 2)) {
+        if (size > 2) __Pyx_RaiseTooManyValuesError(2);
+        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+        __PYX_ERR(0, 162, __pyx_L1_error)
+      }
+      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+      if (likely(PyTuple_CheckExact(sequence))) {
+        __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); 
+        __pyx_t_7 = PyTuple_GET_ITEM(sequence, 1); 
+      } else {
+        __pyx_t_3 = PyList_GET_ITEM(sequence, 0); 
+        __pyx_t_7 = PyList_GET_ITEM(sequence, 1); 
+      }
+      __Pyx_INCREF(__pyx_t_3);
+      __Pyx_INCREF(__pyx_t_7);
+      #else
+      __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 162, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_3);
+      __pyx_t_7 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 162, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_7);
+      #endif
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    } else {
+      Py_ssize_t index = -1;
+      __pyx_t_8 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 162, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_8);
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      __pyx_t_9 = Py_TYPE(__pyx_t_8)->tp_iternext;
+      index = 0; __pyx_t_3 = __pyx_t_9(__pyx_t_8); if (unlikely(!__pyx_t_3)) goto __pyx_L5_unpacking_failed;
+      __Pyx_GOTREF(__pyx_t_3);
+      index = 1; __pyx_t_7 = __pyx_t_9(__pyx_t_8); if (unlikely(!__pyx_t_7)) goto __pyx_L5_unpacking_failed;
+      __Pyx_GOTREF(__pyx_t_7);
+      if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_8), 2) < 0) __PYX_ERR(0, 162, __pyx_L1_error)
+      __pyx_t_9 = NULL;
+      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+      goto __pyx_L6_unpacking_done;
+      __pyx_L5_unpacking_failed:;
+      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+      __pyx_t_9 = NULL;
+      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
+      __PYX_ERR(0, 162, __pyx_L1_error)
+      __pyx_L6_unpacking_done:;
+    }
+    if (!(likely(PyTuple_CheckExact(__pyx_t_7))||((__pyx_t_7) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_7)->tp_name), 0))) __PYX_ERR(0, 162, __pyx_L1_error)
+    __Pyx_XDECREF_SET(__pyx_v_seq1, __pyx_t_3);
+    __pyx_t_3 = 0;
+    __Pyx_XDECREF_SET(__pyx_v_info1, ((PyObject*)__pyx_t_7));
+    __pyx_t_7 = 0;
+/* … */
+  }
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+163:         seq1_key = hash(seq1)
+
    __pyx_t_4 = PyObject_Hash(__pyx_v_seq1); if (unlikely(__pyx_t_4 == ((Py_hash_t)-1))) __PYX_ERR(0, 163, __pyx_L1_error)
+    __pyx_v_seq1_key = __pyx_t_4;
+
+164:         head1_key, tail1_key, head_tail1_key = all_decomp1[seq1][5:8]
+
    if (unlikely(__pyx_v_all_decomp1 == Py_None)) {
+      PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
+      __PYX_ERR(0, 164, __pyx_L1_error)
+    }
+    __pyx_t_1 = __Pyx_PyDict_GetItem(__pyx_v_all_decomp1, __pyx_v_seq1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 164, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_7 = __Pyx_PyObject_GetSlice(__pyx_t_1, 5, 8, NULL, NULL, &__pyx_slice__2, 1, 1, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 164, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_7);
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    if ((likely(PyTuple_CheckExact(__pyx_t_7))) || (PyList_CheckExact(__pyx_t_7))) {
+      PyObject* sequence = __pyx_t_7;
+      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+      if (unlikely(size != 3)) {
+        if (size > 3) __Pyx_RaiseTooManyValuesError(3);
+        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+        __PYX_ERR(0, 164, __pyx_L1_error)
+      }
+      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+      if (likely(PyTuple_CheckExact(sequence))) {
+        __pyx_t_1 = PyTuple_GET_ITEM(sequence, 0); 
+        __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); 
+        __pyx_t_8 = PyTuple_GET_ITEM(sequence, 2); 
+      } else {
+        __pyx_t_1 = PyList_GET_ITEM(sequence, 0); 
+        __pyx_t_3 = PyList_GET_ITEM(sequence, 1); 
+        __pyx_t_8 = PyList_GET_ITEM(sequence, 2); 
+      }
+      __Pyx_INCREF(__pyx_t_1);
+      __Pyx_INCREF(__pyx_t_3);
+      __Pyx_INCREF(__pyx_t_8);
+      #else
+      __pyx_t_1 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 164, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 164, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_3);
+      __pyx_t_8 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 164, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_8);
+      #endif
+      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+    } else {
+      Py_ssize_t index = -1;
+      __pyx_t_10 = PyObject_GetIter(__pyx_t_7); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 164, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_10);
+      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+      __pyx_t_9 = Py_TYPE(__pyx_t_10)->tp_iternext;
+      index = 0; __pyx_t_1 = __pyx_t_9(__pyx_t_10); if (unlikely(!__pyx_t_1)) goto __pyx_L7_unpacking_failed;
+      __Pyx_GOTREF(__pyx_t_1);
+      index = 1; __pyx_t_3 = __pyx_t_9(__pyx_t_10); if (unlikely(!__pyx_t_3)) goto __pyx_L7_unpacking_failed;
+      __Pyx_GOTREF(__pyx_t_3);
+      index = 2; __pyx_t_8 = __pyx_t_9(__pyx_t_10); if (unlikely(!__pyx_t_8)) goto __pyx_L7_unpacking_failed;
+      __Pyx_GOTREF(__pyx_t_8);
+      if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_10), 3) < 0) __PYX_ERR(0, 164, __pyx_L1_error)
+      __pyx_t_9 = NULL;
+      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
+      goto __pyx_L8_unpacking_done;
+      __pyx_L7_unpacking_failed:;
+      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
+      __pyx_t_9 = NULL;
+      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
+      __PYX_ERR(0, 164, __pyx_L1_error)
+      __pyx_L8_unpacking_done:;
+    }
+    __pyx_t_4 = __Pyx_PyInt_AsHash_t(__pyx_t_1); if (unlikely((__pyx_t_4 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 164, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __pyx_t_11 = __Pyx_PyInt_AsHash_t(__pyx_t_3); if (unlikely((__pyx_t_11 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 164, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __pyx_t_12 = __Pyx_PyInt_AsHash_t(__pyx_t_8); if (unlikely((__pyx_t_12 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 164, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+    __pyx_v_head1_key = __pyx_t_4;
+    __pyx_v_tail1_key = __pyx_t_11;
+    __pyx_v_head_tail1_key = __pyx_t_12;
+/* … */
+  __pyx_slice__2 = PySlice_New(__pyx_int_5, __pyx_int_8, Py_None); if (unlikely(!__pyx_slice__2)) __PYX_ERR(0, 164, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_slice__2);
+  __Pyx_GIVEREF(__pyx_slice__2);
+
+165:         _results[(seq1_key, empty2_key)] = base_result
+
    __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_seq1_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 165, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_7);
+    __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_empty2_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 165, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_8);
+    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 165, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_GIVEREF(__pyx_t_7);
+    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_7);
+    __Pyx_GIVEREF(__pyx_t_8);
+    PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_8);
+    __pyx_t_7 = 0;
+    __pyx_t_8 = 0;
+    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 165, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+166:         _results[(head1_key, empty2_key)] = base_result
+
    __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_head1_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 166, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_empty2_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 166, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_8);
+    __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 166, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_7);
+    __Pyx_GIVEREF(__pyx_t_3);
+    PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_3);
+    __Pyx_GIVEREF(__pyx_t_8);
+    PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_t_8);
+    __pyx_t_3 = 0;
+    __pyx_t_8 = 0;
+    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_7, __pyx_v_base_result) < 0)) __PYX_ERR(0, 166, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+
+167:         _results[(tail1_key, empty2_key)] = base_result
+
    __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_tail1_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 167, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_7);
+    __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_empty2_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 167, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_8);
+    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 167, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_GIVEREF(__pyx_t_7);
+    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_7);
+    __Pyx_GIVEREF(__pyx_t_8);
+    PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_8);
+    __pyx_t_7 = 0;
+    __pyx_t_8 = 0;
+    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 167, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+168:         _results[(head_tail1_key, empty2_key)] = base_result
+
    __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_head_tail1_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 168, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_empty2_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 168, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_8);
+    __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 168, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_7);
+    __Pyx_GIVEREF(__pyx_t_3);
+    PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_3);
+    __Pyx_GIVEREF(__pyx_t_8);
+    PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_t_8);
+    __pyx_t_3 = 0;
+    __pyx_t_8 = 0;
+    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_7, __pyx_v_base_result) < 0)) __PYX_ERR(0, 168, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+
+169:         key_decomp1[seq1_key] = info1
+
    __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_seq1_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 169, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_7);
+    if (unlikely(PyDict_SetItem(__pyx_v_key_decomp1, __pyx_t_7, __pyx_v_info1) < 0)) __PYX_ERR(0, 169, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+
 170: 
+
+171:     for seq2, info2 in all_decomp2.items():
+
  if (unlikely(__pyx_v_all_decomp2 == Py_None)) {
+    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "items");
+    __PYX_ERR(0, 171, __pyx_L1_error)
+  }
+  __pyx_t_2 = __Pyx_PyDict_Items(__pyx_v_all_decomp2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 171, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  if (likely(PyList_CheckExact(__pyx_t_2)) || PyTuple_CheckExact(__pyx_t_2)) {
+    __pyx_t_7 = __pyx_t_2; __Pyx_INCREF(__pyx_t_7); __pyx_t_5 = 0;
+    __pyx_t_6 = NULL;
+  } else {
+    __pyx_t_5 = -1; __pyx_t_7 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 171, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_7);
+    __pyx_t_6 = Py_TYPE(__pyx_t_7)->tp_iternext; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 171, __pyx_L1_error)
+  }
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  for (;;) {
+    if (likely(!__pyx_t_6)) {
+      if (likely(PyList_CheckExact(__pyx_t_7))) {
+        if (__pyx_t_5 >= PyList_GET_SIZE(__pyx_t_7)) break;
+        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+        __pyx_t_2 = PyList_GET_ITEM(__pyx_t_7, __pyx_t_5); __Pyx_INCREF(__pyx_t_2); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 171, __pyx_L1_error)
+        #else
+        __pyx_t_2 = PySequence_ITEM(__pyx_t_7, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 171, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        #endif
+      } else {
+        if (__pyx_t_5 >= PyTuple_GET_SIZE(__pyx_t_7)) break;
+        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+        __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_7, __pyx_t_5); __Pyx_INCREF(__pyx_t_2); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 171, __pyx_L1_error)
+        #else
+        __pyx_t_2 = PySequence_ITEM(__pyx_t_7, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 171, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_2);
+        #endif
+      }
+    } else {
+      __pyx_t_2 = __pyx_t_6(__pyx_t_7);
+      if (unlikely(!__pyx_t_2)) {
+        PyObject* exc_type = PyErr_Occurred();
+        if (exc_type) {
+          if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
+          else __PYX_ERR(0, 171, __pyx_L1_error)
+        }
+        break;
+      }
+      __Pyx_GOTREF(__pyx_t_2);
+    }
+    if ((likely(PyTuple_CheckExact(__pyx_t_2))) || (PyList_CheckExact(__pyx_t_2))) {
+      PyObject* sequence = __pyx_t_2;
+      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+      if (unlikely(size != 2)) {
+        if (size > 2) __Pyx_RaiseTooManyValuesError(2);
+        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+        __PYX_ERR(0, 171, __pyx_L1_error)
+      }
+      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+      if (likely(PyTuple_CheckExact(sequence))) {
+        __pyx_t_8 = PyTuple_GET_ITEM(sequence, 0); 
+        __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); 
+      } else {
+        __pyx_t_8 = PyList_GET_ITEM(sequence, 0); 
+        __pyx_t_3 = PyList_GET_ITEM(sequence, 1); 
+      }
+      __Pyx_INCREF(__pyx_t_8);
+      __Pyx_INCREF(__pyx_t_3);
+      #else
+      __pyx_t_8 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 171, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_8);
+      __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 171, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_3);
+      #endif
+      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    } else {
+      Py_ssize_t index = -1;
+      __pyx_t_1 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 171, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext;
+      index = 0; __pyx_t_8 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_8)) goto __pyx_L11_unpacking_failed;
+      __Pyx_GOTREF(__pyx_t_8);
+      index = 1; __pyx_t_3 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_3)) goto __pyx_L11_unpacking_failed;
+      __Pyx_GOTREF(__pyx_t_3);
+      if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_1), 2) < 0) __PYX_ERR(0, 171, __pyx_L1_error)
+      __pyx_t_9 = NULL;
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      goto __pyx_L12_unpacking_done;
+      __pyx_L11_unpacking_failed:;
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      __pyx_t_9 = NULL;
+      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
+      __PYX_ERR(0, 171, __pyx_L1_error)
+      __pyx_L12_unpacking_done:;
+    }
+    if (!(likely(PyTuple_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_3)->tp_name), 0))) __PYX_ERR(0, 171, __pyx_L1_error)
+    __Pyx_XDECREF_SET(__pyx_v_seq2, __pyx_t_8);
+    __pyx_t_8 = 0;
+    __Pyx_XDECREF_SET(__pyx_v_info2, ((PyObject*)__pyx_t_3));
+    __pyx_t_3 = 0;
+/* … */
+  }
+  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+
+172:         seq2_key = hash(seq2)
+
    __pyx_t_12 = PyObject_Hash(__pyx_v_seq2); if (unlikely(__pyx_t_12 == ((Py_hash_t)-1))) __PYX_ERR(0, 172, __pyx_L1_error)
+    __pyx_v_seq2_key = __pyx_t_12;
+
+173:         head2_key, tail2_key, head_tail2_key = all_decomp2[seq2][5:8]
+
    if (unlikely(__pyx_v_all_decomp2 == Py_None)) {
+      PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
+      __PYX_ERR(0, 173, __pyx_L1_error)
+    }
+    __pyx_t_2 = __Pyx_PyDict_GetItem(__pyx_v_all_decomp2, __pyx_v_seq2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 173, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_2);
+    __pyx_t_3 = __Pyx_PyObject_GetSlice(__pyx_t_2, 5, 8, NULL, NULL, &__pyx_slice__2, 1, 1, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 173, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) {
+      PyObject* sequence = __pyx_t_3;
+      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+      if (unlikely(size != 3)) {
+        if (size > 3) __Pyx_RaiseTooManyValuesError(3);
+        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+        __PYX_ERR(0, 173, __pyx_L1_error)
+      }
+      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+      if (likely(PyTuple_CheckExact(sequence))) {
+        __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0); 
+        __pyx_t_8 = PyTuple_GET_ITEM(sequence, 1); 
+        __pyx_t_1 = PyTuple_GET_ITEM(sequence, 2); 
+      } else {
+        __pyx_t_2 = PyList_GET_ITEM(sequence, 0); 
+        __pyx_t_8 = PyList_GET_ITEM(sequence, 1); 
+        __pyx_t_1 = PyList_GET_ITEM(sequence, 2); 
+      }
+      __Pyx_INCREF(__pyx_t_2);
+      __Pyx_INCREF(__pyx_t_8);
+      __Pyx_INCREF(__pyx_t_1);
+      #else
+      __pyx_t_2 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 173, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_2);
+      __pyx_t_8 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 173, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_8);
+      __pyx_t_1 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 173, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      #endif
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    } else {
+      Py_ssize_t index = -1;
+      __pyx_t_10 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 173, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_10);
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __pyx_t_9 = Py_TYPE(__pyx_t_10)->tp_iternext;
+      index = 0; __pyx_t_2 = __pyx_t_9(__pyx_t_10); if (unlikely(!__pyx_t_2)) goto __pyx_L13_unpacking_failed;
+      __Pyx_GOTREF(__pyx_t_2);
+      index = 1; __pyx_t_8 = __pyx_t_9(__pyx_t_10); if (unlikely(!__pyx_t_8)) goto __pyx_L13_unpacking_failed;
+      __Pyx_GOTREF(__pyx_t_8);
+      index = 2; __pyx_t_1 = __pyx_t_9(__pyx_t_10); if (unlikely(!__pyx_t_1)) goto __pyx_L13_unpacking_failed;
+      __Pyx_GOTREF(__pyx_t_1);
+      if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_10), 3) < 0) __PYX_ERR(0, 173, __pyx_L1_error)
+      __pyx_t_9 = NULL;
+      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
+      goto __pyx_L14_unpacking_done;
+      __pyx_L13_unpacking_failed:;
+      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
+      __pyx_t_9 = NULL;
+      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
+      __PYX_ERR(0, 173, __pyx_L1_error)
+      __pyx_L14_unpacking_done:;
+    }
+    __pyx_t_12 = __Pyx_PyInt_AsHash_t(__pyx_t_2); if (unlikely((__pyx_t_12 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 173, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+    __pyx_t_11 = __Pyx_PyInt_AsHash_t(__pyx_t_8); if (unlikely((__pyx_t_11 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 173, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+    __pyx_t_4 = __Pyx_PyInt_AsHash_t(__pyx_t_1); if (unlikely((__pyx_t_4 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 173, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __pyx_v_head2_key = __pyx_t_12;
+    __pyx_v_tail2_key = __pyx_t_11;
+    __pyx_v_head_tail2_key = __pyx_t_4;
+
+174:         _results[(empty1_key, seq2_key)] = base_result
+
    __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_empty1_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 174, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_1 = __Pyx_PyInt_FromHash_t(__pyx_v_seq2_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 174, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 174, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_8);
+    __Pyx_GIVEREF(__pyx_t_3);
+    PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_3);
+    __Pyx_GIVEREF(__pyx_t_1);
+    PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_1);
+    __pyx_t_3 = 0;
+    __pyx_t_1 = 0;
+    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_8, __pyx_v_base_result) < 0)) __PYX_ERR(0, 174, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+
+175:         _results[(empty1_key, head2_key)] = base_result
+
    __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_empty1_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 175, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_8);
+    __pyx_t_1 = __Pyx_PyInt_FromHash_t(__pyx_v_head2_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 175, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 175, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_GIVEREF(__pyx_t_8);
+    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_8);
+    __Pyx_GIVEREF(__pyx_t_1);
+    PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_1);
+    __pyx_t_8 = 0;
+    __pyx_t_1 = 0;
+    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 175, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+176:         _results[(empty1_key, tail2_key)] = base_result
+
    __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_empty1_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 176, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __pyx_t_1 = __Pyx_PyInt_FromHash_t(__pyx_v_tail2_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 176, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 176, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_8);
+    __Pyx_GIVEREF(__pyx_t_3);
+    PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_3);
+    __Pyx_GIVEREF(__pyx_t_1);
+    PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_1);
+    __pyx_t_3 = 0;
+    __pyx_t_1 = 0;
+    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_8, __pyx_v_base_result) < 0)) __PYX_ERR(0, 176, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+
+177:         _results[(empty1_key, head_tail2_key)] = base_result
+
    __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_empty1_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 177, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_8);
+    __pyx_t_1 = __Pyx_PyInt_FromHash_t(__pyx_v_head_tail2_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 177, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 177, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    __Pyx_GIVEREF(__pyx_t_8);
+    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_8);
+    __Pyx_GIVEREF(__pyx_t_1);
+    PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_1);
+    __pyx_t_8 = 0;
+    __pyx_t_1 = 0;
+    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 177, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
+178:         key_decomp2[seq2_key] = info2
+
    __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_seq2_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 178, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    if (unlikely(PyDict_SetItem(__pyx_v_key_decomp2, __pyx_t_3, __pyx_v_info2) < 0)) __PYX_ERR(0, 178, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+
 179: 
+
+180:     cdef Py_hash_t full_seq1_key = hash(full_seq1)
+
  __pyx_t_4 = PyObject_Hash(__pyx_v_full_seq1); if (unlikely(__pyx_t_4 == ((Py_hash_t)-1))) __PYX_ERR(0, 180, __pyx_L1_error)
+  __pyx_v_full_seq1_key = __pyx_t_4;
+
+181:     cdef Py_hash_t full_seq2_key = hash(full_seq2)
+
  __pyx_t_4 = PyObject_Hash(__pyx_v_full_seq2); if (unlikely(__pyx_t_4 == ((Py_hash_t)-1))) __PYX_ERR(0, 181, __pyx_L1_error)
+  __pyx_v_full_seq2_key = __pyx_t_4;
+
 182: 
+
+183:     cdef tuple key0 = (full_seq1_key, full_seq2_key)
+
  __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_full_seq1_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 183, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_7);
+  __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_full_seq2_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 183, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_3);
+  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 183, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_7);
+  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_7);
+  __Pyx_GIVEREF(__pyx_t_3);
+  PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_3);
+  __pyx_t_7 = 0;
+  __pyx_t_3 = 0;
+  __pyx_v_key0 = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+184:     cdef tuple frame0 = (key0, full_seq1, full_seq2)
+
  __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 184, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_INCREF(__pyx_v_key0);
+  __Pyx_GIVEREF(__pyx_v_key0);
+  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_key0);
+  __Pyx_INCREF(__pyx_v_full_seq1);
+  __Pyx_GIVEREF(__pyx_v_full_seq1);
+  PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_full_seq1);
+  __Pyx_INCREF(__pyx_v_full_seq2);
+  __Pyx_GIVEREF(__pyx_v_full_seq2);
+  PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_full_seq2);
+  __pyx_v_frame0 = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+185:     cdef list stack = [frame0]
+
  __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 185, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_INCREF(__pyx_v_frame0);
+  __Pyx_GIVEREF(__pyx_v_frame0);
+  PyList_SET_ITEM(__pyx_t_1, 0, __pyx_v_frame0);
+  __pyx_v_stack = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
+
 186: 
+
+187:     while stack:
+
  while (1) {
+    __pyx_t_13 = (PyList_GET_SIZE(__pyx_v_stack) != 0);
+    if (!__pyx_t_13) break;
+
+188:         frame = stack[-1]
+
    __pyx_t_1 = __Pyx_GetItemInt_List(__pyx_v_stack, -1L, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 188, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    if (!(likely(PyTuple_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(0, 188, __pyx_L1_error)
+    __Pyx_XDECREF_SET(__pyx_v_frame, ((PyObject*)__pyx_t_1));
+    __pyx_t_1 = 0;
+
+189:         key, seq1, seq2 = frame
+
    if (likely(__pyx_v_frame != Py_None)) {
+      PyObject* sequence = __pyx_v_frame;
+      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+      if (unlikely(size != 3)) {
+        if (size > 3) __Pyx_RaiseTooManyValuesError(3);
+        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+        __PYX_ERR(0, 189, __pyx_L1_error)
+      }
+      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+      __pyx_t_1 = PyTuple_GET_ITEM(sequence, 0); 
+      __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); 
+      __pyx_t_7 = PyTuple_GET_ITEM(sequence, 2); 
+      __Pyx_INCREF(__pyx_t_1);
+      __Pyx_INCREF(__pyx_t_3);
+      __Pyx_INCREF(__pyx_t_7);
+      #else
+      __pyx_t_1 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 189, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 189, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_3);
+      __pyx_t_7 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 189, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_7);
+      #endif
+    } else {
+      __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 189, __pyx_L1_error)
+    }
+    if (!(likely(PyTuple_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(0, 189, __pyx_L1_error)
+    __Pyx_XDECREF_SET(__pyx_v_key, ((PyObject*)__pyx_t_1));
+    __pyx_t_1 = 0;
+    __Pyx_XDECREF_SET(__pyx_v_seq1, __pyx_t_3);
+    __pyx_t_3 = 0;
+    __Pyx_XDECREF_SET(__pyx_v_seq2, __pyx_t_7);
+    __pyx_t_7 = 0;
+
+190:         seq1_key, seq2_key = key
+
    if (likely(__pyx_v_key != Py_None)) {
+      PyObject* sequence = __pyx_v_key;
+      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+      if (unlikely(size != 2)) {
+        if (size > 2) __Pyx_RaiseTooManyValuesError(2);
+        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+        __PYX_ERR(0, 190, __pyx_L1_error)
+      }
+      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+      __pyx_t_7 = PyTuple_GET_ITEM(sequence, 0); 
+      __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); 
+      __Pyx_INCREF(__pyx_t_7);
+      __Pyx_INCREF(__pyx_t_3);
+      #else
+      __pyx_t_7 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 190, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_7);
+      __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 190, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_3);
+      #endif
+    } else {
+      __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 190, __pyx_L1_error)
+    }
+    __pyx_t_4 = __Pyx_PyInt_AsHash_t(__pyx_t_7); if (unlikely((__pyx_t_4 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 190, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+    __pyx_t_11 = __Pyx_PyInt_AsHash_t(__pyx_t_3); if (unlikely((__pyx_t_11 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 190, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+    __pyx_v_seq1_key = __pyx_t_4;
+    __pyx_v_seq2_key = __pyx_t_11;
+
+191:         if key not in _results:
+
    __pyx_t_13 = (__Pyx_PyDict_ContainsTF(__pyx_v_key, __pyx_v__results, Py_NE)); if (unlikely(__pyx_t_13 < 0)) __PYX_ERR(0, 191, __pyx_L1_error)
+    __pyx_t_14 = (__pyx_t_13 != 0);
+    if (__pyx_t_14) {
+/* … */
+    }
+
+192:             info1 = key_decomp1[seq1_key]
+
      __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_seq1_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 192, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_3);
+      __pyx_t_7 = __Pyx_PyDict_GetItem(__pyx_v_key_decomp1, __pyx_t_3); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 192, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_7);
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      if (!(likely(PyTuple_CheckExact(__pyx_t_7))||((__pyx_t_7) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_7)->tp_name), 0))) __PYX_ERR(0, 192, __pyx_L1_error)
+      __Pyx_XDECREF_SET(__pyx_v_info1, ((PyObject*)__pyx_t_7));
+      __pyx_t_7 = 0;
+
+193:             tok1, seq1, head1, tail1, head_tail1, head1_key, tail1_key, head_tail1_key, a1, b1 = info1
+
      if (likely(__pyx_v_info1 != Py_None)) {
+        PyObject* sequence = __pyx_v_info1;
+        Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+        if (unlikely(size != 10)) {
+          if (size > 10) __Pyx_RaiseTooManyValuesError(10);
+          else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+          __PYX_ERR(0, 193, __pyx_L1_error)
+        }
+        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+        __pyx_t_7 = PyTuple_GET_ITEM(sequence, 0); 
+        __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); 
+        __pyx_t_1 = PyTuple_GET_ITEM(sequence, 2); 
+        __pyx_t_8 = PyTuple_GET_ITEM(sequence, 3); 
+        __pyx_t_2 = PyTuple_GET_ITEM(sequence, 4); 
+        __pyx_t_10 = PyTuple_GET_ITEM(sequence, 5); 
+        __pyx_t_15 = PyTuple_GET_ITEM(sequence, 6); 
+        __pyx_t_16 = PyTuple_GET_ITEM(sequence, 7); 
+        __pyx_t_17 = PyTuple_GET_ITEM(sequence, 8); 
+        __pyx_t_18 = PyTuple_GET_ITEM(sequence, 9); 
+        __Pyx_INCREF(__pyx_t_7);
+        __Pyx_INCREF(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_1);
+        __Pyx_INCREF(__pyx_t_8);
+        __Pyx_INCREF(__pyx_t_2);
+        __Pyx_INCREF(__pyx_t_10);
+        __Pyx_INCREF(__pyx_t_15);
+        __Pyx_INCREF(__pyx_t_16);
+        __Pyx_INCREF(__pyx_t_17);
+        __Pyx_INCREF(__pyx_t_18);
+        #else
+        {
+          Py_ssize_t i;
+          PyObject** temps[10] = {&__pyx_t_7,&__pyx_t_3,&__pyx_t_1,&__pyx_t_8,&__pyx_t_2,&__pyx_t_10,&__pyx_t_15,&__pyx_t_16,&__pyx_t_17,&__pyx_t_18};
+          for (i=0; i < 10; i++) {
+            PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 193, __pyx_L1_error)
+            __Pyx_GOTREF(item);
+            *(temps[i]) = item;
+          }
+        }
+        #endif
+      } else {
+        __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 193, __pyx_L1_error)
+      }
+      __pyx_t_11 = __Pyx_PyInt_AsHash_t(__pyx_t_10); if (unlikely((__pyx_t_11 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 193, __pyx_L1_error)
+      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
+      __pyx_t_4 = __Pyx_PyInt_AsHash_t(__pyx_t_15); if (unlikely((__pyx_t_4 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 193, __pyx_L1_error)
+      __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
+      __pyx_t_12 = __Pyx_PyInt_AsHash_t(__pyx_t_16); if (unlikely((__pyx_t_12 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 193, __pyx_L1_error)
+      __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_tok1, __pyx_t_7);
+      __pyx_t_7 = 0;
+      __Pyx_DECREF_SET(__pyx_v_seq1, __pyx_t_3);
+      __pyx_t_3 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_head1, __pyx_t_1);
+      __pyx_t_1 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_tail1, __pyx_t_8);
+      __pyx_t_8 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_head_tail1, __pyx_t_2);
+      __pyx_t_2 = 0;
+      __pyx_v_head1_key = __pyx_t_11;
+      __pyx_v_tail1_key = __pyx_t_4;
+      __pyx_v_head_tail1_key = __pyx_t_12;
+      __Pyx_XDECREF_SET(__pyx_v_a1, __pyx_t_17);
+      __pyx_t_17 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_b1, __pyx_t_18);
+      __pyx_t_18 = 0;
+
 194: 
+
+195:             info2 = key_decomp2[seq2_key]
+
      __pyx_t_18 = __Pyx_PyInt_FromHash_t(__pyx_v_seq2_key); if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 195, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_18);
+      __pyx_t_17 = __Pyx_PyDict_GetItem(__pyx_v_key_decomp2, __pyx_t_18); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 195, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_17);
+      __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;
+      if (!(likely(PyTuple_CheckExact(__pyx_t_17))||((__pyx_t_17) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_17)->tp_name), 0))) __PYX_ERR(0, 195, __pyx_L1_error)
+      __Pyx_XDECREF_SET(__pyx_v_info2, ((PyObject*)__pyx_t_17));
+      __pyx_t_17 = 0;
+
+196:             tok2, seq2, head2, tail2, head_tail2, head2_key, tail2_key, head_tail2_key, a2, b2 = info2
+
      if (likely(__pyx_v_info2 != Py_None)) {
+        PyObject* sequence = __pyx_v_info2;
+        Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+        if (unlikely(size != 10)) {
+          if (size > 10) __Pyx_RaiseTooManyValuesError(10);
+          else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+          __PYX_ERR(0, 196, __pyx_L1_error)
+        }
+        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+        __pyx_t_17 = PyTuple_GET_ITEM(sequence, 0); 
+        __pyx_t_18 = PyTuple_GET_ITEM(sequence, 1); 
+        __pyx_t_16 = PyTuple_GET_ITEM(sequence, 2); 
+        __pyx_t_15 = PyTuple_GET_ITEM(sequence, 3); 
+        __pyx_t_10 = PyTuple_GET_ITEM(sequence, 4); 
+        __pyx_t_2 = PyTuple_GET_ITEM(sequence, 5); 
+        __pyx_t_8 = PyTuple_GET_ITEM(sequence, 6); 
+        __pyx_t_1 = PyTuple_GET_ITEM(sequence, 7); 
+        __pyx_t_3 = PyTuple_GET_ITEM(sequence, 8); 
+        __pyx_t_7 = PyTuple_GET_ITEM(sequence, 9); 
+        __Pyx_INCREF(__pyx_t_17);
+        __Pyx_INCREF(__pyx_t_18);
+        __Pyx_INCREF(__pyx_t_16);
+        __Pyx_INCREF(__pyx_t_15);
+        __Pyx_INCREF(__pyx_t_10);
+        __Pyx_INCREF(__pyx_t_2);
+        __Pyx_INCREF(__pyx_t_8);
+        __Pyx_INCREF(__pyx_t_1);
+        __Pyx_INCREF(__pyx_t_3);
+        __Pyx_INCREF(__pyx_t_7);
+        #else
+        {
+          Py_ssize_t i;
+          PyObject** temps[10] = {&__pyx_t_17,&__pyx_t_18,&__pyx_t_16,&__pyx_t_15,&__pyx_t_10,&__pyx_t_2,&__pyx_t_8,&__pyx_t_1,&__pyx_t_3,&__pyx_t_7};
+          for (i=0; i < 10; i++) {
+            PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 196, __pyx_L1_error)
+            __Pyx_GOTREF(item);
+            *(temps[i]) = item;
+          }
+        }
+        #endif
+      } else {
+        __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 196, __pyx_L1_error)
+      }
+      __pyx_t_12 = __Pyx_PyInt_AsHash_t(__pyx_t_2); if (unlikely((__pyx_t_12 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 196, __pyx_L1_error)
+      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+      __pyx_t_4 = __Pyx_PyInt_AsHash_t(__pyx_t_8); if (unlikely((__pyx_t_4 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 196, __pyx_L1_error)
+      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+      __pyx_t_11 = __Pyx_PyInt_AsHash_t(__pyx_t_1); if (unlikely((__pyx_t_11 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 196, __pyx_L1_error)
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_tok2, __pyx_t_17);
+      __pyx_t_17 = 0;
+      __Pyx_DECREF_SET(__pyx_v_seq2, __pyx_t_18);
+      __pyx_t_18 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_head2, __pyx_t_16);
+      __pyx_t_16 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_tail2, __pyx_t_15);
+      __pyx_t_15 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_head_tail2, __pyx_t_10);
+      __pyx_t_10 = 0;
+      __pyx_v_head2_key = __pyx_t_12;
+      __pyx_v_tail2_key = __pyx_t_4;
+      __pyx_v_head_tail2_key = __pyx_t_11;
+      __Pyx_XDECREF_SET(__pyx_v_a2, __pyx_t_3);
+      __pyx_t_3 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_b2, __pyx_t_7);
+      __pyx_t_7 = 0;
+
 197: 
+
+198:             affinity = node_affinity(tok1, tok2)
+
      __Pyx_INCREF(__pyx_v_node_affinity);
+      __pyx_t_3 = __pyx_v_node_affinity; __pyx_t_1 = NULL;
+      __pyx_t_19 = 0;
+      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
+        __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_3);
+        if (likely(__pyx_t_1)) {
+          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
+          __Pyx_INCREF(__pyx_t_1);
+          __Pyx_INCREF(function);
+          __Pyx_DECREF_SET(__pyx_t_3, function);
+          __pyx_t_19 = 1;
+        }
+      }
+      #if CYTHON_FAST_PYCALL
+      if (PyFunction_Check(__pyx_t_3)) {
+        PyObject *__pyx_temp[3] = {__pyx_t_1, __pyx_v_tok1, __pyx_v_tok2};
+        __pyx_t_7 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_19, 2+__pyx_t_19); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 198, __pyx_L1_error)
+        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
+        __Pyx_GOTREF(__pyx_t_7);
+      } else
+      #endif
+      #if CYTHON_FAST_PYCCALL
+      if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
+        PyObject *__pyx_temp[3] = {__pyx_t_1, __pyx_v_tok1, __pyx_v_tok2};
+        __pyx_t_7 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_19, 2+__pyx_t_19); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 198, __pyx_L1_error)
+        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
+        __Pyx_GOTREF(__pyx_t_7);
+      } else
+      #endif
+      {
+        __pyx_t_8 = PyTuple_New(2+__pyx_t_19); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 198, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_8);
+        if (__pyx_t_1) {
+          __Pyx_GIVEREF(__pyx_t_1); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_1); __pyx_t_1 = NULL;
+        }
+        __Pyx_INCREF(__pyx_v_tok1);
+        __Pyx_GIVEREF(__pyx_v_tok1);
+        PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_19, __pyx_v_tok1);
+        __Pyx_INCREF(__pyx_v_tok2);
+        __Pyx_GIVEREF(__pyx_v_tok2);
+        PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_19, __pyx_v_tok2);
+        __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_8, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 198, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_7);
+        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+      }
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_affinity, __pyx_t_7);
+      __pyx_t_7 = 0;
+
 199: 
+
 200:             # Case 2: The current edge in sequence1 is deleted
+
+201:             try_key = (head_tail1_key, seq2_key)
+
      __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_head_tail1_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 201, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_7);
+      __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_seq2_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 201, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_3);
+      __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 201, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_8);
+      __Pyx_GIVEREF(__pyx_t_7);
+      PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_7);
+      __Pyx_GIVEREF(__pyx_t_3);
+      PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_3);
+      __pyx_t_7 = 0;
+      __pyx_t_3 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_8));
+      __pyx_t_8 = 0;
+
+202:             if try_key in _results:
+
      __pyx_t_14 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 202, __pyx_L1_error)
+      __pyx_t_13 = (__pyx_t_14 != 0);
+      if (__pyx_t_13) {
+/* … */
+        goto __pyx_L18;
+      }
+
+203:                 cand1 = _results[try_key]
+
        __pyx_t_8 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 203, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_8);
+        __Pyx_XDECREF_SET(__pyx_v_cand1, __pyx_t_8);
+        __pyx_t_8 = 0;
+
 204:             else:
+
+205:                 miss_frame = try_key, head_tail1, seq2
+
      /*else*/ {
+        __pyx_t_8 = PyTuple_New(3); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 205, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_8);
+        __Pyx_INCREF(__pyx_v_try_key);
+        __Pyx_GIVEREF(__pyx_v_try_key);
+        PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_v_try_key);
+        __Pyx_INCREF(__pyx_v_head_tail1);
+        __Pyx_GIVEREF(__pyx_v_head_tail1);
+        PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_v_head_tail1);
+        __Pyx_INCREF(__pyx_v_seq2);
+        __Pyx_GIVEREF(__pyx_v_seq2);
+        PyTuple_SET_ITEM(__pyx_t_8, 2, __pyx_v_seq2);
+        __Pyx_XDECREF_SET(__pyx_v_miss_frame, ((PyObject*)__pyx_t_8));
+        __pyx_t_8 = 0;
+
+206:                 stack.append(miss_frame)
+
        __pyx_t_20 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_miss_frame); if (unlikely(__pyx_t_20 == ((int)-1))) __PYX_ERR(0, 206, __pyx_L1_error)
+
+207:                 continue
+
        goto __pyx_L15_continue;
+      }
+      __pyx_L18:;
+
 208: 
+
 209:             # Case 3: The current edge in sequence2 is deleted
+
+210:             try_key = (seq1_key, head_tail2_key)
+
      __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_seq1_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 210, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_8);
+      __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_head_tail2_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 210, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_3);
+      __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 210, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_7);
+      __Pyx_GIVEREF(__pyx_t_8);
+      PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_8);
+      __Pyx_GIVEREF(__pyx_t_3);
+      PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_t_3);
+      __pyx_t_8 = 0;
+      __pyx_t_3 = 0;
+      __Pyx_DECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_7));
+      __pyx_t_7 = 0;
+
+211:             if try_key in _results:
+
      __pyx_t_13 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_13 < 0)) __PYX_ERR(0, 211, __pyx_L1_error)
+      __pyx_t_14 = (__pyx_t_13 != 0);
+      if (__pyx_t_14) {
+/* … */
+        goto __pyx_L19;
+      }
+
+212:                 cand2 = _results[try_key]
+
        __pyx_t_7 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 212, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_7);
+        __Pyx_XDECREF_SET(__pyx_v_cand2, __pyx_t_7);
+        __pyx_t_7 = 0;
+
 213:             else:
+
+214:                 miss_frame = try_key, seq1, head_tail2
+
      /*else*/ {
+        __pyx_t_7 = PyTuple_New(3); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 214, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_7);
+        __Pyx_INCREF(__pyx_v_try_key);
+        __Pyx_GIVEREF(__pyx_v_try_key);
+        PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_v_try_key);
+        __Pyx_INCREF(__pyx_v_seq1);
+        __Pyx_GIVEREF(__pyx_v_seq1);
+        PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_v_seq1);
+        __Pyx_INCREF(__pyx_v_head_tail2);
+        __Pyx_GIVEREF(__pyx_v_head_tail2);
+        PyTuple_SET_ITEM(__pyx_t_7, 2, __pyx_v_head_tail2);
+        __Pyx_XDECREF_SET(__pyx_v_miss_frame, ((PyObject*)__pyx_t_7));
+        __pyx_t_7 = 0;
+
+215:                 stack.append(miss_frame)
+
        __pyx_t_20 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_miss_frame); if (unlikely(__pyx_t_20 == ((int)-1))) __PYX_ERR(0, 215, __pyx_L1_error)
+
+216:                 continue
+
        goto __pyx_L15_continue;
+      }
+      __pyx_L19:;
+
 217: 
+
 218:             # Case 1: The LCS involves this edge
+
+219:             if affinity:
+
      __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_v_affinity); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 219, __pyx_L1_error)
+      if (__pyx_t_14) {
+/* … */
+        goto __pyx_L20;
+      }
+
+220:                 try_key = (head1_key, head2_key)
+
        __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_head1_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 220, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_7);
+        __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_head2_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 220, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 220, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_8);
+        __Pyx_GIVEREF(__pyx_t_7);
+        PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_7);
+        __Pyx_GIVEREF(__pyx_t_3);
+        PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_3);
+        __pyx_t_7 = 0;
+        __pyx_t_3 = 0;
+        __Pyx_DECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_8));
+        __pyx_t_8 = 0;
+
+221:                 if try_key in _results:
+
        __pyx_t_14 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 221, __pyx_L1_error)
+        __pyx_t_13 = (__pyx_t_14 != 0);
+        if (__pyx_t_13) {
+/* … */
+          goto __pyx_L21;
+        }
+
+222:                     pval_h, new_heads = _results[try_key]
+
          __pyx_t_8 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 222, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_8);
+          if ((likely(PyTuple_CheckExact(__pyx_t_8))) || (PyList_CheckExact(__pyx_t_8))) {
+            PyObject* sequence = __pyx_t_8;
+            Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+            if (unlikely(size != 2)) {
+              if (size > 2) __Pyx_RaiseTooManyValuesError(2);
+              else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+              __PYX_ERR(0, 222, __pyx_L1_error)
+            }
+            #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+            if (likely(PyTuple_CheckExact(sequence))) {
+              __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); 
+              __pyx_t_7 = PyTuple_GET_ITEM(sequence, 1); 
+            } else {
+              __pyx_t_3 = PyList_GET_ITEM(sequence, 0); 
+              __pyx_t_7 = PyList_GET_ITEM(sequence, 1); 
+            }
+            __Pyx_INCREF(__pyx_t_3);
+            __Pyx_INCREF(__pyx_t_7);
+            #else
+            __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 222, __pyx_L1_error)
+            __Pyx_GOTREF(__pyx_t_3);
+            __pyx_t_7 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 222, __pyx_L1_error)
+            __Pyx_GOTREF(__pyx_t_7);
+            #endif
+            __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+          } else {
+            Py_ssize_t index = -1;
+            __pyx_t_1 = PyObject_GetIter(__pyx_t_8); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 222, __pyx_L1_error)
+            __Pyx_GOTREF(__pyx_t_1);
+            __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+            __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext;
+            index = 0; __pyx_t_3 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_3)) goto __pyx_L22_unpacking_failed;
+            __Pyx_GOTREF(__pyx_t_3);
+            index = 1; __pyx_t_7 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_7)) goto __pyx_L22_unpacking_failed;
+            __Pyx_GOTREF(__pyx_t_7);
+            if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_1), 2) < 0) __PYX_ERR(0, 222, __pyx_L1_error)
+            __pyx_t_9 = NULL;
+            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+            goto __pyx_L23_unpacking_done;
+            __pyx_L22_unpacking_failed:;
+            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+            __pyx_t_9 = NULL;
+            if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
+            __PYX_ERR(0, 222, __pyx_L1_error)
+            __pyx_L23_unpacking_done:;
+          }
+          __Pyx_XDECREF_SET(__pyx_v_pval_h, __pyx_t_3);
+          __pyx_t_3 = 0;
+          __Pyx_XDECREF_SET(__pyx_v_new_heads, __pyx_t_7);
+          __pyx_t_7 = 0;
+
 223:                 else:
+
+224:                     miss_frame = try_key, head1, head2
+
        /*else*/ {
+          __pyx_t_8 = PyTuple_New(3); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 224, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_8);
+          __Pyx_INCREF(__pyx_v_try_key);
+          __Pyx_GIVEREF(__pyx_v_try_key);
+          PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_v_try_key);
+          __Pyx_INCREF(__pyx_v_head1);
+          __Pyx_GIVEREF(__pyx_v_head1);
+          PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_v_head1);
+          __Pyx_INCREF(__pyx_v_head2);
+          __Pyx_GIVEREF(__pyx_v_head2);
+          PyTuple_SET_ITEM(__pyx_t_8, 2, __pyx_v_head2);
+          __Pyx_XDECREF_SET(__pyx_v_miss_frame, ((PyObject*)__pyx_t_8));
+          __pyx_t_8 = 0;
+
+225:                     stack.append(miss_frame)
+
          __pyx_t_20 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_miss_frame); if (unlikely(__pyx_t_20 == ((int)-1))) __PYX_ERR(0, 225, __pyx_L1_error)
+
+226:                     continue
+
          goto __pyx_L15_continue;
+        }
+        __pyx_L21:;
+
 227: 
+
+228:                 try_key = (tail1_key, tail2_key)
+
        __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_tail1_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 228, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_8);
+        __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_tail2_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 228, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_7);
+        __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 228, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __Pyx_GIVEREF(__pyx_t_8);
+        PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_8);
+        __Pyx_GIVEREF(__pyx_t_7);
+        PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_7);
+        __pyx_t_8 = 0;
+        __pyx_t_7 = 0;
+        __Pyx_DECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_3));
+        __pyx_t_3 = 0;
+
+229:                 if try_key in _results:
+
        __pyx_t_13 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_13 < 0)) __PYX_ERR(0, 229, __pyx_L1_error)
+        __pyx_t_14 = (__pyx_t_13 != 0);
+        if (__pyx_t_14) {
+/* … */
+          goto __pyx_L24;
+        }
+
+230:                     pval_t, new_tails = _results[try_key]
+
          __pyx_t_3 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 230, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_3);
+          if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) {
+            PyObject* sequence = __pyx_t_3;
+            Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+            if (unlikely(size != 2)) {
+              if (size > 2) __Pyx_RaiseTooManyValuesError(2);
+              else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+              __PYX_ERR(0, 230, __pyx_L1_error)
+            }
+            #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+            if (likely(PyTuple_CheckExact(sequence))) {
+              __pyx_t_7 = PyTuple_GET_ITEM(sequence, 0); 
+              __pyx_t_8 = PyTuple_GET_ITEM(sequence, 1); 
+            } else {
+              __pyx_t_7 = PyList_GET_ITEM(sequence, 0); 
+              __pyx_t_8 = PyList_GET_ITEM(sequence, 1); 
+            }
+            __Pyx_INCREF(__pyx_t_7);
+            __Pyx_INCREF(__pyx_t_8);
+            #else
+            __pyx_t_7 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 230, __pyx_L1_error)
+            __Pyx_GOTREF(__pyx_t_7);
+            __pyx_t_8 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 230, __pyx_L1_error)
+            __Pyx_GOTREF(__pyx_t_8);
+            #endif
+            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+          } else {
+            Py_ssize_t index = -1;
+            __pyx_t_1 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 230, __pyx_L1_error)
+            __Pyx_GOTREF(__pyx_t_1);
+            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+            __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext;
+            index = 0; __pyx_t_7 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_7)) goto __pyx_L25_unpacking_failed;
+            __Pyx_GOTREF(__pyx_t_7);
+            index = 1; __pyx_t_8 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_8)) goto __pyx_L25_unpacking_failed;
+            __Pyx_GOTREF(__pyx_t_8);
+            if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_1), 2) < 0) __PYX_ERR(0, 230, __pyx_L1_error)
+            __pyx_t_9 = NULL;
+            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+            goto __pyx_L26_unpacking_done;
+            __pyx_L25_unpacking_failed:;
+            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+            __pyx_t_9 = NULL;
+            if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
+            __PYX_ERR(0, 230, __pyx_L1_error)
+            __pyx_L26_unpacking_done:;
+          }
+          __Pyx_XDECREF_SET(__pyx_v_pval_t, __pyx_t_7);
+          __pyx_t_7 = 0;
+          __Pyx_XDECREF_SET(__pyx_v_new_tails, __pyx_t_8);
+          __pyx_t_8 = 0;
+
 231:                 else:
+
+232:                     miss_frame = try_key, tail1, tail2
+
        /*else*/ {
+          __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 232, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_3);
+          __Pyx_INCREF(__pyx_v_try_key);
+          __Pyx_GIVEREF(__pyx_v_try_key);
+          PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_try_key);
+          __Pyx_INCREF(__pyx_v_tail1);
+          __Pyx_GIVEREF(__pyx_v_tail1);
+          PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_tail1);
+          __Pyx_INCREF(__pyx_v_tail2);
+          __Pyx_GIVEREF(__pyx_v_tail2);
+          PyTuple_SET_ITEM(__pyx_t_3, 2, __pyx_v_tail2);
+          __Pyx_XDECREF_SET(__pyx_v_miss_frame, ((PyObject*)__pyx_t_3));
+          __pyx_t_3 = 0;
+
+233:                     stack.append(miss_frame)
+
          __pyx_t_20 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_miss_frame); if (unlikely(__pyx_t_20 == ((int)-1))) __PYX_ERR(0, 233, __pyx_L1_error)
+
+234:                     continue
+
          goto __pyx_L15_continue;
+        }
+        __pyx_L24:;
+
 235: 
+
+236:                 new_head1, new_head2 = new_heads
+
        if ((likely(PyTuple_CheckExact(__pyx_v_new_heads))) || (PyList_CheckExact(__pyx_v_new_heads))) {
+          PyObject* sequence = __pyx_v_new_heads;
+          Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+          if (unlikely(size != 2)) {
+            if (size > 2) __Pyx_RaiseTooManyValuesError(2);
+            else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+            __PYX_ERR(0, 236, __pyx_L1_error)
+          }
+          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+          if (likely(PyTuple_CheckExact(sequence))) {
+            __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); 
+            __pyx_t_8 = PyTuple_GET_ITEM(sequence, 1); 
+          } else {
+            __pyx_t_3 = PyList_GET_ITEM(sequence, 0); 
+            __pyx_t_8 = PyList_GET_ITEM(sequence, 1); 
+          }
+          __Pyx_INCREF(__pyx_t_3);
+          __Pyx_INCREF(__pyx_t_8);
+          #else
+          __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 236, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_3);
+          __pyx_t_8 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 236, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_8);
+          #endif
+        } else {
+          Py_ssize_t index = -1;
+          __pyx_t_7 = PyObject_GetIter(__pyx_v_new_heads); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 236, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_7);
+          __pyx_t_9 = Py_TYPE(__pyx_t_7)->tp_iternext;
+          index = 0; __pyx_t_3 = __pyx_t_9(__pyx_t_7); if (unlikely(!__pyx_t_3)) goto __pyx_L27_unpacking_failed;
+          __Pyx_GOTREF(__pyx_t_3);
+          index = 1; __pyx_t_8 = __pyx_t_9(__pyx_t_7); if (unlikely(!__pyx_t_8)) goto __pyx_L27_unpacking_failed;
+          __Pyx_GOTREF(__pyx_t_8);
+          if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_7), 2) < 0) __PYX_ERR(0, 236, __pyx_L1_error)
+          __pyx_t_9 = NULL;
+          __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+          goto __pyx_L28_unpacking_done;
+          __pyx_L27_unpacking_failed:;
+          __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+          __pyx_t_9 = NULL;
+          if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
+          __PYX_ERR(0, 236, __pyx_L1_error)
+          __pyx_L28_unpacking_done:;
+        }
+        __Pyx_XDECREF_SET(__pyx_v_new_head1, __pyx_t_3);
+        __pyx_t_3 = 0;
+        __Pyx_XDECREF_SET(__pyx_v_new_head2, __pyx_t_8);
+        __pyx_t_8 = 0;
+
+237:                 new_tail1, new_tail2 = new_tails
+
        if ((likely(PyTuple_CheckExact(__pyx_v_new_tails))) || (PyList_CheckExact(__pyx_v_new_tails))) {
+          PyObject* sequence = __pyx_v_new_tails;
+          Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+          if (unlikely(size != 2)) {
+            if (size > 2) __Pyx_RaiseTooManyValuesError(2);
+            else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+            __PYX_ERR(0, 237, __pyx_L1_error)
+          }
+          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+          if (likely(PyTuple_CheckExact(sequence))) {
+            __pyx_t_8 = PyTuple_GET_ITEM(sequence, 0); 
+            __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); 
+          } else {
+            __pyx_t_8 = PyList_GET_ITEM(sequence, 0); 
+            __pyx_t_3 = PyList_GET_ITEM(sequence, 1); 
+          }
+          __Pyx_INCREF(__pyx_t_8);
+          __Pyx_INCREF(__pyx_t_3);
+          #else
+          __pyx_t_8 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 237, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_8);
+          __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 237, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_3);
+          #endif
+        } else {
+          Py_ssize_t index = -1;
+          __pyx_t_7 = PyObject_GetIter(__pyx_v_new_tails); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 237, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_7);
+          __pyx_t_9 = Py_TYPE(__pyx_t_7)->tp_iternext;
+          index = 0; __pyx_t_8 = __pyx_t_9(__pyx_t_7); if (unlikely(!__pyx_t_8)) goto __pyx_L29_unpacking_failed;
+          __Pyx_GOTREF(__pyx_t_8);
+          index = 1; __pyx_t_3 = __pyx_t_9(__pyx_t_7); if (unlikely(!__pyx_t_3)) goto __pyx_L29_unpacking_failed;
+          __Pyx_GOTREF(__pyx_t_3);
+          if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_7), 2) < 0) __PYX_ERR(0, 237, __pyx_L1_error)
+          __pyx_t_9 = NULL;
+          __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+          goto __pyx_L30_unpacking_done;
+          __pyx_L29_unpacking_failed:;
+          __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+          __pyx_t_9 = NULL;
+          if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
+          __PYX_ERR(0, 237, __pyx_L1_error)
+          __pyx_L30_unpacking_done:;
+        }
+        __Pyx_XDECREF_SET(__pyx_v_new_tail1, __pyx_t_8);
+        __pyx_t_8 = 0;
+        __Pyx_XDECREF_SET(__pyx_v_new_tail2, __pyx_t_3);
+        __pyx_t_3 = 0;
+
 238: 
+
+239:                 subseq1 = a1 + new_head1 + b1 + new_tail1
+
        __pyx_t_3 = PyNumber_Add(__pyx_v_a1, __pyx_v_new_head1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 239, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __pyx_t_8 = PyNumber_Add(__pyx_t_3, __pyx_v_b1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 239, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_8);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_3 = PyNumber_Add(__pyx_t_8, __pyx_v_new_tail1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 239, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+        __Pyx_XDECREF_SET(__pyx_v_subseq1, __pyx_t_3);
+        __pyx_t_3 = 0;
+
+240:                 subseq2 = a2 + new_head2 + b2 + new_tail2
+
        __pyx_t_3 = PyNumber_Add(__pyx_v_a2, __pyx_v_new_head2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 240, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __pyx_t_8 = PyNumber_Add(__pyx_t_3, __pyx_v_b2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 240, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_8);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __pyx_t_3 = PyNumber_Add(__pyx_t_8, __pyx_v_new_tail2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 240, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+        __Pyx_XDECREF_SET(__pyx_v_subseq2, __pyx_t_3);
+        __pyx_t_3 = 0;
+
 241: 
+
+242:                 res3 = (subseq1, subseq2)
+
        __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 242, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __Pyx_INCREF(__pyx_v_subseq1);
+        __Pyx_GIVEREF(__pyx_v_subseq1);
+        PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_subseq1);
+        __Pyx_INCREF(__pyx_v_subseq2);
+        __Pyx_GIVEREF(__pyx_v_subseq2);
+        PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_subseq2);
+        __Pyx_XDECREF_SET(__pyx_v_res3, ((PyObject*)__pyx_t_3));
+        __pyx_t_3 = 0;
+
+243:                 val3 = pval_h + pval_t + affinity
+
        __pyx_t_3 = PyNumber_Add(__pyx_v_pval_h, __pyx_v_pval_t); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 243, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_3);
+        __pyx_t_8 = PyNumber_Add(__pyx_t_3, __pyx_v_affinity); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 243, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_8);
+        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+        __Pyx_XDECREF_SET(__pyx_v_val3, __pyx_t_8);
+        __pyx_t_8 = 0;
+
+244:                 cand3 = (val3, res3)
+
        __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 244, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_8);
+        __Pyx_INCREF(__pyx_v_val3);
+        __Pyx_GIVEREF(__pyx_v_val3);
+        PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_v_val3);
+        __Pyx_INCREF(__pyx_v_res3);
+        __Pyx_GIVEREF(__pyx_v_res3);
+        PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_v_res3);
+        __Pyx_XDECREF_SET(__pyx_v_cand3, ((PyObject*)__pyx_t_8));
+        __pyx_t_8 = 0;
+
 245:             else:
+
+246:                 cand3 = (-1, None)
+
      /*else*/ {
+        __Pyx_INCREF(__pyx_tuple_);
+        __Pyx_XDECREF_SET(__pyx_v_cand3, __pyx_tuple_);
+      }
+      __pyx_L20:;
+
 247: 
+
 248:             # We solved the frame
+
+249:             _results[key] = max(cand1, cand2, cand3)
+
      __Pyx_INCREF(__pyx_v_cand2);
+      __pyx_t_8 = __pyx_v_cand2;
+      __Pyx_INCREF(__pyx_v_cand3);
+      __pyx_t_21 = __pyx_v_cand3;
+      __Pyx_INCREF(__pyx_v_cand1);
+      __pyx_t_3 = __pyx_v_cand1;
+      __pyx_t_1 = PyObject_RichCompare(__pyx_t_8, __pyx_t_3, Py_GT); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 249, __pyx_L1_error)
+      __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 249, __pyx_L1_error)
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      if (__pyx_t_14) {
+        __Pyx_INCREF(__pyx_t_8);
+        __pyx_t_7 = __pyx_t_8;
+      } else {
+        __Pyx_INCREF(__pyx_t_3);
+        __pyx_t_7 = __pyx_t_3;
+      }
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __Pyx_INCREF(__pyx_t_7);
+      __pyx_t_3 = __pyx_t_7;
+      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+      __pyx_t_1 = PyObject_RichCompare(__pyx_t_21, __pyx_t_3, Py_GT); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 249, __pyx_L1_error)
+      __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 249, __pyx_L1_error)
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      if (__pyx_t_14) {
+        __Pyx_INCREF(__pyx_t_21);
+        __pyx_t_7 = __pyx_t_21;
+      } else {
+        __Pyx_INCREF(__pyx_t_3);
+        __pyx_t_7 = __pyx_t_3;
+      }
+      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
+      __Pyx_DECREF(__pyx_t_21); __pyx_t_21 = 0;
+      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+      __pyx_t_8 = __pyx_t_7;
+      __Pyx_INCREF(__pyx_t_8);
+      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
+      if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_v_key, __pyx_t_8) < 0)) __PYX_ERR(0, 249, __pyx_L1_error)
+      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+
+250:         stack.pop()
+
    __pyx_t_8 = __Pyx_PyList_Pop(__pyx_v_stack); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 250, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_8);
+    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+    __pyx_L15_continue:;
+  }
+
 251: 
+
 252:     # The stack pop is our solution
+
+253:     (val, best) = _results[key0]
+
  __pyx_t_8 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_key0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 253, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_8);
+  if ((likely(PyTuple_CheckExact(__pyx_t_8))) || (PyList_CheckExact(__pyx_t_8))) {
+    PyObject* sequence = __pyx_t_8;
+    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+    if (unlikely(size != 2)) {
+      if (size > 2) __Pyx_RaiseTooManyValuesError(2);
+      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+      __PYX_ERR(0, 253, __pyx_L1_error)
+    }
+    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+    if (likely(PyTuple_CheckExact(sequence))) {
+      __pyx_t_7 = PyTuple_GET_ITEM(sequence, 0); 
+      __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); 
+    } else {
+      __pyx_t_7 = PyList_GET_ITEM(sequence, 0); 
+      __pyx_t_3 = PyList_GET_ITEM(sequence, 1); 
+    }
+    __Pyx_INCREF(__pyx_t_7);
+    __Pyx_INCREF(__pyx_t_3);
+    #else
+    __pyx_t_7 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 253, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_7);
+    __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 253, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_3);
+    #endif
+    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+  } else {
+    Py_ssize_t index = -1;
+    __pyx_t_1 = PyObject_GetIter(__pyx_t_8); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 253, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
+    __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext;
+    index = 0; __pyx_t_7 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_7)) goto __pyx_L31_unpacking_failed;
+    __Pyx_GOTREF(__pyx_t_7);
+    index = 1; __pyx_t_3 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_3)) goto __pyx_L31_unpacking_failed;
+    __Pyx_GOTREF(__pyx_t_3);
+    if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_1), 2) < 0) __PYX_ERR(0, 253, __pyx_L1_error)
+    __pyx_t_9 = NULL;
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    goto __pyx_L32_unpacking_done;
+    __pyx_L31_unpacking_failed:;
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __pyx_t_9 = NULL;
+    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
+    __PYX_ERR(0, 253, __pyx_L1_error)
+    __pyx_L32_unpacking_done:;
+  }
+  if (!(likely(PyTuple_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_3)->tp_name), 0))) __PYX_ERR(0, 253, __pyx_L1_error)
+  __pyx_v_val = __pyx_t_7;
+  __pyx_t_7 = 0;
+  __Pyx_DECREF_SET(__pyx_v_best, ((PyObject*)__pyx_t_3));
+  __pyx_t_3 = 0;
+
+254:     found = (best, val)
+
  __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 254, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_8);
+  __Pyx_INCREF(__pyx_v_best);
+  __Pyx_GIVEREF(__pyx_v_best);
+  PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_v_best);
+  __Pyx_INCREF(__pyx_v_val);
+  __Pyx_GIVEREF(__pyx_v_val);
+  PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_v_val);
+  __pyx_v_found = ((PyObject*)__pyx_t_8);
+  __pyx_t_8 = 0;
+
+255:     return found
+
  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(__pyx_v_found);
+  __pyx_r = __pyx_v_found;
+  goto __pyx_L0;
+
 256: 
+
 257: 
+
+258: cdef tuple balanced_decomp_unsafe_cython(sequence, dict open_to_close):
+
static PyObject *__pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_balanced_decomp_unsafe_cython(PyObject *__pyx_v_sequence, PyObject *__pyx_v_open_to_close) {
+  int __pyx_v_stacklen;
+  int __pyx_v_head_stop;
+  PyObject *__pyx_v_tok_curr = NULL;
+  PyObject *__pyx_v_want_close = NULL;
+  PyObject *__pyx_v_pop_close = NULL;
+  PyObject *__pyx_v_pop_open = NULL;
+  PyObject *__pyx_v_head = NULL;
+  PyObject *__pyx_v_tail = NULL;
+  PyObject *__pyx_v_head_tail = NULL;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("balanced_decomp_unsafe_cython", 0);
+/* … */
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython.balanced_decomp_unsafe_cython", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_tok_curr);
+  __Pyx_XDECREF(__pyx_v_want_close);
+  __Pyx_XDECREF(__pyx_v_pop_close);
+  __Pyx_XDECREF(__pyx_v_pop_open);
+  __Pyx_XDECREF(__pyx_v_head);
+  __Pyx_XDECREF(__pyx_v_tail);
+  __Pyx_XDECREF(__pyx_v_head_tail);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+259:     cdef int stacklen = 1  # always +1 in the first iteration
+
  __pyx_v_stacklen = 1;
+
+260:     cdef int head_stop = 1
+
  __pyx_v_head_stop = 1;
+
 261: 
+
+262:     tok_curr = sequence[0]
+
  __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_sequence, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 262, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_tok_curr = __pyx_t_1;
+  __pyx_t_1 = 0;
+
+263:     want_close = open_to_close[tok_curr]
+
  if (unlikely(__pyx_v_open_to_close == Py_None)) {
+    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
+    __PYX_ERR(0, 263, __pyx_L1_error)
+  }
+  __pyx_t_1 = __Pyx_PyDict_GetItem(__pyx_v_open_to_close, __pyx_v_tok_curr); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 263, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_want_close = __pyx_t_1;
+  __pyx_t_1 = 0;
+
 264: 
+
 265:     # for tok_curr in sequence[1:]:
+
+266:     for head_stop in range(1, len(sequence)):
+
  __pyx_t_2 = PyObject_Length(__pyx_v_sequence); if (unlikely(__pyx_t_2 == ((Py_ssize_t)-1))) __PYX_ERR(0, 266, __pyx_L1_error)
+  __pyx_t_3 = __pyx_t_2;
+  for (__pyx_t_4 = 1; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) {
+    __pyx_v_head_stop = __pyx_t_4;
+
+267:         tok_curr = sequence[head_stop]
+
    __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_sequence, __pyx_v_head_stop, int, 1, __Pyx_PyInt_From_int, 0, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 267, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF_SET(__pyx_v_tok_curr, __pyx_t_1);
+    __pyx_t_1 = 0;
+
+268:         stacklen += 1 if tok_curr in open_to_close else -1
+
    if (unlikely(__pyx_v_open_to_close == Py_None)) {
+      PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
+      __PYX_ERR(0, 268, __pyx_L1_error)
+    }
+    __pyx_t_6 = (__Pyx_PyDict_ContainsTF(__pyx_v_tok_curr, __pyx_v_open_to_close, Py_EQ)); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(0, 268, __pyx_L1_error)
+    if ((__pyx_t_6 != 0)) {
+      __pyx_t_5 = 1;
+    } else {
+      __pyx_t_5 = -1L;
+    }
+    __pyx_v_stacklen = (__pyx_v_stacklen + __pyx_t_5);
+
+269:         if stacklen == 0 and tok_curr == want_close:
+
    __pyx_t_7 = ((__pyx_v_stacklen == 0) != 0);
+    if (__pyx_t_7) {
+    } else {
+      __pyx_t_6 = __pyx_t_7;
+      goto __pyx_L6_bool_binop_done;
+    }
+    __pyx_t_1 = PyObject_RichCompare(__pyx_v_tok_curr, __pyx_v_want_close, Py_EQ); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 269, __pyx_L1_error)
+    __pyx_t_7 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 269, __pyx_L1_error)
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+    __pyx_t_6 = __pyx_t_7;
+    __pyx_L6_bool_binop_done:;
+    if (__pyx_t_6) {
+/* … */
+    }
+  }
+  __pyx_L4_break:;
+
+270:             pop_close = sequence[head_stop:head_stop + 1]
+
      __pyx_t_1 = __Pyx_PyObject_GetSlice(__pyx_v_sequence, __pyx_v_head_stop, (__pyx_v_head_stop + 1), NULL, NULL, NULL, 1, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 270, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      __pyx_v_pop_close = __pyx_t_1;
+      __pyx_t_1 = 0;
+
+271:             break
+
      goto __pyx_L4_break;
+
 272: 
+
+273:     pop_open = sequence[0:1]
+
  __pyx_t_1 = __Pyx_PyObject_GetSlice(__pyx_v_sequence, 0, 1, NULL, NULL, &__pyx_slice__3, 1, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 273, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_pop_open = __pyx_t_1;
+  __pyx_t_1 = 0;
+/* … */
+  __pyx_slice__3 = PySlice_New(__pyx_int_0, __pyx_int_1, Py_None); if (unlikely(!__pyx_slice__3)) __PYX_ERR(0, 273, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_slice__3);
+  __Pyx_GIVEREF(__pyx_slice__3);
+
+274:     head = sequence[1:head_stop]
+
  __pyx_t_1 = __Pyx_PyObject_GetSlice(__pyx_v_sequence, 1, __pyx_v_head_stop, NULL, NULL, NULL, 1, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 274, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_head = __pyx_t_1;
+  __pyx_t_1 = 0;
+
+275:     tail = sequence[head_stop + 1:]
+
  __pyx_t_1 = __Pyx_PyObject_GetSlice(__pyx_v_sequence, (__pyx_v_head_stop + 1), 0, NULL, NULL, NULL, 1, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 275, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_tail = __pyx_t_1;
+  __pyx_t_1 = 0;
+
+276:     head_tail = head + tail
+
  __pyx_t_1 = PyNumber_Add(__pyx_v_head, __pyx_v_tail); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 276, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_head_tail = __pyx_t_1;
+  __pyx_t_1 = 0;
+
+277:     return pop_open, pop_close, head, tail, head_tail
+
  __Pyx_XDECREF(__pyx_r);
+  if (unlikely(!__pyx_v_pop_close)) { __Pyx_RaiseUnboundLocalError("pop_close"); __PYX_ERR(0, 277, __pyx_L1_error) }
+  __pyx_t_1 = PyTuple_New(5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 277, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_INCREF(__pyx_v_pop_open);
+  __Pyx_GIVEREF(__pyx_v_pop_open);
+  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_pop_open);
+  __Pyx_INCREF(__pyx_v_pop_close);
+  __Pyx_GIVEREF(__pyx_v_pop_close);
+  PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_pop_close);
+  __Pyx_INCREF(__pyx_v_head);
+  __Pyx_GIVEREF(__pyx_v_head);
+  PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_head);
+  __Pyx_INCREF(__pyx_v_tail);
+  __Pyx_GIVEREF(__pyx_v_tail);
+  PyTuple_SET_ITEM(__pyx_t_1, 3, __pyx_v_tail);
+  __Pyx_INCREF(__pyx_v_head_tail);
+  __Pyx_GIVEREF(__pyx_v_head_tail);
+  PyTuple_SET_ITEM(__pyx_t_1, 4, __pyx_v_head_tail);
+  __pyx_r = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
+  goto __pyx_L0;
+
 278: 
+
 279: 
+
+280: cdef generate_all_decomp_cython(seq, open_to_close, open_to_node=None):
+
static PyObject *__pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython(PyObject *__pyx_v_seq, PyObject *__pyx_v_open_to_close, struct __pyx_opt_args_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython *__pyx_optional_args) {
+  PyObject *__pyx_v_open_to_node = ((PyObject *)Py_None);
+  PyObject *__pyx_v_all_decomp = NULL;
+  PyObject *__pyx_v_stack = NULL;
+  PyObject *__pyx_v_pop_open = NULL;
+  PyObject *__pyx_v_pop_close = NULL;
+  PyObject *__pyx_v_head = NULL;
+  PyObject *__pyx_v_tail = NULL;
+  PyObject *__pyx_v_head_tail = NULL;
+  PyObject *__pyx_v_node = NULL;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("generate_all_decomp_cython", 0);
+  if (__pyx_optional_args) {
+    if (__pyx_optional_args->__pyx_n > 0) {
+      __pyx_v_open_to_node = __pyx_optional_args->open_to_node;
+    }
+  }
+  __Pyx_INCREF(__pyx_v_seq);
+/* … */
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_6);
+  __Pyx_XDECREF(__pyx_t_7);
+  __Pyx_XDECREF(__pyx_t_8);
+  __Pyx_XDECREF(__pyx_t_9);
+  __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython.generate_all_decomp_cython", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_all_decomp);
+  __Pyx_XDECREF(__pyx_v_stack);
+  __Pyx_XDECREF(__pyx_v_pop_open);
+  __Pyx_XDECREF(__pyx_v_pop_close);
+  __Pyx_XDECREF(__pyx_v_head);
+  __Pyx_XDECREF(__pyx_v_tail);
+  __Pyx_XDECREF(__pyx_v_head_tail);
+  __Pyx_XDECREF(__pyx_v_node);
+  __Pyx_XDECREF(__pyx_v_seq);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
 281:     """
+
 282:     Cython version of :func:`generate_all_decomp`. 
+
 283: 
+
 284:     >>> seq, open_to_close, nodes = random_balanced_sequence(10)
+
 285:     >>> seq, open_to_close, nodes = tree_to_seq(tree, mode='chr', strhack=True)
+
 286:     >>> all_decomp = generate_all_decomp_cython(seq, open_to_close)
+
 287:     """
+
+288:     all_decomp = {}
+
  __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 288, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_all_decomp = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+289:     stack = [seq]
+
  __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 289, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_INCREF(__pyx_v_seq);
+  __Pyx_GIVEREF(__pyx_v_seq);
+  PyList_SET_ITEM(__pyx_t_1, 0, __pyx_v_seq);
+  __pyx_v_stack = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+290:     while stack:
+
  while (1) {
+    __pyx_t_2 = (PyList_GET_SIZE(__pyx_v_stack) != 0);
+    if (!__pyx_t_2) break;
+
+291:         seq = stack.pop()
+
    __pyx_t_1 = __Pyx_PyList_Pop(__pyx_v_stack); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 291, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF_SET(__pyx_v_seq, __pyx_t_1);
+    __pyx_t_1 = 0;
+
+292:         if seq not in all_decomp and seq:
+
    __pyx_t_3 = (__Pyx_PyDict_ContainsTF(__pyx_v_seq, __pyx_v_all_decomp, Py_NE)); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 292, __pyx_L1_error)
+    __pyx_t_4 = (__pyx_t_3 != 0);
+    if (__pyx_t_4) {
+    } else {
+      __pyx_t_2 = __pyx_t_4;
+      goto __pyx_L6_bool_binop_done;
+    }
+    __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_v_seq); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 292, __pyx_L1_error)
+    __pyx_t_2 = __pyx_t_4;
+    __pyx_L6_bool_binop_done:;
+    if (__pyx_t_2) {
+/* … */
+    }
+  }
+
+293:             pop_open, pop_close, head, tail, head_tail = balanced_decomp_unsafe_cython(seq, open_to_close)
+
      if (!(likely(PyDict_CheckExact(__pyx_v_open_to_close))||((__pyx_v_open_to_close) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "dict", Py_TYPE(__pyx_v_open_to_close)->tp_name), 0))) __PYX_ERR(0, 293, __pyx_L1_error)
+      __pyx_t_1 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_balanced_decomp_unsafe_cython(__pyx_v_seq, ((PyObject*)__pyx_v_open_to_close)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 293, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      if (likely(__pyx_t_1 != Py_None)) {
+        PyObject* sequence = __pyx_t_1;
+        Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+        if (unlikely(size != 5)) {
+          if (size > 5) __Pyx_RaiseTooManyValuesError(5);
+          else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+          __PYX_ERR(0, 293, __pyx_L1_error)
+        }
+        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+        __pyx_t_5 = PyTuple_GET_ITEM(sequence, 0); 
+        __pyx_t_6 = PyTuple_GET_ITEM(sequence, 1); 
+        __pyx_t_7 = PyTuple_GET_ITEM(sequence, 2); 
+        __pyx_t_8 = PyTuple_GET_ITEM(sequence, 3); 
+        __pyx_t_9 = PyTuple_GET_ITEM(sequence, 4); 
+        __Pyx_INCREF(__pyx_t_5);
+        __Pyx_INCREF(__pyx_t_6);
+        __Pyx_INCREF(__pyx_t_7);
+        __Pyx_INCREF(__pyx_t_8);
+        __Pyx_INCREF(__pyx_t_9);
+        #else
+        {
+          Py_ssize_t i;
+          PyObject** temps[5] = {&__pyx_t_5,&__pyx_t_6,&__pyx_t_7,&__pyx_t_8,&__pyx_t_9};
+          for (i=0; i < 5; i++) {
+            PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 293, __pyx_L1_error)
+            __Pyx_GOTREF(item);
+            *(temps[i]) = item;
+          }
+        }
+        #endif
+        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      } else {
+        __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 293, __pyx_L1_error)
+      }
+      __Pyx_XDECREF_SET(__pyx_v_pop_open, __pyx_t_5);
+      __pyx_t_5 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_pop_close, __pyx_t_6);
+      __pyx_t_6 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_head, __pyx_t_7);
+      __pyx_t_7 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_tail, __pyx_t_8);
+      __pyx_t_8 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_head_tail, __pyx_t_9);
+      __pyx_t_9 = 0;
+
+294:             node = open_to_node[pop_open[0]]
+
      __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_pop_open, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 294, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_1);
+      __pyx_t_9 = __Pyx_PyObject_GetItem(__pyx_v_open_to_node, __pyx_t_1); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 294, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_9);
+      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+      __Pyx_XDECREF_SET(__pyx_v_node, __pyx_t_9);
+      __pyx_t_9 = 0;
+
+295:             all_decomp[seq] = (node, pop_open, pop_close, head, tail, head_tail)
+
      __pyx_t_9 = PyTuple_New(6); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 295, __pyx_L1_error)
+      __Pyx_GOTREF(__pyx_t_9);
+      __Pyx_INCREF(__pyx_v_node);
+      __Pyx_GIVEREF(__pyx_v_node);
+      PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_v_node);
+      __Pyx_INCREF(__pyx_v_pop_open);
+      __Pyx_GIVEREF(__pyx_v_pop_open);
+      PyTuple_SET_ITEM(__pyx_t_9, 1, __pyx_v_pop_open);
+      __Pyx_INCREF(__pyx_v_pop_close);
+      __Pyx_GIVEREF(__pyx_v_pop_close);
+      PyTuple_SET_ITEM(__pyx_t_9, 2, __pyx_v_pop_close);
+      __Pyx_INCREF(__pyx_v_head);
+      __Pyx_GIVEREF(__pyx_v_head);
+      PyTuple_SET_ITEM(__pyx_t_9, 3, __pyx_v_head);
+      __Pyx_INCREF(__pyx_v_tail);
+      __Pyx_GIVEREF(__pyx_v_tail);
+      PyTuple_SET_ITEM(__pyx_t_9, 4, __pyx_v_tail);
+      __Pyx_INCREF(__pyx_v_head_tail);
+      __Pyx_GIVEREF(__pyx_v_head_tail);
+      PyTuple_SET_ITEM(__pyx_t_9, 5, __pyx_v_head_tail);
+      if (unlikely(PyDict_SetItem(__pyx_v_all_decomp, __pyx_v_seq, __pyx_t_9) < 0)) __PYX_ERR(0, 295, __pyx_L1_error)
+      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
+
+296:             stack.append(head_tail)
+
      __pyx_t_10 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_head_tail); if (unlikely(__pyx_t_10 == ((int)-1))) __PYX_ERR(0, 296, __pyx_L1_error)
+
+297:             stack.append(head)
+
      __pyx_t_10 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_head); if (unlikely(__pyx_t_10 == ((int)-1))) __PYX_ERR(0, 297, __pyx_L1_error)
+
+298:             stack.append(tail)
+
      __pyx_t_10 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_tail); if (unlikely(__pyx_t_10 == ((int)-1))) __PYX_ERR(0, 298, __pyx_L1_error)
+
+299:     return all_decomp
+
  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(__pyx_v_all_decomp);
+  __pyx_r = __pyx_v_all_decomp;
+  goto __pyx_L0;
+
 300: 
+
 301: 
+
+302: cdef tuple balanced_decomp_prehash_cython(seq, dict open_to_close, open_to_node):
+
static PyObject *__pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_balanced_decomp_prehash_cython(PyObject *__pyx_v_seq, PyObject *__pyx_v_open_to_close, PyObject *__pyx_v_open_to_node) {
+  PyObject *__pyx_v_info = 0;
+  PyObject *__pyx_v_pop_open = NULL;
+  PyObject *__pyx_v_pop_close = NULL;
+  PyObject *__pyx_v_head = NULL;
+  PyObject *__pyx_v_tail = NULL;
+  PyObject *__pyx_v_head_tail = NULL;
+  Py_hash_t __pyx_v_head_key;
+  Py_hash_t __pyx_v_tail_key;
+  Py_hash_t __pyx_v_head_tail_key;
+  PyObject *__pyx_v_node = NULL;
+  PyObject *__pyx_v_a = NULL;
+  PyObject *__pyx_v_b = NULL;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("balanced_decomp_prehash_cython", 0);
+/* … */
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_2);
+  __Pyx_XDECREF(__pyx_t_3);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_6);
+  __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython.balanced_decomp_prehash_cython", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_info);
+  __Pyx_XDECREF(__pyx_v_pop_open);
+  __Pyx_XDECREF(__pyx_v_pop_close);
+  __Pyx_XDECREF(__pyx_v_head);
+  __Pyx_XDECREF(__pyx_v_tail);
+  __Pyx_XDECREF(__pyx_v_head_tail);
+  __Pyx_XDECREF(__pyx_v_node);
+  __Pyx_XDECREF(__pyx_v_a);
+  __Pyx_XDECREF(__pyx_v_b);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
 303:     """
+
 304:     Cython version of :func:`balanced_decomp_unsafe`. 
+
 305:     """
+
 306:     cdef tuple info
+
+307:     pop_open, pop_close, head, tail, head_tail = balanced_decomp_unsafe_cython(seq, open_to_close)
+
  __pyx_t_1 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_balanced_decomp_unsafe_cython(__pyx_v_seq, __pyx_v_open_to_close); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 307, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  if (likely(__pyx_t_1 != Py_None)) {
+    PyObject* sequence = __pyx_t_1;
+    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+    if (unlikely(size != 5)) {
+      if (size > 5) __Pyx_RaiseTooManyValuesError(5);
+      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+      __PYX_ERR(0, 307, __pyx_L1_error)
+    }
+    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+    __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0); 
+    __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); 
+    __pyx_t_4 = PyTuple_GET_ITEM(sequence, 2); 
+    __pyx_t_5 = PyTuple_GET_ITEM(sequence, 3); 
+    __pyx_t_6 = PyTuple_GET_ITEM(sequence, 4); 
+    __Pyx_INCREF(__pyx_t_2);
+    __Pyx_INCREF(__pyx_t_3);
+    __Pyx_INCREF(__pyx_t_4);
+    __Pyx_INCREF(__pyx_t_5);
+    __Pyx_INCREF(__pyx_t_6);
+    #else
+    {
+      Py_ssize_t i;
+      PyObject** temps[5] = {&__pyx_t_2,&__pyx_t_3,&__pyx_t_4,&__pyx_t_5,&__pyx_t_6};
+      for (i=0; i < 5; i++) {
+        PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 307, __pyx_L1_error)
+        __Pyx_GOTREF(item);
+        *(temps[i]) = item;
+      }
+    }
+    #endif
+    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  } else {
+    __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 307, __pyx_L1_error)
+  }
+  __pyx_v_pop_open = __pyx_t_2;
+  __pyx_t_2 = 0;
+  __pyx_v_pop_close = __pyx_t_3;
+  __pyx_t_3 = 0;
+  __pyx_v_head = __pyx_t_4;
+  __pyx_t_4 = 0;
+  __pyx_v_tail = __pyx_t_5;
+  __pyx_t_5 = 0;
+  __pyx_v_head_tail = __pyx_t_6;
+  __pyx_t_6 = 0;
+
+308:     cdef Py_hash_t head_key = hash(head)
+
  __pyx_t_7 = PyObject_Hash(__pyx_v_head); if (unlikely(__pyx_t_7 == ((Py_hash_t)-1))) __PYX_ERR(0, 308, __pyx_L1_error)
+  __pyx_v_head_key = __pyx_t_7;
+
+309:     cdef Py_hash_t tail_key = hash(tail)
+
  __pyx_t_7 = PyObject_Hash(__pyx_v_tail); if (unlikely(__pyx_t_7 == ((Py_hash_t)-1))) __PYX_ERR(0, 309, __pyx_L1_error)
+  __pyx_v_tail_key = __pyx_t_7;
+
+310:     cdef Py_hash_t head_tail_key = hash(head_tail)
+
  __pyx_t_7 = PyObject_Hash(__pyx_v_head_tail); if (unlikely(__pyx_t_7 == ((Py_hash_t)-1))) __PYX_ERR(0, 310, __pyx_L1_error)
+  __pyx_v_head_tail_key = __pyx_t_7;
+
+311:     node = open_to_node[pop_open[0]]
+
  __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_pop_open, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 311, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_6 = __Pyx_PyObject_GetItem(__pyx_v_open_to_node, __pyx_t_1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 311, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_6);
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+  __pyx_v_node = __pyx_t_6;
+  __pyx_t_6 = 0;
+
+312:     a = pop_open
+
  __Pyx_INCREF(__pyx_v_pop_open);
+  __pyx_v_a = __pyx_v_pop_open;
+
+313:     b = pop_close
+
  __Pyx_INCREF(__pyx_v_pop_close);
+  __pyx_v_b = __pyx_v_pop_close;
+
+314:     info = (node, seq, head, tail, head_tail, head_key, tail_key, head_tail_key, a, b)
+
  __pyx_t_6 = __Pyx_PyInt_FromHash_t(__pyx_v_head_key); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 314, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_6);
+  __pyx_t_1 = __Pyx_PyInt_FromHash_t(__pyx_v_tail_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 314, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_t_5 = __Pyx_PyInt_FromHash_t(__pyx_v_head_tail_key); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 314, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_5);
+  __pyx_t_4 = PyTuple_New(10); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 314, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_4);
+  __Pyx_INCREF(__pyx_v_node);
+  __Pyx_GIVEREF(__pyx_v_node);
+  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_node);
+  __Pyx_INCREF(__pyx_v_seq);
+  __Pyx_GIVEREF(__pyx_v_seq);
+  PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_seq);
+  __Pyx_INCREF(__pyx_v_head);
+  __Pyx_GIVEREF(__pyx_v_head);
+  PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_v_head);
+  __Pyx_INCREF(__pyx_v_tail);
+  __Pyx_GIVEREF(__pyx_v_tail);
+  PyTuple_SET_ITEM(__pyx_t_4, 3, __pyx_v_tail);
+  __Pyx_INCREF(__pyx_v_head_tail);
+  __Pyx_GIVEREF(__pyx_v_head_tail);
+  PyTuple_SET_ITEM(__pyx_t_4, 4, __pyx_v_head_tail);
+  __Pyx_GIVEREF(__pyx_t_6);
+  PyTuple_SET_ITEM(__pyx_t_4, 5, __pyx_t_6);
+  __Pyx_GIVEREF(__pyx_t_1);
+  PyTuple_SET_ITEM(__pyx_t_4, 6, __pyx_t_1);
+  __Pyx_GIVEREF(__pyx_t_5);
+  PyTuple_SET_ITEM(__pyx_t_4, 7, __pyx_t_5);
+  __Pyx_INCREF(__pyx_v_a);
+  __Pyx_GIVEREF(__pyx_v_a);
+  PyTuple_SET_ITEM(__pyx_t_4, 8, __pyx_v_a);
+  __Pyx_INCREF(__pyx_v_b);
+  __Pyx_GIVEREF(__pyx_v_b);
+  PyTuple_SET_ITEM(__pyx_t_4, 9, __pyx_v_b);
+  __pyx_t_6 = 0;
+  __pyx_t_1 = 0;
+  __pyx_t_5 = 0;
+  __pyx_v_info = ((PyObject*)__pyx_t_4);
+  __pyx_t_4 = 0;
+
+315:     return info
+
  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(__pyx_v_info);
+  __pyx_r = __pyx_v_info;
+  goto __pyx_L0;
+
 316: 
+
 317: 
+
+318: cdef dict generate_all_decomp_prehash_cython(seq, dict open_to_close, open_to_node):
+
static PyObject *__pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_prehash_cython(PyObject *__pyx_v_seq, PyObject *__pyx_v_open_to_close, PyObject *__pyx_v_open_to_node) {
+  PyObject *__pyx_v_all_decomp = 0;
+  PyObject *__pyx_v_stack = 0;
+  PyObject *__pyx_v_info = 0;
+  PyObject *__pyx_v_key = NULL;
+  PyObject *__pyx_v_head = NULL;
+  PyObject *__pyx_v_tail = NULL;
+  PyObject *__pyx_v_head_tail = NULL;
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("generate_all_decomp_prehash_cython", 0);
+  __Pyx_INCREF(__pyx_v_seq);
+/* … */
+  /* function exit code */
+  __pyx_L1_error:;
+  __Pyx_XDECREF(__pyx_t_1);
+  __Pyx_XDECREF(__pyx_t_4);
+  __Pyx_XDECREF(__pyx_t_5);
+  __Pyx_XDECREF(__pyx_t_6);
+  __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython.generate_all_decomp_prehash_cython", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __pyx_r = 0;
+  __pyx_L0:;
+  __Pyx_XDECREF(__pyx_v_all_decomp);
+  __Pyx_XDECREF(__pyx_v_stack);
+  __Pyx_XDECREF(__pyx_v_info);
+  __Pyx_XDECREF(__pyx_v_key);
+  __Pyx_XDECREF(__pyx_v_head);
+  __Pyx_XDECREF(__pyx_v_tail);
+  __Pyx_XDECREF(__pyx_v_head_tail);
+  __Pyx_XDECREF(__pyx_v_seq);
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
 319:     """
+
 320:     Cython version of :func:`generate_all_decomp_prehash`. 
+
 321:     """
+
+322:     cdef dict all_decomp = {}
+
  __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 322, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __pyx_v_all_decomp = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
+
+323:     cdef list stack = [seq]
+
  __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 323, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+  __Pyx_INCREF(__pyx_v_seq);
+  __Pyx_GIVEREF(__pyx_v_seq);
+  PyList_SET_ITEM(__pyx_t_1, 0, __pyx_v_seq);
+  __pyx_v_stack = ((PyObject*)__pyx_t_1);
+  __pyx_t_1 = 0;
+
 324:     cdef tuple info
+
+325:     while stack:
+
  while (1) {
+    __pyx_t_2 = (PyList_GET_SIZE(__pyx_v_stack) != 0);
+    if (!__pyx_t_2) break;
+
+326:         seq = stack.pop()
+
    __pyx_t_1 = __Pyx_PyList_Pop(__pyx_v_stack); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 326, __pyx_L1_error)
+    __Pyx_GOTREF(__pyx_t_1);
+    __Pyx_DECREF_SET(__pyx_v_seq, __pyx_t_1);
+    __pyx_t_1 = 0;
+
+327:         if seq:
+
    __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_seq); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 327, __pyx_L1_error)
+    if (__pyx_t_2) {
+/* … */
+    }
+  }
+
 328:             # key = hash(seq)
+
+329:             key = seq
+
      __Pyx_INCREF(__pyx_v_seq);
+      __Pyx_XDECREF_SET(__pyx_v_key, __pyx_v_seq);
+
+330:             if key not in all_decomp:
+
      __pyx_t_2 = (__Pyx_PyDict_ContainsTF(__pyx_v_key, __pyx_v_all_decomp, Py_NE)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 330, __pyx_L1_error)
+      __pyx_t_3 = (__pyx_t_2 != 0);
+      if (__pyx_t_3) {
+/* … */
+      }
+
+331:                 info = balanced_decomp_prehash_cython(seq, open_to_close, open_to_node)
+
        __pyx_t_1 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_balanced_decomp_prehash_cython(__pyx_v_seq, __pyx_v_open_to_close, __pyx_v_open_to_node); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 331, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_1);
+        __Pyx_XDECREF_SET(__pyx_v_info, ((PyObject*)__pyx_t_1));
+        __pyx_t_1 = 0;
+
+332:                 head, tail, head_tail = info[2:5]
+
        if (unlikely(__pyx_v_info == Py_None)) {
+          PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
+          __PYX_ERR(0, 332, __pyx_L1_error)
+        }
+        __pyx_t_1 = __Pyx_PyTuple_GetSlice(__pyx_v_info, 2, 5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 332, __pyx_L1_error)
+        __Pyx_GOTREF(__pyx_t_1);
+        if (1) {
+          PyObject* sequence = __pyx_t_1;
+          Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
+          if (unlikely(size != 3)) {
+            if (size > 3) __Pyx_RaiseTooManyValuesError(3);
+            else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
+            __PYX_ERR(0, 332, __pyx_L1_error)
+          }
+          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
+          __pyx_t_4 = PyTuple_GET_ITEM(sequence, 0); 
+          __pyx_t_5 = PyTuple_GET_ITEM(sequence, 1); 
+          __pyx_t_6 = PyTuple_GET_ITEM(sequence, 2); 
+          __Pyx_INCREF(__pyx_t_4);
+          __Pyx_INCREF(__pyx_t_5);
+          __Pyx_INCREF(__pyx_t_6);
+          #else
+          __pyx_t_4 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 332, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_4);
+          __pyx_t_5 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 332, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_5);
+          __pyx_t_6 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 332, __pyx_L1_error)
+          __Pyx_GOTREF(__pyx_t_6);
+          #endif
+          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+        }
+        __Pyx_XDECREF_SET(__pyx_v_head, __pyx_t_4);
+        __pyx_t_4 = 0;
+        __Pyx_XDECREF_SET(__pyx_v_tail, __pyx_t_5);
+        __pyx_t_5 = 0;
+        __Pyx_XDECREF_SET(__pyx_v_head_tail, __pyx_t_6);
+        __pyx_t_6 = 0;
+
+333:                 all_decomp[key] = info
+
        if (unlikely(PyDict_SetItem(__pyx_v_all_decomp, __pyx_v_key, __pyx_v_info) < 0)) __PYX_ERR(0, 333, __pyx_L1_error)
+
+334:                 stack.append(head_tail)
+
        __pyx_t_7 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_head_tail); if (unlikely(__pyx_t_7 == ((int)-1))) __PYX_ERR(0, 334, __pyx_L1_error)
+
+335:                 stack.append(head)
+
        __pyx_t_7 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_head); if (unlikely(__pyx_t_7 == ((int)-1))) __PYX_ERR(0, 335, __pyx_L1_error)
+
+336:                 stack.append(tail)
+
        __pyx_t_7 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_tail); if (unlikely(__pyx_t_7 == ((int)-1))) __PYX_ERR(0, 336, __pyx_L1_error)
+
+337:     return all_decomp
+
  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(__pyx_v_all_decomp);
+  __pyx_r = __pyx_v_all_decomp;
+  goto __pyx_L0;
+
 338: 
+
 339: 
+
+340: class IdentityDict:
+
  __pyx_t_1 = __Pyx_Py3MetaclassPrepare((PyObject *) NULL, __pyx_empty_tuple, __pyx_n_s_IdentityDict, __pyx_n_s_IdentityDict, (PyObject *) NULL, __pyx_n_s_networkx_algorithms_isomorphism, __pyx_kp_s_Used_when_open_to_node_is_unspe); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 340, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_1);
+/* … */
+  __pyx_t_2 = __Pyx_Py3ClassCreate(((PyObject*)&__Pyx_DefaultClassType), __pyx_n_s_IdentityDict, __pyx_empty_tuple, __pyx_t_1, NULL, 0, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 340, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s_IdentityDict, __pyx_t_2) < 0) __PYX_ERR(0, 340, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+
 341:     """ Used when ``open_to_node`` is unspecified """
+
+342:     def __getitem__(self, key):
+
/* Python wrapper */
+static PyObject *__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict_1__getitem__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
+static PyMethodDef __pyx_mdef_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict_1__getitem__ = {"__getitem__", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict_1__getitem__, METH_VARARGS|METH_KEYWORDS, 0};
+static PyObject *__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict_1__getitem__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
+  CYTHON_UNUSED PyObject *__pyx_v_self = 0;
+  PyObject *__pyx_v_key = 0;
+  PyObject *__pyx_r = 0;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__getitem__ (wrapper)", 0);
+  {
+    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_self,&__pyx_n_s_key,0};
+    PyObject* values[2] = {0,0};
+    if (unlikely(__pyx_kwds)) {
+      Py_ssize_t kw_args;
+      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
+      switch (pos_args) {
+        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+        CYTHON_FALLTHROUGH;
+        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+        CYTHON_FALLTHROUGH;
+        case  0: break;
+        default: goto __pyx_L5_argtuple_error;
+      }
+      kw_args = PyDict_Size(__pyx_kwds);
+      switch (pos_args) {
+        case  0:
+        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_self)) != 0)) kw_args--;
+        else goto __pyx_L5_argtuple_error;
+        CYTHON_FALLTHROUGH;
+        case  1:
+        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_key)) != 0)) kw_args--;
+        else {
+          __Pyx_RaiseArgtupleInvalid("__getitem__", 1, 2, 2, 1); __PYX_ERR(0, 342, __pyx_L3_error)
+        }
+      }
+      if (unlikely(kw_args > 0)) {
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__getitem__") < 0)) __PYX_ERR(0, 342, __pyx_L3_error)
+      }
+    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
+      goto __pyx_L5_argtuple_error;
+    } else {
+      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
+      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
+    }
+    __pyx_v_self = values[0];
+    __pyx_v_key = values[1];
+  }
+  goto __pyx_L4_argument_unpacking_done;
+  __pyx_L5_argtuple_error:;
+  __Pyx_RaiseArgtupleInvalid("__getitem__", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 342, __pyx_L3_error)
+  __pyx_L3_error:;
+  __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython.IdentityDict.__getitem__", __pyx_clineno, __pyx_lineno, __pyx_filename);
+  __Pyx_RefNannyFinishContext();
+  return NULL;
+  __pyx_L4_argument_unpacking_done:;
+  __pyx_r = __pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict___getitem__(__pyx_self, __pyx_v_self, __pyx_v_key);
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
+
+  /* function exit code */
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+
+static PyObject *__pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict___getitem__(CYTHON_UNUSED PyObject *__pyx_self, CYTHON_UNUSED PyObject *__pyx_v_self, PyObject *__pyx_v_key) {
+  PyObject *__pyx_r = NULL;
+  __Pyx_RefNannyDeclarations
+  __Pyx_RefNannySetupContext("__getitem__", 0);
+/* … */
+  /* function exit code */
+  __pyx_L0:;
+  __Pyx_XGIVEREF(__pyx_r);
+  __Pyx_RefNannyFinishContext();
+  return __pyx_r;
+}
+/* … */
+  __pyx_tuple__8 = PyTuple_Pack(2, __pyx_n_s_self, __pyx_n_s_key); if (unlikely(!__pyx_tuple__8)) __PYX_ERR(0, 342, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_tuple__8);
+  __Pyx_GIVEREF(__pyx_tuple__8);
+/* … */
+  __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict_1__getitem__, 0, __pyx_n_s_IdentityDict___getitem, NULL, __pyx_n_s_networkx_algorithms_isomorphism, __pyx_d, ((PyObject *)__pyx_codeobj__9)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 342, __pyx_L1_error)
+  __Pyx_GOTREF(__pyx_t_2);
+  if (__Pyx_SetNameInClass(__pyx_t_1, __pyx_n_s_getitem, __pyx_t_2) < 0) __PYX_ERR(0, 342, __pyx_L1_error)
+  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
+
+343:         return key
+
  __Pyx_XDECREF(__pyx_r);
+  __Pyx_INCREF(__pyx_v_key);
+  __pyx_r = __pyx_v_key;
+  goto __pyx_L0;
+
diff --git a/netharn/initializers/_nx_ext/balanced_sequence_cython.pyx b/netharn/initializers/_nx_ext/balanced_sequence_cython.pyx new file mode 100644 index 0000000..b9f0df5 --- /dev/null +++ b/netharn/initializers/_nx_ext/balanced_sequence_cython.pyx @@ -0,0 +1,344 @@ +# distutils: language = c++ +""" +This module re-implements functions in :module:`balanced_sequence` in cython +and obtains 40-50x speedups in common circumstances. There are likely more +speed improvements that could be made. + +CommandLine +----------- +# Explicitly build this cython module (must in networkx repo root) +cythonize -a -i networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx + + +Examples +-------- +>>> from networkx.algorithms.isomorphism._embedding.balanced_sequence_cython import _lcs_iter_prehash2_cython +>>> from networkx.algorithms.isomorphism._embedding.balanced_sequence_cython import _lcs_iter_simple_alt2_cython +>>> from networkx.algorithms.isomorphism._embedding.demodata import random_balanced_sequence +>>> seq1, open_to_close1 = random_balanced_sequence(300, mode='paren') +>>> seq2, open_to_close2 = random_balanced_sequence(300, mode='paren') +>>> open_to_close = {**open_to_close1, **open_to_close2} +>>> full_seq1 = seq1 +>>> full_seq2 = seq2 +>>> import operator +>>> node_affinity = operator.eq +>>> open_to_node = IdentityDict() +>>> best1, value1 = _lcs_iter_prehash2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node) +>>> best2, value2 = _lcs_iter_simple_alt2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node) +>>> assert value1 == value1 +""" + + +def _lcs_iter_prehash2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node): + """ + Version of the lcs iterative algorithm where we precompute hash values. + + This is the current fastest implementation candidate for the LCS problem, + but note that the alternative version is faster in some cases. + """ + cdef dict all_decomp1 = generate_all_decomp_prehash_cython(full_seq1, open_to_close, open_to_node) + cdef dict all_decomp2 = generate_all_decomp_prehash_cython(full_seq2, open_to_close, open_to_node) + cdef dict key_decomp1 = {} + cdef dict key_decomp2 = {} + + cdef dict _results = {} + # Populate base cases + empty1 = type(next(iter(all_decomp1.keys())))() + empty2 = type(next(iter(all_decomp2.keys())))() + cdef Py_hash_t empty1_key = hash(empty1) + cdef Py_hash_t empty2_key = hash(empty2) + cdef tuple best = (empty1, empty2) + + cdef tuple info1, info2 + cdef tuple try_key, key + cdef Py_hash_t seq1_key, seq2_key + cdef Py_hash_t head1_key, tail1_key, head_tail1_key + cdef Py_hash_t head2_key, tail2_key, head_tail2_key + cdef tuple frame + cdef tuple miss_frame + + base_result = (0, best) + for seq1, info1 in all_decomp1.items(): + seq1_key = hash(seq1) + head1_key, tail1_key, head_tail1_key = all_decomp1[seq1][5:8] + _results[(seq1_key, empty2_key)] = base_result + _results[(head1_key, empty2_key)] = base_result + _results[(tail1_key, empty2_key)] = base_result + _results[(head_tail1_key, empty2_key)] = base_result + key_decomp1[seq1_key] = info1 + + for seq2, info2 in all_decomp2.items(): + seq2_key = hash(seq2) + head2_key, tail2_key, head_tail2_key = all_decomp2[seq2][5:8] + _results[(empty1_key, seq2_key)] = base_result + _results[(empty1_key, head2_key)] = base_result + _results[(empty1_key, tail2_key)] = base_result + _results[(empty1_key, head_tail2_key)] = base_result + key_decomp2[seq2_key] = info2 + + cdef Py_hash_t full_seq1_key = hash(full_seq1) + cdef Py_hash_t full_seq2_key = hash(full_seq2) + + cdef tuple key0 = (full_seq1_key, full_seq2_key) + cdef tuple frame0 = (key0, full_seq1, full_seq2) + cdef list stack = [frame0] + + while stack: + frame = stack[-1] + key, seq1, seq2 = frame + seq1_key, seq2_key = key + if key not in _results: + info1 = key_decomp1[seq1_key] + tok1, seq1, head1, tail1, head_tail1, head1_key, tail1_key, head_tail1_key, a1, b1 = info1 + + info2 = key_decomp2[seq2_key] + tok2, seq2, head2, tail2, head_tail2, head2_key, tail2_key, head_tail2_key, a2, b2 = info2 + + affinity = node_affinity(tok1, tok2) + + # Case 2: The current edge in sequence1 is deleted + try_key = (head_tail1_key, seq2_key) + if try_key in _results: + cand1 = _results[try_key] + else: + miss_frame = try_key, head_tail1, seq2 + stack.append(miss_frame) + continue + + # Case 3: The current edge in sequence2 is deleted + try_key = (seq1_key, head_tail2_key) + if try_key in _results: + cand2 = _results[try_key] + else: + miss_frame = try_key, seq1, head_tail2 + stack.append(miss_frame) + continue + + # Case 1: The LCS involves this edge + if affinity: + try_key = (head1_key, head2_key) + if try_key in _results: + pval_h, new_heads = _results[try_key] + else: + miss_frame = try_key, head1, head2 + stack.append(miss_frame) + continue + + try_key = (tail1_key, tail2_key) + if try_key in _results: + pval_t, new_tails = _results[try_key] + else: + miss_frame = try_key, tail1, tail2 + stack.append(miss_frame) + continue + + new_head1, new_head2 = new_heads + new_tail1, new_tail2 = new_tails + + subseq1 = a1 + new_head1 + b1 + new_tail1 + subseq2 = a2 + new_head2 + b2 + new_tail2 + + res3 = (subseq1, subseq2) + val3 = pval_h + pval_t + affinity + cand3 = (val3, res3) + else: + cand3 = (-1, None) + + # We solved the frame + _results[key] = max(cand1, cand2, cand3) + stack.pop() + + # The stack pop is our solution + (val, best) = _results[key0] + found = (best, val) + return found + + + + +def _lcs_iter_simple_alt2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node): + """ + Depth first stack trajectory and replace try except statements with ifs + """ + if open_to_node is None: + open_to_node = IdentityDict() + all_decomp1 = generate_all_decomp_cython(full_seq1, open_to_close, open_to_node) + all_decomp2 = generate_all_decomp_cython(full_seq2, open_to_close, open_to_node) + + key0 = (full_seq1, full_seq2) + frame0 = key0 + stack = [frame0] + + _results = {} + # Populate base cases + empty1 = type(next(iter(all_decomp1.keys())))() + empty2 = type(next(iter(all_decomp2.keys())))() + best = (empty1, empty2) + base_result = (0, best) + for seq1 in all_decomp1.keys(): + key1 = seq1 + t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[key1] + _results[(seq1, empty2)] = base_result + _results[(head1, empty2)] = base_result + _results[(tail1, empty2)] = base_result + _results[(head_tail1, empty2)] = base_result + + for seq2 in all_decomp2.keys(): + key2 = seq2 + t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[key2] + _results[(empty1, seq2)] = base_result + _results[(empty1, head2)] = base_result + _results[(empty1, tail2)] = base_result + _results[(empty1, head_tail2)] = base_result + + while stack: + key = stack[-1] + if key not in _results: + seq1, seq2 = key + + t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[seq1] + t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[seq2] + + # Case 2: The current edge in sequence1 is deleted + try_key = (head_tail1, seq2) + if try_key in _results: + cand1 = _results[try_key] + else: + # stack.append(key) + stack.append(try_key) + continue + + # Case 3: The current edge in sequence2 is deleted + try_key = (seq1, head_tail2) + if try_key in _results: + cand2 = _results[try_key] + else: + # stack.append(key) + stack.append(try_key) + continue + + # Case 1: The LCS involves this edge + affinity = node_affinity(t1, t2) + if affinity: + try_key = (head1, head2) + if try_key in _results: + pval_h, new_heads = _results[try_key] + else: + # stack.append(key) + stack.append(try_key) + continue + + try_key = (tail1, tail2) + if try_key in _results: + pval_t, new_tails = _results[try_key] + else: + # stack.append(key) + stack.append(try_key) + continue + + new_head1, new_head2 = new_heads + new_tail1, new_tail2 = new_tails + + subseq1 = a1 + new_head1 + b1 + new_tail1 + subseq2 = a2 + new_head2 + b2 + new_tail2 + + res3 = (subseq1, subseq2) + val3 = pval_h + pval_t + affinity + cand3 = (val3, res3) + else: + cand3 = (-1, None) + + # We solved the frame + _results[key] = max(cand1, cand2, cand3) + stack.pop() + + val, best = _results[key0] + found = (best, val) + return found + + +cdef tuple balanced_decomp_unsafe_cython(sequence, dict open_to_close): + """ + Cython version of :func:`balanced_decomp_unsafe`. + """ + cdef int stacklen = 1 # always +1 in the first iteration + cdef int head_stop = 1 + + tok_curr = sequence[0] + want_close = open_to_close[tok_curr] + + # for tok_curr in sequence[1:]: + for head_stop in range(1, len(sequence)): + tok_curr = sequence[head_stop] + stacklen += 1 if tok_curr in open_to_close else -1 + if stacklen == 0 and tok_curr == want_close: + pop_close = sequence[head_stop:head_stop + 1] + break + + pop_open = sequence[0:1] + head = sequence[1:head_stop] + tail = sequence[head_stop + 1:] + head_tail = head + tail + return pop_open, pop_close, head, tail, head_tail + + +cdef generate_all_decomp_cython(seq, open_to_close, open_to_node=None): + """ + Cython version of :func:`generate_all_decomp`. + """ + all_decomp = {} + stack = [seq] + while stack: + seq = stack.pop() + if seq not in all_decomp and seq: + pop_open, pop_close, head, tail, head_tail = balanced_decomp_unsafe_cython(seq, open_to_close) + node = open_to_node[pop_open[0]] + all_decomp[seq] = (node, pop_open, pop_close, head, tail, head_tail) + stack.append(head_tail) + stack.append(head) + stack.append(tail) + return all_decomp + + +cdef tuple balanced_decomp_prehash_cython(seq, dict open_to_close, open_to_node): + """ + Cython version of :func:`balanced_decomp_unsafe`. + """ + cdef tuple info + pop_open, pop_close, head, tail, head_tail = balanced_decomp_unsafe_cython(seq, open_to_close) + cdef Py_hash_t head_key = hash(head) + cdef Py_hash_t tail_key = hash(tail) + cdef Py_hash_t head_tail_key = hash(head_tail) + node = open_to_node[pop_open[0]] + a = pop_open + b = pop_close + info = (node, seq, head, tail, head_tail, head_key, tail_key, head_tail_key, a, b) + return info + + +cdef dict generate_all_decomp_prehash_cython(seq, dict open_to_close, open_to_node): + """ + Cython version of :func:`generate_all_decomp_prehash`. + """ + cdef dict all_decomp = {} + cdef list stack = [seq] + cdef tuple info + while stack: + seq = stack.pop() + if seq: + # key = hash(seq) + key = seq + if key not in all_decomp: + info = balanced_decomp_prehash_cython(seq, open_to_close, open_to_node) + head, tail, head_tail = info[2:5] + all_decomp[key] = info + stack.append(head_tail) + stack.append(head) + stack.append(tail) + return all_decomp + + +class IdentityDict: + """ Used when ``open_to_node`` is unspecified """ + def __getitem__(self, key): + return key diff --git a/netharn/initializers/_nx_ext/benchmarks.py b/netharn/initializers/_nx_ext/benchmarks.py new file mode 100644 index 0000000..2a9e70a --- /dev/null +++ b/netharn/initializers/_nx_ext/benchmarks.py @@ -0,0 +1,387 @@ +from netharn.initializers._nx_ext.path_embedding import ( # NOQA + maximum_common_path_embedding) +# from netharn.initializers._nx_ext.tree_embedding import ( # NOQA +# maximum_common_ordered_tree_embedding, tree_to_seq) +from netharn.initializers._nx_ext.demodata import random_paths +from netharn.initializers._nx_ext.demodata import random_ordered_tree # NOQA +import operator + + +def bench_maximum_common_path_embedding(): + """ + xdoctest -m netharn.initializers._nx_ext.benchmarks bench_maximum_common_path_embedding + """ + import itertools as it + import ubelt as ub + import timerit + from netharn.initializers._nx_ext import balanced_sequence + from netharn.initializers._nx_ext import path_embedding + + data_modes = [] + + # Define which implementations we are going to test + run_basis = { + 'mode': [ + 'chr', + # 'number' + # 'tuple', # by far the slowest + ], + 'impl': balanced_sequence.available_impls_longest_common_balanced_sequence(), + } + + # Define the properties of the random data we are going to test on + data_basis = { + 'size': [20, 50], + 'max_depth': [8, 16], + 'common': [8, 16], + 'prefix_depth1': [0, 4], + 'prefix_depth2': [0, 4], + # 'labels': [26 ** 1, 26 ** 8] + 'labels': [1, 26] + } + + # run_basis['impl'] = set(run_basis['impl']) & { + # 'iter-alt2-cython', + # 'iter-prehash2-cython', + # 'iter-prehash2', + # 'iter-alt2', + # # 'iter-alt1', + # # 'iter-prehash', + # # 'iter', + # # 'recurse' + # } + + # TODO: parametarize demo names + # BENCH_MODE = None + # BENCH_MODE = 'small' + # BENCH_MODE = 'small2' + # BENCH_MODE = 'recursion-error' + BENCH_MODE = 'medium' + # BENCH_MODE = 'large' + + if BENCH_MODE == 'small': + data_basis = { + 'size': [30], + 'max_depth': [8, 2], + 'common': [2, 8], + 'prefix_depth1': [0, 4], + 'prefix_depth2': [0], + 'labels': [4] + } + run_basis['impl'] = set(run_basis['impl']) & { + # 'iter-alt2-cython', + 'iter-prehash2-cython', + 'iter-prehash2', + # 'iter-alt2', + # 'iter', + # 'recurse', + } + run_basis['impl'] = ub.oset(balanced_sequence.available_impls_longest_common_balanced_sequence()) - { + 'recurse', + } + # runparam_to_time = { + # ('chr', 'iter-prehash2-cython'): {'mean': 0.062, 'max': 0.157}, + # ('chr', 'iter-prehash2') : {'mean': 0.071, 'max': 0.185}, + # } + + if BENCH_MODE == 'small2': + data_basis = { + 'size': [30], + 'max_depth': [8, 2], + 'common': [2, 8], + 'prefix_depth1': [0, 4], + 'prefix_depth2': [0], + 'labels': [4] + } + run_basis['impl'] = ub.oset(balanced_sequence.available_impls_longest_common_balanced_sequence()) - { + 'recurse', + } + run_basis['mode'] = ['number', 'chr'] + # runparam_to_time = { + # ('chr', 'iter-alt2-cython') : {'mean': 0.036, 'max': 0.094}, + # ('chr', 'iter-alt2') : {'mean': 0.049, 'max': 0.125}, + # ('chr', 'iter-alt1') : {'mean': 0.050, 'max': 0.129}, + # ('chr', 'iter-prehash2-cython') : {'mean': 0.057, 'max': 0.146}, + # ('number', 'iter-prehash2-cython'): {'mean': 0.057, 'max': 0.146}, + # ('chr', 'iter') : {'mean': 0.064, 'max': 0.167}, + # ('chr', 'iter-prehash2') : {'mean': 0.066, 'max': 0.170}, + # ('number', 'iter-prehash2') : {'mean': 0.067, 'max': 0.176}, + # ('chr', 'iter-prehash') : {'mean': 0.073, 'max': 0.187}, + # ('number', 'iter-prehash') : {'mean': 0.074, 'max': 0.196}, + # ('number', 'iter-alt1') : {'mean': 0.126, 'max': 0.344}, + # ('number', 'iter-alt2-cython') : {'mean': 0.133, 'max': 0.363}, + # ('number', 'iter') : {'mean': 0.140, 'max': 0.386}, + # ('number', 'iter-alt2') : {'mean': 0.149, 'max': 0.408}, + # } + + if BENCH_MODE == 'medium': + data_basis = { + 'size': [30, 40], + 'max_depth': [4, 8], + 'common': [8, 50], + 'prefix_depth1': [0, 4], + 'prefix_depth2': [2], + 'labels': [8, 1] + } + # Results + # runparam_to_time = { + # ('chr', 'iter-alt2-cython') : {'mean': 0.112, 'max': 0.467}, + # ('chr', 'recurse') : {'mean': 0.153, 'max': 0.648}, + # ('chr', 'iter-alt2') : {'mean': 0.155, 'max': 0.661}, + # ('chr', 'iter-alt1') : {'mean': 0.163, 'max': 0.707}, + # ('chr', 'iter-prehash2-cython'): {'mean': 0.197, 'max': 0.849}, + # ('chr', 'iter') : {'mean': 0.216, 'max': 0.933}, + # ('chr', 'iter-prehash2') : {'mean': 0.225, 'max': 0.974}, + # ('chr', 'iter-prehash') : {'mean': 0.253, 'max': 1.097}, + # } + + if BENCH_MODE == 'large': + data_basis = { + 'size': [30, 40], + 'max_depth': [4, 12], # 64000 + 'common': [8, 32], + 'prefix_depth1': [0, 4], + 'prefix_depth2': [2], + 'labels': [8] + } + run_basis['impl'] = balanced_sequence.available_impls_longest_common_balanced_sequence() + # runparam_to_time = { + # ('chr', 'iter-alt2-cython') : {'mean': 0.282, 'max': 0.923}, + # ('chr', 'recurse') : {'mean': 0.397, 'max': 1.297}, + # ('chr', 'iter-alt2') : {'mean': 0.409, 'max': 1.328}, + # ('chr', 'iter-alt1') : {'mean': 0.438, 'max': 1.428}, + # ('chr', 'iter-prehash2-cython'): {'mean': 0.511, 'max': 1.668}, + # ('chr', 'iter') : {'mean': 0.580, 'max': 1.915}, + # ('chr', 'iter-prehash2') : {'mean': 0.605, 'max': 1.962}, + # ('chr', 'iter-prehash') : {'mean': 0.679, 'max': 2.211}, + # } + + elif BENCH_MODE == 'too-big': + data_basis = { + 'size': [100], + 'max_depth': [8], + 'common': [80], + 'prefix_depth1': [4], + 'prefix_depth2': [2], + 'labels': [8] + } + if BENCH_MODE == 'recursion-error': + data_basis = { + 'size': [0], + 'max_depth': [512], + 'common': [4], + 'prefix_depth1': [0], + 'prefix_depth2': [0], + 'labels': [256] + } + run_basis['impl'] = ub.oset(['recurse']) | ub.oset(balanced_sequence.available_impls_longest_common_balanced_sequence()) + # Results + # complexity = 69.48 + # stats1 = {'depth': 395, 'n_edges': 1203, 'n_leafs': 4, 'n_nodes': 1207, 'npaths': 4} + # stats2 = {'depth': 395, 'n_edges': 1203, 'n_leafs': 4, 'n_nodes': 1207, 'npaths': 4} + # runparam_to_time = { + # ('chr', 'recurse') : {'mean': NAN, 'max': NAN}, + # ('chr', 'iter-alt2-cython') : {'mean': 7.979, 'max': 7.979}, + # ('chr', 'iter-alt2') : {'mean': 11.307, 'max': 11.307}, + # ('chr', 'iter-alt1') : {'mean': 11.659, 'max': 11.659}, + # ('chr', 'iter-prehash2-cython'): {'mean': 15.230, 'max': 15.230}, + # ('chr', 'iter-prehash2') : {'mean': 17.058, 'max': 17.058}, + # ('chr', 'iter') : {'mean': 18.377, 'max': 18.377}, + # ('chr', 'iter-prehash') : {'mean': 19.508, 'max': 19.508}, + # } + + data_modes = [ + dict(zip(data_basis.keys(), vals)) + for vals in it.product(*data_basis.values())] + run_modes = [ + dict(zip(run_basis.keys(), vals)) + for vals in it.product(*run_basis.values())] + + print('len(data_modes) = {!r}'.format(len(data_modes))) + print('len(run_modes) = {!r}'.format(len(run_modes))) + print('total = {}'.format(len(data_modes) * len(run_modes))) + + seed = 0 + # if len(data_modes) < 10: + # for datakw in data_modes: + # _datakw = ub.dict_diff(datakw, {'complexity'}) + # paths1, paths2 = random_paths(seed=seed, **datakw) + # print('paths1 = {}'.format(ub.repr2(paths1, nl=1))) + # print('paths2 = {}'.format(ub.repr2(paths2, nl=1))) + # print('---') + for idx, datakw in enumerate(data_modes): + print('datakw = {}'.format(ub.repr2(datakw, nl=1))) + _datakw = ub.dict_diff(datakw, {'complexity'}) + paths1, paths2 = random_paths(seed=seed, **_datakw) + tree1 = path_embedding.paths_to_otree(paths1) + tree2 = path_embedding.paths_to_otree(paths2) + stats1 = { + 'npaths': len(paths1), + 'n_nodes': len(tree1.nodes), + 'n_edges': len(tree1.edges), + 'n_leafs': len([n for n in tree1.nodes if len(tree1.succ[n]) == 0]), + 'depth': max(len(p.split('/')) for p in paths1), + } + stats2 = { + 'npaths': len(paths2), + 'n_nodes': len(tree2.nodes), + 'n_edges': len(tree2.edges), + 'n_leafs': len([n for n in tree2.nodes if len(tree2.succ[n]) == 0]), + 'depth': max(len(p.split('/')) for p in paths2), + } + complexity = ( + stats1['n_nodes'] * min(stats1['n_leafs'], stats1['depth']) * + stats2['n_nodes'] * min(stats2['n_leafs'], stats2['depth'])) ** .25 + + datakw['complexity'] = complexity + print('datakw = {}'.format(ub.repr2(datakw, nl=0, precision=2))) + + if True: + # idx + 4 > len(data_modes): + print('stats1 = {}'.format(ub.repr2(stats1, nl=0))) + print('stats2 = {}'.format(ub.repr2(stats2, nl=0))) + # print('complexity = {:.2f}'.format(complexity)) + + total = len(data_modes) * len(run_modes) + print('len(data_modes) = {!r}'.format(len(data_modes))) + print('len(run_modes) = {!r}'.format(len(run_modes))) + print('total = {!r}'.format(total)) + seed = 0 + + prog = ub.ProgIter(total=total, verbose=3) + prog.begin() + results = [] + ti = timerit.Timerit(1, bestof=1, verbose=1, unit='s') + for datakw in data_modes: + _datakw = ub.dict_diff(datakw, {'complexity'}) + paths1, paths2 = random_paths(seed=seed, **_datakw) + print('---') + prog.step(4) + tree1 = path_embedding.paths_to_otree(paths1) + tree2 = path_embedding.paths_to_otree(paths2) + stats1 = { + 'npaths': len(paths1), + 'n_nodes': len(tree1.nodes), + 'n_edges': len(tree1.edges), + 'n_leafs': len([n for n in tree1.nodes if len(tree1.succ[n]) == 0]), + 'depth': max(len(p.split('/')) for p in paths1), + } + stats2 = { + 'npaths': len(paths2), + 'n_nodes': len(tree2.nodes), + 'n_edges': len(tree2.edges), + 'n_leafs': len([n for n in tree2.nodes if len(tree2.succ[n]) == 0]), + 'depth': max(len(p.split('/')) for p in paths2), + } + complexity = ( + stats1['n_nodes'] * min(stats1['n_leafs'], stats1['depth']) * + stats2['n_nodes'] * min(stats2['n_leafs'], stats2['depth'])) ** .25 + + datakw['complexity'] = complexity + print('datakw = {}'.format(ub.repr2(datakw, nl=0, precision=2))) + + if True: + # idx + 4 > len(data_modes): + print('stats1 = {}'.format(ub.repr2(stats1, nl=0))) + print('stats2 = {}'.format(ub.repr2(stats2, nl=0))) + for runkw in run_modes: + paramkw = {**datakw, **runkw} + run_key = ub.repr2( + paramkw, sep='', itemsep='', kvsep='', + explicit=1, nobr=1, nl=0, precision=1) + try: + for timer in ti.reset(run_key): + with timer: + maximum_common_path_embedding(paths1, paths2, **runkw) + except RecursionError as ex: + print('ex = {!r}'.format(ex)) + row = paramkw.copy() + row['time'] = float('nan') + else: + row = paramkw.copy() + row['time'] = ti.min() + results.append(row) + prog.end() + + print(ub.repr2(ub.sorted_vals(ti.measures['min']), nl=1, align=':', precision=6)) + + import pandas as pd + import kwarray + df = pd.DataFrame.from_dict(results) + + dataparam_to_time = {} + for mode, subdf in df.groupby(['complexity'] + list(data_basis.keys())): + stats = kwarray.stats_dict(subdf['time']) + stats.pop('min', None) + stats.pop('std', None) + stats.pop('shape', None) + dataparam_to_time[mode] = stats + dataparam_to_time = ub.sorted_vals(dataparam_to_time, key=lambda x: x['max']) + print('dataparam_to_time = {}'.format(ub.repr2(dataparam_to_time, nl=1, precision=3, align=':'))) + print(list(data_basis.keys())) + + runparam_to_time = {} + for mode, subdf in df.groupby(['mode', 'impl']): + stats = kwarray.stats_dict(subdf['time']) + stats.pop('min', None) + stats.pop('std', None) + stats.pop('shape', None) + runparam_to_time[mode] = stats + runparam_to_time = ub.sorted_vals(runparam_to_time, key=lambda x: x['max']) + print('runparam_to_time = {}'.format(ub.repr2(runparam_to_time, nl=1, precision=3, align=':'))) + + +def benchmark_balanced_sequence_single(): + from netharn.initializers._nx_ext import balanced_sequence + from netharn.initializers._nx_ext import demodata + import ubelt as ub + mode = 'number' + seq1, open_to_close = demodata.random_balanced_sequence(200, mode=mode) + seq2, open_to_close = demodata.random_balanced_sequence(400, mode=mode, open_to_close=open_to_close) + longest_common_balanced_sequence = balanced_sequence.longest_common_balanced_sequence + impls = balanced_sequence.available_impls_longest_common_balanced_sequence() + results = {} + for impl in impls: + with ub.Timer(impl): + best, val = longest_common_balanced_sequence( + seq1, seq2, open_to_close, node_affinity=None, impl=impl) + results[impl] = val + assert allsame(results.values()) + + +def allsame(iterable, eq=operator.eq): + """ + Determine if all items in a sequence are the same + + Args: + iterable (Iterable[A]): + items to determine if they are all the same + + eq (Callable[[A, A], bool], default=operator.eq): + function used to test for equality + + Returns: + bool: True if all items are equal, otherwise False + + Example: + >>> allsame([1, 1, 1, 1]) + True + >>> allsame([]) + True + >>> allsame([0, 1]) + False + >>> iterable = iter([0, 1, 1, 1]) + >>> next(iterable) + >>> allsame(iterable) + True + >>> allsame(range(10)) + False + >>> allsame(range(10), lambda a, b: True) + True + """ + iter_ = iter(iterable) + try: + first = next(iter_) + except StopIteration: + return True + return all(eq(first, item) for item in iter_) diff --git a/netharn/initializers/_nx_ext/demodata.py b/netharn/initializers/_nx_ext/demodata.py new file mode 100644 index 0000000..edcd827 --- /dev/null +++ b/netharn/initializers/_nx_ext/demodata.py @@ -0,0 +1,239 @@ +""" +Helpers for creating random data for tests / benchmarks for the tree embedding +algorithms. +""" + + +def random_paths( + size=10, max_depth=10, common=0, prefix_depth1=0, prefix_depth2=0, + sep='/', labels=26, seed=None): + """ + Returns two randomly created paths (as in directory structures) for use in + testing and benchmarking :func:`maximum_common_path_embedding`. + + Parameters + ---------- + size : int + The number of independant random paths + + max_depth : int + Maximum depth for the independant random paths + + common : int + The number of shared common paths + + prefix_depth1: int + Depth of the random prefix attacheded to first common paths + + prefix_depth2: int + Depth of the random prefix attacheded to second common paths + + labels: int or collection + Number of or collection of tokens that can be used as node labels + + sep: str + path separator + + seed: + Random state or seed + + Examples + -------- + >>> paths1, paths2 = random_paths( + >>> size=5, max_depth=3, common=6, + >>> prefix_depth1=3, prefix_depth2=3, labels=2 ** 64, + >>> seed=0) + >>> from netharn.initializers._nx_ext.path_embedding import paths_to_otree + >>> from netharn.initializers._nx_ext.tree_embedding import tree_to_seq + >>> tree = paths_to_otree(paths1) + >>> seq, open_to_close, node_to_open = tree_to_seq(tree, mode='chr') + >>> seq, open_to_close, node_to_open = tree_to_seq(tree, mode='number') + >>> seq, open_to_close, node_to_open = tree_to_seq(tree, mode='tuple') + >>> # xdoctest: +REQUIRES(module:ubelt) + >>> import ubelt as ub + >>> print('paths1 = {}'.format(ub.repr2(paths1, nl=1))) + >>> print('paths2 = {}'.format(ub.repr2(paths2, nl=1))) + """ + from networkx.utils import create_py_random_state + rng = create_py_random_state(seed) + + if isinstance(labels, int): + alphabet = list(map(chr, range(ord('a'), ord('z')))) + + def random_label(): + digit = rng.randint(0, labels) + label = _convert_digit_base(digit, alphabet) + return label + else: + from functools import partial + random_label = partial(rng.choice, labels) + + def random_path(rng, max_depth): + depth = rng.randint(1, max_depth) + parts = [str(random_label()) for _ in range(depth)] + path = sep.join(parts) + return path + + # These paths might be shared (but usually not) + iid_paths1 = {random_path(rng, max_depth) for _ in range(size)} + iid_paths2 = {random_path(rng, max_depth) for _ in range(size)} + + # These paths will be shared + common_paths = {random_path(rng, max_depth) for _ in range(common)} + + if prefix_depth1 > 0: + prefix1 = random_path(rng, prefix_depth1) + common1 = {sep.join([prefix1, suff]) for suff in common_paths} + else: + common1 = common_paths + + if prefix_depth2 > 0: + prefix2 = random_path(rng, prefix_depth2) + common2 = {sep.join([prefix2, suff]) for suff in common_paths} + else: + common2 = common_paths + + paths1 = sorted(common1 | iid_paths1) + paths2 = sorted(common2 | iid_paths2) + + return paths1, paths2 + + +def random_ordered_tree(n, seed=None): + """ + Creates a random ordered tree + + TODO + ---- + - [ ] Rename to random_ordered_directed_tree ? + - [ ] Merge in with other data generators? + + Parameters + ---------- + n : int + A positive integer representing the number of nodes in the tree. + + seed : integer, random_state, or None (default) + Indicator of random number generation state. + See :ref:`Randomness`. + + Returns + ------- + networkx.OrderedDiGraph + + Example + ------- + >>> assert len(random_ordered_tree(n=1, seed=0).nodes) == 1 + >>> assert len(random_ordered_tree(n=2, seed=0).nodes) == 2 + >>> assert len(random_ordered_tree(n=3, seed=0).nodes) == 3 + >>> from netharn.initializers._nx_ext.tree_embedding import forest_str + >>> print(forest_str(random_ordered_tree(n=5, seed=3))) + └── 1 + ├── 4 + │   ├── 3 + │   └── 2 + └── 0 + """ + import networkx as nx + from networkx.utils import create_py_random_state + rng = create_py_random_state(seed) + # Create a random undirected tree + utree = nx.random_tree(n, seed=rng) + # Use a random root node and dfs to define edge directions + nodes = list(utree.nodes) + source = rng.choice(nodes) + edges = nx.dfs_edges(utree, source=source) + # Populate the ordered graph + otree = nx.OrderedDiGraph() + otree.add_nodes_from(utree.nodes) + otree.add_edges_from(edges) + return otree + + +def random_balanced_sequence(n, seed=None, mode='chr', open_to_close=None): + r""" + Creates a random balanced sequence for testing / benchmarks + + Parameters + ---------- + n : int + A positive integer representing the number of nodes in the tree. + + seed : integer, random_state, or None (default) + Indicator of random number generation state. + See :ref:`Randomness`. + + open_to_close : dict | None + if specified, updates existing open_to_close with tokens from this + sequence. + + mode: str + the type of sequence returned (see :func:`tree_to_seq` for details) + + Returns + ------- + : tuple + The first item is the sequence itself + the second item is the open_to_close mappings. + + Example + ------- + >>> # Demo the various sequence encodings that we might use + >>> seq, open_to_close = random_balanced_sequence(2, seed=1, mode='tuple') + >>> print('seq = {!r}'.format(seq)) + >>> seq, open_to_close = random_balanced_sequence(4, seed=1, mode='chr') + >>> print('seq = {!r}'.format(seq)) + >>> seq, open_to_close = random_balanced_sequence(4, seed=1, mode='number') + >>> print('seq = {!r}'.format(seq)) + >>> seq, open_to_close = random_balanced_sequence(4, seed=1, mode='str') + >>> print('seq = {!r}'.format(seq)) + >>> seq, open_to_close = random_balanced_sequence(10, seed=1, mode='paren') + >>> print('seq = {!r}'.format(seq)) + seq = (('open', 0), ('open', 1), ('close', 1), ('close', 0)) + seq = '\x00\x02\x04\x06\x07\x05\x03\x01' + seq = (1, 2, 3, 4, -4, -3, -2, -1) + seq = ('2(', '1(', '0(', '3(', ')3', ')0', ')1', ')2') + seq = '([[[]{{}}](){{[]}}])' + """ + from networkx.utils import create_py_random_state + from netharn.initializers._nx_ext.tree_embedding import tree_to_seq + # Create a random otree and then convert it to a balanced sequence + rng = create_py_random_state(seed) + tree = random_ordered_tree(n, seed=rng) + if mode == 'paren': + pool = '[{(' + for node in tree.nodes: + tree.nodes[node]['label'] = rng.choice(pool) + seq, open_to_close, _ = tree_to_seq( + tree, mode=mode, open_to_close=open_to_close, strhack=1) + else: + seq, open_to_close, _ = tree_to_seq( + tree, mode=mode, open_to_close=open_to_close) + return seq, open_to_close + + +def _convert_digit_base(digit, alphabet): + """ + Parameters + ---------- + digit : int + number in base 10 to convert + + alphabet : list + symbols of the conversion base + """ + baselen = len(alphabet) + x = digit + if x == 0: + return alphabet[0] + sign = 1 if x > 0 else -1 + x *= sign + digits = [] + while x: + digits.append(alphabet[x % baselen]) + x //= baselen + if sign < 0: + digits.append('-') + digits.reverse() + newbase_str = ''.join(digits) + return newbase_str diff --git a/netharn/initializers/_nx_ext/path_embedding.py b/netharn/initializers/_nx_ext/path_embedding.py new file mode 100644 index 0000000..0a7a71a --- /dev/null +++ b/netharn/initializers/_nx_ext/path_embedding.py @@ -0,0 +1,143 @@ +import networkx as nx +from .tree_embedding import maximum_common_ordered_tree_embedding + + +def maximum_common_path_embedding(paths1, paths2, sep='/', impl='iter-alt2', mode='chr'): + """ + Finds the maximum path embedding common between two sets of paths + + Parameters + ---------- + paths1, paths2: List[str] + a list of paths + + sep: str + path separator character + + impl: str + backend runtime to use + + mode: str + backend representation to use + + Returns + ------- + :tuple + corresponding lists subpaths1 and subpaths2 which are subsets of + paths1 and path2 respectively + + Examples + -------- + >>> paths1 = [ + >>> '/usr/bin/python', + >>> '/usr/bin/python3.6.1', + >>> '/usr/lib/python3.6/dist-packages/networkx', + >>> '/usr/lib/python3.6/dist-packages/numpy', + >>> '/usr/include/python3.6/Python.h', + >>> ] + >>> paths2 = [ + >>> '/usr/local/bin/python', + >>> '/usr/bin/python3.6.2', + >>> '/usr/local/lib/python3.6/dist-packages/networkx', + >>> '/usr/local/lib/python3.6/dist-packages/scipy', + >>> '/usr/local/include/python3.6/Python.h', + >>> ] + >>> subpaths1, subpaths2 = maximum_common_path_embedding(paths1, paths2) + >>> import pprint + >>> print('subpaths1 = {}'.format(pprint.pformat(subpaths1))) + >>> print('subpaths2 = {}'.format(pprint.pformat(subpaths2))) + subpaths1 = ['/usr/bin/python', + '/usr/include/python3.6/Python.h', + '/usr/lib/python3.6/dist-packages/networkx'] + subpaths2 = ['/usr/local/bin/python', + '/usr/local/include/python3.6/Python.h', + '/usr/local/lib/python3.6/dist-packages/networkx'] + """ + # the longest common balanced sequence problem + def _affinity(node1, node2): + score = 0 + for t1, t2 in zip(node1[::-1], node2[::-1]): + if t1 == t2: + score += 1 + else: + break + return score + node_affinity = _affinity + + tree1 = paths_to_otree(paths1, sep=sep) + tree2 = paths_to_otree(paths2, sep=sep) + + subtree1, subtree2 = maximum_common_ordered_tree_embedding( + tree1, tree2, node_affinity=node_affinity, impl=impl, mode=mode) + + subpaths1 = [sep.join(node) for node in subtree1.nodes if subtree1.out_degree[node] == 0] + subpaths2 = [sep.join(node) for node in subtree2.nodes if subtree2.out_degree[node] == 0] + return subpaths1, subpaths2 + + +def paths_to_otree(paths, sep='/'): + """ + Generates an ordered tree from a list of path strings + + Parameters + ---------- + paths: List[str] + a list of paths + + sep : str + path separation character. defaults to "/" + + Returns + ------- + nx.OrderedDiGraph + + Example + ------- + >>> from netharn.initializers._nx_ext.tree_embedding import forest_str + >>> paths = [ + >>> '/etc/ld.so.conf', + >>> '/usr/bin/python3.6', + >>> '/usr/include/python3.6/Python.h', + >>> '/usr/lib/python3.6/config-3.6m-x86_64-linux-gnu/libpython3.6.so', + >>> '/usr/local/bin/gnumake.h', + >>> '/usr/local/etc', + >>> '/usr/local/lib/python3.6/dist-packages/', + >>> ] + >>> otree = paths_to_otree(paths) + >>> print(forest_str(otree)) + └── / + ├── usr + │   ├── local + │   │   ├── lib + │   │   │   └── python3.6 + │   │   │   └── dist-packages + │   │   │   └── + │   │   ├── etc + │   │   └── bin + │   │   └── gnumake.h + │   ├── lib + │   │   └── python3.6 + │   │   └── config-3.6m-x86_64-linux-gnu + │   │   └── libpython3.6.so + │   ├── include + │   │   └── python3.6 + │   │   └── Python.h + │   └── bin + │   └── python3.6 + └── etc + └── ld.so.conf + """ + otree = nx.OrderedDiGraph() + for path in sorted(paths): + parts = tuple(path.split(sep)) + node_path = [] + for i in range(1, len(parts) + 1): + node = parts[0:i] + otree.add_node(node) + otree.nodes[node]['label'] = node[-1] + node_path.append(node) + for u, v in zip(node_path[:-1], node_path[1:]): + otree.add_edge(u, v) + if ('',) in otree.nodes: + otree.nodes[('',)]['label'] = sep + return otree diff --git a/netharn/initializers/_nx_ext/tests/test_balanced_sequence.py b/netharn/initializers/_nx_ext/tests/test_balanced_sequence.py new file mode 100644 index 0000000..ed88346 --- /dev/null +++ b/netharn/initializers/_nx_ext/tests/test_balanced_sequence.py @@ -0,0 +1,32 @@ + + +def test_all_implementations_are_same(): + """ + Tests several random sequences + """ + from netharn.initializers._nx_ext import balanced_sequence + from netharn.initializers._nx_ext import demodata + from networkx.utils import create_py_random_state + + seed = 93024896892223032652928827097264 + rng = create_py_random_state(seed) + + maxsize = 20 + num_trials = 5 + + for _ in range(num_trials): + n1 = rng.randint(1, maxsize) + n2 = rng.randint(1, maxsize) + + seq1, open_to_close = demodata.random_balanced_sequence(n1, seed=rng) + seq2, open_to_close = demodata.random_balanced_sequence(n2, open_to_close=open_to_close, seed=rng) + longest_common_balanced_sequence = balanced_sequence.longest_common_balanced_sequence + + # Note: the returned sequences may be different (maximum embeddings may not + # be unique), but the values should all be the same. + results = {} + impls = balanced_sequence.available_impls_longest_common_balanced_sequence() + for impl in impls: + best, val = longest_common_balanced_sequence( + seq1, seq2, open_to_close, node_affinity=None, impl=impl) + results[impl] = val diff --git a/netharn/initializers/_nx_ext/tests/test_path_embedding.py b/netharn/initializers/_nx_ext/tests/test_path_embedding.py new file mode 100644 index 0000000..82f2cd9 --- /dev/null +++ b/netharn/initializers/_nx_ext/tests/test_path_embedding.py @@ -0,0 +1,260 @@ +from netharn.initializers._nx_ext.path_embedding import maximum_common_path_embedding +from netharn.initializers._nx_ext.demodata import random_paths + + +def test_not_compatable(): + paths1 = [ + 'foo/bar' + ] + paths2 = [ + 'baz/biz' + ] + embedding1, embedding2 = maximum_common_path_embedding(paths1, paths2) + assert len(embedding1) == 0 + assert len(embedding2) == 0 + + +def test_compatable(): + paths1 = [ + 'root/suffix1' + ] + paths2 = [ + 'root/suffix2' + ] + embedding1, embedding2 = maximum_common_path_embedding(paths1, paths2) + assert embedding1 == ['root'] + assert embedding2 == ['root'] + + paths1 = [ + 'root/suffix1' + ] + paths2 = [ + 'root' + ] + embedding1, embedding2 = maximum_common_path_embedding(paths1, paths2) + assert embedding1 == ['root'] + assert embedding2 == ['root'] + + +def test_prefixed(): + paths1 = [ + 'prefix1/root/suffix1' + ] + paths2 = [ + 'root/suffix2' + ] + embedding1, embedding2 = maximum_common_path_embedding(paths1, paths2) + assert embedding1 == ['prefix1/root'] + assert embedding2 == ['root'] + + paths1 = [ + 'prefix1/root/suffix1' + ] + paths2 = [ + 'prefix1/root/suffix2' + ] + embedding1, embedding2 = maximum_common_path_embedding(paths1, paths2) + assert embedding1 == ['prefix1/root'] + assert embedding2 == ['prefix1/root'] + + +def test_simple1(): + paths1 = [ + 'root/file1', + 'root/file2', + 'root/file3', + ] + paths2 = [ + 'prefix1/root/file1', + 'prefix1/root/file2', + 'root/file3', + ] + embedding1, embedding2 = maximum_common_path_embedding(paths1, paths2) + assert embedding1 == paths1 + assert embedding2 == paths2 + + paths1 = [ + 'root/file1', + 'root/file2', + 'root/file3', + ] + paths2 = [ + 'prefix1/root/file1', + 'prefix1/root/file2', + 'prefix2/root/file3', + 'prefix2/root/file4', + ] + embedding1, embedding2 = maximum_common_path_embedding(paths1, paths2) + assert embedding1 == paths1 + + +def test_random1(): + paths1, paths2 = random_paths(10, seed=321) + embedding1, embedding2 = maximum_common_path_embedding(paths1, paths2) + + +def _demodata_resnet_module_state(arch): + """ + Construct paths corresponding to resnet convnet state keys to + simulate a real world use case for path-embeddings. + + Ignore + ------ + # Check to make sure the demodata agrees with real data + import torchvision + paths_true = list(torchvision.models.resnet50().state_dict().keys()) + paths_demo = _demodata_resnet_module_state('resnet50') + print(ub.hzcat([ub.repr2(paths_true, nl=2), ub.repr2(paths_demo)])) + assert paths_demo == paths_true + + paths_true = list(torchvision.models.resnet18().state_dict().keys()) + paths_demo = _demodata_resnet_module_state('resnet18') + print(ub.hzcat([ub.repr2(paths_true, nl=2), ub.repr2(paths_demo)])) + assert paths_demo == paths_true + + paths_true = list(torchvision.models.resnet152().state_dict().keys()) + paths_demo = _demodata_resnet_module_state('resnet152') + print(ub.hzcat([ub.repr2(paths_true, nl=2), ub.repr2(paths_demo)])) + assert paths_demo == paths_true + """ + if arch == 'resnet18': + block_type = 'basic' + layer_blocks = [2, 2, 2, 2] + elif arch == 'resnet50': + block_type = 'bottleneck' + layer_blocks = [3, 4, 6, 3] + elif arch == 'resnet152': + block_type = 'bottleneck' + layer_blocks = [3, 8, 36, 3] + else: + raise KeyError(arch) + paths = [] + paths += [ + 'conv1.weight', + 'bn1.weight', + 'bn1.bias', + 'bn1.running_mean', + 'bn1.running_var', + 'bn1.num_batches_tracked', + ] + if block_type == 'bottleneck': + num_convs = 3 + elif block_type == 'basic': + num_convs = 2 + else: + raise KeyError(block_type) + + for layer_idx, nblocks in enumerate(layer_blocks, start=1): + for block_idx in range(0, nblocks): + prefix = 'layer{}.{}.'.format(layer_idx, block_idx) + + for conv_idx in range(1, num_convs + 1): + paths += [ + prefix + 'conv{}.weight'.format(conv_idx), + prefix + 'bn{}.weight'.format(conv_idx), + prefix + 'bn{}.bias'.format(conv_idx), + prefix + 'bn{}.running_mean'.format(conv_idx), + prefix + 'bn{}.running_var'.format(conv_idx), + prefix + 'bn{}.num_batches_tracked'.format(conv_idx), + ] + if block_idx == 0 and layer_idx > 0: + if block_type != 'basic' or layer_idx > 1: + paths += [ + prefix + 'downsample.0.weight', + prefix + 'downsample.1.weight', + prefix + 'downsample.1.bias', + prefix + 'downsample.1.running_mean', + prefix + 'downsample.1.running_var', + prefix + 'downsample.1.num_batches_tracked', + ] + paths += [ + 'fc.weight', + 'fc.bias', + ] + return paths + + +def test_realworld_case1(): + """ + import torchvision + paths1 = list(torchvision.models.resnet50().state_dict().keys()) + + print(ub.hzcat(['paths1 = {}'.format(ub.repr2(paths1, nl=2)), ub.repr2(paths)])) + len(paths1) + """ + # times: resnet18: 0.16 seconds + # times: resnet50: 0.93 seconds + # times: resnet152: 9.83 seconds + paths1 = _demodata_resnet_module_state('resnet50') + paths2 = ['module.' + p for p in paths1] + # import ubelt as ub + # with ub.Timer('test-real-world-case'): + embedding1, embedding2 = maximum_common_path_embedding( + paths1, paths2, sep='.') + assert [p[len('module.'):] for p in embedding2] == embedding1 + + +def test_realworld_case2(): + """ + import torchvision + paths1 = list(torchvision.models.resnet152().state_dict().keys()) + print('paths1 = {}'.format(ub.repr2(paths1, nl=2))) + """ + backbone = _demodata_resnet_module_state('resnet18') + + # Detector strips of prefix and suffix of the backbone net + subpaths = ['detector.' + p for p in backbone[6:-2]] + paths1 = [ + 'detector.conv1.weight', + 'detector.bn1.weight', + 'detector.bn1.bias', + ] + subpaths + [ + 'detector.head1.conv1.weight', + 'detector.head1.conv2.weight', + 'detector.head1.conv3.weight', + 'detector.head1.fc.weight', + 'detector.head1.fc.bias', + 'detector.head2.conv1.weight', + 'detector.head2.conv2.weight', + 'detector.head2.conv3.weight', + 'detector.head2.fc.weight', + 'detector.head2.fc.bias', + ] + + paths2 = ['module.' + p for p in backbone] + + # import ubelt as ub + # with ub.Timer('test-real-world-case'): + embedding1, embedding2 = maximum_common_path_embedding( + paths1, paths2, sep='.') + + mapping = dict(zip(embedding1, embedding2)) + + # Note in the embedding case there may be superfluous assignments + # but they can either be discarded in post-processing or they wont + # be in the solution if we use isomorphisms instead of embeddings + assert len(subpaths) < len(mapping), ( + 'all subpaths should be in the mapping') + + non_common1 = set(paths1) - set(embedding1) + non_common2 = set(paths2) - set(embedding2) + + assert non_common2 == { + 'module.bn1.num_batches_tracked', + 'module.bn1.running_mean', + 'module.bn1.running_var', + } + + assert non_common1 == { + 'detector.conv1.weight', + 'detector.head1.conv1.weight', + 'detector.head1.conv2.weight', + 'detector.head1.conv3.weight', + 'detector.head1.fc.bias', + 'detector.head1.fc.weight', + 'detector.head2.conv2.weight', + 'detector.head2.conv3.weight', + } + # print('non_common1 = {}'.format(ub.repr2(non_common1, nl=1))) + # print('non_common2 = {}'.format(ub.repr2(non_common2, nl=1))) + # assert [p[len('module.'):] for p in embedding2] == embedding1 diff --git a/netharn/initializers/_nx_ext/tests/test_tree_embedding.py b/netharn/initializers/_nx_ext/tests/test_tree_embedding.py new file mode 100644 index 0000000..b9a2048 --- /dev/null +++ b/netharn/initializers/_nx_ext/tests/test_tree_embedding.py @@ -0,0 +1,109 @@ +from netharn.initializers._nx_ext.tree_embedding import ( + maximum_common_ordered_tree_embedding, forest_str) + +from netharn.initializers._nx_ext.demodata import ( + random_ordered_tree +) +import networkx as nx +import pytest +from networkx.utils import create_py_random_state + + +def test_null_common_embedding(): + """ + The empty graph is not a tree and should raise an error + """ + empty = nx.OrderedDiGraph() + non_empty = random_ordered_tree(n=1) + + with pytest.raises(nx.NetworkXPointlessConcept): + maximum_common_ordered_tree_embedding(empty, empty) + + with pytest.raises(nx.NetworkXPointlessConcept): + maximum_common_ordered_tree_embedding(empty, non_empty) + + with pytest.raises(nx.NetworkXPointlessConcept): + maximum_common_ordered_tree_embedding(non_empty, empty) + + +def test_self_common_embedding(): + """ + The common embedding of a tree with itself should always be itself + """ + rng = create_py_random_state(85652972257) + for n in range(1, 10): + tree = random_ordered_tree(n=n, seed=rng) + embedding1, embedding2 = maximum_common_ordered_tree_embedding(tree, tree) + assert tree.edges == embedding1.edges + + +def test_common_tree_embedding_small(): + tree1 = nx.OrderedDiGraph([(0, 1)]) + tree2 = nx.OrderedDiGraph([(0, 1), (1, 2)]) + print(forest_str(tree1)) + print(forest_str(tree2)) + + embedding1, embedding2 = maximum_common_ordered_tree_embedding(tree1, tree2) + print(forest_str(embedding1)) + print(forest_str(embedding2)) + + +def test_common_tree_embedding_small2(): + tree1 = nx.OrderedDiGraph([(0, 1), (2, 3), (4, 5), (5, 6)]) + tree2 = nx.OrderedDiGraph([(0, 1), (1, 2), (0, 3)]) + print(forest_str(tree1)) + print(forest_str(tree2)) + + embedding1, embedding2 = maximum_common_ordered_tree_embedding(tree1, tree2, node_affinity=None) + print(forest_str(embedding1)) + print(forest_str(embedding2)) + + +def test_all_implementations_are_same(): + """ + Tests several random sequences + """ + from netharn.initializers._nx_ext import balanced_sequence + from netharn.initializers._nx_ext import demodata + from networkx.utils import create_py_random_state + + seed = 24658885408229410362279507020239 + rng = create_py_random_state(seed) + + maxsize = 20 + num_trials = 5 + + for _ in range(num_trials): + n1 = rng.randint(1, maxsize) + n2 = rng.randint(1, maxsize) + + tree1 = demodata.random_ordered_tree(n1, seed=rng) + tree2 = demodata.random_ordered_tree(n2, seed=rng) + + # Note: the returned sequences may be different (maximum embeddings may not + # be unique), but the values should all be the same. + results = {} + impls = balanced_sequence.available_impls_longest_common_balanced_sequence() + for impl in impls: + # FIXME: do we need to rework the return value here? + subtree1, subtree2 = maximum_common_ordered_tree_embedding( + tree1, tree2, node_affinity=None, impl=impl) + _check_common_embedding_invariants(tree1, tree2, subtree1, subtree2) + results[impl] = len(subtree1.nodes) + + x = max(results.values()) + assert all(v == x for v in results.values()) + + +def _check_embedding_invariants(tree, subtree): + assert set(subtree.nodes).issubset(set(tree.nodes)), 'must have a node subset' + assert len(subtree.edges) <= len(tree.edges) + + +def _check_common_embedding_invariants(tree1, tree2, subtree1, subtree2): + """ + Validates that this solution satisfies properties of an embedding + """ + _check_embedding_invariants(tree1, subtree1) + _check_embedding_invariants(tree2, subtree2) + assert len(subtree1.nodes) == len(subtree2.nodes) diff --git a/netharn/initializers/_nx_ext/tree_embedding.py b/netharn/initializers/_nx_ext/tree_embedding.py new file mode 100644 index 0000000..faac200 --- /dev/null +++ b/netharn/initializers/_nx_ext/tree_embedding.py @@ -0,0 +1,512 @@ +""" +Algorithm for computing tree embeddings +""" +import networkx as nx +from collections import OrderedDict, defaultdict +from .balanced_sequence import longest_common_balanced_sequence, UnbalancedException + + +def maximum_common_ordered_tree_embedding( + tree1, tree2, node_affinity='auto', impl='iter-alt2', mode='chr'): + """ + Finds the maximum common subtree-embedding between two ordered trees. + + A tree S is an embedded subtree of T if it can be obtained from T by a + series of edge contractions. + + Note this produces a subtree embedding, which is not necessarilly a + subgraph isomorphism (although a subgraph isomorphism is also an + embedding.) + + The maximum common embedded subtree problem can be solved in in + `O(n1 * n2 * min(d1, l1) * min(d2, l2))` time on ordered trees with n1 and + n2 nodes, of depth d1 and d2 and with l1 and l2 leaves, respectively. + + Implements algorithm described in [1]_, which introduces the problem as + follows: + + "An important generalization of tree and subtree isomorphism, known as + minor containment, is the problem of determining whether a tree is + isomorphic to an embedded subtree of another tree, where an embedded + subtree of a tree is obtained by contracting some of the edges in the tree. + A further generalization of minor containment on trees, known as maximum + common embedded subtree, is the problem of finding or determining the size + of a largest common embedded subtree of two trees. The latter also + generalizes the maximum common subtree isomorphism problem, in which a + common subtree of largest size is contained as a subtree, not only + embedded, in the two trees." + + Parameters + ---------- + tree1, tree2 : nx.OrderedDiGraph + Trees to find the maximum embedding between + + node_affinity : None | str | callable + Function for to determine if two nodes can be matched. The return is + interpreted as a weight that is used to break ties. If None then any + node can match any other node and only the topology is important. + The default is "eq", which is the same as ``operator.eq``. + + impl : str + Determines the backend implementation + + mode : str + Determines the backend representation + + References + ---------- + .. [1] Lozano, Antoni, and Gabriel Valiente. + "On the maximum common embedded subtree problem for ordered trees." + String Algorithmics (2004): 155-170. + https://pdfs.semanticscholar.org/0b6e/061af02353f7d9b887f9a378be70be64d165.pdf + + Returns + ------- + Tuple[nx.OrderedDiGraph, nx.OrderedDiGraph] : + The maximum value common embedding for each tree with respect to the + chosen ``node_affinity`` function. The topology of both graphs will + always be the same, the only difference is that the node labels in the + first and second embeddings will correspond to ``tree1`` and `tree2`` + respectively. When ``node_affinity='eq'`` then embeddings should be + identical. + + Example + ------- + >>> from netharn.initializers._nx_ext.tree_embedding import * # NOQA + >>> from netharn.initializers._nx_ext.demodata import random_ordered_tree # NOQA + >>> tree1 = random_ordered_tree(7, seed=3257073545741117277206611) + >>> tree2 = random_ordered_tree(7, seed=123568587133124688238689717) + >>> print('tree1') + >>> forest_str(tree1, eager=1) + >>> print('tree2') + >>> forest_str(tree2, eager=1) + >>> embedding1, embedding2 = maximum_common_ordered_tree_embedding(tree1, tree2 ) + >>> print('embedding1') + >>> forest_str(embedding1, eager=1) + >>> print('embedding2') + >>> forest_str(embedding2, eager=1) + tree1 + └── 1 + ├── 6 + │   ├── 4 + │   └── 3 + └── 0 + └── 5 + └── 2 + tree2 + └── 4 + └── 1 + ├── 2 + │   ├── 6 + │   └── 0 + └── 3 + └── 5 + embedding1 + └── 1 + ├── 6 + └── 5 + embedding2 + └── 1 + ├── 6 + └── 5 + """ + if not (isinstance(tree1, nx.OrderedDiGraph) and nx.is_forest(tree1)): + raise nx.NetworkXNotImplemented('only implemented for directed ordered trees') + if not (isinstance(tree1, nx.OrderedDiGraph) and nx.is_forest(tree2)): + raise nx.NetworkXNotImplemented('only implemented for directed ordered trees') + + # Convert the trees to balanced sequences + sequence1, open_to_close, node_to_open = tree_to_seq( + tree1, open_to_close=None, node_to_open=None, mode=mode) + sequence2, open_to_close, node_to_open = tree_to_seq( + tree2, open_to_close, node_to_open, mode=mode) + seq1 = sequence1 + seq2 = sequence2 + + # FIXME: I think this may cause bugs in two cases, which may or may not be + # possible, but I need to look into it and provide a fix or justification + # as to why these cases wont be hit: + # (1) when the two trees share nodes that have different open tokens + # (2) when the mapping between nodes to opening tokens is not unique. + # I'm not sure if this second case can happen when we are converting + # from a tree to a sequence, there are certainly sequences where the + # same opening token might share multiple tree nodes. + open_to_node = invert_dict(node_to_open) + + # Solve the longest common balanced sequence problem + best, value = longest_common_balanced_sequence( + seq1, seq2, open_to_close, open_to_node=open_to_node, + node_affinity=node_affinity, impl=impl) + subseq1, subseq2 = best + + # Convert the subsequence back into a tree + embedding1 = seq_to_tree(subseq1, open_to_close, open_to_node) + embedding2 = seq_to_tree(subseq2, open_to_close, open_to_node) + return embedding1, embedding2 + + +def tree_to_seq(tree, open_to_close=None, node_to_open=None, mode='tuple', strhack=None): + r""" + Converts an ordered tree to a balanced sequence for use in algorithm + reductions. + + Parameters + ---------- + open_to_close : Dict | None + Dictionary of opening to closing tokens to be updated for problems + where multiple trees are converted to sequences. + + open_to_node : Dict | None + Dictionary of opening tokens to nodes to be updated for problems where + multiple trees are converted to sequences. + + mode : str + Currently hacky and needs refactor. + Can be 'tuple', 'number', or 'chr'. + Hackier variants are 'str' and 'paren'. + + strhack : bool + Currently hacky and needs refactor. If False, always return a tuple of + items, if True, tries to return a string of items. If None, tries to + choose a value depending on mode. + + Example + ------- + >>> from netharn.initializers._nx_ext.tree_embedding import * # NOQA + >>> tree = nx.path_graph(3, nx.OrderedDiGraph) + >>> print(forest_str(tree)) + >>> sequence, open_to_close, node_to_open = tree_to_seq(tree, mode='number') + >>> print('sequence = {!r}'.format(sequence)) + └── 0 + └── 1 + └── 2 + sequence = (1, 2, 3, -3, -2, -1) + + >>> tree = nx.balanced_tree(2, 2, nx.OrderedDiGraph) + >>> print(forest_str(tree)) + >>> sequence, open_to_close, node_to_open = tree_to_seq(tree, mode='number') + >>> print('sequence = {!r}'.format(sequence)) + └── 0 + ├── 2 + │   ├── 6 + │   └── 5 + └── 1 + ├── 4 + └── 3 + sequence = (1, 2, 3, -3, 4, -4, -2, 5, 6, -6, 7, -7, -5, -1) + + >>> from netharn.initializers._nx_ext.demodata import random_ordered_tree # NOQA + >>> tree = random_ordered_tree(2, seed=1) + >>> sequence, open_to_close, node_to_open = tree_to_seq(tree, mode='tuple') + >>> print('sequence = {!r}'.format(sequence)) + >>> sequence, open_to_close, node_to_open = tree_to_seq(tree, mode='chr') + >>> print('sequence = {!r}'.format(sequence)) + >>> sequence, open_to_close, node_to_open = tree_to_seq(tree, mode='number') + >>> print('sequence = {!r}'.format(sequence)) + sequence = (('open', 0), ('open', 1), ('close', 1), ('close', 0)) + sequence = '\x00\x02\x03\x01' + sequence = (1, 2, -2, -1) + """ + # mapping between opening and closing tokens + sources = [n for n in tree.nodes if tree.in_degree[n] == 0] + sequence = [] + + if strhack is None: + if mode == 'chr': + strhack = True + + if open_to_close is None: + open_to_close = {} + if node_to_open is None: + node_to_open = {} + + if strhack: + if mode == 'paren': + all_labels = {n['label'] for n in list(tree.nodes.values())} + assert all(x == 1 for x in map(len, all_labels)) + + for source in sources: + for u, v, etype in nx.dfs_labeled_edges(tree, source=source): + if etype == 'forward': + # u has been visited by v has not + if v not in node_to_open: + if mode == 'tuple': + open_tok = ('open', v) + close_tok = ('close', v) + elif mode == 'number': + open_tok = len(node_to_open) + 1 + close_tok = -open_tok + elif mode == 'str': + open_tok = '{}('.format(v) + close_tok = '){}'.format(v) + elif mode == 'chr': + if not strhack: + # note ussing the accent mark wont work in string + # mode even though the close tok renders as a + # single character. + open_tok = str(v) + close_tok = str(v) + u'\u0301' + else: + # utf8 can only encode this many chars + assert len(node_to_open) < (1112064 // 2) + open_tok = chr(len(node_to_open) * 2) + close_tok = chr(len(node_to_open) * 2 + 1) + elif mode == 'paren': + open_tok = tree.nodes[v]['label'] + assert strhack + if open_tok == '{': + close_tok = '}' + elif open_tok == '[': + close_tok = ']' + elif open_tok == '(': + close_tok = ')' + else: + raise KeyError(open_tok) + else: + raise KeyError(mode) + node_to_open[v] = open_tok + open_to_close[open_tok] = close_tok + open_tok = node_to_open[v] + sequence.append(open_tok) + elif etype == 'reverse': + # Both u and v are visited and the edge is in the tree + close_tok = open_to_close[node_to_open[v]] + sequence.append(close_tok) + else: + raise KeyError(etype) + sequence = tuple(sequence) + if strhack: + sequence = ''.join(sequence) + return sequence, open_to_close, node_to_open + + +def seq_to_tree(subseq, open_to_close, open_to_node): + """ + Converts a balanced sequence to an ordered tree + + Parameters + ---------- + subseq : Tuple | str + a balanced sequence of hashable items as a string or tuple + + open_to_close : Dict + a dictionary that maps opening tokens to closing tokens in the balanced + sequence problem. + + open_to_node : Dict + a dictionary that maps a sequence token to a node corresponding to an + original problem (e.g. a tree node). Must be unique. If unspecified new + nodes will be generated and the opening sequence token will be used as + a node label. + + Example + -------- + >>> from netharn.initializers._nx_ext.demodata import random_ordered_tree + >>> open_to_close = {'{': '}', '(': ')', '[': ']'} + >>> open_to_node = None + >>> subseq = '({[[]]})[[][]]{{}}' + >>> subtree = seq_to_tree(subseq, open_to_close, open_to_node) + >>> print(forest_str(subtree)) + ├── { + │   └── { + ├── [ + │   ├── [ + │   └── [ + └── ( + └── { + └── [ + └── [ + """ + nextnode = 0 # only used if open_to_node is not specified + subtree = nx.OrderedDiGraph() + stack = [] + for token in subseq: + if token in open_to_close: + if open_to_node is None: + node = nextnode + nextnode += 1 + else: + node = open_to_node[token] + if stack: + parent_tok, parent_node = stack[-1] + subtree.add_edge(parent_node, node) + else: + subtree.add_node(node) + if open_to_node is None: + subtree.nodes[node]['label'] = token + stack.append((token, node)) + else: + if not stack: + raise UnbalancedException + prev_open, prev_node = stack.pop() + want_close = open_to_close[prev_open] + if token != want_close: + raise UnbalancedException + return subtree + + +def invert_dict(dict_, unique_vals=True): + """ + Swaps the keys and values in a dictionary. + + Parameters + ---------- + dict_ (Dict[A, B]): dictionary to invert + + unique_vals (bool, default=True): if False, the values of the new + dictionary are sets of the original keys. + + Returns + ------- + Dict[B, A] | Dict[B, Set[A]]: + the inverted dictionary + + Notes + ----- + The must values be hashable. + + If the original dictionary contains duplicate values, then only one of + the corresponding keys will be returned and the others will be + discarded. This can be prevented by setting ``unique_vals=False``, + causing the inverted keys to be returned in a set. + + Example + ------- + >>> from netharn.initializers._nx_ext.tree_embedding import * # NOQA + >>> dict_ = {'a': 1, 'b': 2} + >>> inverted = invert_dict(dict_) + >>> assert inverted == {1: 'a', 2: 'b'} + + Example + ------- + >>> from netharn.initializers._nx_ext.tree_embedding import * # NOQA + >>> dict_ = OrderedDict([(2, 'a'), (1, 'b'), (0, 'c'), (None, 'd')]) + >>> inverted = invert_dict(dict_) + >>> assert list(inverted.keys())[0] == 'a' + + Example + ------- + >>> from netharn.initializers._nx_ext.tree_embedding import * # NOQA + >>> dict_ = {'a': 1, 'b': 0, 'c': 0, 'd': 0, 'f': 2} + >>> inverted = invert_dict(dict_, unique_vals=False) + >>> assert inverted == {0: {'b', 'c', 'd'}, 1: {'a'}, 2: {'f'}} + """ + if unique_vals: + if isinstance(dict_, OrderedDict): + inverted = OrderedDict((val, key) for key, val in dict_.items()) + else: + inverted = {val: key for key, val in dict_.items()} + else: + # Handle non-unique keys using groups + inverted = defaultdict(set) + for key, value in dict_.items(): + inverted[value].add(key) + inverted = dict(inverted) + return inverted + + +def forest_str(graph, eager=False, write=None, use_labels=True): + """ + Creates a nice utf8 representation of a directed forest + + Parameters + ---------- + graph : nx.DiGraph + graph to represent (must be a tree, forest, or the empty graph) + + eager : bool + if True, the text will be written directly to stdout or the write + function if specified + + write : callable + function to use to write to, if None new lines are appended to + a list and returned + + use_labels : bool + if True will use the "label" attribute of a node to display if it + exists otherwise it will use the node value itself. + + Returns + ------- + str : + utf8 representation of the tree / forest + + TODO + ---- + - [ ] Is this a generally useful utility? + + Example + ------- + >>> import networkx as nx + >>> graph = nx.balanced_tree(r=2, h=3, create_using=nx.DiGraph) + >>> print(forest_str(graph)) + └── 0 + ├── 2 + │   ├── 6 + │   │   ├── 14 + │   │   └── 13 + │   └── 5 + │   ├── 12 + │   └── 11 + └── 1 + ├── 4 + │   ├── 10 + │   └── 9 + └── 3 + ├── 8 + └── 7 + """ + printbuf = [] + if eager: + if write is None: + lazyprint = print + else: + lazyprint = write + else: + lazyprint = printbuf.append + + if len(graph.nodes) == 0: + lazyprint('') + else: + assert nx.is_forest(graph) + sources = [n for n in graph.nodes if graph.in_degree[n] == 0] + + stack = [] + for idx, node in enumerate(sources): + # islast_next = (idx == len(sources)) + islast_next = (idx == 0) + stack.append((node, '', islast_next)) + + while stack: + node, indent, islast = stack.pop() + if islast: + this_prefix = indent + '└── ' + next_prefix = indent + ' ' + else: + this_prefix = indent + '├── ' + next_prefix = indent + '│   ' + label = graph.nodes[node].get('label', node) + + lazyprint(this_prefix + str(label)) + graph.succ[node] + children = graph.succ[node] + for idx, child in enumerate(children, start=1): + # islast_next = (idx == len(children)) + islast_next = (idx <= 1) + try_frame = (child, next_prefix, islast_next) + stack.append(try_frame) + + if printbuf: + return '\n'.join(printbuf) + else: + return '' + + +if __name__ == '__main__': + """ + CommandLine: + python -m netharn.initializers._nx_ext.tree_embedding all + python -m netharn.initializers._nx_ext all + """ + import xdoctest + xdoctest.doctest_module(__file__) diff --git a/netharn/initializers/_nx_extensions.py b/netharn/initializers/_nx_extensions.py deleted file mode 100644 index e364ef8..0000000 --- a/netharn/initializers/_nx_extensions.py +++ /dev/null @@ -1,1004 +0,0 @@ -""" -EXPERIMENTAL : NEW WORK ON THIS IS HAPPENING IN NETWORKX ITSELF - -ONCE THAT IS DONE I WILL MODIFY THE ALGORITHMS HERE. -""" - -import operator -import ubelt as ub -import networkx as nx - -try: - import xdev - profile = xdev.profile -except Exception: - profile = ub.identity - - -# Cython gives a 40x speed boost in the nx version but not here -TRY_USE_CYTHON = 0 - - -@profile -def maximum_common_ordered_tree_embedding(tree1, tree2, node_affinity='auto'): - """ - Finds the maximum common subtree-embedding between two ordered trees. - - A tree S is an embedded subtree of T if it can be obtained from T by a - series of edge contractions. - - Note this produces a subtree embedding, which is not necessarilly a - subgraph isomorphism (although a subgraph isomorphism is also an - embedding.) - - The maximum common embedded subtree problem can be solved in in - `O(n1 * n2 * min(d1, l1) * min(d2, l2))` time on ordered trees with n1 and - n2 nodes, of depth d1 and d2 and with l1 and l2 leaves, respectively - - Implements algorithm described in [1]_. - - References: - On the Maximum Common Embedded Subtree Problem for Ordered Trees - https://pdfs.semanticscholar.org/0b6e/061af02353f7d9b887f9a378be70be64d165.pdf - - http://algo.inria.fr/flajolet/Publications/FlSiSt90.pdf - - Notes: - Exact algorithms for computing the tree edit distance between unordered trees - https://pdf.sciencedirectassets.com/271538/1-s2.0-S0304397510X00299/1-s2.0-S0304397510005463/main.pdf ? - - Tree Edit Distance and Common Subtrees - https://upcommons.upc.edu/bitstream/handle/2117/97554/R02-20.pdf - - A Survey on Tree Edit Distance and Related Problems - https://grfia.dlsi.ua.es/ml/algorithms/references/editsurvey_bille.pdf - - Args: - - tree1 (nx.OrderedDiGraph): first ordered tree - tree2 (nx.OrderedDiGraph): second ordered tree - node_affinity (callable): function - - Example: - >>> from netharn.initializers._nx_extensions import * # NOQA - >>> from netharn.initializers._nx_extensions import _lcs, _print_forest - >>> def random_ordered_tree(n, seed=None): - >>> tree = nx.dfs_tree(nx.random_tree(n, seed=seed)) - >>> otree = nx.OrderedDiGraph() - >>> otree.add_edges_from(tree.edges) - >>> return otree - >>> tree1 = random_ordered_tree(10, seed=1) - >>> tree2 = random_ordered_tree(10, seed=2) - >>> print('tree1') - >>> _print_forest(tree1) - >>> print('tree2') - >>> _print_forest(tree2) - - >>> embedding1, embedding2 = maximum_common_ordered_tree_embedding(tree1, tree2 ) - >>> print('embedding1') - >>> _print_forest(embedding1) - >>> print('embedding2') - >>> _print_forest(embedding2) - """ - if not (isinstance(tree1, nx.OrderedDiGraph) and nx.is_forest(tree1)): - raise nx.NetworkXNotImplemented('only implemented for directed ordered trees') - if not (isinstance(tree1, nx.OrderedDiGraph) and nx.is_forest(tree2)): - raise nx.NetworkXNotImplemented('only implemented for directed ordered trees') - - # Convert the trees to balanced sequences - sequence1, open_to_close, toks = tree_to_balanced_sequence(tree1, open_to_close=None, toks=None) - sequence2, open_to_close, toks = tree_to_balanced_sequence(tree2, open_to_close, toks) - seq1 = sequence1 - seq2 = sequence2 - - open_to_tok = ub.invert_dict(toks) - - # Solve the longest common balanced sequence problem - best, value = longest_common_balanced_sequence( - seq1, seq2, open_to_close, open_to_tok=open_to_tok, node_affinity=node_affinity) - subseq1, subseq2 = best - - # Convert the subsequence back into a tree - embedding1 = seq_to_tree(subseq1, open_to_close, toks) - embedding2 = seq_to_tree(subseq2, open_to_close, toks) - return embedding1, embedding2 - - -@profile -def maximum_common_ordered_subtree_isomorphism(tree1, tree2, node_affinity='auto'): - """ - Isomorphic version of `maximum_common_ordered_tree_embedding`. - - CommandLine: - xdoctest -m /home/joncrall/code/netharn/netharn/initializers/_nx_extensions.py maximum_common_ordered_subtree_isomorphism:1 --profile && cat profile_output.txt - - Ignore: - >>> from netharn.initializers._nx_extensions import * # NOQA - >>> from netharn.initializers._nx_extensions import _lcs, _print_forest - >>> def random_ordered_tree(n, seed=None): - >>> tree = nx.dfs_tree(nx.random_tree(n, seed=seed)) - >>> otree = nx.OrderedDiGraph() - >>> otree.add_edges_from(tree.edges) - >>> return otree - >>> tree1 = random_ordered_tree(10, seed=3) - >>> tree2 = random_ordered_tree(10, seed=2) - >>> tree1.add_edges_from(tree2.edges, weight=1) - >>> tree1 = nx.minimum_spanning_arborescence(tree1) - >>> tree2.add_edges_from(tree1.edges, weight=1) - >>> tree2 = nx.minimum_spanning_arborescence(tree2) - >>> tree1.remove_edge(4, 7) - >>> tree1.remove_edge(4, 9) - >>> tree1.add_edge(4, 10) - >>> tree1.add_edge(10, 7) - >>> tree1.add_edge(10, 9) - >>> #tree1.add_edges_from([(9, 11), (11, 12), (12, 13), (13, 14)]) - >>> #tree2.add_edges_from([(9, 11), (11, 12), (12, 13), (13, 14)]) - >>> tree1.add_edges_from([(9, 11), (11, 12)]) - >>> tree2.add_edges_from([(9, 11), (11, 12)]) - >>> tree2.add_edge(100, 0) - >>> tree1.add_edge(102, 100) - >>> tree1.add_edge(100, 101) - >>> tree1.add_edge(101, 0) - >>> tree1.add_edge(5, 201) - >>> tree1.add_edge(5, 202) - >>> tree1.add_edge(5, 203) - >>> tree1.add_edge(201, 2000) - >>> tree1.add_edge(2000, 2001) - >>> tree1.add_edge(2001, 2002) - >>> tree1.add_edge(2002, 2003) - >>> tree2.add_edge(5, 202) - >>> tree2.add_edge(5, 203) - >>> tree2.add_edge(5, 201) - >>> tree2.add_edge(201, 2000) - >>> tree2.add_edge(2000, 2001) - >>> tree2.add_edge(2001, 2002) - >>> tree2.add_edge(2002, 2003) - >>> print('-----') - >>> print('tree1') - >>> _print_forest(tree1) - >>> print('tree2') - >>> _print_forest(tree2) - >>> subtree1, subtree2 = maximum_common_ordered_subtree_isomorphism(tree1, tree2 ) - >>> print('-----') - >>> print('subtree1') - >>> _print_forest(subtree1) - >>> print('subtree2') - >>> _print_forest(subtree2) - >>> embedding1, embedding2 = maximum_common_ordered_tree_embedding(tree1, tree2) - >>> print('-----') - >>> print('embedding1') - >>> _print_forest(embedding1) - >>> print('embedding2') - >>> _print_forest(embedding2) - >>> if 0: - >>> ti = timerit.Timerit(6, bestof=2, verbose=2) - >>> for timer in ti.reset('isomorphism'): - >>> with timer: - >>> maximum_common_ordered_subtree_isomorphism(tree1, tree2 ) - >>> for timer in ti.reset('embedding'): - >>> with timer: - >>> maximum_common_ordered_tree_embedding(tree1, tree2 ) - >>> from networkx import isomorphism - >>> assert isomorphism.DiGraphMatcher(tree1, subtree1).subgraph_is_isomorphic() - >>> assert isomorphism.DiGraphMatcher(tree2, subtree2).subgraph_is_isomorphic() - >>> list(isomorphism.DiGraphMatcher(tree1, tree2).subgraph_isomorphisms_iter()) - >>> list(isomorphism.DiGraphMatcher(tree1, tree2).subgraph_monomorphisms_iter()) - >>> list(isomorphism.DiGraphMatcher(subtree1, subtree2).subgraph_isomorphisms_iter()) - >>> list(isomorphism.DiGraphMatcher(tree1, subtree1).subgraph_isomorphisms_iter()) - >>> list(isomorphism.DiGraphMatcher(tree2, subtree2).subgraph_isomorphisms_iter()) - - Ignore: - >>> from netharn.initializers._nx_extensions import * # NOQA - >>> from netharn.initializers._nx_extensions import _lcs, _print_forest - >>> def random_ordered_tree(n, seed=None): - >>> if n > 0: - >>> tree = nx.dfs_tree(nx.random_tree(n, seed=seed)) - >>> otree = nx.OrderedDiGraph() - >>> if n > 0: - >>> otree.add_edges_from(tree.edges) - >>> return otree - >>> import random - >>> rng = random.Random(90269698983701724775426457020022) - >>> num = 1000 - >>> def _gen_seeds(num): - >>> for _ in range(num): - >>> yield (rng.randint(0, 50), rng.randint(0, 50), rng.randint(0, 2 ** 64), rng.randint(0, 2 ** 64)) - >>> for n1, n2, s1, s2 in ub.ProgIter(_gen_seeds(num=num), total=num, verbose=3): - >>> tree1 = random_ordered_tree(n1, seed=s1) - >>> tree2 = random_ordered_tree(n2, seed=s2) - >>> #print('-----') - >>> #print('tree1') - >>> #_print_forest(tree1) - >>> #print('tree2') - >>> #_print_forest(tree2) - >>> subtree1, subtree2 = maximum_common_ordered_subtree_isomorphism(tree1, tree2, node_affinity='auto') - >>> #print('-----') - >>> #print('subtree1') - >>> #_print_forest(subtree1) - >>> #print('subtree2') - >>> #_print_forest(subtree2) - >>> from networkx import isomorphism - >>> assert isomorphism.DiGraphMatcher(tree1, subtree1).subgraph_is_isomorphic() - >>> assert isomorphism.DiGraphMatcher(tree2, subtree2).subgraph_is_isomorphic() - - """ - try: - if not (isinstance(tree1, nx.OrderedDiGraph) and nx.is_forest(tree1)): - raise nx.NetworkXNotImplemented('only implemented for directed ordered trees') - if not (isinstance(tree1, nx.OrderedDiGraph) and nx.is_forest(tree2)): - raise nx.NetworkXNotImplemented('only implemented for directed ordered trees') - except nx.NetworkXPointlessConcept: - subtree1 = nx.OrderedDiGraph() - subtree2 = nx.OrderedDiGraph() - return subtree1, subtree2 - - # Convert the trees to balanced sequences - sequence1, open_to_close, toks = tree_to_balanced_sequence(tree1, open_to_close=None, toks=None, mode='chr') - sequence2, open_to_close, toks = tree_to_balanced_sequence(tree2, open_to_close, toks, mode='chr') - seq1 = sequence1 - seq2 = sequence2 - - open_to_tok = ub.invert_dict(toks) - - # Solve the longest common balanced sequence problem - best, value = longest_common_isomorphic_sequence( - seq1, seq2, open_to_close, open_to_tok=open_to_tok, node_affinity=node_affinity) - subseq1, subseq2 = best - - # Convert the subsequence back into a tree - subtree1 = seq_to_tree(subseq1, open_to_close, toks) - subtree2 = seq_to_tree(subseq2, open_to_close, toks) - return subtree1, subtree2 - - -class UnbalancedException(Exception): - pass - - -def tree_to_balanced_sequence(tree, open_to_close=None, toks=None, mode='tuple'): - from collections import namedtuple - Token = namedtuple('Token', ['action', 'value']) - # mapping between opening and closing tokens - sources = [n for n in tree.nodes if tree.in_degree[n] == 0] - sequence = [] - - if open_to_close is None: - open_to_close = {} - if toks is None: - toks = {} - - for source in sources: - for u, v, etype in nx.dfs_labeled_edges(tree, source=source): - if etype == 'forward': - # u has been visited by v has not - if v not in toks: - if mode == 'tuple': - # TODO: token encoding scheme where subdirectories - # are matchable via a custom operation. - # open_tok = '<{}>'.format(v) - # close_tok = ''.format(v) - open_tok = Token('open', v) - close_tok = Token('close', v) - elif mode == 'number': - open_tok = len(toks) + 1 - close_tok = -open_tok - elif mode == 'paren': - open_tok = '{}('.format(v) - close_tok = '){}'.format(v) - elif mode == 'chr': - open_tok = str(v) - close_tok = str(v) + u'\u0301' - # chr(ord(v) + 128) - toks[v] = open_tok - open_to_close[open_tok] = close_tok - open_tok = toks[v] - sequence.append(open_tok) - elif etype == 'reverse': - # Both u and v are visited and the edge is in the tree - close_tok = open_to_close[toks[v]] - sequence.append(close_tok) - else: - raise KeyError(etype) - sequence = tuple(sequence) - return sequence, open_to_close, toks - - -def seq_to_tree(subseq, open_to_close, toks): - open_to_tok = ub.invert_dict(toks) - subtree = nx.OrderedDiGraph() - stack = [] - for token in subseq: - if token in open_to_close: - node = open_to_tok[token] - if stack: - parent = open_to_tok[stack[-1]] - subtree.add_edge(parent, node) - else: - subtree.add_node(node) - stack.append(token) - else: - if not stack: - raise Exception - prev_open = stack.pop() - want_close = open_to_close[prev_open] - if token != want_close: - raise Exception - return subtree - - -def random_ordered_tree(n, seed=None): - tree = nx.dfs_tree(nx.random_tree(n, seed=seed)) - otree = nx.OrderedDiGraph() - otree.add_edges_from(tree.edges) - return otree - - -@profile -def generate_balance_unsafe_python(sequence, open_to_close): - """ - Benchmark: - >>> tree = random_ordered_tree(1000) - >>> sequence, open_to_close, toks = tree_to_balanced_sequence(tree, mode='tuple') - >>> sequence, open_to_close, toks = tree_to_balanced_sequence(tree, mode='number') - >>> import timerit - >>> ti = timerit.Timerit(100, bestof=10, verbose=2) - >>> for timer in ti.reset('time'): - >>> with timer: - >>> list(generate_balance_unsafe(sequence, open_to_close)) - >>> import timerit - >>> ti = timerit.Timerit(100, bestof=10, verbose=2) - >>> for timer in ti.reset('time'): - >>> with timer: - >>> list(generate_balance_unsafe_cython(sequence, open_to_close)) - """ - stacklen = 0 - for token in sequence: - if token in open_to_close: - stacklen += 1 - else: - stacklen -= 1 - yield stacklen == 0, token - - -@profile -def balanced_decomp(sequence, open_to_close): - """ - Note this is not exactly the same as the decomposition in the paper. - That is because we also return the "wrapping" element, and we let the - user do the head + tail concatenation. - - Example: - >>> open_to_close = {0: 1} - >>> sequence = [0, 0, 0, 1, 1, 1, 0, 1] - >>> open_to_close = {'{': '}', '(': ')', '[': ']'} - >>> sequence = '({[[]]})[[][]]' - >>> a1, b1, head, tail = balanced_decomp(sequence, open_to_close) - >>> a2, b2, tail1, tail2 = balanced_decomp(tail, open_to_close) - """ - gen = generate_balance(sequence, open_to_close) - - bal_curr, tok_curr = next(gen) - pop_open = sequence[0:1] - want_close = open_to_close[tok_curr] - - head_stop = 1 - for head_stop, (bal_curr, tok_curr) in enumerate(gen, start=1): - if tok_curr is None: - break - elif bal_curr and tok_curr == want_close: - pop_close = sequence[head_stop:head_stop + 1] - break - head = sequence[1:head_stop] - # if __debug__: - # list(gen) # exhaust the generator to check we are balanced - tail = sequence[head_stop + 1:] - return pop_open, pop_close, head, tail - - -@profile -def balanced_decomp_unsafe(sequence, open_to_close): - """ - open_to_close = {0: 1} - sequence = [0, 0, 0, 1, 1, 1, 0, 1] - open_to_close = {'{': '}', '(': ')', '[': ']'} - sequence = '({[[]]})[[][]]' - a1, b1, head, tail = balanced_decomp(sequence, open_to_close) - a2, b2, tail1, tail2 = balanced_decomp(tail, open_to_close) - - Benchmark: - >>> from netharn.initializers._nx_extensions import * # NOQA - >>> tree = random_ordered_tree(100) - >>> sequence, open_to_close, toks = tree_to_balanced_sequence(tree) - >>> import timerit - >>> ti = timerit.Timerit(100, bestof=10, verbose=2, unit='us') - >>> for timer in ti.reset('safe-python'): - >>> with timer: - >>> list(balanced_decomp(sequence, open_to_close)) - >>> for timer in ti.reset('unsafe-python'): - >>> with timer: - >>> list(balanced_decomp_unsafe(sequence, open_to_close)) - >>> for timer in ti.reset('unsafe-python-v2'): - >>> with timer: - >>> list(balanced_decomp_unsafe2_python(sequence, open_to_close)) - >>> for timer in ti.reset('unsafe-c/python-v2'): - >>> with timer: - >>> list(balanced_decomp_unsafe2(sequence, open_to_close)) - """ - gen = generate_balance_unsafe(sequence, open_to_close) - - bal_curr, tok_curr = next(gen) - pop_open = sequence[0:1] - want_close = open_to_close[tok_curr] - - head_stop = 1 - for head_stop, (bal_curr, tok_curr) in enumerate(gen, start=1): - if bal_curr and tok_curr == want_close: - pop_close = sequence[head_stop:head_stop + 1] - break - head = sequence[1:head_stop] - tail = sequence[head_stop + 1:] - return pop_open, pop_close, head, tail - - -@profile -def balanced_decomp_unsafe2_python(sequence, open_to_close): - stacklen = 0 - seq_iter = iter(sequence) - tok_curr = next(seq_iter) - stacklen += 1 if tok_curr in open_to_close else -1 - want_close = open_to_close[tok_curr] - - head_stop = 1 - for head_stop, tok_curr in enumerate(seq_iter, start=1): - stacklen += 1 if tok_curr in open_to_close else -1 - if stacklen == 0 and tok_curr == want_close: - break - - pop_close = sequence[head_stop:head_stop + 1] - pop_open = sequence[0:1] - head = sequence[1:head_stop] - tail = sequence[head_stop + 1:] - return pop_open, pop_close, head, tail - - -generate_balance_unsafe = generate_balance_unsafe_python -balanced_decomp_unsafe2 = balanced_decomp_unsafe2_python - - -if TRY_USE_CYTHON: - try: - from netharn.initializers import _nx_extensions_cython_backend as cyb - - generate_balance_unsafe_cython = cyb.generate_balance_unsafe_cython - generate_balance_unsafe = cyb.generate_balance_unsafe_cython - - balanced_decomp_unsafe2_cython = cyb.balanced_decomp_unsafe2_cython - balanced_decomp_unsafe2 = cyb.balanced_decomp_unsafe2_cython - except Exception: - pass - - -def generate_balance(sequence, open_to_close, safe=True): - """ - Args: - safe (bool): if True we will error if the sequence is not balanced - if you are SURE the sequence is balanced set safe=False to slightly - improve runtime. - - - CommandLine: - xdoctest -m /home/joncrall/code/netharn/netharn/initializers/_nx_extensions.py generate_balance:1 --profile - - Example: - >>> open_to_close = {0: 1} - >>> sequence = [0, 0, 0, 1, 1, 1] - >>> gen = list(generate_balance(sequence, open_to_close)) - >>> for flag, token in gen: - >>> print('flag={:d}, token={}'.format(flag, token)) - - Example: - >>> tree = random_ordered_tree(1000) - >>> sequence, open_to_close, toks = tree_to_balanced_sequence(tree) - >>> gen = list(generate_balance(sequence, open_to_close)) - >>> for flag, token in gen: - >>> print('flag={:d}, token={}'.format(flag, token)) - - Benchmark: - >>> from netharn.initializers._nx_extensions import * # NOQA - >>> tree = random_ordered_tree(100) - >>> sequence, open_to_close, toks = tree_to_balanced_sequence(tree) - >>> import timerit - >>> ti = timerit.Timerit(100, bestof=10, verbose=2, unit='us') - >>> for timer in ti.reset('safe-python'): - >>> with timer: - >>> list(generate_balance(sequence, open_to_close)) - >>> for timer in ti.reset('unsafe-python'): - >>> with timer: - >>> list(generate_balance_unsafe(sequence, open_to_close)) - - Ignore: - from netharn.initializers._nx_extensions import * # NOQA - from numba import jit - jit_generate_balance = jit(forceobj=True)(generate_balance) - - open_to_close = {0: 1} - sequence = [0, 0, 0, 1, 1, 1] - list(jit_generate_balance(sequence, open_to_close)) - - tree = random_ordered_tree(1000) - sequence, open_to_close, toks = tree_to_balanced_sequence(tree) - - import timerit - ti = timerit.Timerit(100, bestof=10, verbose=2, unit='us') - - for timer in ti.reset('safe-python'): - with timer: - list(generate_balance(sequence, open_to_close)) - - for timer in ti.reset('unsafe-python'): - with timer: - list(generate_balance_unsafe(sequence, open_to_close)) - - for timer in ti.reset('numba'): - with timer: - list(jit_generate_balance(sequence, open_to_close)) - """ - if safe: - stack = [] - # Traversing the Expression - for token in sequence: - - if token in open_to_close: - # Push opening elements onto the stack - stack.append(token) - else: - # Check that closing elements - if not stack: - raise UnbalancedException - prev_open = stack.pop() - want_close = open_to_close[prev_open] - - if token != want_close: - raise UnbalancedException - - # If the stack is empty the sequence is currently balanced - currently_balanced = not bool(stack) - yield currently_balanced, token - - if stack: - raise UnbalancedException - else: - yield from generate_balance_unsafe(sequence, open_to_close) - - -@profile -def longest_common_balanced_sequence(seq1, seq2, open_to_close, node_affinity='auto', open_to_tok=None): - """ - CommandLine: - xdoctest -m /home/joncrall/code/netharn/netharn/initializers/_nx_extensions.py longest_common_balanced_sequence:0 --profile && cat profile_output.txt - - Example: - >>> tree1 = random_ordered_tree(100, seed=1) - >>> tree2 = random_ordered_tree(100, seed=2) - >>> seq1, open_to_close, toks = tree_to_balanced_sequence(tree1) - >>> seq2, open_to_close, toks = tree_to_balanced_sequence(tree2, open_to_close, toks) - >>> longest_common_balanced_sequence(seq1, seq2, open_to_close) - - Benchmark: - >>> tree1 = random_ordered_tree(20, seed=1) - >>> tree2 = random_ordered_tree(20, seed=2) - >>> seq1, open_to_close, toks = tree_to_balanced_sequence(tree1) - >>> seq2, open_to_close, toks = tree_to_balanced_sequence(tree2, open_to_close, toks) - >>> longest_common_balanced_sequence(seq1, seq2, open_to_close) - - import sys, ubelt - sys.path.append(ubelt.expandpath('~/code/netharn')) - from netharn.initializers._nx_extensions import * # NOQA - from netharn.initializers._nx_extensions import _best_prefix_transform, _lcs, _print_forest - - open_to_close = {'0': '1'} - seq1 = '0010010010111100001011011011' - seq2 = '001000101101110001000100101110111011' - - open_to_close = {'(': ')'} - seq1 = '(()(()(()())))(((()())())())' - seq2 = '(()((()())()))((()((()(()()))()))())' - longest_common_balanced_sequence(seq1, seq2, open_to_close) - - open_to_close = {'0': '1'} - seq1 = '0010010010111100001011011011' - seq2 = '001000101101110001000100101110111011' - longest_common_balanced_sequence(seq1, seq2, open_to_close) - - open_to_close = {'0': '1'} - seq1 = '001101' - seq2 = '00110011' - seq1 = '001101' - seq2 = '00110011' - longest_common_balanced_sequence(seq1, seq2, open_to_close) - - open_to_close = {'{': '}', '(': ')', '[': ']'} - seq1 = '(({}{([])}[{}]))' - seq2 = '((({}[{{}}])))' - - seq1 = '({[[[]]]}){}' - seq2 = '{}{[[[]]]}' - best, value = longest_common_balanced_sequence(seq1, seq2, open_to_close) - subseq1, subseq2 = best - print('subseq1 = {!r}'.format(subseq1)) - """ - if node_affinity == 'auto': - node_affinity = operator.eq - if node_affinity is None: - def _matchany(a, b): - return True - node_affinity = _matchany - _memo = {} - _seq_memo = {} - if open_to_tok is None: - class Dummy: - def __getitem__(self, key): - return key - open_to_tok = Dummy() - best, value = _lcs(seq1, seq2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo) - return best, value - - -@profile -def _lcs(seq1, seq2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo): - if not seq1: - return (seq1, seq1), 0 - elif not seq2: - return (seq2, seq2), 0 - else: - # if len(seq2) < len(seq1): - # seq1, seq2 = seq2, seq1 - # key = (seq1, seq2) - key1 = hash(seq1) # using hash(seq) is faster than seq itself - key2 = hash(seq2) - key = hash((key1, key2)) - if key in _memo: - return _memo[key] - - # TODO: we can probably just do a single linear run through the - # sequences to index the sub-sequence locations and then apply an - # offset when we run the decomposed sequence. - if key1 in _seq_memo: - a1, b1, head1, tail1, head1_tail1 = _seq_memo[key1] - else: - a1, b1, head1, tail1 = balanced_decomp_unsafe2(seq1, open_to_close) - head1_tail1 = head1 + tail1 - _seq_memo[key1] = a1, b1, head1, tail1, head1_tail1 - - if key2 in _seq_memo: - a2, b2, head2, tail2, head2_tail2 = _seq_memo[key2] - else: - a2, b2, head2, tail2 = balanced_decomp_unsafe2(seq2, open_to_close) - head2_tail2 = head2 + tail2 - _seq_memo[key2] = a2, b2, head2, tail2, head2_tail2 - - # Case 2: The current edge in sequence1 is deleted - best, val = _lcs(head1_tail1, seq2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo) - - # Case 3: The current edge in sequence2 is deleted - cand, val_alt = _lcs(seq1, head2_tail2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo) - if val_alt > val: - best = cand - val = val_alt - - # Case 1: The LCS involves this edge - t1 = open_to_tok[a1[0]] - t2 = open_to_tok[a2[0]] - # if node_affinity(a1[0], a2[0]): - affinity = node_affinity(t1, t2) - if affinity: - new_heads, pval_h = _lcs(head1, head2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo) - new_tails, pval_t = _lcs(tail1, tail2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo) - - new_head1, new_head2 = new_heads - new_tail1, new_tail2 = new_tails - - subseq1 = a1 + new_head1 + b1 + new_tail1 - subseq2 = a2 + new_head2 + b2 + new_tail2 - - cand = (subseq1, subseq2) - val_alt = pval_h + pval_t + affinity - if val_alt > val: - best = cand - val = val_alt - - found = (best, val) - _memo[key] = found - return found - - -@profile -def longest_common_isomorphic_sequence(seq1, seq2, open_to_close, node_affinity='auto', open_to_tok=None): - if node_affinity == 'auto': - node_affinity = operator.eq - if node_affinity is None: - def _matchany(a, b): - return True - node_affinity = _matchany - _memo = {} - _seq_memo = {} - if open_to_tok is None: - class Dummy: - def __getitem__(self, key): - return key - open_to_tok = Dummy() - best_lvl, value_lvl, best_low, value_low = _lcsi(seq1, seq2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo) - - if value_lvl > value_low: - best = best_lvl - value = value_lvl - else: - best = best_low - value = value_low - - return best, value - - -@profile -def _lcsi(seq1, seq2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo): - """ - Prototype isomorphic only version - """ - if not seq1: - return (seq1, seq1), 0, (seq1, seq1), 0 - elif not seq2: - return (seq2, seq2), 0, (seq2, seq2), 0 - else: - key1 = hash(seq1) - key2 = hash(seq2) - key = hash((key1, key2)) - if key in _memo: - return _memo[key] - - if key1 in _seq_memo: - a1, b1, head1, tail1, head1_tail1 = _seq_memo[key1] - else: - a1, b1, head1, tail1 = balanced_decomp_unsafe2(seq1, open_to_close) - head1_tail1 = head1 + tail1 - _seq_memo[key1] = a1, b1, head1, tail1, head1_tail1 - - if key2 in _seq_memo: - a2, b2, head2, tail2, head2_tail2 = _seq_memo[key2] - else: - a2, b2, head2, tail2 = balanced_decomp_unsafe2(seq2, open_to_close) - head2_tail2 = head2 + tail2 - _seq_memo[key2] = a2, b2, head2, tail2, head2_tail2 - - # TODO: IS THIS THE CORRECT MODIFICATION TO THE RECURRANCE TO - # ACHIEVE A SUBTREE ISOMORPHISM INSTEAD OF AN EMBEDDING? - r""" - - tree1 = nx.OrderedDiGraph() - tree1.add_nodes_from(['a', 'b', 'c', 'd', 'e', 'f', 'g']) - tree1.add_edges_from([('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'e'), ('b', 'f'), ('c', 'g')]) - - _print_forest(tree1) - - └── a - ├── b - │   ├── e - │   └── f - ├── c - │   └── g - └── d - - seq1, open_to_close, toks = tree_to_balanced_sequence(tree1, mode='chr') - a, b, head1, tail1 = balanced_decomp(seq1, open_to_close) - _print_forest(seq_to_tree(head1, open_to_close, toks)) - _print_forest(seq_to_tree(tail1, open_to_close, toks)) - - CONTRACTED NODE: - a - - HEAD (children of the contracted node) - - ├── b - │   ├── e - │   └── f - ├── c - │   └── g - └── d - - TAIL (right siblings of the contracted node) - -- - - a, b, head11, tail11 = balanced_decomp(head1, open_to_close) - _print_forest(seq_to_tree(head11, open_to_close, toks)) - _print_forest(seq_to_tree(tail11, open_to_close, toks)) - - CONTRACTED NODE: - b - - HEAD OF HEAD - ├── e - └── f - - TAIL OF HEAD - ├── c - │   └── g - └── d - - - The problem here is that if you are at a level where two levels down - there are two matches, you will return those two matches as the best - solution at that layer, and therefore you won't flag if there is a - feasible solution at this layer. This is a problem because that - feasible low-value solution might be part of the highest value - solution. - - Perhaps we return two solutions at each step: the solution value at - this level if one exists, and the solution value at any other depth. - We are allowed to add to the first, but can take the second if we want - to. - - This should work because we know a solution that skipped a layer will - never be added to, and we are always keeping track of the solution that - might change. By the time we get to the root level, we have enough info - to know which is better. - """ - - # If any of these cases are selected we are not choosing the leftmost - # node as our match - best_lvl, val_lvl, best_low, val_low = None, -1, None, -1 - - # TODO: it may be the case that some of these tests are redundant, in - # which case we could simplify and speed up the algorithm. We would - # need to prove that the value in one of these tests was always lower - # than the value in another one of these tests, in that case we could - # remove the former. - - # When using the head part of the decomp, we can only update the "low" candidate - cand_lvl, score_lvl, cand_low, score_low = _lcsi(head1, seq2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo) - if score_low > val_low: - val_low = score_low - best_low = cand_low - if score_lvl > val_low: - val_low = score_lvl - best_low = cand_lvl - - cand_lvl, score_lvl, cand_low, score_low = _lcsi(seq1, head2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo) - if score_low > val_low: - val_low = score_low - best_low = cand_low - if score_lvl > val_low: - val_low = score_lvl - best_low = cand_lvl - - # As long as we are only using the tail part of the decomp we can update - # both the lvl and low scores - cand_lvl, score_lvl, cand_low, score_low = _lcsi(tail1, seq2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo) - if score_lvl > val_lvl: - val_lvl = score_lvl - best_lvl = cand_lvl - if score_low > val_low: - val_low = score_low - best_low = cand_low - - cand_lvl, score_lvl, cand_low, score_low = _lcsi(seq1, tail2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo) - if score_lvl > val_lvl: - val_lvl = score_lvl - best_lvl = cand_lvl - if score_low > val_low: - val_low = score_low - best_low = cand_low - - # This is the case where we found a matching node - t1 = open_to_tok[a1[0]] - t2 = open_to_tok[a2[0]] - affinity = node_affinity(t1, t2) - if affinity: - - new_heads_lvl, pval_h_lvl, new_heads_low, pval_h_low = _lcsi(head1, head2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo) - new_tails_lvl, pval_t_lvl, new_tails_low, pval_t_low = _lcsi(tail1, tail2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo) - - # Add to the best solution at the former level - score_lvl = pval_h_lvl + pval_t_lvl + affinity - if score_lvl > val_lvl: - new_head1, new_head2 = new_heads_lvl - new_tail1, new_tail2 = new_tails_lvl - subseq1 = a1 + new_head1 + b1 + new_tail1 - subseq2 = a2 + new_head2 + b2 + new_tail2 - cand_lvl = (subseq1, subseq2) - val_lvl = score_lvl - best_lvl = cand_lvl - - # In my big tests these were never hit once, is it true that this - # test was covered by a previous case? - cand_low = new_heads_low - score_low = pval_h_low - if score_low > val_low: - val_low = score_low - best_low = cand_low - - cand_low = new_tails_low - score_low = pval_t_low - if score_low > val_low: - val_low = score_low - best_low = cand_low - - # We return two solutions: - # the best AT this level (lvl), and the best AT any lowers (low). - found = (best_lvl, val_lvl, best_low, val_low) - _memo[key] = found - return found - - -def _print_forest(graph): - """ - Nice ascii representation of a forest - - Ignore: - graph = nx.balanced_tree(r=2, h=3, create_using=nx.DiGraph) - _print_forest(graph) - - graph = CategoryTree.demo('coco').graph - _print_forest(graph) - """ - if len(graph.nodes) == 0: - print('--') - return - assert nx.is_forest(graph) - - def _recurse(node, indent='', islast=False): - if islast: - this_prefix = indent + '└── ' - next_prefix = indent + ' ' - else: - this_prefix = indent + '├── ' - next_prefix = indent + '│   ' - label = graph.nodes[node].get('label', node) - print(this_prefix + str(label)) - graph.succ[node] - children = graph.succ[node] - for idx, child in enumerate(children, start=1): - islast_next = (idx == len(children)) - _recurse(child, indent=next_prefix, islast=islast_next) - - sources = [n for n in graph.nodes if graph.in_degree[n] == 0] - for idx, node in enumerate(sources, start=1): - islast_next = (idx == len(sources)) - _recurse(node, indent='', islast=islast_next) - - -def maximum_common_ordered_paths(paths1, paths2, sep='/'): - import networkx as nx - - # the longest common balanced sequence problem - def _affinity(tok1, tok2): - score = 0 - for t1, t2 in zip(tok1[::-1], tok2[::-1]): - if t1 == t2: - score += 1 - else: - break - return score - # return tok1[-1] == tok2[-1] - node_affinity = _affinity - # import operator - # eq = operator.eq - - def paths_to_tree(paths): - tree = nx.OrderedDiGraph() - for path in sorted(paths): - parts = tuple(path.split(sep)) - node_path = [] - for i in range(1, len(parts) + 1): - node = parts[0:i] - tree.add_node(node) - tree.nodes[node]['label'] = node[-1] - node_path.append(node) - for u, v in ub.iter_window(node_path, 2): - tree.add_edge(u, v) - return tree - - tree1 = paths_to_tree(paths1) - tree2 = paths_to_tree(paths2) - - subtree1, subtree2 = maximum_common_ordered_tree_embedding(tree1, tree2, node_affinity=node_affinity) - # subtree1, subtree2 = maximum_common_ordered_subtree_isomorphism(tree1, tree2, node_affinity=node_affinity) - - subpaths1 = [sep.join(node) for node in subtree1.nodes if subtree1.out_degree[node] == 0] - subpaths2 = [sep.join(node) for node in subtree2.nodes if subtree2.out_degree[node] == 0] - return subpaths1, subpaths2 diff --git a/netharn/initializers/_nx_extensions_cython_backend.pyx b/netharn/initializers/_nx_extensions_cython_backend.pyx deleted file mode 100644 index c3d312e..0000000 --- a/netharn/initializers/_nx_extensions_cython_backend.pyx +++ /dev/null @@ -1,46 +0,0 @@ -""" -cythonize -a -i ~/code/netharn/netharn/initializers/_nx_extensions_cython_backend.pyx - - >>> from netharn.initializers import _nx_extensions_cython_backend - >>> import timerit - >>> ti = timerit.Timerit(100, bestof=10, verbose=2) - >>> for timer in ti.reset('time'): - >>> with timer: - >>> list(_nx_extensions_cython_backend.generate_balance_unsafe_cython(sequence, open_to_close)) - -""" - -def generate_balance_unsafe_cython(sequence, open_to_close): - cdef tuple item - cdef bint flag - cdef int stacklen = 0 - for token in sequence: - if token in open_to_close: - stacklen += 1 - else: - stacklen -= 1 - flag = stacklen == 0 - item = (flag, token) - yield item - - -def balanced_decomp_unsafe2_cython(tuple sequence, dict open_to_close): - cdef int stacklen = 1 # always +1 in the first iteration - cdef int head_stop = 1 - - tok_curr = sequence[0] - want_close = open_to_close[tok_curr] - - # for tok_curr in sequence[1:]: - for head_stop in range(1, len(sequence)): - tok_curr = sequence[head_stop] - stacklen += 1 if tok_curr in open_to_close else -1 - if stacklen == 0 and tok_curr == want_close: - pop_close = sequence[head_stop:head_stop + 1] - break - - pop_open = sequence[0:1] - head = sequence[1:head_stop] - tail = sequence[head_stop + 1:] - return pop_open, pop_close, head, tail - diff --git a/netharn/initializers/balanced_sequence.py b/netharn/initializers/balanced_sequence.py deleted file mode 100644 index 13d5db1..0000000 --- a/netharn/initializers/balanced_sequence.py +++ /dev/null @@ -1,969 +0,0 @@ -import operator -import ubelt as ub -import networkx as nx - -try: - import xdev - profile = xdev.profile -except Exception: - profile = ub.identity - - -# @profile -def longest_common_balanced_sequence(seq1, seq2, open_to_close, open_to_tok=None, node_affinity='auto', impl='iter'): - """ - CommandLine: - xdoctest -m /home/joncrall/code/netharn/netharn/initializers/balanced_sequence.py longest_common_balanced_sequence:0 --profile && cat profile_output.txt - - Example: - >>> from netharn.initializers.balanced_sequence import * # NOQA - >>> from netharn.initializers.balanced_sequence import _lcs_iter_prehash, _lcs_iter_simple, _lcs_recurse, _print_forest - >>> tree1 = random_ordered_tree(5, seed=10, pool='[{(') - >>> tree2 = random_ordered_tree(5, seed=3, pool='[{(') - - >>> import kwarray - >>> rng = kwarray.ensure_rng(3432432, 'python') - >>> tree1 = random_ordered_tree(100, seed=rng, pool='[{(') - >>> tree2 = random_ordered_tree(100, seed=rng, pool='[{(') - >>> if len(tree1.nodes) < 20: - >>> _print_forest(tree1) - >>> _print_forest(tree2) - >>> seq1, open_to_close, toks = tree_to_balanced_sequence(tree1, mode='label', strhack=1) - >>> seq2, open_to_close, toks = tree_to_balanced_sequence(tree2, open_to_close, toks, mode='label', strhack=1) - >>> full_seq1 = seq1 - >>> full_seq2 = seq2 - >>> print('seq1 = {!r}'.format(seq1)) - >>> print('seq2 = {!r}'.format(seq2)) - >>> open_to_tok = ub.invert_dict(toks) - >>> node_affinity = operator.eq - >>> with ub.Timer('iterative-alt2'): - >>> best1, val1 = longest_common_balanced_sequence(seq1, seq2, open_to_close, open_to_tok, impl='iter-alt2') - >>> print('val1, best1 = {}, {!r}'.format(val1, best1)) - >>> with ub.Timer('iterative-alt1'): - >>> best1, val1 = longest_common_balanced_sequence(seq1, seq2, open_to_close, open_to_tok, impl='iter-alt1') - >>> print('val1, best1 = {}, {!r}'.format(val1, best1)) - >>> with ub.Timer('iterative'): - >>> best1, val1 = longest_common_balanced_sequence(seq1, seq2, open_to_close, open_to_tok, impl='iter') - >>> print('val1, best1 = {}, {!r}'.format(val1, best1)) - >>> with ub.Timer('recursive'): - >>> best2, val2 = longest_common_balanced_sequence(seq1, seq2, open_to_close, open_to_tok, impl='recurse') - >>> print('val2, best2 = {}, {!r}'.format(val2, best2)) - >>> #with ub.Timer('iterative-prehash'): - >>> # best1, val1 = longest_common_balanced_sequence(seq1, seq2, open_to_close, open_to_tok, impl='iter-prehash') - >>> # print('val1, best1 = {}, {!r}'.format(val1, best1)) - """ - if node_affinity == 'auto' or node_affinity == 'eq': - node_affinity = operator.eq - if node_affinity is None: - def _matchany(a, b): - return True - node_affinity = _matchany - _memo = {} - _seq_memo = {} - if open_to_tok is None: - class Dummy: - def __getitem__(self, key): - return key - open_to_tok = Dummy() - full_seq1 = seq1 - full_seq2 = seq2 - if impl == 'recurse': - best, value = _lcs_recurse(full_seq1, full_seq2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo) - elif impl == 'iter': - best, value = _lcs_iter_simple(full_seq1, full_seq2, open_to_close, node_affinity, open_to_tok) - elif impl == 'iter-prehash': - best, value = _lcs_iter_prehash(full_seq1, full_seq2, open_to_close, node_affinity, open_to_tok) - elif impl == 'iter-alt1': - best, value = _lcs_iter_simple_alt1(full_seq1, full_seq2, open_to_close, node_affinity, open_to_tok) - elif impl == 'iter-alt2': - best, value = _lcs_iter_simple_alt2(full_seq1, full_seq2, open_to_close, node_affinity, open_to_tok) - else: - raise KeyError(impl) - return best, value - - -@profile -def _lcs_iter_simple(full_seq1, full_seq2, open_to_close, node_affinity, open_to_tok): - """ - Converts _lcs_recursive to an iterative algorithm using a fairly - straightforward method that effectivly simulates callstacks - """ - all_decomp1 = generate_all_decompositions(full_seq1, open_to_close, open_to_tok) - all_decomp2 = generate_all_decompositions(full_seq2, open_to_close, open_to_tok) - - args0 = (full_seq1, full_seq2) - frame0 = args0 - stack = [frame0] - - _results = {} - # Populate base cases - empty1 = type(ub.peek(all_decomp1.keys()))() - empty2 = type(ub.peek(all_decomp2.keys()))() - best = (empty1, empty2) - base_result = (0, best) - for seq1 in all_decomp1.keys(): - key1 = seq1 - t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[key1] - _results[(seq1, empty2)] = base_result - _results[(head1, empty2)] = base_result - _results[(tail1, empty2)] = base_result - _results[(head_tail1, empty2)] = base_result - - for seq2 in all_decomp2.keys(): - key2 = seq2 - t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[key2] - _results[(empty1, seq2)] = base_result - _results[(empty1, head2)] = base_result - _results[(empty1, tail2)] = base_result - _results[(empty1, head_tail2)] = base_result - - del args0 - del frame0 - del empty1 - del empty2 - del best - del base_result - - missing_frames = [] - while stack: - key = stack.pop() - if key not in _results: - seq1, seq2 = key - missing_frames.clear() - - # try: - t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[seq1] - # except KeyError: - # a1, b1, head1, tail1 = balanced_decomp_unsafe(seq1, open_to_close) - # head_tail1 = head1 + tail1 - # all_decomp1[seq1] = a1, b1, head1, tail1, head_tail1 - - # try: - t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[seq2] - # except KeyError: - # a2, b2, head2, tail2 = balanced_decomp_unsafe(seq2, open_to_close) - # head_tail2 = head2 + tail2 - # all_decomp2[seq2] = a2, b2, head2, tail2, head_tail2 - - # Case 2: The current edge in sequence1 is deleted - try: - try_key = (head_tail1, seq2) - cand1 = _results[try_key] - except KeyError: - missing_frames.append(try_key) - - # Case 3: The current edge in sequence2 is deleted - try: - try_key = (seq1, head_tail2) - cand2 = _results[try_key] - except KeyError: - missing_frames.append(try_key) - - # Case 1: The LCS involves this edge - affinity = node_affinity(t1, t2) - if affinity: - try: - try_key = (head1, head2) - pval_h, new_heads = _results[try_key] - except KeyError: - missing_frames.append(try_key) - - try: - try_key = (tail1, tail2) - pval_t, new_tails = _results[try_key] - except KeyError: - missing_frames.append(try_key) - - if not missing_frames: - new_head1, new_head2 = new_heads - new_tail1, new_tail2 = new_tails - - subseq1 = a1 + new_head1 + b1 + new_tail1 - subseq2 = a2 + new_head2 + b2 + new_tail2 - - res3 = (subseq1, subseq2) - val3 = pval_h + pval_t + affinity - cand3 = (val3, res3) - else: - cand3 = (-1, None) - - if missing_frames: - # We did not solve this frame yet - stack.append(key) - stack.extend(missing_frames) - # stack.extend(missing_frames[::-1]) - else: - # We solved the frame - _results[key] = max(cand1, cand2, cand3) - - val, best = _results[key] - found = (best, val) - return found - - -@profile -def _lcs_iter_simple_alt1(full_seq1, full_seq2, open_to_close, node_affinity, open_to_tok): - """ - Depth first stack trajectory - """ - all_decomp1 = generate_all_decompositions(full_seq1, open_to_close, open_to_tok) - all_decomp2 = generate_all_decompositions(full_seq2, open_to_close, open_to_tok) - - args0 = (full_seq1, full_seq2) - frame0 = args0 - stack = [frame0] - - _results = {} - # Populate base cases - empty1 = type(ub.peek(all_decomp1.keys()))() - empty2 = type(ub.peek(all_decomp2.keys()))() - best = (empty1, empty2) - base_result = (0, best) - for seq1 in all_decomp1.keys(): - key1 = seq1 - t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[key1] - _results[(seq1, empty2)] = base_result - _results[(head1, empty2)] = base_result - _results[(tail1, empty2)] = base_result - _results[(head_tail1, empty2)] = base_result - - for seq2 in all_decomp2.keys(): - key2 = seq2 - t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[key2] - _results[(empty1, seq2)] = base_result - _results[(empty1, head2)] = base_result - _results[(empty1, tail2)] = base_result - _results[(empty1, head_tail2)] = base_result - - del args0 - del frame0 - del empty1 - del empty2 - del best - del base_result - - while stack: - key = stack.pop() - if key not in _results: - seq1, seq2 = key - - t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[seq1] - - t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[seq2] - - # Case 2: The current edge in sequence1 is deleted - try: - try_key = (head_tail1, seq2) - cand1 = _results[try_key] - except KeyError: - stack.append(key) - stack.append(try_key) - continue - - # Case 3: The current edge in sequence2 is deleted - try: - try_key = (seq1, head_tail2) - cand2 = _results[try_key] - except KeyError: - stack.append(key) - stack.append(try_key) - continue - - # Case 1: The LCS involves this edge - affinity = node_affinity(t1, t2) - if affinity: - try: - try_key = (head1, head2) - pval_h, new_heads = _results[try_key] - except KeyError: - stack.append(key) - stack.append(try_key) - continue - - try: - try_key = (tail1, tail2) - pval_t, new_tails = _results[try_key] - except KeyError: - stack.append(key) - stack.append(try_key) - continue - - new_head1, new_head2 = new_heads - new_tail1, new_tail2 = new_tails - - subseq1 = a1 + new_head1 + b1 + new_tail1 - subseq2 = a2 + new_head2 + b2 + new_tail2 - - res3 = (subseq1, subseq2) - val3 = pval_h + pval_t + affinity - cand3 = (val3, res3) - else: - cand3 = (-1, None) - - # We solved the frame - _results[key] = max(cand1, cand2, cand3) - - val, best = _results[key] - found = (best, val) - return found - - -@profile -def _lcs_iter_simple_alt2(full_seq1, full_seq2, open_to_close, node_affinity, open_to_tok): - """ - Depth first stack trajectory and replace try except statements with ifs - """ - all_decomp1 = generate_all_decompositions(full_seq1, open_to_close, open_to_tok) - all_decomp2 = generate_all_decompositions(full_seq2, open_to_close, open_to_tok) - - key0 = (full_seq1, full_seq2) - frame0 = key0 - stack = [frame0] - - _results = {} - # Populate base cases - empty1 = type(ub.peek(all_decomp1.keys()))() - empty2 = type(ub.peek(all_decomp2.keys()))() - best = (empty1, empty2) - base_result = (0, best) - for seq1 in all_decomp1.keys(): - key1 = seq1 - t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[key1] - _results[(seq1, empty2)] = base_result - _results[(head1, empty2)] = base_result - _results[(tail1, empty2)] = base_result - _results[(head_tail1, empty2)] = base_result - - for seq2 in all_decomp2.keys(): - key2 = seq2 - t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[key2] - _results[(empty1, seq2)] = base_result - _results[(empty1, head2)] = base_result - _results[(empty1, tail2)] = base_result - _results[(empty1, head_tail2)] = base_result - - del frame0 - del empty1 - del empty2 - del best - del base_result - - while stack: - key = stack[-1] - if key not in _results: - seq1, seq2 = key - - t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[seq1] - t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[seq2] - - # Case 2: The current edge in sequence1 is deleted - try_key = (head_tail1, seq2) - if try_key in _results: - cand1 = _results[try_key] - else: - # stack.append(key) - stack.append(try_key) - continue - - # Case 3: The current edge in sequence2 is deleted - try_key = (seq1, head_tail2) - if try_key in _results: - cand2 = _results[try_key] - else: - # stack.append(key) - stack.append(try_key) - continue - - # Case 1: The LCS involves this edge - affinity = node_affinity(t1, t2) - if affinity: - try_key = (head1, head2) - if try_key in _results: - pval_h, new_heads = _results[try_key] - else: - # stack.append(key) - stack.append(try_key) - continue - - try_key = (tail1, tail2) - if try_key in _results: - pval_t, new_tails = _results[try_key] - else: - # stack.append(key) - stack.append(try_key) - continue - - new_head1, new_head2 = new_heads - new_tail1, new_tail2 = new_tails - - subseq1 = a1 + new_head1 + b1 + new_tail1 - subseq2 = a2 + new_head2 + b2 + new_tail2 - - res3 = (subseq1, subseq2) - val3 = pval_h + pval_t + affinity - cand3 = (val3, res3) - else: - cand3 = (-1, None) - - # We solved the frame - _results[key] = max(cand1, cand2, cand3) - stack.pop() - - val, best = _results[key0] - found = (best, val) - return found - - -@profile -def _lcs_iter_prehash(full_seq1, full_seq2, open_to_close, node_affinity, open_to_tok): - """ - Version of the lcs iterative algorithm where we precompute hash values - - This is actually slower than the simple version - """ - def decomp_info(seq, open_to_close): - pop_open, pop_close, head, tail = balanced_decomp_unsafe(seq, open_to_close) - head_tail = head + tail - head_key = hash(head) - tail_key = hash(tail) - head_tail_key = hash(head_tail) - tok = open_to_tok[pop_open[0]] - a = pop_open - b = pop_close - info = (tok, seq, head, tail, head_tail, head_key, tail_key, head_tail_key, a, b) - return info - - def gen_decomp_v2(seq, open_to_close): - _genmemo = {} - def _gen(seq): - if seq: - key = hash(seq) - if key not in _genmemo: - info = decomp_info(seq, open_to_close) - head, tail, head_tail = info[2:5] - _genmemo[key] = info - yield (seq, _genmemo[key]) - yield from _gen(head_tail) - yield from _gen(head) - yield from _gen(tail) - all_decomp = dict(_gen(seq)) - return all_decomp - - all_decomp1 = gen_decomp_v2(full_seq1, open_to_close) - all_decomp2 = gen_decomp_v2(full_seq2, open_to_close) - - key_decomp1 = {} - key_decomp2 = {} - _results = {} - # Populate base cases - empty1 = type(ub.peek(all_decomp1.keys()))() - empty2 = type(ub.peek(all_decomp2.keys()))() - empty1_key = hash(empty1) - empty2_key = hash(empty2) - best = (empty1, empty2) - base_result = (0, best) - for seq1, info1 in all_decomp1.items(): - seq1_key = hash(seq1) - head1_key, tail1_key, head_tail1_key = all_decomp1[seq1][5:8] - _results[(seq1_key, empty2_key)] = base_result - _results[(head1_key, empty2_key)] = base_result - _results[(tail1_key, empty2_key)] = base_result - _results[(head_tail1_key, empty2_key)] = base_result - key_decomp1[seq1_key] = info1 - - for seq2, info2 in all_decomp2.items(): - seq2_key = hash(seq2) - head2_key, tail2_key, head_tail2_key = all_decomp2[seq2][5:8] - _results[(empty1_key, seq2_key)] = base_result - _results[(empty1_key, head2_key)] = base_result - _results[(empty1_key, tail2_key)] = base_result - _results[(empty1_key, head_tail2_key)] = base_result - key_decomp2[seq2_key] = info2 - - full_seq1_key = hash(full_seq1) - full_seq2_key = hash(full_seq2) - key0 = (full_seq1_key, full_seq2_key) - frame0 = key0, full_seq1, full_seq2 - stack = [frame0] - missing_frames = [] - while stack: - frame = stack.pop() - key, seq1, seq2 = frame - seq1_key, seq2_key = key - if key not in _results: - missing_frames.clear() - - try: - info1 = key_decomp1[seq1_key] - except KeyError: - info1 = decomp_info(seq1, open_to_close) - key_decomp1[seq1_key] = info1 - tok1, seq1, head1, tail1, head_tail1, head1_key, tail1_key, head_tail1_key, a1, b1 = info1 - - try: - info2 = key_decomp2[seq2_key] - except KeyError: - info2 = decomp_info(seq2, open_to_close) - key_decomp2[seq2_key] = info2 - tok2, seq2, head2, tail2, head_tail2, head2_key, tail2_key, head_tail2_key, a2, b2 = info2 - - affinity = node_affinity(tok1, tok2) - - # Case 2: The current edge in sequence1 is deleted - try: - try_key = (head_tail1_key, seq2_key) - cand1 = _results[try_key] - except KeyError: - miss_frame = try_key, head_tail1, seq2 - missing_frames.append(miss_frame) - - # Case 3: The current edge in sequence2 is deleted - try: - try_key = (seq1_key, head_tail2_key) - cand2 = _results[try_key] - except KeyError: - miss_frame = try_key, seq1, head_tail2 - missing_frames.append(miss_frame) - - # Case 1: The LCS involves this edge - if affinity: - try: - try_key = (head1_key, head2_key) - pval_h, new_heads = _results[try_key] - except KeyError: - miss_frame = try_key, head1, head2 - missing_frames.append(miss_frame) - - try: - try_key = (tail1_key, tail2_key) - pval_t, new_tails = _results[try_key] - except KeyError: - miss_frame = try_key, tail1, tail2 - missing_frames.append(miss_frame) - - if not missing_frames: - new_head1, new_head2 = new_heads - new_tail1, new_tail2 = new_tails - - subseq1 = a1 + new_head1 + b1 + new_tail1 - subseq2 = a2 + new_head2 + b2 + new_tail2 - - res3 = (subseq1, subseq2) - val3 = pval_h + pval_t + affinity - cand3 = (val3, res3) - else: - cand3 = (-1, None) - - if missing_frames: - # We did not solve this frame yet - stack.append(frame) - stack.extend(missing_frames[::-1]) - else: - # We solved the frame - _results[key] = max(cand1, cand2, cand3) - - # The stack pop is our solution - (val, best) = _results[key] - found = (best, val) - return found - - -def generate_all_decompositions(seq, open_to_close, open_to_tok=None): - """ - Can doing this a-priori speed up the algorithm? - - open_to_close = {0: 1} - sequence = [0, 0, 0, 1, 1, 1, 0, 1] - open_to_close = {'{': '}', '(': ')', '[': ']'} - seq = '({[[]]})[[][]]{{}}' - pop_open, pop_close, head, tail = balanced_decomp(seq, open_to_close) - - >>> tree = random_ordered_tree(10) - >>> seq, open_to_close, toks = tree_to_balanced_sequence(tree) - >>> all_decomp = generate_all_decompositions(seq, open_to_close) - """ - if open_to_tok is None: - class Dummy: - def __getitem__(self, key): - return key - open_to_tok = Dummy() - _memo = {} - def _gen(seq): - if not seq: - pass - # yield None - elif seq in _memo: - pass - # yield (seq, _memo[seq]) - else: - pop_open, pop_close, head, tail = balanced_decomp(seq, open_to_close) - head_tail = head + tail - tok = open_to_tok[pop_open[0]] - _memo[seq] = (tok, pop_open, pop_close, head, tail, head_tail) - yield (seq, _memo[seq]) - yield from _gen(head_tail) - yield from _gen(head) - yield from _gen(tail) - all_decomp = dict(_gen(seq)) - return all_decomp - - -@profile -def _lcs_recurse(seq1, seq2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo): - if not seq1: - return (seq1, seq1), 0 - elif not seq2: - return (seq2, seq2), 0 - else: - # if len(seq2) < len(seq1): - # seq1, seq2 = seq2, seq1 - # key = (seq1, seq2) - key1 = hash(seq1) # using hash(seq) is faster than seq itself - key2 = hash(seq2) - key = hash((key1, key2)) - if key in _memo: - return _memo[key] - - # TODO: we can probably just do a single linear run through the - # sequences to index the sub-sequence locations and then apply an - # offset when we run the decomposed sequence. - if key1 in _seq_memo: - a1, b1, head1, tail1, head1_tail1 = _seq_memo[key1] - else: - a1, b1, head1, tail1 = balanced_decomp_unsafe(seq1, open_to_close) - head1_tail1 = head1 + tail1 - _seq_memo[key1] = a1, b1, head1, tail1, head1_tail1 - - if key2 in _seq_memo: - a2, b2, head2, tail2, head2_tail2 = _seq_memo[key2] - else: - a2, b2, head2, tail2 = balanced_decomp_unsafe(seq2, open_to_close) - head2_tail2 = head2 + tail2 - _seq_memo[key2] = a2, b2, head2, tail2, head2_tail2 - - # Case 2: The current edge in sequence1 is deleted - best, val = _lcs_recurse(head1_tail1, seq2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo) - - # Case 3: The current edge in sequence2 is deleted - cand, val_alt = _lcs_recurse(seq1, head2_tail2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo) - if val_alt > val: - best = cand - val = val_alt - - # Case 1: The LCS involves this edge - t1 = open_to_tok[a1[0]] - t2 = open_to_tok[a2[0]] - # if node_affinity(a1[0], a2[0]): - affinity = node_affinity(t1, t2) - if affinity: - new_heads, pval_h = _lcs_recurse(head1, head2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo) - new_tails, pval_t = _lcs_recurse(tail1, tail2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo) - - new_head1, new_head2 = new_heads - new_tail1, new_tail2 = new_tails - - subseq1 = a1 + new_head1 + b1 + new_tail1 - subseq2 = a2 + new_head2 + b2 + new_tail2 - - cand = (subseq1, subseq2) - val_alt = pval_h + pval_t + affinity - if val_alt > val: - best = cand - val = val_alt - - found = (best, val) - _memo[key] = found - return found - - -class UnbalancedException(Exception): - pass - - -def balanced_decomp(sequence, open_to_close): - """ - Note this is not exactly the same as the decomposition in the paper. - That is because we also return the "wrapping" element, and we let the - user do the head + tail concatenation. - - Example: - >>> open_to_close = {0: 1} - >>> sequence = [0, 0, 0, 1, 1, 1, 0, 1] - >>> open_to_close = {'{': '}', '(': ')', '[': ']'} - >>> sequence = '({[[]]})[[][]]' - >>> a1, b1, head, tail = balanced_decomp(sequence, open_to_close) - >>> a2, b2, tail1, tail2 = balanced_decomp(tail, open_to_close) - """ - gen = generate_balance(sequence, open_to_close) - - bal_curr, tok_curr = next(gen) - pop_open = sequence[0:1] - want_close = open_to_close[tok_curr] - - head_stop = 1 - for head_stop, (bal_curr, tok_curr) in enumerate(gen, start=1): - if tok_curr is None: - break - elif bal_curr and tok_curr == want_close: - pop_close = sequence[head_stop:head_stop + 1] - break - head = sequence[1:head_stop] - # if __debug__: - # list(gen) # exhaust the generator to check we are balanced - tail = sequence[head_stop + 1:] - return pop_open, pop_close, head, tail - - -def tree_to_balanced_sequence(tree, open_to_close=None, toks=None, mode='tuple', strhack=False): - from collections import namedtuple - Token = namedtuple('Token', ['action', 'value']) - # mapping between opening and closing tokens - sources = [n for n in tree.nodes if tree.in_degree[n] == 0] - sequence = [] - - if open_to_close is None: - open_to_close = {} - if toks is None: - toks = {} - - if strhack: - if mode == 'label': - all_labels = {n['label'] for n in list(tree.nodes.values())} - assert all(x == 1 for x in map(len, all_labels)) - - for source in sources: - for u, v, etype in nx.dfs_labeled_edges(tree, source=source): - if etype == 'forward': - # u has been visited by v has not - if v not in toks: - if mode == 'tuple': - # TODO: token encoding scheme where subdirectories - # are matchable via a custom operation. - # open_tok = '<{}>'.format(v) - # close_tok = ''.format(v) - open_tok = Token('open', v) - close_tok = Token('close', v) - elif mode == 'number': - open_tok = len(toks) + 1 - close_tok = -open_tok - elif mode == 'paren': - open_tok = '{}('.format(v) - close_tok = '){}'.format(v) - elif mode == 'chr': - open_tok = str(v) - close_tok = str(v) + u'\u0301' - elif mode == 'label': - open_tok = tree.nodes[v]['label'] - assert strhack - if open_tok == '{': - close_tok = '}' - if open_tok == '[': - close_tok = ']' - if open_tok == '(': - close_tok = ')' - toks[v] = open_tok - open_to_close[open_tok] = close_tok - open_tok = toks[v] - sequence.append(open_tok) - elif etype == 'reverse': - # Both u and v are visited and the edge is in the tree - close_tok = open_to_close[toks[v]] - sequence.append(close_tok) - else: - raise KeyError(etype) - sequence = tuple(sequence) - if strhack: - sequence = ''.join(sequence) - return sequence, open_to_close, toks - - -def seq_to_tree(subseq, open_to_close, toks): - open_to_tok = ub.invert_dict(toks) - subtree = nx.OrderedDiGraph() - stack = [] - for token in subseq: - if token in open_to_close: - node = open_to_tok[token] - if stack: - parent = open_to_tok[stack[-1]] - subtree.add_edge(parent, node) - else: - subtree.add_node(node) - stack.append(token) - else: - if not stack: - raise Exception - prev_open = stack.pop() - want_close = open_to_close[prev_open] - if token != want_close: - raise Exception - return subtree - - -def random_ordered_tree(n, seed=None, pool=None): - import kwarray - rng = kwarray.ensure_rng(seed, 'python') - tree = nx.dfs_tree(nx.random_tree(n, seed=seed)) - otree = nx.OrderedDiGraph() - otree.add_edges_from(tree.edges) - if pool is not None: - for node in otree.nodes: - otree.nodes[node]['label'] = rng.choice(pool) - return otree - - -def generate_balance_unsafe(sequence, open_to_close): - """ - Benchmark: - >>> tree = random_ordered_tree(1000) - >>> sequence, open_to_close, toks = tree_to_balanced_sequence(tree, mode='tuple') - >>> sequence, open_to_close, toks = tree_to_balanced_sequence(tree, mode='number') - >>> import timerit - >>> ti = timerit.Timerit(100, bestof=10, verbose=2) - >>> for timer in ti.reset('time'): - >>> with timer: - >>> list(generate_balance_unsafe(sequence, open_to_close)) - >>> import timerit - >>> ti = timerit.Timerit(100, bestof=10, verbose=2) - >>> for timer in ti.reset('time'): - >>> with timer: - >>> list(generate_balance_unsafe_cython(sequence, open_to_close)) - """ - stacklen = 0 - for token in sequence: - if token in open_to_close: - stacklen += 1 - else: - stacklen -= 1 - yield stacklen == 0, token - - -def balanced_decomp_unsafe(sequence, open_to_close): - """ - Example: - >>> open_to_close = {'{': '}', '(': ')', '[': ']'} - >>> sequence = '({[[]]})[[][]]' - >>> print('sequence = {!r}'.format(sequence)) - >>> a1, b1, head, tail = balanced_decomp(sequence, open_to_close) - >>> print('a1 = {!r}'.format(a1)) - >>> print('tail = {!r}'.format(tail)) - >>> print('head = {!r}'.format(head)) - >>> a2, b2, tail1, tail2 = balanced_decomp(tail, open_to_close) - >>> print('a2 = {!r}'.format(a2)) - >>> print('tail1 = {!r}'.format(tail1)) - >>> print('tail2 = {!r}'.format(tail2)) - """ - gen = generate_balance_unsafe(sequence, open_to_close) - - bal_curr, tok_curr = next(gen) - pop_open = sequence[0:1] - want_close = open_to_close[tok_curr] - - head_stop = 1 - for head_stop, (bal_curr, tok_curr) in enumerate(gen, start=1): - if bal_curr and tok_curr == want_close: - pop_close = sequence[head_stop:head_stop + 1] - break - head = sequence[1:head_stop] - tail = sequence[head_stop + 1:] - return pop_open, pop_close, head, tail - - -def generate_balance(sequence, open_to_close): - """ - Safe version - - Example: - >>> open_to_close = {0: 1} - >>> sequence = [0, 0, 0, 1, 1, 1] - >>> gen = list(generate_balance(sequence, open_to_close)) - >>> for flag, token in gen: - >>> print('flag={:d}, token={}'.format(flag, token)) - - Example: - >>> tree = random_ordered_tree(1000) - >>> sequence, open_to_close, toks = tree_to_balanced_sequence(tree) - >>> gen = list(generate_balance(sequence, open_to_close)) - >>> for flag, token in gen: - >>> print('flag={:d}, token={}'.format(flag, token)) - """ - stack = [] - # Traversing the Expression - for token in sequence: - - if token in open_to_close: - # Push opening elements onto the stack - stack.append(token) - else: - # Check that closing elements - if not stack: - raise UnbalancedException - prev_open = stack.pop() - want_close = open_to_close[prev_open] - - if token != want_close: - raise UnbalancedException - - # If the stack is empty the sequence is currently balanced - currently_balanced = not bool(stack) - yield currently_balanced, token - - if stack: - raise UnbalancedException - - -def _print_forest(graph): - """ - Nice ascii representation of a forest - - Ignore: - graph = nx.balanced_tree(r=2, h=3, create_using=nx.DiGraph) - _print_forest(graph) - - graph = CategoryTree.demo('coco').graph - _print_forest(graph) - """ - if len(graph.nodes) == 0: - print('--') - return - assert nx.is_forest(graph) - - def _recurse(node, indent='', islast=False): - if islast: - this_prefix = indent + '└── ' - next_prefix = indent + ' ' - else: - this_prefix = indent + '├── ' - next_prefix = indent + '│   ' - label = graph.nodes[node].get('label', node) - print(this_prefix + str(label)) - graph.succ[node] - children = graph.succ[node] - for idx, child in enumerate(children, start=1): - islast_next = (idx == len(children)) - _recurse(child, indent=next_prefix, islast=islast_next) - - sources = [n for n in graph.nodes if graph.in_degree[n] == 0] - for idx, node in enumerate(sources, start=1): - islast_next = (idx == len(sources)) - _recurse(node, indent='', islast=islast_next) - - -__notes_ = """ - - # if 0: - # tuples = [(i + 1, i + 2, i + 3,) for i in range(4)] - # import timerit - - # ti = timerit.Timerit(100, bestof=10, verbose=2) - # import itertools as it - # for timer in ti.reset('time'): - # with timer: - # tuple(it.chain.from_iterable(tuples)) - # for timer in ti.reset('time'): - # with timer: - # res = tuples[0] - # for a in tuples[1:]: - # res = res + a - -""" diff --git a/netharn/initializers/bseq2.py b/netharn/initializers/bseq2.py deleted file mode 100644 index 1b26842..0000000 --- a/netharn/initializers/bseq2.py +++ /dev/null @@ -1,612 +0,0 @@ -import operator -import ubelt as ub -import networkx as nx - -try: - import xdev - profile = xdev.profile -except Exception: - profile = ub.identity - - -def longest_common_balanced_sequence(seq1, seq2, open_to_close, open_to_tok=None, node_affinity='auto', impl='iter'): - """ - CommandLine: - xdoctest -m /home/joncrall/code/netharn/netharn/initializers/balanced_sequence.py longest_common_balanced_sequence:0 --profile && cat profile_output.txt - - Example: - >>> from netharn.initializers.balanced_sequence import * # NOQA - >>> tree1 = random_ordered_tree(5, seed=10, pool='[{(') - >>> tree2 = random_ordered_tree(5, seed=3, pool='[{(') - - >>> import kwarray - >>> rng = kwarray.ensure_rng(None, 'python') - >>> tree1 = random_ordered_tree(100, seed=rng, pool='[{(') - >>> tree2 = random_ordered_tree(200, seed=rng, pool='[{(') - >>> if len(tree1.nodes) < 20: - >>> _print_forest(tree1) - >>> _print_forest(tree2) - >>> seq1, open_to_close, toks = tree_to_balanced_sequence(tree1, mode='label', strhack=1) - >>> seq2, open_to_close, toks = tree_to_balanced_sequence(tree2, open_to_close, toks, mode='label', strhack=1) - >>> full_seq1 = seq1 - >>> full_seq2 = seq2 - >>> print('seq1 = {!r}'.format(seq1)) - >>> print('seq2 = {!r}'.format(seq2)) - >>> open_to_tok = ub.invert_dict(toks) - >>> with ub.Timer('recursive'): - >>> best2, val2 = longest_common_balanced_sequence(seq1, seq2, open_to_close, open_to_tok, impl='recurse') - >>> print('val2, best2 = {}, {!r}'.format(val2, best2)) - >>> with ub.Timer('iterative'): - >>> best1, val1 = longest_common_balanced_sequence(seq1, seq2, open_to_close, open_to_tok, impl='iter') - >>> print('val1, best1 = {}, {!r}'.format(val1, best1)) - """ - if node_affinity == 'auto' or node_affinity == 'eq': - node_affinity = operator.eq - if node_affinity is None: - def _matchany(a, b): - return True - node_affinity = _matchany - _memo = {} - _seq_memo = {} - if open_to_tok is None: - class Dummy: - def __getitem__(self, key): - return key - open_to_tok = Dummy() - full_seq1 = seq1 - full_seq2 = seq2 - if impl == 'recurse': - best, value = _lcs_recurse(full_seq1, full_seq2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo) - elif impl == 'iter': - best, value = _lcs_iter(full_seq1, full_seq2, open_to_close, node_affinity, open_to_tok) - else: - raise KeyError(impl) - return best, value - - -@profile -def _lcs_iter(full_seq1, full_seq2, open_to_close, node_affinity, open_to_tok): - def decomp_info(seq, open_to_close): - pop_open, pop_close, head, tail = balanced_decomp_unsafe(seq, open_to_close) - head_tail = head + tail - head_key = hash(head) - tail_key = hash(tail) - head_tail_key = hash(head_tail) - tok = open_to_tok[pop_open[0]] - a = pop_open - b = pop_close - info = (tok, seq, head, tail, head_tail, head_key, tail_key, head_tail_key, a, b) - return info - - def gen_decomp_v2(seq, open_to_close): - _genmemo = {} - def _gen(seq): - if seq: - key = hash(seq) - if key not in _genmemo: - info = decomp_info(seq, open_to_close) - head, tail, head_tail = info[2:5] - _genmemo[key] = info - yield (seq, _genmemo[key]) - yield from _gen(head_tail) - yield from _gen(head) - yield from _gen(tail) - all_decomp = dict(_gen(seq)) - return all_decomp - - all_decomp1 = gen_decomp_v2(full_seq1, open_to_close) - all_decomp2 = gen_decomp_v2(full_seq2, open_to_close) - - key_decomp1 = {} - key_decomp2 = {} - _results = {} - # Populate base cases - empty1 = type(ub.peek(all_decomp1.keys()))() - empty2 = type(ub.peek(all_decomp2.keys()))() - empty1_key = hash(empty1) - empty2_key = hash(empty2) - best = (empty1, empty2) - base_result = (0, best) - for seq1, info1 in all_decomp1.items(): - seq1_key = hash(seq1) - head1_key, tail1_key, head_tail1_key = all_decomp1[seq1][5:8] - _results[(seq1_key, empty2_key)] = base_result - _results[(head1_key, empty2_key)] = base_result - _results[(tail1_key, empty2_key)] = base_result - _results[(head_tail1_key, empty2_key)] = base_result - key_decomp1[seq1_key] = info1 - - for seq2, info2 in all_decomp2.items(): - seq2_key = hash(seq2) - head2_key, tail2_key, head_tail2_key = all_decomp2[seq2][5:8] - _results[(empty1_key, seq2_key)] = base_result - _results[(empty1_key, head2_key)] = base_result - _results[(empty1_key, tail2_key)] = base_result - _results[(empty1_key, head_tail2_key)] = base_result - key_decomp2[seq2_key] = info2 - - full_seq1_key = hash(full_seq1) - full_seq2_key = hash(full_seq2) - key0 = (full_seq1_key, full_seq2_key) - frame0 = key0, full_seq1, full_seq2 - stack = [frame0] - missing_frames = [] - num_misses = 0 - while stack: - frame = stack.pop() - key, seq1, seq2 = frame - seq1_key, seq2_key = key - if key not in _results: - missing_frames.clear() - - try: - info1 = key_decomp1[seq1_key] - except KeyError: - info1 = decomp_info(seq1, open_to_close) - key_decomp1[seq1_key] = info1 - tok1, seq1, head1, tail1, head_tail1, head1_key, tail1_key, head_tail1_key, a1, b1 = info1 - - try: - info2 = key_decomp2[seq2_key] - except KeyError: - info2 = decomp_info(seq2, open_to_close) - key_decomp2[seq2_key] = info2 - tok2, seq2, head2, tail2, head_tail2, head2_key, tail2_key, head_tail2_key, a2, b2 = info2 - - affinity = node_affinity(tok1, tok2) - - # Case 2: The current edge in sequence1 is deleted - try: - try_key = (head_tail1_key, seq2_key) - cand1 = _results[try_key] - except KeyError: - miss_frame = try_key, head_tail1, seq2 - missing_frames.append(miss_frame) - - # Case 3: The current edge in sequence2 is deleted - try: - try_key = (seq1_key, head_tail2_key) - cand2 = _results[try_key] - except KeyError: - miss_frame = try_key, seq1, head_tail2 - missing_frames.append(miss_frame) - - # Case 1: The LCS involves this edge - if affinity: - try: - try_key = (head1_key, head2_key) - pval_h, new_heads = _results[try_key] - except KeyError: - miss_frame = try_key, head1, head2 - missing_frames.append(miss_frame) - - try: - try_key = (tail1_key, tail2_key) - pval_t, new_tails = _results[try_key] - except KeyError: - miss_frame = try_key, tail1, tail2 - missing_frames.append(miss_frame) - - if not missing_frames: - new_head1, new_head2 = new_heads - new_tail1, new_tail2 = new_tails - - subseq1 = a1 + new_head1 + b1 + new_tail1 - subseq2 = a2 + new_head2 + b2 + new_tail2 - - res3 = (subseq1, subseq2) - val3 = pval_h + pval_t + affinity - cand3 = (val3, res3) - else: - cand3 = (-1, None) - - if missing_frames: - num_misses += 1 - # We did not solve this frame yet - stack.append(frame) - stack.extend(missing_frames[::-1]) - else: - # We solved the frame - _results[key] = max(cand1, cand2, cand3) - - print('num_misses = {!r}'.format(num_misses)) - - # The stack pop is our solution - (val, best) = _results[key] - found = (best, val) - return found - - -def generate_all_decompositions(seq, open_to_close): - """ - Can doing this a-priori speed up the algorithm? - - open_to_close = {0: 1} - sequence = [0, 0, 0, 1, 1, 1, 0, 1] - open_to_close = {'{': '}', '(': ')', '[': ']'} - seq = '({[[]]})[[][]]{{}}' - pop_open, pop_close, head, tail = balanced_decomp(seq, open_to_close) - - >>> tree = random_ordered_tree(1000) - >>> seq, open_to_close, toks = tree_to_balanced_sequence(tree) - >>> all_decomp = _generate_all_decompositions(seq, open_to_close) - """ - _memo = {} - def _gen(seq): - if not seq: - pass - # yield None - elif seq in _memo: - pass - # yield (seq, _memo[seq]) - else: - pop_open, pop_close, head, tail = balanced_decomp(seq, open_to_close) - head_tail = head + tail - _memo[seq] = (pop_open, pop_close, head, tail, head_tail) - yield (seq, _memo[seq]) - yield from _gen(head_tail) - yield from _gen(head) - yield from _gen(tail) - all_decomp = dict(_gen(seq)) - return all_decomp - - -@profile -def _lcs_recurse(seq1, seq2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo): - if not seq1: - return (seq1, seq1), 0 - elif not seq2: - return (seq2, seq2), 0 - else: - # if len(seq2) < len(seq1): - # seq1, seq2 = seq2, seq1 - # key = (seq1, seq2) - key1 = hash(seq1) # using hash(seq) is faster than seq itself - key2 = hash(seq2) - key = hash((key1, key2)) - if key in _memo: - return _memo[key] - - # TODO: we can probably just do a single linear run through the - # sequences to index the sub-sequence locations and then apply an - # offset when we run the decomposed sequence. - if key1 in _seq_memo: - a1, b1, head1, tail1, head1_tail1 = _seq_memo[key1] - else: - a1, b1, head1, tail1 = balanced_decomp_unsafe(seq1, open_to_close) - head1_tail1 = head1 + tail1 - _seq_memo[key1] = a1, b1, head1, tail1, head1_tail1 - - if key2 in _seq_memo: - a2, b2, head2, tail2, head2_tail2 = _seq_memo[key2] - else: - a2, b2, head2, tail2 = balanced_decomp_unsafe(seq2, open_to_close) - head2_tail2 = head2 + tail2 - _seq_memo[key2] = a2, b2, head2, tail2, head2_tail2 - - # Case 2: The current edge in sequence1 is deleted - best, val = _lcs_recurse(head1_tail1, seq2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo) - - # Case 3: The current edge in sequence2 is deleted - cand, val_alt = _lcs_recurse(seq1, head2_tail2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo) - if val_alt > val: - best = cand - val = val_alt - - # Case 1: The LCS involves this edge - t1 = open_to_tok[a1[0]] - t2 = open_to_tok[a2[0]] - # if node_affinity(a1[0], a2[0]): - affinity = node_affinity(t1, t2) - if affinity: - new_heads, pval_h = _lcs_recurse(head1, head2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo) - new_tails, pval_t = _lcs_recurse(tail1, tail2, open_to_close, node_affinity, open_to_tok, _memo, _seq_memo) - - new_head1, new_head2 = new_heads - new_tail1, new_tail2 = new_tails - - subseq1 = a1 + new_head1 + b1 + new_tail1 - subseq2 = a2 + new_head2 + b2 + new_tail2 - - cand = (subseq1, subseq2) - val_alt = pval_h + pval_t + affinity - if val_alt > val: - best = cand - val = val_alt - - found = (best, val) - _memo[key] = found - return found - - -class UnbalancedException(Exception): - pass - - -def balanced_decomp(sequence, open_to_close): - """ - Note this is not exactly the same as the decomposition in the paper. - That is because we also return the "wrapping" element, and we let the - user do the head + tail concatenation. - - Example: - >>> open_to_close = {0: 1} - >>> sequence = [0, 0, 0, 1, 1, 1, 0, 1] - >>> open_to_close = {'{': '}', '(': ')', '[': ']'} - >>> sequence = '({[[]]})[[][]]' - >>> a1, b1, head, tail = balanced_decomp(sequence, open_to_close) - >>> a2, b2, tail1, tail2 = balanced_decomp(tail, open_to_close) - """ - gen = generate_balance(sequence, open_to_close) - - bal_curr, tok_curr = next(gen) - pop_open = sequence[0:1] - want_close = open_to_close[tok_curr] - - head_stop = 1 - for head_stop, (bal_curr, tok_curr) in enumerate(gen, start=1): - if tok_curr is None: - break - elif bal_curr and tok_curr == want_close: - pop_close = sequence[head_stop:head_stop + 1] - break - head = sequence[1:head_stop] - # if __debug__: - # list(gen) # exhaust the generator to check we are balanced - tail = sequence[head_stop + 1:] - return pop_open, pop_close, head, tail - - -def tree_to_balanced_sequence(tree, open_to_close=None, toks=None, mode='tuple', strhack=False): - from collections import namedtuple - Token = namedtuple('Token', ['action', 'value']) - # mapping between opening and closing tokens - sources = [n for n in tree.nodes if tree.in_degree[n] == 0] - sequence = [] - - if open_to_close is None: - open_to_close = {} - if toks is None: - toks = {} - - if strhack: - if mode == 'label': - all_labels = {n['label'] for n in list(tree.nodes.values())} - assert all(x == 1 for x in map(len, all_labels)) - - for source in sources: - for u, v, etype in nx.dfs_labeled_edges(tree, source=source): - if etype == 'forward': - # u has been visited by v has not - if v not in toks: - if mode == 'tuple': - # TODO: token encoding scheme where subdirectories - # are matchable via a custom operation. - # open_tok = '<{}>'.format(v) - # close_tok = ''.format(v) - open_tok = Token('open', v) - close_tok = Token('close', v) - elif mode == 'number': - open_tok = len(toks) + 1 - close_tok = -open_tok - elif mode == 'paren': - open_tok = '{}('.format(v) - close_tok = '){}'.format(v) - elif mode == 'chr': - open_tok = str(v) - close_tok = str(v) + u'\u0301' - elif mode == 'label': - open_tok = tree.nodes[v]['label'] - assert strhack - if open_tok == '{': - close_tok = '}' - if open_tok == '[': - close_tok = ']' - if open_tok == '(': - close_tok = ')' - toks[v] = open_tok - open_to_close[open_tok] = close_tok - open_tok = toks[v] - sequence.append(open_tok) - elif etype == 'reverse': - # Both u and v are visited and the edge is in the tree - close_tok = open_to_close[toks[v]] - sequence.append(close_tok) - else: - raise KeyError(etype) - sequence = tuple(sequence) - if strhack: - sequence = ''.join(sequence) - return sequence, open_to_close, toks - - -def seq_to_tree(subseq, open_to_close, toks): - open_to_tok = ub.invert_dict(toks) - subtree = nx.OrderedDiGraph() - stack = [] - for token in subseq: - if token in open_to_close: - node = open_to_tok[token] - if stack: - parent = open_to_tok[stack[-1]] - subtree.add_edge(parent, node) - else: - subtree.add_node(node) - stack.append(token) - else: - if not stack: - raise Exception - prev_open = stack.pop() - want_close = open_to_close[prev_open] - if token != want_close: - raise Exception - return subtree - - -def random_ordered_tree(n, seed=None, pool=None): - import kwarray - rng = kwarray.ensure_rng(seed, 'python') - tree = nx.dfs_tree(nx.random_tree(n, seed=seed)) - otree = nx.OrderedDiGraph() - otree.add_edges_from(tree.edges) - if pool is not None: - for node in otree.nodes: - otree.nodes[node]['label'] = rng.choice(pool) - return otree - - -def generate_balance_unsafe(sequence, open_to_close): - """ - Benchmark: - >>> tree = random_ordered_tree(1000) - >>> sequence, open_to_close, toks = tree_to_balanced_sequence(tree, mode='tuple') - >>> sequence, open_to_close, toks = tree_to_balanced_sequence(tree, mode='number') - >>> import timerit - >>> ti = timerit.Timerit(100, bestof=10, verbose=2) - >>> for timer in ti.reset('time'): - >>> with timer: - >>> list(generate_balance_unsafe(sequence, open_to_close)) - >>> import timerit - >>> ti = timerit.Timerit(100, bestof=10, verbose=2) - >>> for timer in ti.reset('time'): - >>> with timer: - >>> list(generate_balance_unsafe_cython(sequence, open_to_close)) - """ - stacklen = 0 - for token in sequence: - if token in open_to_close: - stacklen += 1 - else: - stacklen -= 1 - yield stacklen == 0, token - - -def balanced_decomp_unsafe(sequence, open_to_close): - """ - Example: - >>> open_to_close = {'{': '}', '(': ')', '[': ']'} - >>> sequence = '({[[]]})[[][]]' - >>> print('sequence = {!r}'.format(sequence)) - >>> a1, b1, head, tail = balanced_decomp(sequence, open_to_close) - >>> print('a1 = {!r}'.format(a1)) - >>> print('tail = {!r}'.format(tail)) - >>> print('head = {!r}'.format(head)) - >>> a2, b2, tail1, tail2 = balanced_decomp(tail, open_to_close) - >>> print('a2 = {!r}'.format(a2)) - >>> print('tail1 = {!r}'.format(tail1)) - >>> print('tail2 = {!r}'.format(tail2)) - """ - gen = generate_balance_unsafe(sequence, open_to_close) - - bal_curr, tok_curr = next(gen) - pop_open = sequence[0:1] - want_close = open_to_close[tok_curr] - - head_stop = 1 - for head_stop, (bal_curr, tok_curr) in enumerate(gen, start=1): - if bal_curr and tok_curr == want_close: - pop_close = sequence[head_stop:head_stop + 1] - break - head = sequence[1:head_stop] - tail = sequence[head_stop + 1:] - return pop_open, pop_close, head, tail - - -def generate_balance(sequence, open_to_close): - """ - Safe version - - Example: - >>> open_to_close = {0: 1} - >>> sequence = [0, 0, 0, 1, 1, 1] - >>> gen = list(generate_balance(sequence, open_to_close)) - >>> for flag, token in gen: - >>> print('flag={:d}, token={}'.format(flag, token)) - - Example: - >>> tree = random_ordered_tree(1000) - >>> sequence, open_to_close, toks = tree_to_balanced_sequence(tree) - >>> gen = list(generate_balance(sequence, open_to_close)) - >>> for flag, token in gen: - >>> print('flag={:d}, token={}'.format(flag, token)) - """ - stack = [] - # Traversing the Expression - for token in sequence: - - if token in open_to_close: - # Push opening elements onto the stack - stack.append(token) - else: - # Check that closing elements - if not stack: - raise UnbalancedException - prev_open = stack.pop() - want_close = open_to_close[prev_open] - - if token != want_close: - raise UnbalancedException - - # If the stack is empty the sequence is currently balanced - currently_balanced = not bool(stack) - yield currently_balanced, token - - if stack: - raise UnbalancedException - - -def _print_forest(graph): - """ - Nice ascii representation of a forest - - Ignore: - graph = nx.balanced_tree(r=2, h=3, create_using=nx.DiGraph) - _print_forest(graph) - - graph = CategoryTree.demo('coco').graph - _print_forest(graph) - """ - if len(graph.nodes) == 0: - print('--') - return - assert nx.is_forest(graph) - - def _recurse(node, indent='', islast=False): - if islast: - this_prefix = indent + '└── ' - next_prefix = indent + ' ' - else: - this_prefix = indent + '├── ' - next_prefix = indent + '│   ' - label = graph.nodes[node].get('label', node) - print(this_prefix + str(label)) - graph.succ[node] - children = graph.succ[node] - for idx, child in enumerate(children, start=1): - islast_next = (idx == len(children)) - _recurse(child, indent=next_prefix, islast=islast_next) - - sources = [n for n in graph.nodes if graph.in_degree[n] == 0] - for idx, node in enumerate(sources, start=1): - islast_next = (idx == len(sources)) - _recurse(node, indent='', islast=islast_next) - - -__notes_ = """ - - # if 0: - # tuples = [(i + 1, i + 2, i + 3,) for i in range(4)] - # import timerit - - # ti = timerit.Timerit(100, bestof=10, verbose=2) - # import itertools as it - # for timer in ti.reset('time'): - # with timer: - # tuple(it.chain.from_iterable(tuples)) - # for timer in ti.reset('time'): - # with timer: - # res = tuples[0] - # for a in tuples[1:]: - # res = res + a - -""" diff --git a/netharn/initializers/functional.py b/netharn/initializers/functional.py index 1c488c5..0d8ff87 100644 --- a/netharn/initializers/functional.py +++ b/netharn/initializers/functional.py @@ -603,7 +603,7 @@ def maximum_common_ordered_subpaths(paths1, paths2, sep='.'): Example: >>> import torchvision >>> resnet50 = torchvision.models.resnet50() - >>> paths1 = sorted(resnet50.state_dict().keys())[0:100] + >>> paths1 = sorted(resnet50.state_dict().keys()) >>> paths2 = ['prefix.' + k for k in paths1] >>> paths2.append('extra_key') >>> subpaths1, subpaths2 = maximum_common_ordered_subpaths(paths1, paths2) @@ -718,9 +718,9 @@ def maximum_common_ordered_subpaths(paths1, paths2, sep='.'): # DiGM.is_isomorphic() # list(DiGM.subgraph_isomorphisms_iter()) - from netharn.initializers import _nx_extensions - subtree1, subtree2 = _nx_extensions.maximum_common_ordered_tree_embedding(tree1, tree2, node_affinity=node_affinity) - # subtree1, subtree2 = _nx_extensions.maximum_common_ordered_subtree_isomorphism(tree1, tree2, node_affinity=node_affinity) + from netharn.initializers import _nx_ext + subtree1, subtree2 = _nx_ext.maximum_common_ordered_tree_embedding(tree1, tree2, node_affinity=node_affinity) + # subtree1, subtree2 = _nx_ext.maximum_common_ordered_subtree_isomorphism(tree1, tree2, node_affinity=node_affinity) subpaths1 = [sep.join(node) for node in subtree1.nodes if subtree1.out_degree[node] == 0] subpaths2 = [sep.join(node) for node in subtree2.nodes if subtree2.out_degree[node] == 0] diff --git a/netharn/schedulers/core.py b/netharn/schedulers/core.py index 2bb2e02..2967e85 100644 --- a/netharn/schedulers/core.py +++ b/netharn/schedulers/core.py @@ -1,6 +1,56 @@ import torch.optim.lr_scheduler from collections import defaultdict +""" + +# Notes on torch schedulers + +import torch +from torch.optim import lr_scheduler +from torch import optim + + +parameters = list(torch.nn.Conv1d(1, 1, 1).parameters()) + +base_lr = 1e-3 +optimizer = optim.SGD(parameters, lr=base_lr) + + +schedulers = {} +scheduler = lr_scheduler.CosineAnnealingLR(optimizer, T_max=20) +schedulers[scheduler.__class__.__name__] = scheduler +scheduler = lr_scheduler.OneCycleLR(optimizer, max_lr=base_lr, total_steps=100) +schedulers[scheduler.__class__.__name__] = scheduler +scheduler = lr_scheduler.StepLR(optimizer, step_size=30) +schedulers[scheduler.__class__.__name__] = scheduler +scheduler = lr_scheduler.ExponentialLR(optimizer, gamma=0.9) +schedulers[scheduler.__class__.__name__] = scheduler + +key = scheduler.__class__.__name__ + + +xdata = list(range(100)) +ydata = ub.ddict(list) + +for key, scheduler in schedulers.items(): + + # Reset optimizer LR + for g in optimizer.param_groups: + g['lr'] = base_lr + + for x in xdata: + lr = scheduler.get_last_lr()[0] + scheduler.step() + ydata[key].append(lr) + +import kwplot +kwplot.autompl() + +kwplot.multi_plot(xdata=xdata, ydata=ydata) + + +""" + class CommonMixin(object): -- GitLab From 0bbe1eb027bb13c2a8251c9747ba390f980d29be Mon Sep 17 00:00:00 2001 From: joncrall Date: Mon, 7 Sep 2020 13:08:48 -0400 Subject: [PATCH 10/54] wip --- .../_nx_ext/balanced_sequence_cython.cpp | 10787 ---------------- .../_nx_ext/balanced_sequence_cython.html | 4497 ------- 2 files changed, 15284 deletions(-) delete mode 100644 netharn/initializers/_nx_ext/balanced_sequence_cython.cpp delete mode 100644 netharn/initializers/_nx_ext/balanced_sequence_cython.html diff --git a/netharn/initializers/_nx_ext/balanced_sequence_cython.cpp b/netharn/initializers/_nx_ext/balanced_sequence_cython.cpp deleted file mode 100644 index 38e742a..0000000 --- a/netharn/initializers/_nx_ext/balanced_sequence_cython.cpp +++ /dev/null @@ -1,10787 +0,0 @@ -/* Generated by Cython 0.29.20 */ - -/* BEGIN: Cython Metadata -{ - "distutils": { - "language": "c++", - "name": "networkx.algorithms.isomorphism._embedding.balanced_sequence_cython", - "sources": [ - "/home/joncrall/code/networkx/networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx" - ] - }, - "module_name": "networkx.algorithms.isomorphism._embedding.balanced_sequence_cython" -} -END: Cython Metadata */ - -#define PY_SSIZE_T_CLEAN -#include "Python.h" -#ifndef Py_PYTHON_H - #error Python headers needed to compile C extensions, please install development version of Python. -#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000) - #error Cython requires Python 2.6+ or Python 3.3+. -#else -#define CYTHON_ABI "0_29_20" -#define CYTHON_HEX_VERSION 0x001D14F0 -#define CYTHON_FUTURE_DIVISION 0 -#include -#ifndef offsetof - #define offsetof(type, member) ( (size_t) & ((type*)0) -> member ) -#endif -#if !defined(WIN32) && !defined(MS_WINDOWS) - #ifndef __stdcall - #define __stdcall - #endif - #ifndef __cdecl - #define __cdecl - #endif - #ifndef __fastcall - #define __fastcall - #endif -#endif -#ifndef DL_IMPORT - #define DL_IMPORT(t) t -#endif -#ifndef DL_EXPORT - #define DL_EXPORT(t) t -#endif -#define __PYX_COMMA , -#ifndef HAVE_LONG_LONG - #if PY_VERSION_HEX >= 0x02070000 - #define HAVE_LONG_LONG - #endif -#endif -#ifndef PY_LONG_LONG - #define PY_LONG_LONG LONG_LONG -#endif -#ifndef Py_HUGE_VAL - #define Py_HUGE_VAL HUGE_VAL -#endif -#ifdef PYPY_VERSION - #define CYTHON_COMPILING_IN_PYPY 1 - #define CYTHON_COMPILING_IN_PYSTON 0 - #define CYTHON_COMPILING_IN_CPYTHON 0 - #undef CYTHON_USE_TYPE_SLOTS - #define CYTHON_USE_TYPE_SLOTS 0 - #undef CYTHON_USE_PYTYPE_LOOKUP - #define CYTHON_USE_PYTYPE_LOOKUP 0 - #if PY_VERSION_HEX < 0x03050000 - #undef CYTHON_USE_ASYNC_SLOTS - #define CYTHON_USE_ASYNC_SLOTS 0 - #elif !defined(CYTHON_USE_ASYNC_SLOTS) - #define CYTHON_USE_ASYNC_SLOTS 1 - #endif - #undef CYTHON_USE_PYLIST_INTERNALS - #define CYTHON_USE_PYLIST_INTERNALS 0 - #undef CYTHON_USE_UNICODE_INTERNALS - #define CYTHON_USE_UNICODE_INTERNALS 0 - #undef CYTHON_USE_UNICODE_WRITER - #define CYTHON_USE_UNICODE_WRITER 0 - #undef CYTHON_USE_PYLONG_INTERNALS - #define CYTHON_USE_PYLONG_INTERNALS 0 - #undef CYTHON_AVOID_BORROWED_REFS - #define CYTHON_AVOID_BORROWED_REFS 1 - #undef CYTHON_ASSUME_SAFE_MACROS - #define CYTHON_ASSUME_SAFE_MACROS 0 - #undef CYTHON_UNPACK_METHODS - #define CYTHON_UNPACK_METHODS 0 - #undef CYTHON_FAST_THREAD_STATE - #define CYTHON_FAST_THREAD_STATE 0 - #undef CYTHON_FAST_PYCALL - #define CYTHON_FAST_PYCALL 0 - #undef CYTHON_PEP489_MULTI_PHASE_INIT - #define CYTHON_PEP489_MULTI_PHASE_INIT 0 - #undef CYTHON_USE_TP_FINALIZE - #define CYTHON_USE_TP_FINALIZE 0 - #undef CYTHON_USE_DICT_VERSIONS - #define CYTHON_USE_DICT_VERSIONS 0 - #undef CYTHON_USE_EXC_INFO_STACK - #define CYTHON_USE_EXC_INFO_STACK 0 -#elif defined(PYSTON_VERSION) - #define CYTHON_COMPILING_IN_PYPY 0 - #define CYTHON_COMPILING_IN_PYSTON 1 - #define CYTHON_COMPILING_IN_CPYTHON 0 - #ifndef CYTHON_USE_TYPE_SLOTS - #define CYTHON_USE_TYPE_SLOTS 1 - #endif - #undef CYTHON_USE_PYTYPE_LOOKUP - #define CYTHON_USE_PYTYPE_LOOKUP 0 - #undef CYTHON_USE_ASYNC_SLOTS - #define CYTHON_USE_ASYNC_SLOTS 0 - #undef CYTHON_USE_PYLIST_INTERNALS - #define CYTHON_USE_PYLIST_INTERNALS 0 - #ifndef CYTHON_USE_UNICODE_INTERNALS - #define CYTHON_USE_UNICODE_INTERNALS 1 - #endif - #undef CYTHON_USE_UNICODE_WRITER - #define CYTHON_USE_UNICODE_WRITER 0 - #undef CYTHON_USE_PYLONG_INTERNALS - #define CYTHON_USE_PYLONG_INTERNALS 0 - #ifndef CYTHON_AVOID_BORROWED_REFS - #define CYTHON_AVOID_BORROWED_REFS 0 - #endif - #ifndef CYTHON_ASSUME_SAFE_MACROS - #define CYTHON_ASSUME_SAFE_MACROS 1 - #endif - #ifndef CYTHON_UNPACK_METHODS - #define CYTHON_UNPACK_METHODS 1 - #endif - #undef CYTHON_FAST_THREAD_STATE - #define CYTHON_FAST_THREAD_STATE 0 - #undef CYTHON_FAST_PYCALL - #define CYTHON_FAST_PYCALL 0 - #undef CYTHON_PEP489_MULTI_PHASE_INIT - #define CYTHON_PEP489_MULTI_PHASE_INIT 0 - #undef CYTHON_USE_TP_FINALIZE - #define CYTHON_USE_TP_FINALIZE 0 - #undef CYTHON_USE_DICT_VERSIONS - #define CYTHON_USE_DICT_VERSIONS 0 - #undef CYTHON_USE_EXC_INFO_STACK - #define CYTHON_USE_EXC_INFO_STACK 0 -#else - #define CYTHON_COMPILING_IN_PYPY 0 - #define CYTHON_COMPILING_IN_PYSTON 0 - #define CYTHON_COMPILING_IN_CPYTHON 1 - #ifndef CYTHON_USE_TYPE_SLOTS - #define CYTHON_USE_TYPE_SLOTS 1 - #endif - #if PY_VERSION_HEX < 0x02070000 - #undef CYTHON_USE_PYTYPE_LOOKUP - #define CYTHON_USE_PYTYPE_LOOKUP 0 - #elif !defined(CYTHON_USE_PYTYPE_LOOKUP) - #define CYTHON_USE_PYTYPE_LOOKUP 1 - #endif - #if PY_MAJOR_VERSION < 3 - #undef CYTHON_USE_ASYNC_SLOTS - #define CYTHON_USE_ASYNC_SLOTS 0 - #elif !defined(CYTHON_USE_ASYNC_SLOTS) - #define CYTHON_USE_ASYNC_SLOTS 1 - #endif - #if PY_VERSION_HEX < 0x02070000 - #undef CYTHON_USE_PYLONG_INTERNALS - #define CYTHON_USE_PYLONG_INTERNALS 0 - #elif !defined(CYTHON_USE_PYLONG_INTERNALS) - #define CYTHON_USE_PYLONG_INTERNALS 1 - #endif - #ifndef CYTHON_USE_PYLIST_INTERNALS - #define CYTHON_USE_PYLIST_INTERNALS 1 - #endif - #ifndef CYTHON_USE_UNICODE_INTERNALS - #define CYTHON_USE_UNICODE_INTERNALS 1 - #endif - #if PY_VERSION_HEX < 0x030300F0 - #undef CYTHON_USE_UNICODE_WRITER - #define CYTHON_USE_UNICODE_WRITER 0 - #elif !defined(CYTHON_USE_UNICODE_WRITER) - #define CYTHON_USE_UNICODE_WRITER 1 - #endif - #ifndef CYTHON_AVOID_BORROWED_REFS - #define CYTHON_AVOID_BORROWED_REFS 0 - #endif - #ifndef CYTHON_ASSUME_SAFE_MACROS - #define CYTHON_ASSUME_SAFE_MACROS 1 - #endif - #ifndef CYTHON_UNPACK_METHODS - #define CYTHON_UNPACK_METHODS 1 - #endif - #ifndef CYTHON_FAST_THREAD_STATE - #define CYTHON_FAST_THREAD_STATE 1 - #endif - #ifndef CYTHON_FAST_PYCALL - #define CYTHON_FAST_PYCALL 1 - #endif - #ifndef CYTHON_PEP489_MULTI_PHASE_INIT - #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000) - #endif - #ifndef CYTHON_USE_TP_FINALIZE - #define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1) - #endif - #ifndef CYTHON_USE_DICT_VERSIONS - #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1) - #endif - #ifndef CYTHON_USE_EXC_INFO_STACK - #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3) - #endif -#endif -#if !defined(CYTHON_FAST_PYCCALL) -#define CYTHON_FAST_PYCCALL (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1) -#endif -#if CYTHON_USE_PYLONG_INTERNALS - #include "longintrepr.h" - #undef SHIFT - #undef BASE - #undef MASK - #ifdef SIZEOF_VOID_P - enum { __pyx_check_sizeof_voidp = 1 / (int)(SIZEOF_VOID_P == sizeof(void*)) }; - #endif -#endif -#ifndef __has_attribute - #define __has_attribute(x) 0 -#endif -#ifndef __has_cpp_attribute - #define __has_cpp_attribute(x) 0 -#endif -#ifndef CYTHON_RESTRICT - #if defined(__GNUC__) - #define CYTHON_RESTRICT __restrict__ - #elif defined(_MSC_VER) && _MSC_VER >= 1400 - #define CYTHON_RESTRICT __restrict - #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - #define CYTHON_RESTRICT restrict - #else - #define CYTHON_RESTRICT - #endif -#endif -#ifndef CYTHON_UNUSED -# if defined(__GNUC__) -# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) -# define CYTHON_UNUSED __attribute__ ((__unused__)) -# else -# define CYTHON_UNUSED -# endif -# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER)) -# define CYTHON_UNUSED __attribute__ ((__unused__)) -# else -# define CYTHON_UNUSED -# endif -#endif -#ifndef CYTHON_MAYBE_UNUSED_VAR -# if defined(__cplusplus) - template void CYTHON_MAYBE_UNUSED_VAR( const T& ) { } -# else -# define CYTHON_MAYBE_UNUSED_VAR(x) (void)(x) -# endif -#endif -#ifndef CYTHON_NCP_UNUSED -# if CYTHON_COMPILING_IN_CPYTHON -# define CYTHON_NCP_UNUSED -# else -# define CYTHON_NCP_UNUSED CYTHON_UNUSED -# endif -#endif -#define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None) -#ifdef _MSC_VER - #ifndef _MSC_STDINT_H_ - #if _MSC_VER < 1300 - typedef unsigned char uint8_t; - typedef unsigned int uint32_t; - #else - typedef unsigned __int8 uint8_t; - typedef unsigned __int32 uint32_t; - #endif - #endif -#else - #include -#endif -#ifndef CYTHON_FALLTHROUGH - #if defined(__cplusplus) && __cplusplus >= 201103L - #if __has_cpp_attribute(fallthrough) - #define CYTHON_FALLTHROUGH [[fallthrough]] - #elif __has_cpp_attribute(clang::fallthrough) - #define CYTHON_FALLTHROUGH [[clang::fallthrough]] - #elif __has_cpp_attribute(gnu::fallthrough) - #define CYTHON_FALLTHROUGH [[gnu::fallthrough]] - #endif - #endif - #ifndef CYTHON_FALLTHROUGH - #if __has_attribute(fallthrough) - #define CYTHON_FALLTHROUGH __attribute__((fallthrough)) - #else - #define CYTHON_FALLTHROUGH - #endif - #endif - #if defined(__clang__ ) && defined(__apple_build_version__) - #if __apple_build_version__ < 7000000 - #undef CYTHON_FALLTHROUGH - #define CYTHON_FALLTHROUGH - #endif - #endif -#endif - -#ifndef __cplusplus - #error "Cython files generated with the C++ option must be compiled with a C++ compiler." -#endif -#ifndef CYTHON_INLINE - #if defined(__clang__) - #define CYTHON_INLINE __inline__ __attribute__ ((__unused__)) - #else - #define CYTHON_INLINE inline - #endif -#endif -template -void __Pyx_call_destructor(T& x) { - x.~T(); -} -template -class __Pyx_FakeReference { - public: - __Pyx_FakeReference() : ptr(NULL) { } - __Pyx_FakeReference(const T& ref) : ptr(const_cast(&ref)) { } - T *operator->() { return ptr; } - T *operator&() { return ptr; } - operator T&() { return *ptr; } - template bool operator ==(U other) { return *ptr == other; } - template bool operator !=(U other) { return *ptr != other; } - private: - T *ptr; -}; - -#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag) - #define Py_OptimizeFlag 0 -#endif -#define __PYX_BUILD_PY_SSIZE_T "n" -#define CYTHON_FORMAT_SSIZE_T "z" -#if PY_MAJOR_VERSION < 3 - #define __Pyx_BUILTIN_MODULE_NAME "__builtin__" - #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ - PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) - #define __Pyx_DefaultClassType PyClass_Type -#else - #define __Pyx_BUILTIN_MODULE_NAME "builtins" -#if PY_VERSION_HEX >= 0x030800A4 && PY_VERSION_HEX < 0x030800B2 - #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ - PyCode_New(a, 0, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) -#else - #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ - PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) -#endif - #define __Pyx_DefaultClassType PyType_Type -#endif -#ifndef Py_TPFLAGS_CHECKTYPES - #define Py_TPFLAGS_CHECKTYPES 0 -#endif -#ifndef Py_TPFLAGS_HAVE_INDEX - #define Py_TPFLAGS_HAVE_INDEX 0 -#endif -#ifndef Py_TPFLAGS_HAVE_NEWBUFFER - #define Py_TPFLAGS_HAVE_NEWBUFFER 0 -#endif -#ifndef Py_TPFLAGS_HAVE_FINALIZE - #define Py_TPFLAGS_HAVE_FINALIZE 0 -#endif -#ifndef METH_STACKLESS - #define METH_STACKLESS 0 -#endif -#if PY_VERSION_HEX <= 0x030700A3 || !defined(METH_FASTCALL) - #ifndef METH_FASTCALL - #define METH_FASTCALL 0x80 - #endif - typedef PyObject *(*__Pyx_PyCFunctionFast) (PyObject *self, PyObject *const *args, Py_ssize_t nargs); - typedef PyObject *(*__Pyx_PyCFunctionFastWithKeywords) (PyObject *self, PyObject *const *args, - Py_ssize_t nargs, PyObject *kwnames); -#else - #define __Pyx_PyCFunctionFast _PyCFunctionFast - #define __Pyx_PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords -#endif -#if CYTHON_FAST_PYCCALL -#define __Pyx_PyFastCFunction_Check(func)\ - ((PyCFunction_Check(func) && (METH_FASTCALL == (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))))) -#else -#define __Pyx_PyFastCFunction_Check(func) 0 -#endif -#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) - #define PyObject_Malloc(s) PyMem_Malloc(s) - #define PyObject_Free(p) PyMem_Free(p) - #define PyObject_Realloc(p) PyMem_Realloc(p) -#endif -#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030400A1 - #define PyMem_RawMalloc(n) PyMem_Malloc(n) - #define PyMem_RawRealloc(p, n) PyMem_Realloc(p, n) - #define PyMem_RawFree(p) PyMem_Free(p) -#endif -#if CYTHON_COMPILING_IN_PYSTON - #define __Pyx_PyCode_HasFreeVars(co) PyCode_HasFreeVars(co) - #define __Pyx_PyFrame_SetLineNumber(frame, lineno) PyFrame_SetLineNumber(frame, lineno) -#else - #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) - #define __Pyx_PyFrame_SetLineNumber(frame, lineno) (frame)->f_lineno = (lineno) -#endif -#if !CYTHON_FAST_THREAD_STATE || PY_VERSION_HEX < 0x02070000 - #define __Pyx_PyThreadState_Current PyThreadState_GET() -#elif PY_VERSION_HEX >= 0x03060000 - #define __Pyx_PyThreadState_Current _PyThreadState_UncheckedGet() -#elif PY_VERSION_HEX >= 0x03000000 - #define __Pyx_PyThreadState_Current PyThreadState_GET() -#else - #define __Pyx_PyThreadState_Current _PyThreadState_Current -#endif -#if PY_VERSION_HEX < 0x030700A2 && !defined(PyThread_tss_create) && !defined(Py_tss_NEEDS_INIT) -#include "pythread.h" -#define Py_tss_NEEDS_INIT 0 -typedef int Py_tss_t; -static CYTHON_INLINE int PyThread_tss_create(Py_tss_t *key) { - *key = PyThread_create_key(); - return 0; -} -static CYTHON_INLINE Py_tss_t * PyThread_tss_alloc(void) { - Py_tss_t *key = (Py_tss_t *)PyObject_Malloc(sizeof(Py_tss_t)); - *key = Py_tss_NEEDS_INIT; - return key; -} -static CYTHON_INLINE void PyThread_tss_free(Py_tss_t *key) { - PyObject_Free(key); -} -static CYTHON_INLINE int PyThread_tss_is_created(Py_tss_t *key) { - return *key != Py_tss_NEEDS_INIT; -} -static CYTHON_INLINE void PyThread_tss_delete(Py_tss_t *key) { - PyThread_delete_key(*key); - *key = Py_tss_NEEDS_INIT; -} -static CYTHON_INLINE int PyThread_tss_set(Py_tss_t *key, void *value) { - return PyThread_set_key_value(*key, value); -} -static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { - return PyThread_get_key_value(*key); -} -#endif -#if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized) -#define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n)) -#else -#define __Pyx_PyDict_NewPresized(n) PyDict_New() -#endif -#if PY_MAJOR_VERSION >= 3 || CYTHON_FUTURE_DIVISION - #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) - #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) -#else - #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) - #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) -#endif -#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 && CYTHON_USE_UNICODE_INTERNALS -#define __Pyx_PyDict_GetItemStr(dict, name) _PyDict_GetItem_KnownHash(dict, name, ((PyASCIIObject *) name)->hash) -#else -#define __Pyx_PyDict_GetItemStr(dict, name) PyDict_GetItem(dict, name) -#endif -#if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) - #define CYTHON_PEP393_ENABLED 1 - #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ - 0 : _PyUnicode_Ready((PyObject *)(op))) - #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) - #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) - #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) - #define __Pyx_PyUnicode_KIND(u) PyUnicode_KIND(u) - #define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u) - #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) - #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch) - #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) -#else - #define CYTHON_PEP393_ENABLED 0 - #define PyUnicode_1BYTE_KIND 1 - #define PyUnicode_2BYTE_KIND 2 - #define PyUnicode_4BYTE_KIND 4 - #define __Pyx_PyUnicode_READY(op) (0) - #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u) - #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i])) - #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((sizeof(Py_UNICODE) == 2) ? 65535 : 1114111) - #define __Pyx_PyUnicode_KIND(u) (sizeof(Py_UNICODE)) - #define __Pyx_PyUnicode_DATA(u) ((void*)PyUnicode_AS_UNICODE(u)) - #define __Pyx_PyUnicode_READ(k, d, i) ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i])) - #define __Pyx_PyUnicode_WRITE(k, d, i, ch) (((void)(k)), ((Py_UNICODE*)d)[i] = ch) - #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_SIZE(u)) -#endif -#if CYTHON_COMPILING_IN_PYPY - #define __Pyx_PyUnicode_Concat(a, b) PyNumber_Add(a, b) - #define __Pyx_PyUnicode_ConcatSafe(a, b) PyNumber_Add(a, b) -#else - #define __Pyx_PyUnicode_Concat(a, b) PyUnicode_Concat(a, b) - #define __Pyx_PyUnicode_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ?\ - PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b)) -#endif -#if CYTHON_COMPILING_IN_PYPY && !defined(PyUnicode_Contains) - #define PyUnicode_Contains(u, s) PySequence_Contains(u, s) -#endif -#if CYTHON_COMPILING_IN_PYPY && !defined(PyByteArray_Check) - #define PyByteArray_Check(obj) PyObject_TypeCheck(obj, &PyByteArray_Type) -#endif -#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Format) - #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt) -#endif -#define __Pyx_PyString_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyString_Check(b) && !PyString_CheckExact(b)))) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b)) -#define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyUnicode_Check(b) && !PyUnicode_CheckExact(b)))) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b)) -#if PY_MAJOR_VERSION >= 3 - #define __Pyx_PyString_Format(a, b) PyUnicode_Format(a, b) -#else - #define __Pyx_PyString_Format(a, b) PyString_Format(a, b) -#endif -#if PY_MAJOR_VERSION < 3 && !defined(PyObject_ASCII) - #define PyObject_ASCII(o) PyObject_Repr(o) -#endif -#if PY_MAJOR_VERSION >= 3 - #define PyBaseString_Type PyUnicode_Type - #define PyStringObject PyUnicodeObject - #define PyString_Type PyUnicode_Type - #define PyString_Check PyUnicode_Check - #define PyString_CheckExact PyUnicode_CheckExact -#ifndef PyObject_Unicode - #define PyObject_Unicode PyObject_Str -#endif -#endif -#if PY_MAJOR_VERSION >= 3 - #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj) - #define __Pyx_PyBaseString_CheckExact(obj) PyUnicode_CheckExact(obj) -#else - #define __Pyx_PyBaseString_Check(obj) (PyString_Check(obj) || PyUnicode_Check(obj)) - #define __Pyx_PyBaseString_CheckExact(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj)) -#endif -#ifndef PySet_CheckExact - #define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type) -#endif -#if PY_VERSION_HEX >= 0x030900A4 - #define __Pyx_SET_REFCNT(obj, refcnt) Py_SET_REFCNT(obj, refcnt) - #define __Pyx_SET_SIZE(obj, size) Py_SET_SIZE(obj, size) -#else - #define __Pyx_SET_REFCNT(obj, refcnt) Py_REFCNT(obj) = (refcnt) - #define __Pyx_SET_SIZE(obj, size) Py_SIZE(obj) = (size) -#endif -#if CYTHON_ASSUME_SAFE_MACROS - #define __Pyx_PySequence_SIZE(seq) Py_SIZE(seq) -#else - #define __Pyx_PySequence_SIZE(seq) PySequence_Size(seq) -#endif -#if PY_MAJOR_VERSION >= 3 - #define PyIntObject PyLongObject - #define PyInt_Type PyLong_Type - #define PyInt_Check(op) PyLong_Check(op) - #define PyInt_CheckExact(op) PyLong_CheckExact(op) - #define PyInt_FromString PyLong_FromString - #define PyInt_FromUnicode PyLong_FromUnicode - #define PyInt_FromLong PyLong_FromLong - #define PyInt_FromSize_t PyLong_FromSize_t - #define PyInt_FromSsize_t PyLong_FromSsize_t - #define PyInt_AsLong PyLong_AsLong - #define PyInt_AS_LONG PyLong_AS_LONG - #define PyInt_AsSsize_t PyLong_AsSsize_t - #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask - #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask - #define PyNumber_Int PyNumber_Long -#endif -#if PY_MAJOR_VERSION >= 3 - #define PyBoolObject PyLongObject -#endif -#if PY_MAJOR_VERSION >= 3 && CYTHON_COMPILING_IN_PYPY - #ifndef PyUnicode_InternFromString - #define PyUnicode_InternFromString(s) PyUnicode_FromString(s) - #endif -#endif -#if PY_VERSION_HEX < 0x030200A4 - typedef long Py_hash_t; - #define __Pyx_PyInt_FromHash_t PyInt_FromLong - #define __Pyx_PyInt_AsHash_t PyInt_AsLong -#else - #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t - #define __Pyx_PyInt_AsHash_t PyInt_AsSsize_t -#endif -#if PY_MAJOR_VERSION >= 3 - #define __Pyx_PyMethod_New(func, self, klass) ((self) ? PyMethod_New(func, self) : (Py_INCREF(func), func)) -#else - #define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass) -#endif -#if CYTHON_USE_ASYNC_SLOTS - #if PY_VERSION_HEX >= 0x030500B1 - #define __Pyx_PyAsyncMethodsStruct PyAsyncMethods - #define __Pyx_PyType_AsAsync(obj) (Py_TYPE(obj)->tp_as_async) - #else - #define __Pyx_PyType_AsAsync(obj) ((__Pyx_PyAsyncMethodsStruct*) (Py_TYPE(obj)->tp_reserved)) - #endif -#else - #define __Pyx_PyType_AsAsync(obj) NULL -#endif -#ifndef __Pyx_PyAsyncMethodsStruct - typedef struct { - unaryfunc am_await; - unaryfunc am_aiter; - unaryfunc am_anext; - } __Pyx_PyAsyncMethodsStruct; -#endif - -#if defined(WIN32) || defined(MS_WINDOWS) - #define _USE_MATH_DEFINES -#endif -#include -#ifdef NAN -#define __PYX_NAN() ((float) NAN) -#else -static CYTHON_INLINE float __PYX_NAN() { - float value; - memset(&value, 0xFF, sizeof(value)); - return value; -} -#endif -#if defined(__CYGWIN__) && defined(_LDBL_EQ_DBL) -#define __Pyx_truncl trunc -#else -#define __Pyx_truncl truncl -#endif - -#define __PYX_MARK_ERR_POS(f_index, lineno) \ - { __pyx_filename = __pyx_f[f_index]; (void)__pyx_filename; __pyx_lineno = lineno; (void)__pyx_lineno; __pyx_clineno = __LINE__; (void)__pyx_clineno; } -#define __PYX_ERR(f_index, lineno, Ln_error) \ - { __PYX_MARK_ERR_POS(f_index, lineno) goto Ln_error; } - -#ifndef __PYX_EXTERN_C - #ifdef __cplusplus - #define __PYX_EXTERN_C extern "C" - #else - #define __PYX_EXTERN_C extern - #endif -#endif - -#define __PYX_HAVE__networkx__algorithms__isomorphism___embedding__balanced_sequence_cython -#define __PYX_HAVE_API__networkx__algorithms__isomorphism___embedding__balanced_sequence_cython -/* Early includes */ -#ifdef _OPENMP -#include -#endif /* _OPENMP */ - -#if defined(PYREX_WITHOUT_ASSERTIONS) && !defined(CYTHON_WITHOUT_ASSERTIONS) -#define CYTHON_WITHOUT_ASSERTIONS -#endif - -typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* encoding; - const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; - -#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0 -#define __PYX_DEFAULT_STRING_ENCODING_IS_UTF8 0 -#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT (PY_MAJOR_VERSION >= 3 && __PYX_DEFAULT_STRING_ENCODING_IS_UTF8) -#define __PYX_DEFAULT_STRING_ENCODING "" -#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString -#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize -#define __Pyx_uchar_cast(c) ((unsigned char)c) -#define __Pyx_long_cast(x) ((long)x) -#define __Pyx_fits_Py_ssize_t(v, type, is_signed) (\ - (sizeof(type) < sizeof(Py_ssize_t)) ||\ - (sizeof(type) > sizeof(Py_ssize_t) &&\ - likely(v < (type)PY_SSIZE_T_MAX ||\ - v == (type)PY_SSIZE_T_MAX) &&\ - (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||\ - v == (type)PY_SSIZE_T_MIN))) ||\ - (sizeof(type) == sizeof(Py_ssize_t) &&\ - (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||\ - v == (type)PY_SSIZE_T_MAX))) ) -static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) { - return (size_t) i < (size_t) limit; -} -#if defined (__cplusplus) && __cplusplus >= 201103L - #include - #define __Pyx_sst_abs(value) std::abs(value) -#elif SIZEOF_INT >= SIZEOF_SIZE_T - #define __Pyx_sst_abs(value) abs(value) -#elif SIZEOF_LONG >= SIZEOF_SIZE_T - #define __Pyx_sst_abs(value) labs(value) -#elif defined (_MSC_VER) - #define __Pyx_sst_abs(value) ((Py_ssize_t)_abs64(value)) -#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - #define __Pyx_sst_abs(value) llabs(value) -#elif defined (__GNUC__) - #define __Pyx_sst_abs(value) __builtin_llabs(value) -#else - #define __Pyx_sst_abs(value) ((value<0) ? -value : value) -#endif -static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject*); -static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length); -#define __Pyx_PyByteArray_FromString(s) PyByteArray_FromStringAndSize((const char*)s, strlen((const char*)s)) -#define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l) -#define __Pyx_PyBytes_FromString PyBytes_FromString -#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize -static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*); -#if PY_MAJOR_VERSION < 3 - #define __Pyx_PyStr_FromString __Pyx_PyBytes_FromString - #define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize -#else - #define __Pyx_PyStr_FromString __Pyx_PyUnicode_FromString - #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize -#endif -#define __Pyx_PyBytes_AsWritableString(s) ((char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyBytes_AsWritableSString(s) ((signed char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyBytes_AsWritableUString(s) ((unsigned char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyBytes_AsString(s) ((const char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyBytes_AsSString(s) ((const signed char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyBytes_AsUString(s) ((const unsigned char*) PyBytes_AS_STRING(s)) -#define __Pyx_PyObject_AsWritableString(s) ((char*) __Pyx_PyObject_AsString(s)) -#define __Pyx_PyObject_AsWritableSString(s) ((signed char*) __Pyx_PyObject_AsString(s)) -#define __Pyx_PyObject_AsWritableUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s)) -#define __Pyx_PyObject_AsSString(s) ((const signed char*) __Pyx_PyObject_AsString(s)) -#define __Pyx_PyObject_AsUString(s) ((const unsigned char*) __Pyx_PyObject_AsString(s)) -#define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s) -#define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s) -#define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s) -#define __Pyx_PyStr_FromCString(s) __Pyx_PyStr_FromString((const char*)s) -#define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s) -static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) { - const Py_UNICODE *u_end = u; - while (*u_end++) ; - return (size_t)(u_end - u - 1); -} -#define __Pyx_PyUnicode_FromUnicode(u) PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u)) -#define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode -#define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode -#define __Pyx_NewRef(obj) (Py_INCREF(obj), obj) -#define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None) -static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b); -static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); -static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject*); -static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); -#define __Pyx_PySequence_Tuple(obj)\ - (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) -static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); -static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); -#if CYTHON_ASSUME_SAFE_MACROS -#define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) -#else -#define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x) -#endif -#define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x)) -#if PY_MAJOR_VERSION >= 3 -#define __Pyx_PyNumber_Int(x) (PyLong_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Long(x)) -#else -#define __Pyx_PyNumber_Int(x) (PyInt_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Int(x)) -#endif -#define __Pyx_PyNumber_Float(x) (PyFloat_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Float(x)) -#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII -static int __Pyx_sys_getdefaultencoding_not_ascii; -static int __Pyx_init_sys_getdefaultencoding_params(void) { - PyObject* sys; - PyObject* default_encoding = NULL; - PyObject* ascii_chars_u = NULL; - PyObject* ascii_chars_b = NULL; - const char* default_encoding_c; - sys = PyImport_ImportModule("sys"); - if (!sys) goto bad; - default_encoding = PyObject_CallMethod(sys, (char*) "getdefaultencoding", NULL); - Py_DECREF(sys); - if (!default_encoding) goto bad; - default_encoding_c = PyBytes_AsString(default_encoding); - if (!default_encoding_c) goto bad; - if (strcmp(default_encoding_c, "ascii") == 0) { - __Pyx_sys_getdefaultencoding_not_ascii = 0; - } else { - char ascii_chars[128]; - int c; - for (c = 0; c < 128; c++) { - ascii_chars[c] = c; - } - __Pyx_sys_getdefaultencoding_not_ascii = 1; - ascii_chars_u = PyUnicode_DecodeASCII(ascii_chars, 128, NULL); - if (!ascii_chars_u) goto bad; - ascii_chars_b = PyUnicode_AsEncodedString(ascii_chars_u, default_encoding_c, NULL); - if (!ascii_chars_b || !PyBytes_Check(ascii_chars_b) || memcmp(ascii_chars, PyBytes_AS_STRING(ascii_chars_b), 128) != 0) { - PyErr_Format( - PyExc_ValueError, - "This module compiled with c_string_encoding=ascii, but default encoding '%.200s' is not a superset of ascii.", - default_encoding_c); - goto bad; - } - Py_DECREF(ascii_chars_u); - Py_DECREF(ascii_chars_b); - } - Py_DECREF(default_encoding); - return 0; -bad: - Py_XDECREF(default_encoding); - Py_XDECREF(ascii_chars_u); - Py_XDECREF(ascii_chars_b); - return -1; -} -#endif -#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3 -#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL) -#else -#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL) -#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT -static char* __PYX_DEFAULT_STRING_ENCODING; -static int __Pyx_init_sys_getdefaultencoding_params(void) { - PyObject* sys; - PyObject* default_encoding = NULL; - char* default_encoding_c; - sys = PyImport_ImportModule("sys"); - if (!sys) goto bad; - default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL); - Py_DECREF(sys); - if (!default_encoding) goto bad; - default_encoding_c = PyBytes_AsString(default_encoding); - if (!default_encoding_c) goto bad; - __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c) + 1); - if (!__PYX_DEFAULT_STRING_ENCODING) goto bad; - strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c); - Py_DECREF(default_encoding); - return 0; -bad: - Py_XDECREF(default_encoding); - return -1; -} -#endif -#endif - - -/* Test for GCC > 2.95 */ -#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))) - #define likely(x) __builtin_expect(!!(x), 1) - #define unlikely(x) __builtin_expect(!!(x), 0) -#else /* !__GNUC__ or GCC < 2.95 */ - #define likely(x) (x) - #define unlikely(x) (x) -#endif /* __GNUC__ */ -static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; } - -static PyObject *__pyx_m = NULL; -static PyObject *__pyx_d; -static PyObject *__pyx_b; -static PyObject *__pyx_cython_runtime = NULL; -static PyObject *__pyx_empty_tuple; -static PyObject *__pyx_empty_bytes; -static PyObject *__pyx_empty_unicode; -static int __pyx_lineno; -static int __pyx_clineno = 0; -static const char * __pyx_cfilenm= __FILE__; -static const char *__pyx_filename; - - -static const char *__pyx_f[] = { - "_embedding/balanced_sequence_cython.pyx", -}; - -/*--- Type declarations ---*/ -struct __pyx_opt_args_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython; - -/* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":280 - * - * - * cdef generate_all_decomp_cython(seq, open_to_close, open_to_node=None): # <<<<<<<<<<<<<< - * """ - * Cython version of :func:`generate_all_decomp`. - */ -struct __pyx_opt_args_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython { - int __pyx_n; - PyObject *open_to_node; -}; - -/* --- Runtime support code (head) --- */ -/* Refnanny.proto */ -#ifndef CYTHON_REFNANNY - #define CYTHON_REFNANNY 0 -#endif -#if CYTHON_REFNANNY - typedef struct { - void (*INCREF)(void*, PyObject*, int); - void (*DECREF)(void*, PyObject*, int); - void (*GOTREF)(void*, PyObject*, int); - void (*GIVEREF)(void*, PyObject*, int); - void* (*SetupContext)(const char*, int, const char*); - void (*FinishContext)(void**); - } __Pyx_RefNannyAPIStruct; - static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; - static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); - #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL; -#ifdef WITH_THREAD - #define __Pyx_RefNannySetupContext(name, acquire_gil)\ - if (acquire_gil) {\ - PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\ - __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ - PyGILState_Release(__pyx_gilstate_save);\ - } else {\ - __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ - } -#else - #define __Pyx_RefNannySetupContext(name, acquire_gil)\ - __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) -#endif - #define __Pyx_RefNannyFinishContext()\ - __Pyx_RefNanny->FinishContext(&__pyx_refnanny) - #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__) - #define __Pyx_XINCREF(r) do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0) - #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0) - #define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0) - #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0) -#else - #define __Pyx_RefNannyDeclarations - #define __Pyx_RefNannySetupContext(name, acquire_gil) - #define __Pyx_RefNannyFinishContext() - #define __Pyx_INCREF(r) Py_INCREF(r) - #define __Pyx_DECREF(r) Py_DECREF(r) - #define __Pyx_GOTREF(r) - #define __Pyx_GIVEREF(r) - #define __Pyx_XINCREF(r) Py_XINCREF(r) - #define __Pyx_XDECREF(r) Py_XDECREF(r) - #define __Pyx_XGOTREF(r) - #define __Pyx_XGIVEREF(r) -#endif -#define __Pyx_XDECREF_SET(r, v) do {\ - PyObject *tmp = (PyObject *) r;\ - r = v; __Pyx_XDECREF(tmp);\ - } while (0) -#define __Pyx_DECREF_SET(r, v) do {\ - PyObject *tmp = (PyObject *) r;\ - r = v; __Pyx_DECREF(tmp);\ - } while (0) -#define __Pyx_CLEAR(r) do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0) -#define __Pyx_XCLEAR(r) do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0) - -/* PyObjectGetAttrStr.proto */ -#if CYTHON_USE_TYPE_SLOTS -static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name); -#else -#define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n) -#endif - -/* GetBuiltinName.proto */ -static PyObject *__Pyx_GetBuiltinName(PyObject *name); - -/* RaiseArgTupleInvalid.proto */ -static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, - Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); - -/* RaiseDoubleKeywords.proto */ -static void __Pyx_RaiseDoubleKeywordsError(const char* func_name, PyObject* kw_name); - -/* ParseKeywords.proto */ -static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[],\ - PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args,\ - const char* function_name); - -/* PyDictVersioning.proto */ -#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS -#define __PYX_DICT_VERSION_INIT ((PY_UINT64_T) -1) -#define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag) -#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\ - (version_var) = __PYX_GET_DICT_VERSION(dict);\ - (cache_var) = (value); -#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\ - static PY_UINT64_T __pyx_dict_version = 0;\ - static PyObject *__pyx_dict_cached_value = NULL;\ - if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\ - (VAR) = __pyx_dict_cached_value;\ - } else {\ - (VAR) = __pyx_dict_cached_value = (LOOKUP);\ - __pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\ - }\ -} -static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj); -static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj); -static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version); -#else -#define __PYX_GET_DICT_VERSION(dict) (0) -#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var) -#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP); -#endif - -/* GetModuleGlobalName.proto */ -#if CYTHON_USE_DICT_VERSIONS -#define __Pyx_GetModuleGlobalName(var, name) {\ - static PY_UINT64_T __pyx_dict_version = 0;\ - static PyObject *__pyx_dict_cached_value = NULL;\ - (var) = (likely(__pyx_dict_version == __PYX_GET_DICT_VERSION(__pyx_d))) ?\ - (likely(__pyx_dict_cached_value) ? __Pyx_NewRef(__pyx_dict_cached_value) : __Pyx_GetBuiltinName(name)) :\ - __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ -} -#define __Pyx_GetModuleGlobalNameUncached(var, name) {\ - PY_UINT64_T __pyx_dict_version;\ - PyObject *__pyx_dict_cached_value;\ - (var) = __Pyx__GetModuleGlobalName(name, &__pyx_dict_version, &__pyx_dict_cached_value);\ -} -static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value); -#else -#define __Pyx_GetModuleGlobalName(var, name) (var) = __Pyx__GetModuleGlobalName(name) -#define __Pyx_GetModuleGlobalNameUncached(var, name) (var) = __Pyx__GetModuleGlobalName(name) -static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name); -#endif - -/* PyFunctionFastCall.proto */ -#if CYTHON_FAST_PYCALL -#define __Pyx_PyFunction_FastCall(func, args, nargs)\ - __Pyx_PyFunction_FastCallDict((func), (args), (nargs), NULL) -#if 1 || PY_VERSION_HEX < 0x030600B1 -static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs); -#else -#define __Pyx_PyFunction_FastCallDict(func, args, nargs, kwargs) _PyFunction_FastCallDict(func, args, nargs, kwargs) -#endif -#define __Pyx_BUILD_ASSERT_EXPR(cond)\ - (sizeof(char [1 - 2*!(cond)]) - 1) -#ifndef Py_MEMBER_SIZE -#define Py_MEMBER_SIZE(type, member) sizeof(((type *)0)->member) -#endif - static size_t __pyx_pyframe_localsplus_offset = 0; - #include "frameobject.h" - #define __Pxy_PyFrame_Initialize_Offsets()\ - ((void)__Pyx_BUILD_ASSERT_EXPR(sizeof(PyFrameObject) == offsetof(PyFrameObject, f_localsplus) + Py_MEMBER_SIZE(PyFrameObject, f_localsplus)),\ - (void)(__pyx_pyframe_localsplus_offset = ((size_t)PyFrame_Type.tp_basicsize) - Py_MEMBER_SIZE(PyFrameObject, f_localsplus))) - #define __Pyx_PyFrame_GetLocalsplus(frame)\ - (assert(__pyx_pyframe_localsplus_offset), (PyObject **)(((char *)(frame)) + __pyx_pyframe_localsplus_offset)) -#endif - -/* PyObjectCall.proto */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw); -#else -#define __Pyx_PyObject_Call(func, arg, kw) PyObject_Call(func, arg, kw) -#endif - -/* PyObjectCallMethO.proto */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg); -#endif - -/* PyObjectCallNoArg.proto */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func); -#else -#define __Pyx_PyObject_CallNoArg(func) __Pyx_PyObject_Call(func, __pyx_empty_tuple, NULL) -#endif - -/* PyCFunctionFastCall.proto */ -#if CYTHON_FAST_PYCCALL -static CYTHON_INLINE PyObject *__Pyx_PyCFunction_FastCall(PyObject *func, PyObject **args, Py_ssize_t nargs); -#else -#define __Pyx_PyCFunction_FastCall(func, args, nargs) (assert(0), NULL) -#endif - -/* PyObjectCallOneArg.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg); - -/* PyThreadStateGet.proto */ -#if CYTHON_FAST_THREAD_STATE -#define __Pyx_PyThreadState_declare PyThreadState *__pyx_tstate; -#define __Pyx_PyThreadState_assign __pyx_tstate = __Pyx_PyThreadState_Current; -#define __Pyx_PyErr_Occurred() __pyx_tstate->curexc_type -#else -#define __Pyx_PyThreadState_declare -#define __Pyx_PyThreadState_assign -#define __Pyx_PyErr_Occurred() PyErr_Occurred() -#endif - -/* PyErrFetchRestore.proto */ -#if CYTHON_FAST_THREAD_STATE -#define __Pyx_PyErr_Clear() __Pyx_ErrRestore(NULL, NULL, NULL) -#define __Pyx_ErrRestoreWithState(type, value, tb) __Pyx_ErrRestoreInState(PyThreadState_GET(), type, value, tb) -#define __Pyx_ErrFetchWithState(type, value, tb) __Pyx_ErrFetchInState(PyThreadState_GET(), type, value, tb) -#define __Pyx_ErrRestore(type, value, tb) __Pyx_ErrRestoreInState(__pyx_tstate, type, value, tb) -#define __Pyx_ErrFetch(type, value, tb) __Pyx_ErrFetchInState(__pyx_tstate, type, value, tb) -static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); -static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); -#if CYTHON_COMPILING_IN_CPYTHON -#define __Pyx_PyErr_SetNone(exc) (Py_INCREF(exc), __Pyx_ErrRestore((exc), NULL, NULL)) -#else -#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) -#endif -#else -#define __Pyx_PyErr_Clear() PyErr_Clear() -#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) -#define __Pyx_ErrRestoreWithState(type, value, tb) PyErr_Restore(type, value, tb) -#define __Pyx_ErrFetchWithState(type, value, tb) PyErr_Fetch(type, value, tb) -#define __Pyx_ErrRestoreInState(tstate, type, value, tb) PyErr_Restore(type, value, tb) -#define __Pyx_ErrFetchInState(tstate, type, value, tb) PyErr_Fetch(type, value, tb) -#define __Pyx_ErrRestore(type, value, tb) PyErr_Restore(type, value, tb) -#define __Pyx_ErrFetch(type, value, tb) PyErr_Fetch(type, value, tb) -#endif - -/* IterNext.proto */ -#define __Pyx_PyIter_Next(obj) __Pyx_PyIter_Next2(obj, NULL) -static CYTHON_INLINE PyObject *__Pyx_PyIter_Next2(PyObject *, PyObject *); - -/* GetItemInt.proto */ -#define __Pyx_GetItemInt(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ - (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ - __Pyx_GetItemInt_Fast(o, (Py_ssize_t)i, is_list, wraparound, boundscheck) :\ - (is_list ? (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL) :\ - __Pyx_GetItemInt_Generic(o, to_py_func(i)))) -#define __Pyx_GetItemInt_List(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ - (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ - __Pyx_GetItemInt_List_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) :\ - (PyErr_SetString(PyExc_IndexError, "list index out of range"), (PyObject*)NULL)) -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, - int wraparound, int boundscheck); -#define __Pyx_GetItemInt_Tuple(o, i, type, is_signed, to_py_func, is_list, wraparound, boundscheck)\ - (__Pyx_fits_Py_ssize_t(i, type, is_signed) ?\ - __Pyx_GetItemInt_Tuple_Fast(o, (Py_ssize_t)i, wraparound, boundscheck) :\ - (PyErr_SetString(PyExc_IndexError, "tuple index out of range"), (PyObject*)NULL)) -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, - int wraparound, int boundscheck); -static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j); -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, - int is_list, int wraparound, int boundscheck); - -/* ObjectGetItem.proto */ -#if CYTHON_USE_TYPE_SLOTS -static CYTHON_INLINE PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject* key); -#else -#define __Pyx_PyObject_GetItem(obj, key) PyObject_GetItem(obj, key) -#endif - -/* RaiseTooManyValuesToUnpack.proto */ -static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected); - -/* RaiseNeedMoreValuesToUnpack.proto */ -static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index); - -/* IterFinish.proto */ -static CYTHON_INLINE int __Pyx_IterFinish(void); - -/* UnpackItemEndCheck.proto */ -static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected); - -/* PyDictContains.proto */ -static CYTHON_INLINE int __Pyx_PyDict_ContainsTF(PyObject* item, PyObject* dict, int eq) { - int result = PyDict_Contains(dict, item); - return unlikely(result < 0) ? result : (result == (eq == Py_EQ)); -} - -/* DictGetItem.proto */ -#if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY -static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key); -#define __Pyx_PyObject_Dict_GetItem(obj, name)\ - (likely(PyDict_CheckExact(obj)) ?\ - __Pyx_PyDict_GetItem(obj, name) : PyObject_GetItem(obj, name)) -#else -#define __Pyx_PyDict_GetItem(d, key) PyObject_GetItem(d, key) -#define __Pyx_PyObject_Dict_GetItem(obj, name) PyObject_GetItem(obj, name) -#endif - -/* ListAppend.proto */ -#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS -static CYTHON_INLINE int __Pyx_PyList_Append(PyObject* list, PyObject* x) { - PyListObject* L = (PyListObject*) list; - Py_ssize_t len = Py_SIZE(list); - if (likely(L->allocated > len) & likely(len > (L->allocated >> 1))) { - Py_INCREF(x); - PyList_SET_ITEM(list, len, x); - __Pyx_SET_SIZE(list, len + 1); - return 0; - } - return PyList_Append(list, x); -} -#else -#define __Pyx_PyList_Append(L,x) PyList_Append(L,x) -#endif - -/* PyObjectGetMethod.proto */ -static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method); - -/* PyObjectCallMethod0.proto */ -static PyObject* __Pyx_PyObject_CallMethod0(PyObject* obj, PyObject* method_name); - -/* pop.proto */ -static CYTHON_INLINE PyObject* __Pyx__PyObject_Pop(PyObject* L); -#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS -static CYTHON_INLINE PyObject* __Pyx_PyList_Pop(PyObject* L); -#define __Pyx_PyObject_Pop(L) (likely(PyList_CheckExact(L)) ?\ - __Pyx_PyList_Pop(L) : __Pyx__PyObject_Pop(L)) -#else -#define __Pyx_PyList_Pop(L) __Pyx__PyObject_Pop(L) -#define __Pyx_PyObject_Pop(L) __Pyx__PyObject_Pop(L) -#endif - -/* UnpackUnboundCMethod.proto */ -typedef struct { - PyObject *type; - PyObject **method_name; - PyCFunction func; - PyObject *method; - int flag; -} __Pyx_CachedCFunction; - -/* CallUnboundCMethod0.proto */ -static PyObject* __Pyx__CallUnboundCMethod0(__Pyx_CachedCFunction* cfunc, PyObject* self); -#if CYTHON_COMPILING_IN_CPYTHON -#define __Pyx_CallUnboundCMethod0(cfunc, self)\ - (likely((cfunc)->func) ?\ - (likely((cfunc)->flag == METH_NOARGS) ? (*((cfunc)->func))(self, NULL) :\ - (PY_VERSION_HEX >= 0x030600B1 && likely((cfunc)->flag == METH_FASTCALL) ?\ - (PY_VERSION_HEX >= 0x030700A0 ?\ - (*(__Pyx_PyCFunctionFast)(void*)(PyCFunction)(cfunc)->func)(self, &__pyx_empty_tuple, 0) :\ - (*(__Pyx_PyCFunctionFastWithKeywords)(void*)(PyCFunction)(cfunc)->func)(self, &__pyx_empty_tuple, 0, NULL)) :\ - (PY_VERSION_HEX >= 0x030700A0 && (cfunc)->flag == (METH_FASTCALL | METH_KEYWORDS) ?\ - (*(__Pyx_PyCFunctionFastWithKeywords)(void*)(PyCFunction)(cfunc)->func)(self, &__pyx_empty_tuple, 0, NULL) :\ - (likely((cfunc)->flag == (METH_VARARGS | METH_KEYWORDS)) ? ((*(PyCFunctionWithKeywords)(void*)(PyCFunction)(cfunc)->func)(self, __pyx_empty_tuple, NULL)) :\ - ((cfunc)->flag == METH_VARARGS ? (*((cfunc)->func))(self, __pyx_empty_tuple) :\ - __Pyx__CallUnboundCMethod0(cfunc, self)))))) :\ - __Pyx__CallUnboundCMethod0(cfunc, self)) -#else -#define __Pyx_CallUnboundCMethod0(cfunc, self) __Pyx__CallUnboundCMethod0(cfunc, self) -#endif - -/* py_dict_keys.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyDict_Keys(PyObject* d); - -/* py_dict_items.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyDict_Items(PyObject* d); - -/* SliceObject.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyObject_GetSlice( - PyObject* obj, Py_ssize_t cstart, Py_ssize_t cstop, - PyObject** py_start, PyObject** py_stop, PyObject** py_slice, - int has_cstart, int has_cstop, int wraparound); - -/* RaiseNoneIterError.proto */ -static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void); - -/* None.proto */ -static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname); - -/* SliceTupleAndList.proto */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyList_GetSlice(PyObject* src, Py_ssize_t start, Py_ssize_t stop); -static CYTHON_INLINE PyObject* __Pyx_PyTuple_GetSlice(PyObject* src, Py_ssize_t start, Py_ssize_t stop); -#else -#define __Pyx_PyList_GetSlice(seq, start, stop) PySequence_GetSlice(seq, start, stop) -#define __Pyx_PyTuple_GetSlice(seq, start, stop) PySequence_GetSlice(seq, start, stop) -#endif - -/* FetchCommonType.proto */ -static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type); - -/* CythonFunctionShared.proto */ -#define __Pyx_CyFunction_USED 1 -#define __Pyx_CYFUNCTION_STATICMETHOD 0x01 -#define __Pyx_CYFUNCTION_CLASSMETHOD 0x02 -#define __Pyx_CYFUNCTION_CCLASS 0x04 -#define __Pyx_CyFunction_GetClosure(f)\ - (((__pyx_CyFunctionObject *) (f))->func_closure) -#define __Pyx_CyFunction_GetClassObj(f)\ - (((__pyx_CyFunctionObject *) (f))->func_classobj) -#define __Pyx_CyFunction_Defaults(type, f)\ - ((type *)(((__pyx_CyFunctionObject *) (f))->defaults)) -#define __Pyx_CyFunction_SetDefaultsGetter(f, g)\ - ((__pyx_CyFunctionObject *) (f))->defaults_getter = (g) -typedef struct { - PyCFunctionObject func; -#if PY_VERSION_HEX < 0x030500A0 - PyObject *func_weakreflist; -#endif - PyObject *func_dict; - PyObject *func_name; - PyObject *func_qualname; - PyObject *func_doc; - PyObject *func_globals; - PyObject *func_code; - PyObject *func_closure; - PyObject *func_classobj; - void *defaults; - int defaults_pyobjects; - size_t defaults_size; // used by FusedFunction for copying defaults - int flags; - PyObject *defaults_tuple; - PyObject *defaults_kwdict; - PyObject *(*defaults_getter)(PyObject *); - PyObject *func_annotations; -} __pyx_CyFunctionObject; -static PyTypeObject *__pyx_CyFunctionType = 0; -#define __Pyx_CyFunction_Check(obj) (__Pyx_TypeCheck(obj, __pyx_CyFunctionType)) -static PyObject *__Pyx_CyFunction_Init(__pyx_CyFunctionObject* op, PyMethodDef *ml, - int flags, PyObject* qualname, - PyObject *self, - PyObject *module, PyObject *globals, - PyObject* code); -static CYTHON_INLINE void *__Pyx_CyFunction_InitDefaults(PyObject *m, - size_t size, - int pyobjects); -static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsTuple(PyObject *m, - PyObject *tuple); -static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsKwDict(PyObject *m, - PyObject *dict); -static CYTHON_INLINE void __Pyx_CyFunction_SetAnnotationsDict(PyObject *m, - PyObject *dict); -static int __pyx_CyFunction_init(void); - -/* CythonFunction.proto */ -static PyObject *__Pyx_CyFunction_New(PyMethodDef *ml, - int flags, PyObject* qualname, - PyObject *closure, - PyObject *module, PyObject *globals, - PyObject* code); - -/* SetNameInClass.proto */ -#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 -#define __Pyx_SetNameInClass(ns, name, value)\ - (likely(PyDict_CheckExact(ns)) ? _PyDict_SetItem_KnownHash(ns, name, value, ((PyASCIIObject *) name)->hash) : PyObject_SetItem(ns, name, value)) -#elif CYTHON_COMPILING_IN_CPYTHON -#define __Pyx_SetNameInClass(ns, name, value)\ - (likely(PyDict_CheckExact(ns)) ? PyDict_SetItem(ns, name, value) : PyObject_SetItem(ns, name, value)) -#else -#define __Pyx_SetNameInClass(ns, name, value) PyObject_SetItem(ns, name, value) -#endif - -/* CalculateMetaclass.proto */ -static PyObject *__Pyx_CalculateMetaclass(PyTypeObject *metaclass, PyObject *bases); - -/* Py3ClassCreate.proto */ -static PyObject *__Pyx_Py3MetaclassPrepare(PyObject *metaclass, PyObject *bases, PyObject *name, PyObject *qualname, - PyObject *mkw, PyObject *modname, PyObject *doc); -static PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObject *bases, PyObject *dict, - PyObject *mkw, int calculate_metaclass, int allow_py2_metaclass); - -/* CLineInTraceback.proto */ -#ifdef CYTHON_CLINE_IN_TRACEBACK -#define __Pyx_CLineForTraceback(tstate, c_line) (((CYTHON_CLINE_IN_TRACEBACK)) ? c_line : 0) -#else -static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line); -#endif - -/* CodeObjectCache.proto */ -typedef struct { - PyCodeObject* code_object; - int code_line; -} __Pyx_CodeObjectCacheEntry; -struct __Pyx_CodeObjectCache { - int count; - int max_count; - __Pyx_CodeObjectCacheEntry* entries; -}; -static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL}; -static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line); -static PyCodeObject *__pyx_find_code_object(int code_line); -static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object); - -/* AddTraceback.proto */ -static void __Pyx_AddTraceback(const char *funcname, int c_line, - int py_line, const char *filename); - -/* CIntToPy.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); - -/* CIntToPy.proto */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value); - -/* CIntFromPy.proto */ -static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *); - -/* CIntFromPy.proto */ -static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *); - -/* FastTypeChecks.proto */ -#if CYTHON_COMPILING_IN_CPYTHON -#define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type) -static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b); -static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type); -static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2); -#else -#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) -#define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type) -#define __Pyx_PyErr_GivenExceptionMatches2(err, type1, type2) (PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2)) -#endif -#define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception) - -/* CheckBinaryVersion.proto */ -static int __Pyx_check_binary_version(void); - -/* InitStrings.proto */ -static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); - - -/* Module declarations from 'networkx.algorithms.isomorphism._embedding.balanced_sequence_cython' */ -static PyObject *__pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_balanced_decomp_unsafe_cython(PyObject *, PyObject *); /*proto*/ -static PyObject *__pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython(PyObject *, PyObject *, struct __pyx_opt_args_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython *__pyx_optional_args); /*proto*/ -static PyObject *__pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_balanced_decomp_prehash_cython(PyObject *, PyObject *, PyObject *); /*proto*/ -static PyObject *__pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_prehash_cython(PyObject *, PyObject *, PyObject *); /*proto*/ -#define __Pyx_MODULE_NAME "networkx.algorithms.isomorphism._embedding.balanced_sequence_cython" -extern int __pyx_module_is_main_networkx__algorithms__isomorphism___embedding__balanced_sequence_cython; -int __pyx_module_is_main_networkx__algorithms__isomorphism___embedding__balanced_sequence_cython = 0; - -/* Implementation of 'networkx.algorithms.isomorphism._embedding.balanced_sequence_cython' */ -static PyObject *__pyx_builtin_range; -static const char __pyx_k_a1[] = "a1"; -static const char __pyx_k_a2[] = "a2"; -static const char __pyx_k_b1[] = "b1"; -static const char __pyx_k_b2[] = "b2"; -static const char __pyx_k_t1[] = "t1"; -static const char __pyx_k_t2[] = "t2"; -static const char __pyx_k_doc[] = "__doc__"; -static const char __pyx_k_key[] = "key"; -static const char __pyx_k_pop[] = "pop"; -static const char __pyx_k_val[] = "val"; -static const char __pyx_k_best[] = "best"; -static const char __pyx_k_key0[] = "key0"; -static const char __pyx_k_key1[] = "key1"; -static const char __pyx_k_key2[] = "key2"; -static const char __pyx_k_keys[] = "keys"; -static const char __pyx_k_main[] = "__main__"; -static const char __pyx_k_name[] = "__name__"; -static const char __pyx_k_res3[] = "res3"; -static const char __pyx_k_self[] = "self"; -static const char __pyx_k_seq1[] = "seq1"; -static const char __pyx_k_seq2[] = "seq2"; -static const char __pyx_k_test[] = "__test__"; -static const char __pyx_k_tok1[] = "tok1"; -static const char __pyx_k_tok2[] = "tok2"; -static const char __pyx_k_val3[] = "val3"; -static const char __pyx_k_cand1[] = "cand1"; -static const char __pyx_k_cand2[] = "cand2"; -static const char __pyx_k_cand3[] = "cand3"; -static const char __pyx_k_found[] = "found"; -static const char __pyx_k_frame[] = "frame"; -static const char __pyx_k_head1[] = "head1"; -static const char __pyx_k_head2[] = "head2"; -static const char __pyx_k_info1[] = "info1"; -static const char __pyx_k_info2[] = "info2"; -static const char __pyx_k_items[] = "items"; -static const char __pyx_k_range[] = "range"; -static const char __pyx_k_stack[] = "stack"; -static const char __pyx_k_tail1[] = "tail1"; -static const char __pyx_k_tail2[] = "tail2"; -static const char __pyx_k_empty1[] = "empty1"; -static const char __pyx_k_empty2[] = "empty2"; -static const char __pyx_k_frame0[] = "frame0"; -static const char __pyx_k_module[] = "__module__"; -static const char __pyx_k_pval_h[] = "pval_h"; -static const char __pyx_k_pval_t[] = "pval_t"; -static const char __pyx_k_getitem[] = "__getitem__"; -static const char __pyx_k_prepare[] = "__prepare__"; -static const char __pyx_k_results[] = "_results"; -static const char __pyx_k_subseq1[] = "subseq1"; -static const char __pyx_k_subseq2[] = "subseq2"; -static const char __pyx_k_try_key[] = "try_key"; -static const char __pyx_k_affinity[] = "affinity"; -static const char __pyx_k_qualname[] = "__qualname__"; -static const char __pyx_k_seq1_key[] = "seq1_key"; -static const char __pyx_k_seq2_key[] = "seq2_key"; -static const char __pyx_k_full_seq1[] = "full_seq1"; -static const char __pyx_k_full_seq2[] = "full_seq2"; -static const char __pyx_k_head1_key[] = "head1_key"; -static const char __pyx_k_head2_key[] = "head2_key"; -static const char __pyx_k_metaclass[] = "__metaclass__"; -static const char __pyx_k_new_head1[] = "new_head1"; -static const char __pyx_k_new_head2[] = "new_head2"; -static const char __pyx_k_new_heads[] = "new_heads"; -static const char __pyx_k_new_tail1[] = "new_tail1"; -static const char __pyx_k_new_tail2[] = "new_tail2"; -static const char __pyx_k_new_tails[] = "new_tails"; -static const char __pyx_k_tail1_key[] = "tail1_key"; -static const char __pyx_k_tail2_key[] = "tail2_key"; -static const char __pyx_k_empty1_key[] = "empty1_key"; -static const char __pyx_k_empty2_key[] = "empty2_key"; -static const char __pyx_k_head_tail1[] = "head_tail1"; -static const char __pyx_k_head_tail2[] = "head_tail2"; -static const char __pyx_k_miss_frame[] = "miss_frame"; -static const char __pyx_k_all_decomp1[] = "all_decomp1"; -static const char __pyx_k_all_decomp2[] = "all_decomp2"; -static const char __pyx_k_base_result[] = "base_result"; -static const char __pyx_k_key_decomp1[] = "key_decomp1"; -static const char __pyx_k_key_decomp2[] = "key_decomp2"; -static const char __pyx_k_IdentityDict[] = "IdentityDict"; -static const char __pyx_k_open_to_node[] = "open_to_node"; -static const char __pyx_k_full_seq1_key[] = "full_seq1_key"; -static const char __pyx_k_full_seq2_key[] = "full_seq2_key"; -static const char __pyx_k_node_affinity[] = "node_affinity"; -static const char __pyx_k_open_to_close[] = "open_to_close"; -static const char __pyx_k_head_tail1_key[] = "head_tail1_key"; -static const char __pyx_k_head_tail2_key[] = "head_tail2_key"; -static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback"; -static const char __pyx_k_IdentityDict___getitem[] = "IdentityDict.__getitem__"; -static const char __pyx_k_lcs_iter_prehash2_cython[] = "_lcs_iter_prehash2_cython"; -static const char __pyx_k_lcs_iter_simple_alt2_cython[] = "_lcs_iter_simple_alt2_cython"; -static const char __pyx_k_This_module_re_implements_funct[] = "\nThis module re-implements functions in :module:`balanced_sequence` in cython\nand obtains 40-50x speedups in common circumstances. There are likely more\nspeed improvements that could be made.\n\nCommandLine\n-----------\n# Explicitly build this cython module\ncythonize -a -i $HOME/code/networkx/networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx\n\n\nExamples\n--------\n>>> from networkx.algorithms.isomorphism._embedding.balanced_sequence_cython import *\n>>> from networkx.algorithms.isomorphism._embedding.demodata import random_balanced_sequence\n>>> seq1, open_to_close1 = random_balanced_sequence(300, mode='paren')\n>>> seq2, open_to_close2 = random_balanced_sequence(300, mode='paren')\n>>> open_to_close = {**open_to_close1, **open_to_close2}\n>>> full_seq1 = seq1\n>>> full_seq2 = seq2\n>>> import operator\n>>> node_affinity = operator.eq\n>>> open_to_node = IdentityDict()\n\nwith ub.Timer('cython'):\n best, value = _lcs_iter_simple_alt2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node)\n\nwith ub.Timer('python'):\n best, value = _lcs_iter_simple_alt2(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node)\n\n"; -static const char __pyx_k_Used_when_open_to_node_is_unspe[] = " Used when ``open_to_node`` is unspecified "; -static const char __pyx_k_embedding_balanced_sequence_cyt[] = "_embedding/balanced_sequence_cython.pyx"; -static const char __pyx_k_networkx_algorithms_isomorphism[] = "networkx.algorithms.isomorphism._embedding.balanced_sequence_cython"; -static PyObject *__pyx_n_s_IdentityDict; -static PyObject *__pyx_n_s_IdentityDict___getitem; -static PyObject *__pyx_kp_s_Used_when_open_to_node_is_unspe; -static PyObject *__pyx_n_s_a1; -static PyObject *__pyx_n_s_a2; -static PyObject *__pyx_n_s_affinity; -static PyObject *__pyx_n_s_all_decomp1; -static PyObject *__pyx_n_s_all_decomp2; -static PyObject *__pyx_n_s_b1; -static PyObject *__pyx_n_s_b2; -static PyObject *__pyx_n_s_base_result; -static PyObject *__pyx_n_s_best; -static PyObject *__pyx_n_s_cand1; -static PyObject *__pyx_n_s_cand2; -static PyObject *__pyx_n_s_cand3; -static PyObject *__pyx_n_s_cline_in_traceback; -static PyObject *__pyx_n_s_doc; -static PyObject *__pyx_kp_s_embedding_balanced_sequence_cyt; -static PyObject *__pyx_n_s_empty1; -static PyObject *__pyx_n_s_empty1_key; -static PyObject *__pyx_n_s_empty2; -static PyObject *__pyx_n_s_empty2_key; -static PyObject *__pyx_n_s_found; -static PyObject *__pyx_n_s_frame; -static PyObject *__pyx_n_s_frame0; -static PyObject *__pyx_n_s_full_seq1; -static PyObject *__pyx_n_s_full_seq1_key; -static PyObject *__pyx_n_s_full_seq2; -static PyObject *__pyx_n_s_full_seq2_key; -static PyObject *__pyx_n_s_getitem; -static PyObject *__pyx_n_s_head1; -static PyObject *__pyx_n_s_head1_key; -static PyObject *__pyx_n_s_head2; -static PyObject *__pyx_n_s_head2_key; -static PyObject *__pyx_n_s_head_tail1; -static PyObject *__pyx_n_s_head_tail1_key; -static PyObject *__pyx_n_s_head_tail2; -static PyObject *__pyx_n_s_head_tail2_key; -static PyObject *__pyx_n_s_info1; -static PyObject *__pyx_n_s_info2; -static PyObject *__pyx_n_s_items; -static PyObject *__pyx_n_s_key; -static PyObject *__pyx_n_s_key0; -static PyObject *__pyx_n_s_key1; -static PyObject *__pyx_n_s_key2; -static PyObject *__pyx_n_s_key_decomp1; -static PyObject *__pyx_n_s_key_decomp2; -static PyObject *__pyx_n_s_keys; -static PyObject *__pyx_n_s_lcs_iter_prehash2_cython; -static PyObject *__pyx_n_s_lcs_iter_simple_alt2_cython; -static PyObject *__pyx_n_s_main; -static PyObject *__pyx_n_s_metaclass; -static PyObject *__pyx_n_s_miss_frame; -static PyObject *__pyx_n_s_module; -static PyObject *__pyx_n_s_name; -static PyObject *__pyx_n_s_networkx_algorithms_isomorphism; -static PyObject *__pyx_n_s_new_head1; -static PyObject *__pyx_n_s_new_head2; -static PyObject *__pyx_n_s_new_heads; -static PyObject *__pyx_n_s_new_tail1; -static PyObject *__pyx_n_s_new_tail2; -static PyObject *__pyx_n_s_new_tails; -static PyObject *__pyx_n_s_node_affinity; -static PyObject *__pyx_n_s_open_to_close; -static PyObject *__pyx_n_s_open_to_node; -static PyObject *__pyx_n_s_pop; -static PyObject *__pyx_n_s_prepare; -static PyObject *__pyx_n_s_pval_h; -static PyObject *__pyx_n_s_pval_t; -static PyObject *__pyx_n_s_qualname; -static PyObject *__pyx_n_s_range; -static PyObject *__pyx_n_s_res3; -static PyObject *__pyx_n_s_results; -static PyObject *__pyx_n_s_self; -static PyObject *__pyx_n_s_seq1; -static PyObject *__pyx_n_s_seq1_key; -static PyObject *__pyx_n_s_seq2; -static PyObject *__pyx_n_s_seq2_key; -static PyObject *__pyx_n_s_stack; -static PyObject *__pyx_n_s_subseq1; -static PyObject *__pyx_n_s_subseq2; -static PyObject *__pyx_n_s_t1; -static PyObject *__pyx_n_s_t2; -static PyObject *__pyx_n_s_tail1; -static PyObject *__pyx_n_s_tail1_key; -static PyObject *__pyx_n_s_tail2; -static PyObject *__pyx_n_s_tail2_key; -static PyObject *__pyx_n_s_test; -static PyObject *__pyx_n_s_tok1; -static PyObject *__pyx_n_s_tok2; -static PyObject *__pyx_n_s_try_key; -static PyObject *__pyx_n_s_val; -static PyObject *__pyx_n_s_val3; -static PyObject *__pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython__lcs_iter_simple_alt2_cython(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_full_seq1, PyObject *__pyx_v_full_seq2, PyObject *__pyx_v_open_to_close, PyObject *__pyx_v_node_affinity, PyObject *__pyx_v_open_to_node); /* proto */ -static PyObject *__pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_2_lcs_iter_prehash2_cython(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_full_seq1, PyObject *__pyx_v_full_seq2, PyObject *__pyx_v_open_to_close, PyObject *__pyx_v_node_affinity, PyObject *__pyx_v_open_to_node); /* proto */ -static PyObject *__pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict___getitem__(CYTHON_UNUSED PyObject *__pyx_self, CYTHON_UNUSED PyObject *__pyx_v_self, PyObject *__pyx_v_key); /* proto */ -static __Pyx_CachedCFunction __pyx_umethod_PyDict_Type_items = {0, &__pyx_n_s_items, 0, 0, 0}; -static __Pyx_CachedCFunction __pyx_umethod_PyDict_Type_keys = {0, &__pyx_n_s_keys, 0, 0, 0}; -static __Pyx_CachedCFunction __pyx_umethod_PyList_Type_pop = {0, &__pyx_n_s_pop, 0, 0, 0}; -static PyObject *__pyx_int_0; -static PyObject *__pyx_int_1; -static PyObject *__pyx_int_5; -static PyObject *__pyx_int_8; -static PyObject *__pyx_int_neg_1; -static PyObject *__pyx_tuple_; -static PyObject *__pyx_slice__2; -static PyObject *__pyx_slice__3; -static PyObject *__pyx_tuple__4; -static PyObject *__pyx_tuple__6; -static PyObject *__pyx_tuple__8; -static PyObject *__pyx_codeobj__5; -static PyObject *__pyx_codeobj__7; -static PyObject *__pyx_codeobj__9; -/* Late includes */ - -/* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":35 - * - * - * def _lcs_iter_simple_alt2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node): # <<<<<<<<<<<<<< - * """ - * Depth first stack trajectory and replace try except statements with ifs - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_1_lcs_iter_simple_alt2_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static char __pyx_doc_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython__lcs_iter_simple_alt2_cython[] = "\n Depth first stack trajectory and replace try except statements with ifs\n "; -static PyMethodDef __pyx_mdef_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_1_lcs_iter_simple_alt2_cython = {"_lcs_iter_simple_alt2_cython", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_1_lcs_iter_simple_alt2_cython, METH_VARARGS|METH_KEYWORDS, __pyx_doc_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython__lcs_iter_simple_alt2_cython}; -static PyObject *__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_1_lcs_iter_simple_alt2_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { - PyObject *__pyx_v_full_seq1 = 0; - PyObject *__pyx_v_full_seq2 = 0; - PyObject *__pyx_v_open_to_close = 0; - PyObject *__pyx_v_node_affinity = 0; - PyObject *__pyx_v_open_to_node = 0; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("_lcs_iter_simple_alt2_cython (wrapper)", 0); - { - static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_full_seq1,&__pyx_n_s_full_seq2,&__pyx_n_s_open_to_close,&__pyx_n_s_node_affinity,&__pyx_n_s_open_to_node,0}; - PyObject* values[5] = {0,0,0,0,0}; - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args; - const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); - switch (pos_args) { - case 5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4); - CYTHON_FALLTHROUGH; - case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); - CYTHON_FALLTHROUGH; - case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); - CYTHON_FALLTHROUGH; - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - CYTHON_FALLTHROUGH; - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - CYTHON_FALLTHROUGH; - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - kw_args = PyDict_Size(__pyx_kwds); - switch (pos_args) { - case 0: - if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_full_seq1)) != 0)) kw_args--; - else goto __pyx_L5_argtuple_error; - CYTHON_FALLTHROUGH; - case 1: - if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_full_seq2)) != 0)) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("_lcs_iter_simple_alt2_cython", 1, 5, 5, 1); __PYX_ERR(0, 35, __pyx_L3_error) - } - CYTHON_FALLTHROUGH; - case 2: - if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_open_to_close)) != 0)) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("_lcs_iter_simple_alt2_cython", 1, 5, 5, 2); __PYX_ERR(0, 35, __pyx_L3_error) - } - CYTHON_FALLTHROUGH; - case 3: - if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_node_affinity)) != 0)) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("_lcs_iter_simple_alt2_cython", 1, 5, 5, 3); __PYX_ERR(0, 35, __pyx_L3_error) - } - CYTHON_FALLTHROUGH; - case 4: - if (likely((values[4] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_open_to_node)) != 0)) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("_lcs_iter_simple_alt2_cython", 1, 5, 5, 4); __PYX_ERR(0, 35, __pyx_L3_error) - } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "_lcs_iter_simple_alt2_cython") < 0)) __PYX_ERR(0, 35, __pyx_L3_error) - } - } else if (PyTuple_GET_SIZE(__pyx_args) != 5) { - goto __pyx_L5_argtuple_error; - } else { - values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - values[2] = PyTuple_GET_ITEM(__pyx_args, 2); - values[3] = PyTuple_GET_ITEM(__pyx_args, 3); - values[4] = PyTuple_GET_ITEM(__pyx_args, 4); - } - __pyx_v_full_seq1 = values[0]; - __pyx_v_full_seq2 = values[1]; - __pyx_v_open_to_close = values[2]; - __pyx_v_node_affinity = values[3]; - __pyx_v_open_to_node = values[4]; - } - goto __pyx_L4_argument_unpacking_done; - __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("_lcs_iter_simple_alt2_cython", 1, 5, 5, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 35, __pyx_L3_error) - __pyx_L3_error:; - __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython._lcs_iter_simple_alt2_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); - __Pyx_RefNannyFinishContext(); - return NULL; - __pyx_L4_argument_unpacking_done:; - __pyx_r = __pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython__lcs_iter_simple_alt2_cython(__pyx_self, __pyx_v_full_seq1, __pyx_v_full_seq2, __pyx_v_open_to_close, __pyx_v_node_affinity, __pyx_v_open_to_node); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython__lcs_iter_simple_alt2_cython(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_full_seq1, PyObject *__pyx_v_full_seq2, PyObject *__pyx_v_open_to_close, PyObject *__pyx_v_node_affinity, PyObject *__pyx_v_open_to_node) { - PyObject *__pyx_v_all_decomp1 = NULL; - PyObject *__pyx_v_all_decomp2 = NULL; - PyObject *__pyx_v_key0 = NULL; - PyObject *__pyx_v_frame0 = NULL; - PyObject *__pyx_v_stack = NULL; - PyObject *__pyx_v__results = NULL; - PyObject *__pyx_v_empty1 = NULL; - PyObject *__pyx_v_empty2 = NULL; - PyObject *__pyx_v_best = NULL; - PyObject *__pyx_v_base_result = NULL; - PyObject *__pyx_v_seq1 = NULL; - PyObject *__pyx_v_key1 = NULL; - PyObject *__pyx_v_t1 = NULL; - PyObject *__pyx_v_a1 = NULL; - PyObject *__pyx_v_b1 = NULL; - PyObject *__pyx_v_head1 = NULL; - PyObject *__pyx_v_tail1 = NULL; - PyObject *__pyx_v_head_tail1 = NULL; - PyObject *__pyx_v_seq2 = NULL; - PyObject *__pyx_v_key2 = NULL; - PyObject *__pyx_v_t2 = NULL; - PyObject *__pyx_v_a2 = NULL; - PyObject *__pyx_v_b2 = NULL; - PyObject *__pyx_v_head2 = NULL; - PyObject *__pyx_v_tail2 = NULL; - PyObject *__pyx_v_head_tail2 = NULL; - PyObject *__pyx_v_key = NULL; - PyObject *__pyx_v_try_key = NULL; - PyObject *__pyx_v_cand1 = NULL; - PyObject *__pyx_v_cand2 = NULL; - PyObject *__pyx_v_affinity = NULL; - PyObject *__pyx_v_pval_h = NULL; - PyObject *__pyx_v_new_heads = NULL; - PyObject *__pyx_v_pval_t = NULL; - PyObject *__pyx_v_new_tails = NULL; - PyObject *__pyx_v_new_head1 = NULL; - PyObject *__pyx_v_new_head2 = NULL; - PyObject *__pyx_v_new_tail1 = NULL; - PyObject *__pyx_v_new_tail2 = NULL; - PyObject *__pyx_v_subseq1 = NULL; - PyObject *__pyx_v_subseq2 = NULL; - PyObject *__pyx_v_res3 = NULL; - PyObject *__pyx_v_val3 = NULL; - PyObject *__pyx_v_cand3 = NULL; - PyObject *__pyx_v_val = NULL; - PyObject *__pyx_v_found = NULL; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - int __pyx_t_1; - int __pyx_t_2; - PyObject *__pyx_t_3 = NULL; - PyObject *__pyx_t_4 = NULL; - PyObject *__pyx_t_5 = NULL; - struct __pyx_opt_args_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython __pyx_t_6; - PyObject *__pyx_t_7 = NULL; - Py_ssize_t __pyx_t_8; - PyObject *(*__pyx_t_9)(PyObject *); - PyObject *__pyx_t_10 = NULL; - PyObject *__pyx_t_11 = NULL; - PyObject *__pyx_t_12 = NULL; - PyObject *__pyx_t_13 = NULL; - PyObject *__pyx_t_14 = NULL; - PyObject *(*__pyx_t_15)(PyObject *); - int __pyx_t_16; - int __pyx_t_17; - PyObject *__pyx_t_18 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("_lcs_iter_simple_alt2_cython", 0); - __Pyx_INCREF(__pyx_v_open_to_node); - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":39 - * Depth first stack trajectory and replace try except statements with ifs - * """ - * if open_to_node is None: # <<<<<<<<<<<<<< - * open_to_node = IdentityDict() - * all_decomp1 = generate_all_decomp_cython(full_seq1, open_to_close, open_to_node) - */ - __pyx_t_1 = (__pyx_v_open_to_node == Py_None); - __pyx_t_2 = (__pyx_t_1 != 0); - if (__pyx_t_2) { - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":40 - * """ - * if open_to_node is None: - * open_to_node = IdentityDict() # <<<<<<<<<<<<<< - * all_decomp1 = generate_all_decomp_cython(full_seq1, open_to_close, open_to_node) - * all_decomp2 = generate_all_decomp_cython(full_seq2, open_to_close, open_to_node) - */ - __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_IdentityDict); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 40, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_5 = NULL; - if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) { - __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4); - if (likely(__pyx_t_5)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); - __Pyx_INCREF(__pyx_t_5); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_4, function); - } - } - __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5) : __Pyx_PyObject_CallNoArg(__pyx_t_4); - __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; - if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 40, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __Pyx_DECREF_SET(__pyx_v_open_to_node, __pyx_t_3); - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":39 - * Depth first stack trajectory and replace try except statements with ifs - * """ - * if open_to_node is None: # <<<<<<<<<<<<<< - * open_to_node = IdentityDict() - * all_decomp1 = generate_all_decomp_cython(full_seq1, open_to_close, open_to_node) - */ - } - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":41 - * if open_to_node is None: - * open_to_node = IdentityDict() - * all_decomp1 = generate_all_decomp_cython(full_seq1, open_to_close, open_to_node) # <<<<<<<<<<<<<< - * all_decomp2 = generate_all_decomp_cython(full_seq2, open_to_close, open_to_node) - * - */ - __pyx_t_6.__pyx_n = 1; - __pyx_t_6.open_to_node = __pyx_v_open_to_node; - __pyx_t_3 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython(__pyx_v_full_seq1, __pyx_v_open_to_close, &__pyx_t_6); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 41, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_v_all_decomp1 = __pyx_t_3; - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":42 - * open_to_node = IdentityDict() - * all_decomp1 = generate_all_decomp_cython(full_seq1, open_to_close, open_to_node) - * all_decomp2 = generate_all_decomp_cython(full_seq2, open_to_close, open_to_node) # <<<<<<<<<<<<<< - * - * key0 = (full_seq1, full_seq2) - */ - __pyx_t_6.__pyx_n = 1; - __pyx_t_6.open_to_node = __pyx_v_open_to_node; - __pyx_t_3 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython(__pyx_v_full_seq2, __pyx_v_open_to_close, &__pyx_t_6); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 42, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_v_all_decomp2 = __pyx_t_3; - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":44 - * all_decomp2 = generate_all_decomp_cython(full_seq2, open_to_close, open_to_node) - * - * key0 = (full_seq1, full_seq2) # <<<<<<<<<<<<<< - * frame0 = key0 - * stack = [frame0] - */ - __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 44, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_INCREF(__pyx_v_full_seq1); - __Pyx_GIVEREF(__pyx_v_full_seq1); - PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_full_seq1); - __Pyx_INCREF(__pyx_v_full_seq2); - __Pyx_GIVEREF(__pyx_v_full_seq2); - PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_full_seq2); - __pyx_v_key0 = ((PyObject*)__pyx_t_3); - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":45 - * - * key0 = (full_seq1, full_seq2) - * frame0 = key0 # <<<<<<<<<<<<<< - * stack = [frame0] - * - */ - __Pyx_INCREF(__pyx_v_key0); - __pyx_v_frame0 = __pyx_v_key0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":46 - * key0 = (full_seq1, full_seq2) - * frame0 = key0 - * stack = [frame0] # <<<<<<<<<<<<<< - * - * _results = {} - */ - __pyx_t_3 = PyList_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 46, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_INCREF(__pyx_v_frame0); - __Pyx_GIVEREF(__pyx_v_frame0); - PyList_SET_ITEM(__pyx_t_3, 0, __pyx_v_frame0); - __pyx_v_stack = ((PyObject*)__pyx_t_3); - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":48 - * stack = [frame0] - * - * _results = {} # <<<<<<<<<<<<<< - * # Populate base cases - * empty1 = type(next(iter(all_decomp1.keys())))() - */ - __pyx_t_3 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 48, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_v__results = ((PyObject*)__pyx_t_3); - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":50 - * _results = {} - * # Populate base cases - * empty1 = type(next(iter(all_decomp1.keys())))() # <<<<<<<<<<<<<< - * empty2 = type(next(iter(all_decomp2.keys())))() - * best = (empty1, empty2) - */ - __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_all_decomp1, __pyx_n_s_keys); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 50, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __pyx_t_7 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) { - __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_5); - if (likely(__pyx_t_7)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5); - __Pyx_INCREF(__pyx_t_7); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_5, function); - } - } - __pyx_t_4 = (__pyx_t_7) ? __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_7) : __Pyx_PyObject_CallNoArg(__pyx_t_5); - __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; - if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 50, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - __pyx_t_5 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 50, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __pyx_t_4 = __Pyx_PyIter_Next(__pyx_t_5); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 50, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - __Pyx_INCREF(((PyObject *)Py_TYPE(__pyx_t_4))); - __pyx_t_5 = ((PyObject *)Py_TYPE(__pyx_t_4)); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __pyx_t_4 = NULL; - if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) { - __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_5); - if (likely(__pyx_t_4)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5); - __Pyx_INCREF(__pyx_t_4); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_5, function); - } - } - __pyx_t_3 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_5); - __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0; - if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 50, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - __pyx_v_empty1 = __pyx_t_3; - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":51 - * # Populate base cases - * empty1 = type(next(iter(all_decomp1.keys())))() - * empty2 = type(next(iter(all_decomp2.keys())))() # <<<<<<<<<<<<<< - * best = (empty1, empty2) - * base_result = (0, best) - */ - __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_all_decomp2, __pyx_n_s_keys); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 51, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_7 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { - __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_4); - if (likely(__pyx_t_7)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); - __Pyx_INCREF(__pyx_t_7); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_4, function); - } - } - __pyx_t_5 = (__pyx_t_7) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_7) : __Pyx_PyObject_CallNoArg(__pyx_t_4); - __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0; - if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 51, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __pyx_t_4 = PyObject_GetIter(__pyx_t_5); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 51, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - __pyx_t_5 = __Pyx_PyIter_Next(__pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 51, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __Pyx_INCREF(((PyObject *)Py_TYPE(__pyx_t_5))); - __pyx_t_4 = ((PyObject *)Py_TYPE(__pyx_t_5)); __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - __pyx_t_5 = NULL; - if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) { - __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4); - if (likely(__pyx_t_5)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); - __Pyx_INCREF(__pyx_t_5); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_4, function); - } - } - __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5) : __Pyx_PyObject_CallNoArg(__pyx_t_4); - __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; - if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 51, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __pyx_v_empty2 = __pyx_t_3; - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":52 - * empty1 = type(next(iter(all_decomp1.keys())))() - * empty2 = type(next(iter(all_decomp2.keys())))() - * best = (empty1, empty2) # <<<<<<<<<<<<<< - * base_result = (0, best) - * for seq1 in all_decomp1.keys(): - */ - __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 52, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_INCREF(__pyx_v_empty1); - __Pyx_GIVEREF(__pyx_v_empty1); - PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_empty1); - __Pyx_INCREF(__pyx_v_empty2); - __Pyx_GIVEREF(__pyx_v_empty2); - PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_empty2); - __pyx_v_best = __pyx_t_3; - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":53 - * empty2 = type(next(iter(all_decomp2.keys())))() - * best = (empty1, empty2) - * base_result = (0, best) # <<<<<<<<<<<<<< - * for seq1 in all_decomp1.keys(): - * key1 = seq1 - */ - __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 53, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_INCREF(__pyx_int_0); - __Pyx_GIVEREF(__pyx_int_0); - PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_int_0); - __Pyx_INCREF(__pyx_v_best); - __Pyx_GIVEREF(__pyx_v_best); - PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_best); - __pyx_v_base_result = ((PyObject*)__pyx_t_3); - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":54 - * best = (empty1, empty2) - * base_result = (0, best) - * for seq1 in all_decomp1.keys(): # <<<<<<<<<<<<<< - * key1 = seq1 - * t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[key1] - */ - __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_all_decomp1, __pyx_n_s_keys); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 54, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_5 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) { - __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4); - if (likely(__pyx_t_5)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4); - __Pyx_INCREF(__pyx_t_5); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_4, function); - } - } - __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5) : __Pyx_PyObject_CallNoArg(__pyx_t_4); - __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; - if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 54, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - if (likely(PyList_CheckExact(__pyx_t_3)) || PyTuple_CheckExact(__pyx_t_3)) { - __pyx_t_4 = __pyx_t_3; __Pyx_INCREF(__pyx_t_4); __pyx_t_8 = 0; - __pyx_t_9 = NULL; - } else { - __pyx_t_8 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 54, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_9 = Py_TYPE(__pyx_t_4)->tp_iternext; if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 54, __pyx_L1_error) - } - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - for (;;) { - if (likely(!__pyx_t_9)) { - if (likely(PyList_CheckExact(__pyx_t_4))) { - if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_4)) break; - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_3 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_3); __pyx_t_8++; if (unlikely(0 < 0)) __PYX_ERR(0, 54, __pyx_L1_error) - #else - __pyx_t_3 = PySequence_ITEM(__pyx_t_4, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 54, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - #endif - } else { - if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_4)) break; - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_3); __pyx_t_8++; if (unlikely(0 < 0)) __PYX_ERR(0, 54, __pyx_L1_error) - #else - __pyx_t_3 = PySequence_ITEM(__pyx_t_4, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 54, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - #endif - } - } else { - __pyx_t_3 = __pyx_t_9(__pyx_t_4); - if (unlikely(!__pyx_t_3)) { - PyObject* exc_type = PyErr_Occurred(); - if (exc_type) { - if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear(); - else __PYX_ERR(0, 54, __pyx_L1_error) - } - break; - } - __Pyx_GOTREF(__pyx_t_3); - } - __Pyx_XDECREF_SET(__pyx_v_seq1, __pyx_t_3); - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":55 - * base_result = (0, best) - * for seq1 in all_decomp1.keys(): - * key1 = seq1 # <<<<<<<<<<<<<< - * t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[key1] - * _results[(seq1, empty2)] = base_result - */ - __Pyx_INCREF(__pyx_v_seq1); - __Pyx_XDECREF_SET(__pyx_v_key1, __pyx_v_seq1); - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":56 - * for seq1 in all_decomp1.keys(): - * key1 = seq1 - * t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[key1] # <<<<<<<<<<<<<< - * _results[(seq1, empty2)] = base_result - * _results[(head1, empty2)] = base_result - */ - __pyx_t_3 = __Pyx_PyObject_GetItem(__pyx_v_all_decomp1, __pyx_v_key1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 56, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) { - PyObject* sequence = __pyx_t_3; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 6)) { - if (size > 6) __Pyx_RaiseTooManyValuesError(6); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 56, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - if (likely(PyTuple_CheckExact(sequence))) { - __pyx_t_5 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_7 = PyTuple_GET_ITEM(sequence, 1); - __pyx_t_10 = PyTuple_GET_ITEM(sequence, 2); - __pyx_t_11 = PyTuple_GET_ITEM(sequence, 3); - __pyx_t_12 = PyTuple_GET_ITEM(sequence, 4); - __pyx_t_13 = PyTuple_GET_ITEM(sequence, 5); - } else { - __pyx_t_5 = PyList_GET_ITEM(sequence, 0); - __pyx_t_7 = PyList_GET_ITEM(sequence, 1); - __pyx_t_10 = PyList_GET_ITEM(sequence, 2); - __pyx_t_11 = PyList_GET_ITEM(sequence, 3); - __pyx_t_12 = PyList_GET_ITEM(sequence, 4); - __pyx_t_13 = PyList_GET_ITEM(sequence, 5); - } - __Pyx_INCREF(__pyx_t_5); - __Pyx_INCREF(__pyx_t_7); - __Pyx_INCREF(__pyx_t_10); - __Pyx_INCREF(__pyx_t_11); - __Pyx_INCREF(__pyx_t_12); - __Pyx_INCREF(__pyx_t_13); - #else - { - Py_ssize_t i; - PyObject** temps[6] = {&__pyx_t_5,&__pyx_t_7,&__pyx_t_10,&__pyx_t_11,&__pyx_t_12,&__pyx_t_13}; - for (i=0; i < 6; i++) { - PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 56, __pyx_L1_error) - __Pyx_GOTREF(item); - *(temps[i]) = item; - } - } - #endif - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - } else { - Py_ssize_t index = -1; - PyObject** temps[6] = {&__pyx_t_5,&__pyx_t_7,&__pyx_t_10,&__pyx_t_11,&__pyx_t_12,&__pyx_t_13}; - __pyx_t_14 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 56, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_14); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_t_15 = Py_TYPE(__pyx_t_14)->tp_iternext; - for (index=0; index < 6; index++) { - PyObject* item = __pyx_t_15(__pyx_t_14); if (unlikely(!item)) goto __pyx_L6_unpacking_failed; - __Pyx_GOTREF(item); - *(temps[index]) = item; - } - if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_14), 6) < 0) __PYX_ERR(0, 56, __pyx_L1_error) - __pyx_t_15 = NULL; - __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0; - goto __pyx_L7_unpacking_done; - __pyx_L6_unpacking_failed:; - __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0; - __pyx_t_15 = NULL; - if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); - __PYX_ERR(0, 56, __pyx_L1_error) - __pyx_L7_unpacking_done:; - } - __Pyx_XDECREF_SET(__pyx_v_t1, __pyx_t_5); - __pyx_t_5 = 0; - __Pyx_XDECREF_SET(__pyx_v_a1, __pyx_t_7); - __pyx_t_7 = 0; - __Pyx_XDECREF_SET(__pyx_v_b1, __pyx_t_10); - __pyx_t_10 = 0; - __Pyx_XDECREF_SET(__pyx_v_head1, __pyx_t_11); - __pyx_t_11 = 0; - __Pyx_XDECREF_SET(__pyx_v_tail1, __pyx_t_12); - __pyx_t_12 = 0; - __Pyx_XDECREF_SET(__pyx_v_head_tail1, __pyx_t_13); - __pyx_t_13 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":57 - * key1 = seq1 - * t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[key1] - * _results[(seq1, empty2)] = base_result # <<<<<<<<<<<<<< - * _results[(head1, empty2)] = base_result - * _results[(tail1, empty2)] = base_result - */ - __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 57, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_INCREF(__pyx_v_seq1); - __Pyx_GIVEREF(__pyx_v_seq1); - PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_seq1); - __Pyx_INCREF(__pyx_v_empty2); - __Pyx_GIVEREF(__pyx_v_empty2); - PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_empty2); - if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 57, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":58 - * t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[key1] - * _results[(seq1, empty2)] = base_result - * _results[(head1, empty2)] = base_result # <<<<<<<<<<<<<< - * _results[(tail1, empty2)] = base_result - * _results[(head_tail1, empty2)] = base_result - */ - __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 58, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_INCREF(__pyx_v_head1); - __Pyx_GIVEREF(__pyx_v_head1); - PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_head1); - __Pyx_INCREF(__pyx_v_empty2); - __Pyx_GIVEREF(__pyx_v_empty2); - PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_empty2); - if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 58, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":59 - * _results[(seq1, empty2)] = base_result - * _results[(head1, empty2)] = base_result - * _results[(tail1, empty2)] = base_result # <<<<<<<<<<<<<< - * _results[(head_tail1, empty2)] = base_result - * - */ - __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 59, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_INCREF(__pyx_v_tail1); - __Pyx_GIVEREF(__pyx_v_tail1); - PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_tail1); - __Pyx_INCREF(__pyx_v_empty2); - __Pyx_GIVEREF(__pyx_v_empty2); - PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_empty2); - if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 59, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":60 - * _results[(head1, empty2)] = base_result - * _results[(tail1, empty2)] = base_result - * _results[(head_tail1, empty2)] = base_result # <<<<<<<<<<<<<< - * - * for seq2 in all_decomp2.keys(): - */ - __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 60, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_INCREF(__pyx_v_head_tail1); - __Pyx_GIVEREF(__pyx_v_head_tail1); - PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_head_tail1); - __Pyx_INCREF(__pyx_v_empty2); - __Pyx_GIVEREF(__pyx_v_empty2); - PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_empty2); - if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 60, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":54 - * best = (empty1, empty2) - * base_result = (0, best) - * for seq1 in all_decomp1.keys(): # <<<<<<<<<<<<<< - * key1 = seq1 - * t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[key1] - */ - } - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":62 - * _results[(head_tail1, empty2)] = base_result - * - * for seq2 in all_decomp2.keys(): # <<<<<<<<<<<<<< - * key2 = seq2 - * t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[key2] - */ - __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_all_decomp2, __pyx_n_s_keys); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 62, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_13 = NULL; - if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) { - __pyx_t_13 = PyMethod_GET_SELF(__pyx_t_3); - if (likely(__pyx_t_13)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); - __Pyx_INCREF(__pyx_t_13); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_3, function); - } - } - __pyx_t_4 = (__pyx_t_13) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_13) : __Pyx_PyObject_CallNoArg(__pyx_t_3); - __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0; - if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 62, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (likely(PyList_CheckExact(__pyx_t_4)) || PyTuple_CheckExact(__pyx_t_4)) { - __pyx_t_3 = __pyx_t_4; __Pyx_INCREF(__pyx_t_3); __pyx_t_8 = 0; - __pyx_t_9 = NULL; - } else { - __pyx_t_8 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 62, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_9 = Py_TYPE(__pyx_t_3)->tp_iternext; if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 62, __pyx_L1_error) - } - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - for (;;) { - if (likely(!__pyx_t_9)) { - if (likely(PyList_CheckExact(__pyx_t_3))) { - if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_3)) break; - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_4 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_8); __Pyx_INCREF(__pyx_t_4); __pyx_t_8++; if (unlikely(0 < 0)) __PYX_ERR(0, 62, __pyx_L1_error) - #else - __pyx_t_4 = PySequence_ITEM(__pyx_t_3, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 62, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - #endif - } else { - if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_3)) break; - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_8); __Pyx_INCREF(__pyx_t_4); __pyx_t_8++; if (unlikely(0 < 0)) __PYX_ERR(0, 62, __pyx_L1_error) - #else - __pyx_t_4 = PySequence_ITEM(__pyx_t_3, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 62, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - #endif - } - } else { - __pyx_t_4 = __pyx_t_9(__pyx_t_3); - if (unlikely(!__pyx_t_4)) { - PyObject* exc_type = PyErr_Occurred(); - if (exc_type) { - if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear(); - else __PYX_ERR(0, 62, __pyx_L1_error) - } - break; - } - __Pyx_GOTREF(__pyx_t_4); - } - __Pyx_XDECREF_SET(__pyx_v_seq2, __pyx_t_4); - __pyx_t_4 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":63 - * - * for seq2 in all_decomp2.keys(): - * key2 = seq2 # <<<<<<<<<<<<<< - * t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[key2] - * _results[(empty1, seq2)] = base_result - */ - __Pyx_INCREF(__pyx_v_seq2); - __Pyx_XDECREF_SET(__pyx_v_key2, __pyx_v_seq2); - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":64 - * for seq2 in all_decomp2.keys(): - * key2 = seq2 - * t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[key2] # <<<<<<<<<<<<<< - * _results[(empty1, seq2)] = base_result - * _results[(empty1, head2)] = base_result - */ - __pyx_t_4 = __Pyx_PyObject_GetItem(__pyx_v_all_decomp2, __pyx_v_key2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 64, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) { - PyObject* sequence = __pyx_t_4; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 6)) { - if (size > 6) __Pyx_RaiseTooManyValuesError(6); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 64, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - if (likely(PyTuple_CheckExact(sequence))) { - __pyx_t_13 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_12 = PyTuple_GET_ITEM(sequence, 1); - __pyx_t_11 = PyTuple_GET_ITEM(sequence, 2); - __pyx_t_10 = PyTuple_GET_ITEM(sequence, 3); - __pyx_t_7 = PyTuple_GET_ITEM(sequence, 4); - __pyx_t_5 = PyTuple_GET_ITEM(sequence, 5); - } else { - __pyx_t_13 = PyList_GET_ITEM(sequence, 0); - __pyx_t_12 = PyList_GET_ITEM(sequence, 1); - __pyx_t_11 = PyList_GET_ITEM(sequence, 2); - __pyx_t_10 = PyList_GET_ITEM(sequence, 3); - __pyx_t_7 = PyList_GET_ITEM(sequence, 4); - __pyx_t_5 = PyList_GET_ITEM(sequence, 5); - } - __Pyx_INCREF(__pyx_t_13); - __Pyx_INCREF(__pyx_t_12); - __Pyx_INCREF(__pyx_t_11); - __Pyx_INCREF(__pyx_t_10); - __Pyx_INCREF(__pyx_t_7); - __Pyx_INCREF(__pyx_t_5); - #else - { - Py_ssize_t i; - PyObject** temps[6] = {&__pyx_t_13,&__pyx_t_12,&__pyx_t_11,&__pyx_t_10,&__pyx_t_7,&__pyx_t_5}; - for (i=0; i < 6; i++) { - PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 64, __pyx_L1_error) - __Pyx_GOTREF(item); - *(temps[i]) = item; - } - } - #endif - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - } else { - Py_ssize_t index = -1; - PyObject** temps[6] = {&__pyx_t_13,&__pyx_t_12,&__pyx_t_11,&__pyx_t_10,&__pyx_t_7,&__pyx_t_5}; - __pyx_t_14 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 64, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_14); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __pyx_t_15 = Py_TYPE(__pyx_t_14)->tp_iternext; - for (index=0; index < 6; index++) { - PyObject* item = __pyx_t_15(__pyx_t_14); if (unlikely(!item)) goto __pyx_L10_unpacking_failed; - __Pyx_GOTREF(item); - *(temps[index]) = item; - } - if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_14), 6) < 0) __PYX_ERR(0, 64, __pyx_L1_error) - __pyx_t_15 = NULL; - __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0; - goto __pyx_L11_unpacking_done; - __pyx_L10_unpacking_failed:; - __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0; - __pyx_t_15 = NULL; - if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); - __PYX_ERR(0, 64, __pyx_L1_error) - __pyx_L11_unpacking_done:; - } - __Pyx_XDECREF_SET(__pyx_v_t2, __pyx_t_13); - __pyx_t_13 = 0; - __Pyx_XDECREF_SET(__pyx_v_a2, __pyx_t_12); - __pyx_t_12 = 0; - __Pyx_XDECREF_SET(__pyx_v_b2, __pyx_t_11); - __pyx_t_11 = 0; - __Pyx_XDECREF_SET(__pyx_v_head2, __pyx_t_10); - __pyx_t_10 = 0; - __Pyx_XDECREF_SET(__pyx_v_tail2, __pyx_t_7); - __pyx_t_7 = 0; - __Pyx_XDECREF_SET(__pyx_v_head_tail2, __pyx_t_5); - __pyx_t_5 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":65 - * key2 = seq2 - * t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[key2] - * _results[(empty1, seq2)] = base_result # <<<<<<<<<<<<<< - * _results[(empty1, head2)] = base_result - * _results[(empty1, tail2)] = base_result - */ - __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 65, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_INCREF(__pyx_v_empty1); - __Pyx_GIVEREF(__pyx_v_empty1); - PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_empty1); - __Pyx_INCREF(__pyx_v_seq2); - __Pyx_GIVEREF(__pyx_v_seq2); - PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_seq2); - if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_4, __pyx_v_base_result) < 0)) __PYX_ERR(0, 65, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":66 - * t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[key2] - * _results[(empty1, seq2)] = base_result - * _results[(empty1, head2)] = base_result # <<<<<<<<<<<<<< - * _results[(empty1, tail2)] = base_result - * _results[(empty1, head_tail2)] = base_result - */ - __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 66, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_INCREF(__pyx_v_empty1); - __Pyx_GIVEREF(__pyx_v_empty1); - PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_empty1); - __Pyx_INCREF(__pyx_v_head2); - __Pyx_GIVEREF(__pyx_v_head2); - PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_head2); - if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_4, __pyx_v_base_result) < 0)) __PYX_ERR(0, 66, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":67 - * _results[(empty1, seq2)] = base_result - * _results[(empty1, head2)] = base_result - * _results[(empty1, tail2)] = base_result # <<<<<<<<<<<<<< - * _results[(empty1, head_tail2)] = base_result - * - */ - __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 67, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_INCREF(__pyx_v_empty1); - __Pyx_GIVEREF(__pyx_v_empty1); - PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_empty1); - __Pyx_INCREF(__pyx_v_tail2); - __Pyx_GIVEREF(__pyx_v_tail2); - PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_tail2); - if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_4, __pyx_v_base_result) < 0)) __PYX_ERR(0, 67, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":68 - * _results[(empty1, head2)] = base_result - * _results[(empty1, tail2)] = base_result - * _results[(empty1, head_tail2)] = base_result # <<<<<<<<<<<<<< - * - * while stack: - */ - __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 68, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_INCREF(__pyx_v_empty1); - __Pyx_GIVEREF(__pyx_v_empty1); - PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_empty1); - __Pyx_INCREF(__pyx_v_head_tail2); - __Pyx_GIVEREF(__pyx_v_head_tail2); - PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_head_tail2); - if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_4, __pyx_v_base_result) < 0)) __PYX_ERR(0, 68, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":62 - * _results[(head_tail1, empty2)] = base_result - * - * for seq2 in all_decomp2.keys(): # <<<<<<<<<<<<<< - * key2 = seq2 - * t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[key2] - */ - } - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":70 - * _results[(empty1, head_tail2)] = base_result - * - * while stack: # <<<<<<<<<<<<<< - * key = stack[-1] - * if key not in _results: - */ - while (1) { - __pyx_t_2 = (PyList_GET_SIZE(__pyx_v_stack) != 0); - if (!__pyx_t_2) break; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":71 - * - * while stack: - * key = stack[-1] # <<<<<<<<<<<<<< - * if key not in _results: - * seq1, seq2 = key - */ - __pyx_t_3 = __Pyx_GetItemInt_List(__pyx_v_stack, -1L, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 71, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_XDECREF_SET(__pyx_v_key, __pyx_t_3); - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":72 - * while stack: - * key = stack[-1] - * if key not in _results: # <<<<<<<<<<<<<< - * seq1, seq2 = key - * - */ - __pyx_t_2 = (__Pyx_PyDict_ContainsTF(__pyx_v_key, __pyx_v__results, Py_NE)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 72, __pyx_L1_error) - __pyx_t_1 = (__pyx_t_2 != 0); - if (__pyx_t_1) { - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":73 - * key = stack[-1] - * if key not in _results: - * seq1, seq2 = key # <<<<<<<<<<<<<< - * - * t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[seq1] - */ - if ((likely(PyTuple_CheckExact(__pyx_v_key))) || (PyList_CheckExact(__pyx_v_key))) { - PyObject* sequence = __pyx_v_key; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 2)) { - if (size > 2) __Pyx_RaiseTooManyValuesError(2); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 73, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - if (likely(PyTuple_CheckExact(sequence))) { - __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); - } else { - __pyx_t_3 = PyList_GET_ITEM(sequence, 0); - __pyx_t_4 = PyList_GET_ITEM(sequence, 1); - } - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(__pyx_t_4); - #else - __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 73, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 73, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - #endif - } else { - Py_ssize_t index = -1; - __pyx_t_5 = PyObject_GetIter(__pyx_v_key); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 73, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __pyx_t_15 = Py_TYPE(__pyx_t_5)->tp_iternext; - index = 0; __pyx_t_3 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_3)) goto __pyx_L15_unpacking_failed; - __Pyx_GOTREF(__pyx_t_3); - index = 1; __pyx_t_4 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_4)) goto __pyx_L15_unpacking_failed; - __Pyx_GOTREF(__pyx_t_4); - if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_5), 2) < 0) __PYX_ERR(0, 73, __pyx_L1_error) - __pyx_t_15 = NULL; - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - goto __pyx_L16_unpacking_done; - __pyx_L15_unpacking_failed:; - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - __pyx_t_15 = NULL; - if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); - __PYX_ERR(0, 73, __pyx_L1_error) - __pyx_L16_unpacking_done:; - } - __Pyx_XDECREF_SET(__pyx_v_seq1, __pyx_t_3); - __pyx_t_3 = 0; - __Pyx_XDECREF_SET(__pyx_v_seq2, __pyx_t_4); - __pyx_t_4 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":75 - * seq1, seq2 = key - * - * t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[seq1] # <<<<<<<<<<<<<< - * t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[seq2] - * - */ - __pyx_t_4 = __Pyx_PyObject_GetItem(__pyx_v_all_decomp1, __pyx_v_seq1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 75, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) { - PyObject* sequence = __pyx_t_4; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 6)) { - if (size > 6) __Pyx_RaiseTooManyValuesError(6); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 75, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - if (likely(PyTuple_CheckExact(sequence))) { - __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_5 = PyTuple_GET_ITEM(sequence, 1); - __pyx_t_7 = PyTuple_GET_ITEM(sequence, 2); - __pyx_t_10 = PyTuple_GET_ITEM(sequence, 3); - __pyx_t_11 = PyTuple_GET_ITEM(sequence, 4); - __pyx_t_12 = PyTuple_GET_ITEM(sequence, 5); - } else { - __pyx_t_3 = PyList_GET_ITEM(sequence, 0); - __pyx_t_5 = PyList_GET_ITEM(sequence, 1); - __pyx_t_7 = PyList_GET_ITEM(sequence, 2); - __pyx_t_10 = PyList_GET_ITEM(sequence, 3); - __pyx_t_11 = PyList_GET_ITEM(sequence, 4); - __pyx_t_12 = PyList_GET_ITEM(sequence, 5); - } - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(__pyx_t_5); - __Pyx_INCREF(__pyx_t_7); - __Pyx_INCREF(__pyx_t_10); - __Pyx_INCREF(__pyx_t_11); - __Pyx_INCREF(__pyx_t_12); - #else - { - Py_ssize_t i; - PyObject** temps[6] = {&__pyx_t_3,&__pyx_t_5,&__pyx_t_7,&__pyx_t_10,&__pyx_t_11,&__pyx_t_12}; - for (i=0; i < 6; i++) { - PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 75, __pyx_L1_error) - __Pyx_GOTREF(item); - *(temps[i]) = item; - } - } - #endif - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - } else { - Py_ssize_t index = -1; - PyObject** temps[6] = {&__pyx_t_3,&__pyx_t_5,&__pyx_t_7,&__pyx_t_10,&__pyx_t_11,&__pyx_t_12}; - __pyx_t_13 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 75, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_13); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __pyx_t_15 = Py_TYPE(__pyx_t_13)->tp_iternext; - for (index=0; index < 6; index++) { - PyObject* item = __pyx_t_15(__pyx_t_13); if (unlikely(!item)) goto __pyx_L17_unpacking_failed; - __Pyx_GOTREF(item); - *(temps[index]) = item; - } - if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_13), 6) < 0) __PYX_ERR(0, 75, __pyx_L1_error) - __pyx_t_15 = NULL; - __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; - goto __pyx_L18_unpacking_done; - __pyx_L17_unpacking_failed:; - __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; - __pyx_t_15 = NULL; - if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); - __PYX_ERR(0, 75, __pyx_L1_error) - __pyx_L18_unpacking_done:; - } - __Pyx_XDECREF_SET(__pyx_v_t1, __pyx_t_3); - __pyx_t_3 = 0; - __Pyx_XDECREF_SET(__pyx_v_a1, __pyx_t_5); - __pyx_t_5 = 0; - __Pyx_XDECREF_SET(__pyx_v_b1, __pyx_t_7); - __pyx_t_7 = 0; - __Pyx_XDECREF_SET(__pyx_v_head1, __pyx_t_10); - __pyx_t_10 = 0; - __Pyx_XDECREF_SET(__pyx_v_tail1, __pyx_t_11); - __pyx_t_11 = 0; - __Pyx_XDECREF_SET(__pyx_v_head_tail1, __pyx_t_12); - __pyx_t_12 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":76 - * - * t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[seq1] - * t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[seq2] # <<<<<<<<<<<<<< - * - * # Case 2: The current edge in sequence1 is deleted - */ - __pyx_t_4 = __Pyx_PyObject_GetItem(__pyx_v_all_decomp2, __pyx_v_seq2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 76, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) { - PyObject* sequence = __pyx_t_4; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 6)) { - if (size > 6) __Pyx_RaiseTooManyValuesError(6); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 76, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - if (likely(PyTuple_CheckExact(sequence))) { - __pyx_t_12 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_11 = PyTuple_GET_ITEM(sequence, 1); - __pyx_t_10 = PyTuple_GET_ITEM(sequence, 2); - __pyx_t_7 = PyTuple_GET_ITEM(sequence, 3); - __pyx_t_5 = PyTuple_GET_ITEM(sequence, 4); - __pyx_t_3 = PyTuple_GET_ITEM(sequence, 5); - } else { - __pyx_t_12 = PyList_GET_ITEM(sequence, 0); - __pyx_t_11 = PyList_GET_ITEM(sequence, 1); - __pyx_t_10 = PyList_GET_ITEM(sequence, 2); - __pyx_t_7 = PyList_GET_ITEM(sequence, 3); - __pyx_t_5 = PyList_GET_ITEM(sequence, 4); - __pyx_t_3 = PyList_GET_ITEM(sequence, 5); - } - __Pyx_INCREF(__pyx_t_12); - __Pyx_INCREF(__pyx_t_11); - __Pyx_INCREF(__pyx_t_10); - __Pyx_INCREF(__pyx_t_7); - __Pyx_INCREF(__pyx_t_5); - __Pyx_INCREF(__pyx_t_3); - #else - { - Py_ssize_t i; - PyObject** temps[6] = {&__pyx_t_12,&__pyx_t_11,&__pyx_t_10,&__pyx_t_7,&__pyx_t_5,&__pyx_t_3}; - for (i=0; i < 6; i++) { - PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 76, __pyx_L1_error) - __Pyx_GOTREF(item); - *(temps[i]) = item; - } - } - #endif - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - } else { - Py_ssize_t index = -1; - PyObject** temps[6] = {&__pyx_t_12,&__pyx_t_11,&__pyx_t_10,&__pyx_t_7,&__pyx_t_5,&__pyx_t_3}; - __pyx_t_13 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 76, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_13); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __pyx_t_15 = Py_TYPE(__pyx_t_13)->tp_iternext; - for (index=0; index < 6; index++) { - PyObject* item = __pyx_t_15(__pyx_t_13); if (unlikely(!item)) goto __pyx_L19_unpacking_failed; - __Pyx_GOTREF(item); - *(temps[index]) = item; - } - if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_13), 6) < 0) __PYX_ERR(0, 76, __pyx_L1_error) - __pyx_t_15 = NULL; - __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; - goto __pyx_L20_unpacking_done; - __pyx_L19_unpacking_failed:; - __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; - __pyx_t_15 = NULL; - if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); - __PYX_ERR(0, 76, __pyx_L1_error) - __pyx_L20_unpacking_done:; - } - __Pyx_XDECREF_SET(__pyx_v_t2, __pyx_t_12); - __pyx_t_12 = 0; - __Pyx_XDECREF_SET(__pyx_v_a2, __pyx_t_11); - __pyx_t_11 = 0; - __Pyx_XDECREF_SET(__pyx_v_b2, __pyx_t_10); - __pyx_t_10 = 0; - __Pyx_XDECREF_SET(__pyx_v_head2, __pyx_t_7); - __pyx_t_7 = 0; - __Pyx_XDECREF_SET(__pyx_v_tail2, __pyx_t_5); - __pyx_t_5 = 0; - __Pyx_XDECREF_SET(__pyx_v_head_tail2, __pyx_t_3); - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":79 - * - * # Case 2: The current edge in sequence1 is deleted - * try_key = (head_tail1, seq2) # <<<<<<<<<<<<<< - * if try_key in _results: - * cand1 = _results[try_key] - */ - __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 79, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_INCREF(__pyx_v_head_tail1); - __Pyx_GIVEREF(__pyx_v_head_tail1); - PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_head_tail1); - __Pyx_INCREF(__pyx_v_seq2); - __Pyx_GIVEREF(__pyx_v_seq2); - PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_seq2); - __Pyx_XDECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_4)); - __pyx_t_4 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":80 - * # Case 2: The current edge in sequence1 is deleted - * try_key = (head_tail1, seq2) - * if try_key in _results: # <<<<<<<<<<<<<< - * cand1 = _results[try_key] - * else: - */ - __pyx_t_1 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 80, __pyx_L1_error) - __pyx_t_2 = (__pyx_t_1 != 0); - if (__pyx_t_2) { - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":81 - * try_key = (head_tail1, seq2) - * if try_key in _results: - * cand1 = _results[try_key] # <<<<<<<<<<<<<< - * else: - * # stack.append(key) - */ - __pyx_t_4 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 81, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_XDECREF_SET(__pyx_v_cand1, __pyx_t_4); - __pyx_t_4 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":80 - * # Case 2: The current edge in sequence1 is deleted - * try_key = (head_tail1, seq2) - * if try_key in _results: # <<<<<<<<<<<<<< - * cand1 = _results[try_key] - * else: - */ - goto __pyx_L21; - } - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":84 - * else: - * # stack.append(key) - * stack.append(try_key) # <<<<<<<<<<<<<< - * continue - * - */ - /*else*/ { - __pyx_t_16 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_try_key); if (unlikely(__pyx_t_16 == ((int)-1))) __PYX_ERR(0, 84, __pyx_L1_error) - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":85 - * # stack.append(key) - * stack.append(try_key) - * continue # <<<<<<<<<<<<<< - * - * # Case 3: The current edge in sequence2 is deleted - */ - goto __pyx_L12_continue; - } - __pyx_L21:; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":88 - * - * # Case 3: The current edge in sequence2 is deleted - * try_key = (seq1, head_tail2) # <<<<<<<<<<<<<< - * if try_key in _results: - * cand2 = _results[try_key] - */ - __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 88, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_INCREF(__pyx_v_seq1); - __Pyx_GIVEREF(__pyx_v_seq1); - PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_seq1); - __Pyx_INCREF(__pyx_v_head_tail2); - __Pyx_GIVEREF(__pyx_v_head_tail2); - PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_head_tail2); - __Pyx_DECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_4)); - __pyx_t_4 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":89 - * # Case 3: The current edge in sequence2 is deleted - * try_key = (seq1, head_tail2) - * if try_key in _results: # <<<<<<<<<<<<<< - * cand2 = _results[try_key] - * else: - */ - __pyx_t_2 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 89, __pyx_L1_error) - __pyx_t_1 = (__pyx_t_2 != 0); - if (__pyx_t_1) { - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":90 - * try_key = (seq1, head_tail2) - * if try_key in _results: - * cand2 = _results[try_key] # <<<<<<<<<<<<<< - * else: - * # stack.append(key) - */ - __pyx_t_4 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 90, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_XDECREF_SET(__pyx_v_cand2, __pyx_t_4); - __pyx_t_4 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":89 - * # Case 3: The current edge in sequence2 is deleted - * try_key = (seq1, head_tail2) - * if try_key in _results: # <<<<<<<<<<<<<< - * cand2 = _results[try_key] - * else: - */ - goto __pyx_L22; - } - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":93 - * else: - * # stack.append(key) - * stack.append(try_key) # <<<<<<<<<<<<<< - * continue - * - */ - /*else*/ { - __pyx_t_16 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_try_key); if (unlikely(__pyx_t_16 == ((int)-1))) __PYX_ERR(0, 93, __pyx_L1_error) - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":94 - * # stack.append(key) - * stack.append(try_key) - * continue # <<<<<<<<<<<<<< - * - * # Case 1: The LCS involves this edge - */ - goto __pyx_L12_continue; - } - __pyx_L22:; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":97 - * - * # Case 1: The LCS involves this edge - * affinity = node_affinity(t1, t2) # <<<<<<<<<<<<<< - * if affinity: - * try_key = (head1, head2) - */ - __Pyx_INCREF(__pyx_v_node_affinity); - __pyx_t_3 = __pyx_v_node_affinity; __pyx_t_5 = NULL; - __pyx_t_17 = 0; - if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { - __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_3); - if (likely(__pyx_t_5)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); - __Pyx_INCREF(__pyx_t_5); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_3, function); - __pyx_t_17 = 1; - } - } - #if CYTHON_FAST_PYCALL - if (PyFunction_Check(__pyx_t_3)) { - PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_v_t1, __pyx_v_t2}; - __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_17, 2+__pyx_t_17); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 97, __pyx_L1_error) - __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; - __Pyx_GOTREF(__pyx_t_4); - } else - #endif - #if CYTHON_FAST_PYCCALL - if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) { - PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_v_t1, __pyx_v_t2}; - __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_17, 2+__pyx_t_17); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 97, __pyx_L1_error) - __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0; - __Pyx_GOTREF(__pyx_t_4); - } else - #endif - { - __pyx_t_7 = PyTuple_New(2+__pyx_t_17); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 97, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - if (__pyx_t_5) { - __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL; - } - __Pyx_INCREF(__pyx_v_t1); - __Pyx_GIVEREF(__pyx_v_t1); - PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_17, __pyx_v_t1); - __Pyx_INCREF(__pyx_v_t2); - __Pyx_GIVEREF(__pyx_v_t2); - PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_17, __pyx_v_t2); - __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_7, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 97, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - } - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __Pyx_XDECREF_SET(__pyx_v_affinity, __pyx_t_4); - __pyx_t_4 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":98 - * # Case 1: The LCS involves this edge - * affinity = node_affinity(t1, t2) - * if affinity: # <<<<<<<<<<<<<< - * try_key = (head1, head2) - * if try_key in _results: - */ - __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_affinity); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 98, __pyx_L1_error) - if (__pyx_t_1) { - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":99 - * affinity = node_affinity(t1, t2) - * if affinity: - * try_key = (head1, head2) # <<<<<<<<<<<<<< - * if try_key in _results: - * pval_h, new_heads = _results[try_key] - */ - __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 99, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_INCREF(__pyx_v_head1); - __Pyx_GIVEREF(__pyx_v_head1); - PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_head1); - __Pyx_INCREF(__pyx_v_head2); - __Pyx_GIVEREF(__pyx_v_head2); - PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_head2); - __Pyx_DECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_4)); - __pyx_t_4 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":100 - * if affinity: - * try_key = (head1, head2) - * if try_key in _results: # <<<<<<<<<<<<<< - * pval_h, new_heads = _results[try_key] - * else: - */ - __pyx_t_1 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 100, __pyx_L1_error) - __pyx_t_2 = (__pyx_t_1 != 0); - if (__pyx_t_2) { - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":101 - * try_key = (head1, head2) - * if try_key in _results: - * pval_h, new_heads = _results[try_key] # <<<<<<<<<<<<<< - * else: - * # stack.append(key) - */ - __pyx_t_4 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 101, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) { - PyObject* sequence = __pyx_t_4; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 2)) { - if (size > 2) __Pyx_RaiseTooManyValuesError(2); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 101, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - if (likely(PyTuple_CheckExact(sequence))) { - __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_7 = PyTuple_GET_ITEM(sequence, 1); - } else { - __pyx_t_3 = PyList_GET_ITEM(sequence, 0); - __pyx_t_7 = PyList_GET_ITEM(sequence, 1); - } - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(__pyx_t_7); - #else - __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 101, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_7 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 101, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - #endif - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - } else { - Py_ssize_t index = -1; - __pyx_t_5 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 101, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __pyx_t_15 = Py_TYPE(__pyx_t_5)->tp_iternext; - index = 0; __pyx_t_3 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_3)) goto __pyx_L25_unpacking_failed; - __Pyx_GOTREF(__pyx_t_3); - index = 1; __pyx_t_7 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_7)) goto __pyx_L25_unpacking_failed; - __Pyx_GOTREF(__pyx_t_7); - if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_5), 2) < 0) __PYX_ERR(0, 101, __pyx_L1_error) - __pyx_t_15 = NULL; - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - goto __pyx_L26_unpacking_done; - __pyx_L25_unpacking_failed:; - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - __pyx_t_15 = NULL; - if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); - __PYX_ERR(0, 101, __pyx_L1_error) - __pyx_L26_unpacking_done:; - } - __Pyx_XDECREF_SET(__pyx_v_pval_h, __pyx_t_3); - __pyx_t_3 = 0; - __Pyx_XDECREF_SET(__pyx_v_new_heads, __pyx_t_7); - __pyx_t_7 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":100 - * if affinity: - * try_key = (head1, head2) - * if try_key in _results: # <<<<<<<<<<<<<< - * pval_h, new_heads = _results[try_key] - * else: - */ - goto __pyx_L24; - } - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":104 - * else: - * # stack.append(key) - * stack.append(try_key) # <<<<<<<<<<<<<< - * continue - * - */ - /*else*/ { - __pyx_t_16 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_try_key); if (unlikely(__pyx_t_16 == ((int)-1))) __PYX_ERR(0, 104, __pyx_L1_error) - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":105 - * # stack.append(key) - * stack.append(try_key) - * continue # <<<<<<<<<<<<<< - * - * try_key = (tail1, tail2) - */ - goto __pyx_L12_continue; - } - __pyx_L24:; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":107 - * continue - * - * try_key = (tail1, tail2) # <<<<<<<<<<<<<< - * if try_key in _results: - * pval_t, new_tails = _results[try_key] - */ - __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 107, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_INCREF(__pyx_v_tail1); - __Pyx_GIVEREF(__pyx_v_tail1); - PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_tail1); - __Pyx_INCREF(__pyx_v_tail2); - __Pyx_GIVEREF(__pyx_v_tail2); - PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_tail2); - __Pyx_DECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_4)); - __pyx_t_4 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":108 - * - * try_key = (tail1, tail2) - * if try_key in _results: # <<<<<<<<<<<<<< - * pval_t, new_tails = _results[try_key] - * else: - */ - __pyx_t_2 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 108, __pyx_L1_error) - __pyx_t_1 = (__pyx_t_2 != 0); - if (__pyx_t_1) { - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":109 - * try_key = (tail1, tail2) - * if try_key in _results: - * pval_t, new_tails = _results[try_key] # <<<<<<<<<<<<<< - * else: - * # stack.append(key) - */ - __pyx_t_4 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 109, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) { - PyObject* sequence = __pyx_t_4; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 2)) { - if (size > 2) __Pyx_RaiseTooManyValuesError(2); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 109, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - if (likely(PyTuple_CheckExact(sequence))) { - __pyx_t_7 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); - } else { - __pyx_t_7 = PyList_GET_ITEM(sequence, 0); - __pyx_t_3 = PyList_GET_ITEM(sequence, 1); - } - __Pyx_INCREF(__pyx_t_7); - __Pyx_INCREF(__pyx_t_3); - #else - __pyx_t_7 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 109, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 109, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - #endif - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - } else { - Py_ssize_t index = -1; - __pyx_t_5 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 109, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __pyx_t_15 = Py_TYPE(__pyx_t_5)->tp_iternext; - index = 0; __pyx_t_7 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_7)) goto __pyx_L28_unpacking_failed; - __Pyx_GOTREF(__pyx_t_7); - index = 1; __pyx_t_3 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_3)) goto __pyx_L28_unpacking_failed; - __Pyx_GOTREF(__pyx_t_3); - if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_5), 2) < 0) __PYX_ERR(0, 109, __pyx_L1_error) - __pyx_t_15 = NULL; - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - goto __pyx_L29_unpacking_done; - __pyx_L28_unpacking_failed:; - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - __pyx_t_15 = NULL; - if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); - __PYX_ERR(0, 109, __pyx_L1_error) - __pyx_L29_unpacking_done:; - } - __Pyx_XDECREF_SET(__pyx_v_pval_t, __pyx_t_7); - __pyx_t_7 = 0; - __Pyx_XDECREF_SET(__pyx_v_new_tails, __pyx_t_3); - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":108 - * - * try_key = (tail1, tail2) - * if try_key in _results: # <<<<<<<<<<<<<< - * pval_t, new_tails = _results[try_key] - * else: - */ - goto __pyx_L27; - } - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":112 - * else: - * # stack.append(key) - * stack.append(try_key) # <<<<<<<<<<<<<< - * continue - * - */ - /*else*/ { - __pyx_t_16 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_try_key); if (unlikely(__pyx_t_16 == ((int)-1))) __PYX_ERR(0, 112, __pyx_L1_error) - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":113 - * # stack.append(key) - * stack.append(try_key) - * continue # <<<<<<<<<<<<<< - * - * new_head1, new_head2 = new_heads - */ - goto __pyx_L12_continue; - } - __pyx_L27:; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":115 - * continue - * - * new_head1, new_head2 = new_heads # <<<<<<<<<<<<<< - * new_tail1, new_tail2 = new_tails - * - */ - if ((likely(PyTuple_CheckExact(__pyx_v_new_heads))) || (PyList_CheckExact(__pyx_v_new_heads))) { - PyObject* sequence = __pyx_v_new_heads; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 2)) { - if (size > 2) __Pyx_RaiseTooManyValuesError(2); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 115, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - if (likely(PyTuple_CheckExact(sequence))) { - __pyx_t_4 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); - } else { - __pyx_t_4 = PyList_GET_ITEM(sequence, 0); - __pyx_t_3 = PyList_GET_ITEM(sequence, 1); - } - __Pyx_INCREF(__pyx_t_4); - __Pyx_INCREF(__pyx_t_3); - #else - __pyx_t_4 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 115, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 115, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - #endif - } else { - Py_ssize_t index = -1; - __pyx_t_7 = PyObject_GetIter(__pyx_v_new_heads); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 115, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __pyx_t_15 = Py_TYPE(__pyx_t_7)->tp_iternext; - index = 0; __pyx_t_4 = __pyx_t_15(__pyx_t_7); if (unlikely(!__pyx_t_4)) goto __pyx_L30_unpacking_failed; - __Pyx_GOTREF(__pyx_t_4); - index = 1; __pyx_t_3 = __pyx_t_15(__pyx_t_7); if (unlikely(!__pyx_t_3)) goto __pyx_L30_unpacking_failed; - __Pyx_GOTREF(__pyx_t_3); - if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_7), 2) < 0) __PYX_ERR(0, 115, __pyx_L1_error) - __pyx_t_15 = NULL; - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - goto __pyx_L31_unpacking_done; - __pyx_L30_unpacking_failed:; - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - __pyx_t_15 = NULL; - if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); - __PYX_ERR(0, 115, __pyx_L1_error) - __pyx_L31_unpacking_done:; - } - __Pyx_XDECREF_SET(__pyx_v_new_head1, __pyx_t_4); - __pyx_t_4 = 0; - __Pyx_XDECREF_SET(__pyx_v_new_head2, __pyx_t_3); - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":116 - * - * new_head1, new_head2 = new_heads - * new_tail1, new_tail2 = new_tails # <<<<<<<<<<<<<< - * - * subseq1 = a1 + new_head1 + b1 + new_tail1 - */ - if ((likely(PyTuple_CheckExact(__pyx_v_new_tails))) || (PyList_CheckExact(__pyx_v_new_tails))) { - PyObject* sequence = __pyx_v_new_tails; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 2)) { - if (size > 2) __Pyx_RaiseTooManyValuesError(2); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 116, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - if (likely(PyTuple_CheckExact(sequence))) { - __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); - } else { - __pyx_t_3 = PyList_GET_ITEM(sequence, 0); - __pyx_t_4 = PyList_GET_ITEM(sequence, 1); - } - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(__pyx_t_4); - #else - __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 116, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 116, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - #endif - } else { - Py_ssize_t index = -1; - __pyx_t_7 = PyObject_GetIter(__pyx_v_new_tails); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 116, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __pyx_t_15 = Py_TYPE(__pyx_t_7)->tp_iternext; - index = 0; __pyx_t_3 = __pyx_t_15(__pyx_t_7); if (unlikely(!__pyx_t_3)) goto __pyx_L32_unpacking_failed; - __Pyx_GOTREF(__pyx_t_3); - index = 1; __pyx_t_4 = __pyx_t_15(__pyx_t_7); if (unlikely(!__pyx_t_4)) goto __pyx_L32_unpacking_failed; - __Pyx_GOTREF(__pyx_t_4); - if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_7), 2) < 0) __PYX_ERR(0, 116, __pyx_L1_error) - __pyx_t_15 = NULL; - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - goto __pyx_L33_unpacking_done; - __pyx_L32_unpacking_failed:; - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - __pyx_t_15 = NULL; - if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); - __PYX_ERR(0, 116, __pyx_L1_error) - __pyx_L33_unpacking_done:; - } - __Pyx_XDECREF_SET(__pyx_v_new_tail1, __pyx_t_3); - __pyx_t_3 = 0; - __Pyx_XDECREF_SET(__pyx_v_new_tail2, __pyx_t_4); - __pyx_t_4 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":118 - * new_tail1, new_tail2 = new_tails - * - * subseq1 = a1 + new_head1 + b1 + new_tail1 # <<<<<<<<<<<<<< - * subseq2 = a2 + new_head2 + b2 + new_tail2 - * - */ - __pyx_t_4 = PyNumber_Add(__pyx_v_a1, __pyx_v_new_head1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 118, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_3 = PyNumber_Add(__pyx_t_4, __pyx_v_b1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 118, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __pyx_t_4 = PyNumber_Add(__pyx_t_3, __pyx_v_new_tail1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 118, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __Pyx_XDECREF_SET(__pyx_v_subseq1, __pyx_t_4); - __pyx_t_4 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":119 - * - * subseq1 = a1 + new_head1 + b1 + new_tail1 - * subseq2 = a2 + new_head2 + b2 + new_tail2 # <<<<<<<<<<<<<< - * - * res3 = (subseq1, subseq2) - */ - __pyx_t_4 = PyNumber_Add(__pyx_v_a2, __pyx_v_new_head2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 119, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_3 = PyNumber_Add(__pyx_t_4, __pyx_v_b2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 119, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __pyx_t_4 = PyNumber_Add(__pyx_t_3, __pyx_v_new_tail2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 119, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __Pyx_XDECREF_SET(__pyx_v_subseq2, __pyx_t_4); - __pyx_t_4 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":121 - * subseq2 = a2 + new_head2 + b2 + new_tail2 - * - * res3 = (subseq1, subseq2) # <<<<<<<<<<<<<< - * val3 = pval_h + pval_t + affinity - * cand3 = (val3, res3) - */ - __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 121, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_INCREF(__pyx_v_subseq1); - __Pyx_GIVEREF(__pyx_v_subseq1); - PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_subseq1); - __Pyx_INCREF(__pyx_v_subseq2); - __Pyx_GIVEREF(__pyx_v_subseq2); - PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_subseq2); - __Pyx_XDECREF_SET(__pyx_v_res3, ((PyObject*)__pyx_t_4)); - __pyx_t_4 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":122 - * - * res3 = (subseq1, subseq2) - * val3 = pval_h + pval_t + affinity # <<<<<<<<<<<<<< - * cand3 = (val3, res3) - * else: - */ - __pyx_t_4 = PyNumber_Add(__pyx_v_pval_h, __pyx_v_pval_t); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 122, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_3 = PyNumber_Add(__pyx_t_4, __pyx_v_affinity); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 122, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __Pyx_XDECREF_SET(__pyx_v_val3, __pyx_t_3); - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":123 - * res3 = (subseq1, subseq2) - * val3 = pval_h + pval_t + affinity - * cand3 = (val3, res3) # <<<<<<<<<<<<<< - * else: - * cand3 = (-1, None) - */ - __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 123, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_INCREF(__pyx_v_val3); - __Pyx_GIVEREF(__pyx_v_val3); - PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_val3); - __Pyx_INCREF(__pyx_v_res3); - __Pyx_GIVEREF(__pyx_v_res3); - PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_res3); - __Pyx_XDECREF_SET(__pyx_v_cand3, ((PyObject*)__pyx_t_3)); - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":98 - * # Case 1: The LCS involves this edge - * affinity = node_affinity(t1, t2) - * if affinity: # <<<<<<<<<<<<<< - * try_key = (head1, head2) - * if try_key in _results: - */ - goto __pyx_L23; - } - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":125 - * cand3 = (val3, res3) - * else: - * cand3 = (-1, None) # <<<<<<<<<<<<<< - * - * # We solved the frame - */ - /*else*/ { - __Pyx_INCREF(__pyx_tuple_); - __Pyx_XDECREF_SET(__pyx_v_cand3, __pyx_tuple_); - } - __pyx_L23:; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":128 - * - * # We solved the frame - * _results[key] = max(cand1, cand2, cand3) # <<<<<<<<<<<<<< - * stack.pop() - * - */ - __Pyx_INCREF(__pyx_v_cand2); - __pyx_t_3 = __pyx_v_cand2; - __Pyx_INCREF(__pyx_v_cand3); - __pyx_t_18 = __pyx_v_cand3; - __Pyx_INCREF(__pyx_v_cand1); - __pyx_t_4 = __pyx_v_cand1; - __pyx_t_5 = PyObject_RichCompare(__pyx_t_3, __pyx_t_4, Py_GT); __Pyx_XGOTREF(__pyx_t_5); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 128, __pyx_L1_error) - __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 128, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - if (__pyx_t_1) { - __Pyx_INCREF(__pyx_t_3); - __pyx_t_7 = __pyx_t_3; - } else { - __Pyx_INCREF(__pyx_t_4); - __pyx_t_7 = __pyx_t_4; - } - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __Pyx_INCREF(__pyx_t_7); - __pyx_t_4 = __pyx_t_7; - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - __pyx_t_5 = PyObject_RichCompare(__pyx_t_18, __pyx_t_4, Py_GT); __Pyx_XGOTREF(__pyx_t_5); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 128, __pyx_L1_error) - __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 128, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - if (__pyx_t_1) { - __Pyx_INCREF(__pyx_t_18); - __pyx_t_7 = __pyx_t_18; - } else { - __Pyx_INCREF(__pyx_t_4); - __pyx_t_7 = __pyx_t_4; - } - __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; - __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0; - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_t_3 = __pyx_t_7; - __Pyx_INCREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_v_key, __pyx_t_3) < 0)) __PYX_ERR(0, 128, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":72 - * while stack: - * key = stack[-1] - * if key not in _results: # <<<<<<<<<<<<<< - * seq1, seq2 = key - * - */ - } - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":129 - * # We solved the frame - * _results[key] = max(cand1, cand2, cand3) - * stack.pop() # <<<<<<<<<<<<<< - * - * val, best = _results[key0] - */ - __pyx_t_3 = __Pyx_PyList_Pop(__pyx_v_stack); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 129, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_L12_continue:; - } - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":131 - * stack.pop() - * - * val, best = _results[key0] # <<<<<<<<<<<<<< - * found = (best, val) - * return found - */ - __pyx_t_3 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_key0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 131, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) { - PyObject* sequence = __pyx_t_3; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 2)) { - if (size > 2) __Pyx_RaiseTooManyValuesError(2); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 131, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - if (likely(PyTuple_CheckExact(sequence))) { - __pyx_t_7 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); - } else { - __pyx_t_7 = PyList_GET_ITEM(sequence, 0); - __pyx_t_4 = PyList_GET_ITEM(sequence, 1); - } - __Pyx_INCREF(__pyx_t_7); - __Pyx_INCREF(__pyx_t_4); - #else - __pyx_t_7 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 131, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 131, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - #endif - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - } else { - Py_ssize_t index = -1; - __pyx_t_5 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 131, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_t_15 = Py_TYPE(__pyx_t_5)->tp_iternext; - index = 0; __pyx_t_7 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_7)) goto __pyx_L34_unpacking_failed; - __Pyx_GOTREF(__pyx_t_7); - index = 1; __pyx_t_4 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_4)) goto __pyx_L34_unpacking_failed; - __Pyx_GOTREF(__pyx_t_4); - if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_5), 2) < 0) __PYX_ERR(0, 131, __pyx_L1_error) - __pyx_t_15 = NULL; - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - goto __pyx_L35_unpacking_done; - __pyx_L34_unpacking_failed:; - __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0; - __pyx_t_15 = NULL; - if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); - __PYX_ERR(0, 131, __pyx_L1_error) - __pyx_L35_unpacking_done:; - } - __pyx_v_val = __pyx_t_7; - __pyx_t_7 = 0; - __Pyx_DECREF_SET(__pyx_v_best, __pyx_t_4); - __pyx_t_4 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":132 - * - * val, best = _results[key0] - * found = (best, val) # <<<<<<<<<<<<<< - * return found - * - */ - __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 132, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_INCREF(__pyx_v_best); - __Pyx_GIVEREF(__pyx_v_best); - PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_best); - __Pyx_INCREF(__pyx_v_val); - __Pyx_GIVEREF(__pyx_v_val); - PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_val); - __pyx_v_found = ((PyObject*)__pyx_t_3); - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":133 - * val, best = _results[key0] - * found = (best, val) - * return found # <<<<<<<<<<<<<< - * - * - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(__pyx_v_found); - __pyx_r = __pyx_v_found; - goto __pyx_L0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":35 - * - * - * def _lcs_iter_simple_alt2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node): # <<<<<<<<<<<<<< - * """ - * Depth first stack trajectory and replace try except statements with ifs - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_3); - __Pyx_XDECREF(__pyx_t_4); - __Pyx_XDECREF(__pyx_t_5); - __Pyx_XDECREF(__pyx_t_7); - __Pyx_XDECREF(__pyx_t_10); - __Pyx_XDECREF(__pyx_t_11); - __Pyx_XDECREF(__pyx_t_12); - __Pyx_XDECREF(__pyx_t_13); - __Pyx_XDECREF(__pyx_t_14); - __Pyx_XDECREF(__pyx_t_18); - __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython._lcs_iter_simple_alt2_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XDECREF(__pyx_v_all_decomp1); - __Pyx_XDECREF(__pyx_v_all_decomp2); - __Pyx_XDECREF(__pyx_v_key0); - __Pyx_XDECREF(__pyx_v_frame0); - __Pyx_XDECREF(__pyx_v_stack); - __Pyx_XDECREF(__pyx_v__results); - __Pyx_XDECREF(__pyx_v_empty1); - __Pyx_XDECREF(__pyx_v_empty2); - __Pyx_XDECREF(__pyx_v_best); - __Pyx_XDECREF(__pyx_v_base_result); - __Pyx_XDECREF(__pyx_v_seq1); - __Pyx_XDECREF(__pyx_v_key1); - __Pyx_XDECREF(__pyx_v_t1); - __Pyx_XDECREF(__pyx_v_a1); - __Pyx_XDECREF(__pyx_v_b1); - __Pyx_XDECREF(__pyx_v_head1); - __Pyx_XDECREF(__pyx_v_tail1); - __Pyx_XDECREF(__pyx_v_head_tail1); - __Pyx_XDECREF(__pyx_v_seq2); - __Pyx_XDECREF(__pyx_v_key2); - __Pyx_XDECREF(__pyx_v_t2); - __Pyx_XDECREF(__pyx_v_a2); - __Pyx_XDECREF(__pyx_v_b2); - __Pyx_XDECREF(__pyx_v_head2); - __Pyx_XDECREF(__pyx_v_tail2); - __Pyx_XDECREF(__pyx_v_head_tail2); - __Pyx_XDECREF(__pyx_v_key); - __Pyx_XDECREF(__pyx_v_try_key); - __Pyx_XDECREF(__pyx_v_cand1); - __Pyx_XDECREF(__pyx_v_cand2); - __Pyx_XDECREF(__pyx_v_affinity); - __Pyx_XDECREF(__pyx_v_pval_h); - __Pyx_XDECREF(__pyx_v_new_heads); - __Pyx_XDECREF(__pyx_v_pval_t); - __Pyx_XDECREF(__pyx_v_new_tails); - __Pyx_XDECREF(__pyx_v_new_head1); - __Pyx_XDECREF(__pyx_v_new_head2); - __Pyx_XDECREF(__pyx_v_new_tail1); - __Pyx_XDECREF(__pyx_v_new_tail2); - __Pyx_XDECREF(__pyx_v_subseq1); - __Pyx_XDECREF(__pyx_v_subseq2); - __Pyx_XDECREF(__pyx_v_res3); - __Pyx_XDECREF(__pyx_v_val3); - __Pyx_XDECREF(__pyx_v_cand3); - __Pyx_XDECREF(__pyx_v_val); - __Pyx_XDECREF(__pyx_v_found); - __Pyx_XDECREF(__pyx_v_open_to_node); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":136 - * - * - * def _lcs_iter_prehash2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node): # <<<<<<<<<<<<<< - * """ - * Version of the lcs iterative algorithm where we precompute hash values - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_3_lcs_iter_prehash2_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static char __pyx_doc_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_2_lcs_iter_prehash2_cython[] = "\n Version of the lcs iterative algorithm where we precompute hash values\n "; -static PyMethodDef __pyx_mdef_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_3_lcs_iter_prehash2_cython = {"_lcs_iter_prehash2_cython", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_3_lcs_iter_prehash2_cython, METH_VARARGS|METH_KEYWORDS, __pyx_doc_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_2_lcs_iter_prehash2_cython}; -static PyObject *__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_3_lcs_iter_prehash2_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { - PyObject *__pyx_v_full_seq1 = 0; - PyObject *__pyx_v_full_seq2 = 0; - PyObject *__pyx_v_open_to_close = 0; - PyObject *__pyx_v_node_affinity = 0; - PyObject *__pyx_v_open_to_node = 0; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("_lcs_iter_prehash2_cython (wrapper)", 0); - { - static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_full_seq1,&__pyx_n_s_full_seq2,&__pyx_n_s_open_to_close,&__pyx_n_s_node_affinity,&__pyx_n_s_open_to_node,0}; - PyObject* values[5] = {0,0,0,0,0}; - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args; - const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); - switch (pos_args) { - case 5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4); - CYTHON_FALLTHROUGH; - case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); - CYTHON_FALLTHROUGH; - case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); - CYTHON_FALLTHROUGH; - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - CYTHON_FALLTHROUGH; - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - CYTHON_FALLTHROUGH; - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - kw_args = PyDict_Size(__pyx_kwds); - switch (pos_args) { - case 0: - if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_full_seq1)) != 0)) kw_args--; - else goto __pyx_L5_argtuple_error; - CYTHON_FALLTHROUGH; - case 1: - if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_full_seq2)) != 0)) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("_lcs_iter_prehash2_cython", 1, 5, 5, 1); __PYX_ERR(0, 136, __pyx_L3_error) - } - CYTHON_FALLTHROUGH; - case 2: - if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_open_to_close)) != 0)) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("_lcs_iter_prehash2_cython", 1, 5, 5, 2); __PYX_ERR(0, 136, __pyx_L3_error) - } - CYTHON_FALLTHROUGH; - case 3: - if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_node_affinity)) != 0)) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("_lcs_iter_prehash2_cython", 1, 5, 5, 3); __PYX_ERR(0, 136, __pyx_L3_error) - } - CYTHON_FALLTHROUGH; - case 4: - if (likely((values[4] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_open_to_node)) != 0)) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("_lcs_iter_prehash2_cython", 1, 5, 5, 4); __PYX_ERR(0, 136, __pyx_L3_error) - } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "_lcs_iter_prehash2_cython") < 0)) __PYX_ERR(0, 136, __pyx_L3_error) - } - } else if (PyTuple_GET_SIZE(__pyx_args) != 5) { - goto __pyx_L5_argtuple_error; - } else { - values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - values[2] = PyTuple_GET_ITEM(__pyx_args, 2); - values[3] = PyTuple_GET_ITEM(__pyx_args, 3); - values[4] = PyTuple_GET_ITEM(__pyx_args, 4); - } - __pyx_v_full_seq1 = values[0]; - __pyx_v_full_seq2 = values[1]; - __pyx_v_open_to_close = values[2]; - __pyx_v_node_affinity = values[3]; - __pyx_v_open_to_node = values[4]; - } - goto __pyx_L4_argument_unpacking_done; - __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("_lcs_iter_prehash2_cython", 1, 5, 5, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 136, __pyx_L3_error) - __pyx_L3_error:; - __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython._lcs_iter_prehash2_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); - __Pyx_RefNannyFinishContext(); - return NULL; - __pyx_L4_argument_unpacking_done:; - __pyx_r = __pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_2_lcs_iter_prehash2_cython(__pyx_self, __pyx_v_full_seq1, __pyx_v_full_seq2, __pyx_v_open_to_close, __pyx_v_node_affinity, __pyx_v_open_to_node); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_2_lcs_iter_prehash2_cython(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_full_seq1, PyObject *__pyx_v_full_seq2, PyObject *__pyx_v_open_to_close, PyObject *__pyx_v_node_affinity, PyObject *__pyx_v_open_to_node) { - PyObject *__pyx_v_all_decomp1 = 0; - PyObject *__pyx_v_all_decomp2 = 0; - PyObject *__pyx_v_key_decomp1 = 0; - PyObject *__pyx_v_key_decomp2 = 0; - PyObject *__pyx_v__results = 0; - PyObject *__pyx_v_empty1 = NULL; - PyObject *__pyx_v_empty2 = NULL; - Py_hash_t __pyx_v_empty1_key; - Py_hash_t __pyx_v_empty2_key; - PyObject *__pyx_v_best = 0; - PyObject *__pyx_v_info1 = 0; - PyObject *__pyx_v_info2 = 0; - PyObject *__pyx_v_try_key = 0; - PyObject *__pyx_v_key = 0; - Py_hash_t __pyx_v_seq1_key; - Py_hash_t __pyx_v_seq2_key; - Py_hash_t __pyx_v_head1_key; - Py_hash_t __pyx_v_tail1_key; - Py_hash_t __pyx_v_head_tail1_key; - Py_hash_t __pyx_v_head2_key; - Py_hash_t __pyx_v_tail2_key; - Py_hash_t __pyx_v_head_tail2_key; - PyObject *__pyx_v_frame = 0; - PyObject *__pyx_v_miss_frame = 0; - PyObject *__pyx_v_base_result = NULL; - PyObject *__pyx_v_seq1 = NULL; - PyObject *__pyx_v_seq2 = NULL; - Py_hash_t __pyx_v_full_seq1_key; - Py_hash_t __pyx_v_full_seq2_key; - PyObject *__pyx_v_key0 = 0; - PyObject *__pyx_v_frame0 = 0; - PyObject *__pyx_v_stack = 0; - PyObject *__pyx_v_tok1 = NULL; - PyObject *__pyx_v_head1 = NULL; - PyObject *__pyx_v_tail1 = NULL; - PyObject *__pyx_v_head_tail1 = NULL; - PyObject *__pyx_v_a1 = NULL; - PyObject *__pyx_v_b1 = NULL; - PyObject *__pyx_v_tok2 = NULL; - PyObject *__pyx_v_head2 = NULL; - PyObject *__pyx_v_tail2 = NULL; - PyObject *__pyx_v_head_tail2 = NULL; - PyObject *__pyx_v_a2 = NULL; - PyObject *__pyx_v_b2 = NULL; - PyObject *__pyx_v_affinity = NULL; - PyObject *__pyx_v_cand1 = NULL; - PyObject *__pyx_v_cand2 = NULL; - PyObject *__pyx_v_pval_h = NULL; - PyObject *__pyx_v_new_heads = NULL; - PyObject *__pyx_v_pval_t = NULL; - PyObject *__pyx_v_new_tails = NULL; - PyObject *__pyx_v_new_head1 = NULL; - PyObject *__pyx_v_new_head2 = NULL; - PyObject *__pyx_v_new_tail1 = NULL; - PyObject *__pyx_v_new_tail2 = NULL; - PyObject *__pyx_v_subseq1 = NULL; - PyObject *__pyx_v_subseq2 = NULL; - PyObject *__pyx_v_res3 = NULL; - PyObject *__pyx_v_val3 = NULL; - PyObject *__pyx_v_cand3 = NULL; - PyObject *__pyx_v_val = NULL; - PyObject *__pyx_v_found = NULL; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - Py_hash_t __pyx_t_4; - Py_ssize_t __pyx_t_5; - PyObject *(*__pyx_t_6)(PyObject *); - PyObject *__pyx_t_7 = NULL; - PyObject *__pyx_t_8 = NULL; - PyObject *(*__pyx_t_9)(PyObject *); - PyObject *__pyx_t_10 = NULL; - Py_hash_t __pyx_t_11; - Py_hash_t __pyx_t_12; - int __pyx_t_13; - int __pyx_t_14; - PyObject *__pyx_t_15 = NULL; - PyObject *__pyx_t_16 = NULL; - PyObject *__pyx_t_17 = NULL; - PyObject *__pyx_t_18 = NULL; - int __pyx_t_19; - int __pyx_t_20; - PyObject *__pyx_t_21 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("_lcs_iter_prehash2_cython", 0); - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":140 - * Version of the lcs iterative algorithm where we precompute hash values - * """ - * cdef dict all_decomp1 = generate_all_decomp_prehash_cython(full_seq1, open_to_close, open_to_node) # <<<<<<<<<<<<<< - * cdef dict all_decomp2 = generate_all_decomp_prehash_cython(full_seq2, open_to_close, open_to_node) - * cdef dict key_decomp1 = {} - */ - if (!(likely(PyDict_CheckExact(__pyx_v_open_to_close))||((__pyx_v_open_to_close) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "dict", Py_TYPE(__pyx_v_open_to_close)->tp_name), 0))) __PYX_ERR(0, 140, __pyx_L1_error) - __pyx_t_1 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_prehash_cython(__pyx_v_full_seq1, ((PyObject*)__pyx_v_open_to_close), __pyx_v_open_to_node); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 140, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_v_all_decomp1 = ((PyObject*)__pyx_t_1); - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":141 - * """ - * cdef dict all_decomp1 = generate_all_decomp_prehash_cython(full_seq1, open_to_close, open_to_node) - * cdef dict all_decomp2 = generate_all_decomp_prehash_cython(full_seq2, open_to_close, open_to_node) # <<<<<<<<<<<<<< - * cdef dict key_decomp1 = {} - * cdef dict key_decomp2 = {} - */ - if (!(likely(PyDict_CheckExact(__pyx_v_open_to_close))||((__pyx_v_open_to_close) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "dict", Py_TYPE(__pyx_v_open_to_close)->tp_name), 0))) __PYX_ERR(0, 141, __pyx_L1_error) - __pyx_t_1 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_prehash_cython(__pyx_v_full_seq2, ((PyObject*)__pyx_v_open_to_close), __pyx_v_open_to_node); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 141, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_v_all_decomp2 = ((PyObject*)__pyx_t_1); - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":142 - * cdef dict all_decomp1 = generate_all_decomp_prehash_cython(full_seq1, open_to_close, open_to_node) - * cdef dict all_decomp2 = generate_all_decomp_prehash_cython(full_seq2, open_to_close, open_to_node) - * cdef dict key_decomp1 = {} # <<<<<<<<<<<<<< - * cdef dict key_decomp2 = {} - * - */ - __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 142, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_v_key_decomp1 = ((PyObject*)__pyx_t_1); - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":143 - * cdef dict all_decomp2 = generate_all_decomp_prehash_cython(full_seq2, open_to_close, open_to_node) - * cdef dict key_decomp1 = {} - * cdef dict key_decomp2 = {} # <<<<<<<<<<<<<< - * - * cdef dict _results = {} - */ - __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 143, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_v_key_decomp2 = ((PyObject*)__pyx_t_1); - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":145 - * cdef dict key_decomp2 = {} - * - * cdef dict _results = {} # <<<<<<<<<<<<<< - * # Populate base cases - * empty1 = type(next(iter(all_decomp1.keys())))() - */ - __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 145, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_v__results = ((PyObject*)__pyx_t_1); - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":147 - * cdef dict _results = {} - * # Populate base cases - * empty1 = type(next(iter(all_decomp1.keys())))() # <<<<<<<<<<<<<< - * empty2 = type(next(iter(all_decomp2.keys())))() - * cdef Py_hash_t empty1_key = hash(empty1) - */ - if (unlikely(__pyx_v_all_decomp1 == Py_None)) { - PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "keys"); - __PYX_ERR(0, 147, __pyx_L1_error) - } - __pyx_t_2 = __Pyx_PyDict_Keys(__pyx_v_all_decomp1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 147, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 147, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = __Pyx_PyIter_Next(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 147, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __Pyx_INCREF(((PyObject *)Py_TYPE(__pyx_t_2))); - __pyx_t_3 = ((PyObject *)Py_TYPE(__pyx_t_2)); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_2 = NULL; - if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { - __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3); - if (likely(__pyx_t_2)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); - __Pyx_INCREF(__pyx_t_2); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_3, function); - } - } - __pyx_t_1 = (__pyx_t_2) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_2) : __Pyx_PyObject_CallNoArg(__pyx_t_3); - __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 147, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_v_empty1 = __pyx_t_1; - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":148 - * # Populate base cases - * empty1 = type(next(iter(all_decomp1.keys())))() - * empty2 = type(next(iter(all_decomp2.keys())))() # <<<<<<<<<<<<<< - * cdef Py_hash_t empty1_key = hash(empty1) - * cdef Py_hash_t empty2_key = hash(empty2) - */ - if (unlikely(__pyx_v_all_decomp2 == Py_None)) { - PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "keys"); - __PYX_ERR(0, 148, __pyx_L1_error) - } - __pyx_t_3 = __Pyx_PyDict_Keys(__pyx_v_all_decomp2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 148, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_2 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 148, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_t_3 = __Pyx_PyIter_Next(__pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 148, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_INCREF(((PyObject *)Py_TYPE(__pyx_t_3))); - __pyx_t_2 = ((PyObject *)Py_TYPE(__pyx_t_3)); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_t_3 = NULL; - if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) { - __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2); - if (likely(__pyx_t_3)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2); - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_2, function); - } - } - __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0; - if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 148, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_v_empty2 = __pyx_t_1; - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":149 - * empty1 = type(next(iter(all_decomp1.keys())))() - * empty2 = type(next(iter(all_decomp2.keys())))() - * cdef Py_hash_t empty1_key = hash(empty1) # <<<<<<<<<<<<<< - * cdef Py_hash_t empty2_key = hash(empty2) - * cdef tuple best = (empty1, empty2) - */ - __pyx_t_4 = PyObject_Hash(__pyx_v_empty1); if (unlikely(__pyx_t_4 == ((Py_hash_t)-1))) __PYX_ERR(0, 149, __pyx_L1_error) - __pyx_v_empty1_key = __pyx_t_4; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":150 - * empty2 = type(next(iter(all_decomp2.keys())))() - * cdef Py_hash_t empty1_key = hash(empty1) - * cdef Py_hash_t empty2_key = hash(empty2) # <<<<<<<<<<<<<< - * cdef tuple best = (empty1, empty2) - * - */ - __pyx_t_4 = PyObject_Hash(__pyx_v_empty2); if (unlikely(__pyx_t_4 == ((Py_hash_t)-1))) __PYX_ERR(0, 150, __pyx_L1_error) - __pyx_v_empty2_key = __pyx_t_4; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":151 - * cdef Py_hash_t empty1_key = hash(empty1) - * cdef Py_hash_t empty2_key = hash(empty2) - * cdef tuple best = (empty1, empty2) # <<<<<<<<<<<<<< - * - * cdef tuple info1, info2 - */ - __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 151, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_INCREF(__pyx_v_empty1); - __Pyx_GIVEREF(__pyx_v_empty1); - PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_empty1); - __Pyx_INCREF(__pyx_v_empty2); - __Pyx_GIVEREF(__pyx_v_empty2); - PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_empty2); - __pyx_v_best = ((PyObject*)__pyx_t_1); - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":161 - * cdef tuple miss_frame - * - * base_result = (0, best) # <<<<<<<<<<<<<< - * for seq1, info1 in all_decomp1.items(): - * seq1_key = hash(seq1) - */ - __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 161, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_INCREF(__pyx_int_0); - __Pyx_GIVEREF(__pyx_int_0); - PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_int_0); - __Pyx_INCREF(__pyx_v_best); - __Pyx_GIVEREF(__pyx_v_best); - PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_best); - __pyx_v_base_result = ((PyObject*)__pyx_t_1); - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":162 - * - * base_result = (0, best) - * for seq1, info1 in all_decomp1.items(): # <<<<<<<<<<<<<< - * seq1_key = hash(seq1) - * head1_key, tail1_key, head_tail1_key = all_decomp1[seq1][5:8] - */ - if (unlikely(__pyx_v_all_decomp1 == Py_None)) { - PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "items"); - __PYX_ERR(0, 162, __pyx_L1_error) - } - __pyx_t_1 = __Pyx_PyDict_Items(__pyx_v_all_decomp1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 162, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (likely(PyList_CheckExact(__pyx_t_1)) || PyTuple_CheckExact(__pyx_t_1)) { - __pyx_t_2 = __pyx_t_1; __Pyx_INCREF(__pyx_t_2); __pyx_t_5 = 0; - __pyx_t_6 = NULL; - } else { - __pyx_t_5 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 162, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_6 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 162, __pyx_L1_error) - } - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - for (;;) { - if (likely(!__pyx_t_6)) { - if (likely(PyList_CheckExact(__pyx_t_2))) { - if (__pyx_t_5 >= PyList_GET_SIZE(__pyx_t_2)) break; - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_1 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_5); __Pyx_INCREF(__pyx_t_1); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 162, __pyx_L1_error) - #else - __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 162, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - #endif - } else { - if (__pyx_t_5 >= PyTuple_GET_SIZE(__pyx_t_2)) break; - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_5); __Pyx_INCREF(__pyx_t_1); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 162, __pyx_L1_error) - #else - __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 162, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - #endif - } - } else { - __pyx_t_1 = __pyx_t_6(__pyx_t_2); - if (unlikely(!__pyx_t_1)) { - PyObject* exc_type = PyErr_Occurred(); - if (exc_type) { - if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear(); - else __PYX_ERR(0, 162, __pyx_L1_error) - } - break; - } - __Pyx_GOTREF(__pyx_t_1); - } - if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) { - PyObject* sequence = __pyx_t_1; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 2)) { - if (size > 2) __Pyx_RaiseTooManyValuesError(2); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 162, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - if (likely(PyTuple_CheckExact(sequence))) { - __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_7 = PyTuple_GET_ITEM(sequence, 1); - } else { - __pyx_t_3 = PyList_GET_ITEM(sequence, 0); - __pyx_t_7 = PyList_GET_ITEM(sequence, 1); - } - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(__pyx_t_7); - #else - __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 162, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_7 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 162, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - #endif - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - } else { - Py_ssize_t index = -1; - __pyx_t_8 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 162, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_9 = Py_TYPE(__pyx_t_8)->tp_iternext; - index = 0; __pyx_t_3 = __pyx_t_9(__pyx_t_8); if (unlikely(!__pyx_t_3)) goto __pyx_L5_unpacking_failed; - __Pyx_GOTREF(__pyx_t_3); - index = 1; __pyx_t_7 = __pyx_t_9(__pyx_t_8); if (unlikely(!__pyx_t_7)) goto __pyx_L5_unpacking_failed; - __Pyx_GOTREF(__pyx_t_7); - if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_8), 2) < 0) __PYX_ERR(0, 162, __pyx_L1_error) - __pyx_t_9 = NULL; - __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; - goto __pyx_L6_unpacking_done; - __pyx_L5_unpacking_failed:; - __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; - __pyx_t_9 = NULL; - if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); - __PYX_ERR(0, 162, __pyx_L1_error) - __pyx_L6_unpacking_done:; - } - if (!(likely(PyTuple_CheckExact(__pyx_t_7))||((__pyx_t_7) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_7)->tp_name), 0))) __PYX_ERR(0, 162, __pyx_L1_error) - __Pyx_XDECREF_SET(__pyx_v_seq1, __pyx_t_3); - __pyx_t_3 = 0; - __Pyx_XDECREF_SET(__pyx_v_info1, ((PyObject*)__pyx_t_7)); - __pyx_t_7 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":163 - * base_result = (0, best) - * for seq1, info1 in all_decomp1.items(): - * seq1_key = hash(seq1) # <<<<<<<<<<<<<< - * head1_key, tail1_key, head_tail1_key = all_decomp1[seq1][5:8] - * _results[(seq1_key, empty2_key)] = base_result - */ - __pyx_t_4 = PyObject_Hash(__pyx_v_seq1); if (unlikely(__pyx_t_4 == ((Py_hash_t)-1))) __PYX_ERR(0, 163, __pyx_L1_error) - __pyx_v_seq1_key = __pyx_t_4; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":164 - * for seq1, info1 in all_decomp1.items(): - * seq1_key = hash(seq1) - * head1_key, tail1_key, head_tail1_key = all_decomp1[seq1][5:8] # <<<<<<<<<<<<<< - * _results[(seq1_key, empty2_key)] = base_result - * _results[(head1_key, empty2_key)] = base_result - */ - if (unlikely(__pyx_v_all_decomp1 == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(0, 164, __pyx_L1_error) - } - __pyx_t_1 = __Pyx_PyDict_GetItem(__pyx_v_all_decomp1, __pyx_v_seq1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 164, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_7 = __Pyx_PyObject_GetSlice(__pyx_t_1, 5, 8, NULL, NULL, &__pyx_slice__2, 1, 1, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 164, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - if ((likely(PyTuple_CheckExact(__pyx_t_7))) || (PyList_CheckExact(__pyx_t_7))) { - PyObject* sequence = __pyx_t_7; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 3)) { - if (size > 3) __Pyx_RaiseTooManyValuesError(3); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 164, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - if (likely(PyTuple_CheckExact(sequence))) { - __pyx_t_1 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); - __pyx_t_8 = PyTuple_GET_ITEM(sequence, 2); - } else { - __pyx_t_1 = PyList_GET_ITEM(sequence, 0); - __pyx_t_3 = PyList_GET_ITEM(sequence, 1); - __pyx_t_8 = PyList_GET_ITEM(sequence, 2); - } - __Pyx_INCREF(__pyx_t_1); - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(__pyx_t_8); - #else - __pyx_t_1 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 164, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 164, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_8 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 164, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - #endif - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - } else { - Py_ssize_t index = -1; - __pyx_t_10 = PyObject_GetIter(__pyx_t_7); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 164, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_10); - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - __pyx_t_9 = Py_TYPE(__pyx_t_10)->tp_iternext; - index = 0; __pyx_t_1 = __pyx_t_9(__pyx_t_10); if (unlikely(!__pyx_t_1)) goto __pyx_L7_unpacking_failed; - __Pyx_GOTREF(__pyx_t_1); - index = 1; __pyx_t_3 = __pyx_t_9(__pyx_t_10); if (unlikely(!__pyx_t_3)) goto __pyx_L7_unpacking_failed; - __Pyx_GOTREF(__pyx_t_3); - index = 2; __pyx_t_8 = __pyx_t_9(__pyx_t_10); if (unlikely(!__pyx_t_8)) goto __pyx_L7_unpacking_failed; - __Pyx_GOTREF(__pyx_t_8); - if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_10), 3) < 0) __PYX_ERR(0, 164, __pyx_L1_error) - __pyx_t_9 = NULL; - __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; - goto __pyx_L8_unpacking_done; - __pyx_L7_unpacking_failed:; - __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; - __pyx_t_9 = NULL; - if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); - __PYX_ERR(0, 164, __pyx_L1_error) - __pyx_L8_unpacking_done:; - } - __pyx_t_4 = __Pyx_PyInt_AsHash_t(__pyx_t_1); if (unlikely((__pyx_t_4 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 164, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_11 = __Pyx_PyInt_AsHash_t(__pyx_t_3); if (unlikely((__pyx_t_11 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 164, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_t_12 = __Pyx_PyInt_AsHash_t(__pyx_t_8); if (unlikely((__pyx_t_12 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 164, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; - __pyx_v_head1_key = __pyx_t_4; - __pyx_v_tail1_key = __pyx_t_11; - __pyx_v_head_tail1_key = __pyx_t_12; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":165 - * seq1_key = hash(seq1) - * head1_key, tail1_key, head_tail1_key = all_decomp1[seq1][5:8] - * _results[(seq1_key, empty2_key)] = base_result # <<<<<<<<<<<<<< - * _results[(head1_key, empty2_key)] = base_result - * _results[(tail1_key, empty2_key)] = base_result - */ - __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_seq1_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 165, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_empty2_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 165, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 165, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_GIVEREF(__pyx_t_7); - PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_7); - __Pyx_GIVEREF(__pyx_t_8); - PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_8); - __pyx_t_7 = 0; - __pyx_t_8 = 0; - if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 165, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":166 - * head1_key, tail1_key, head_tail1_key = all_decomp1[seq1][5:8] - * _results[(seq1_key, empty2_key)] = base_result - * _results[(head1_key, empty2_key)] = base_result # <<<<<<<<<<<<<< - * _results[(tail1_key, empty2_key)] = base_result - * _results[(head_tail1_key, empty2_key)] = base_result - */ - __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_head1_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 166, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_empty2_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 166, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 166, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __Pyx_GIVEREF(__pyx_t_3); - PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_3); - __Pyx_GIVEREF(__pyx_t_8); - PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_t_8); - __pyx_t_3 = 0; - __pyx_t_8 = 0; - if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_7, __pyx_v_base_result) < 0)) __PYX_ERR(0, 166, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":167 - * _results[(seq1_key, empty2_key)] = base_result - * _results[(head1_key, empty2_key)] = base_result - * _results[(tail1_key, empty2_key)] = base_result # <<<<<<<<<<<<<< - * _results[(head_tail1_key, empty2_key)] = base_result - * key_decomp1[seq1_key] = info1 - */ - __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_tail1_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 167, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_empty2_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 167, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 167, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_GIVEREF(__pyx_t_7); - PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_7); - __Pyx_GIVEREF(__pyx_t_8); - PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_8); - __pyx_t_7 = 0; - __pyx_t_8 = 0; - if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 167, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":168 - * _results[(head1_key, empty2_key)] = base_result - * _results[(tail1_key, empty2_key)] = base_result - * _results[(head_tail1_key, empty2_key)] = base_result # <<<<<<<<<<<<<< - * key_decomp1[seq1_key] = info1 - * - */ - __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_head_tail1_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 168, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_empty2_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 168, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 168, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __Pyx_GIVEREF(__pyx_t_3); - PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_3); - __Pyx_GIVEREF(__pyx_t_8); - PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_t_8); - __pyx_t_3 = 0; - __pyx_t_8 = 0; - if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_7, __pyx_v_base_result) < 0)) __PYX_ERR(0, 168, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":169 - * _results[(tail1_key, empty2_key)] = base_result - * _results[(head_tail1_key, empty2_key)] = base_result - * key_decomp1[seq1_key] = info1 # <<<<<<<<<<<<<< - * - * for seq2, info2 in all_decomp2.items(): - */ - __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_seq1_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 169, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - if (unlikely(PyDict_SetItem(__pyx_v_key_decomp1, __pyx_t_7, __pyx_v_info1) < 0)) __PYX_ERR(0, 169, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":162 - * - * base_result = (0, best) - * for seq1, info1 in all_decomp1.items(): # <<<<<<<<<<<<<< - * seq1_key = hash(seq1) - * head1_key, tail1_key, head_tail1_key = all_decomp1[seq1][5:8] - */ - } - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":171 - * key_decomp1[seq1_key] = info1 - * - * for seq2, info2 in all_decomp2.items(): # <<<<<<<<<<<<<< - * seq2_key = hash(seq2) - * head2_key, tail2_key, head_tail2_key = all_decomp2[seq2][5:8] - */ - if (unlikely(__pyx_v_all_decomp2 == Py_None)) { - PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "items"); - __PYX_ERR(0, 171, __pyx_L1_error) - } - __pyx_t_2 = __Pyx_PyDict_Items(__pyx_v_all_decomp2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 171, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - if (likely(PyList_CheckExact(__pyx_t_2)) || PyTuple_CheckExact(__pyx_t_2)) { - __pyx_t_7 = __pyx_t_2; __Pyx_INCREF(__pyx_t_7); __pyx_t_5 = 0; - __pyx_t_6 = NULL; - } else { - __pyx_t_5 = -1; __pyx_t_7 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 171, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __pyx_t_6 = Py_TYPE(__pyx_t_7)->tp_iternext; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 171, __pyx_L1_error) - } - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - for (;;) { - if (likely(!__pyx_t_6)) { - if (likely(PyList_CheckExact(__pyx_t_7))) { - if (__pyx_t_5 >= PyList_GET_SIZE(__pyx_t_7)) break; - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_2 = PyList_GET_ITEM(__pyx_t_7, __pyx_t_5); __Pyx_INCREF(__pyx_t_2); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 171, __pyx_L1_error) - #else - __pyx_t_2 = PySequence_ITEM(__pyx_t_7, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 171, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - #endif - } else { - if (__pyx_t_5 >= PyTuple_GET_SIZE(__pyx_t_7)) break; - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_7, __pyx_t_5); __Pyx_INCREF(__pyx_t_2); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 171, __pyx_L1_error) - #else - __pyx_t_2 = PySequence_ITEM(__pyx_t_7, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 171, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - #endif - } - } else { - __pyx_t_2 = __pyx_t_6(__pyx_t_7); - if (unlikely(!__pyx_t_2)) { - PyObject* exc_type = PyErr_Occurred(); - if (exc_type) { - if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear(); - else __PYX_ERR(0, 171, __pyx_L1_error) - } - break; - } - __Pyx_GOTREF(__pyx_t_2); - } - if ((likely(PyTuple_CheckExact(__pyx_t_2))) || (PyList_CheckExact(__pyx_t_2))) { - PyObject* sequence = __pyx_t_2; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 2)) { - if (size > 2) __Pyx_RaiseTooManyValuesError(2); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 171, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - if (likely(PyTuple_CheckExact(sequence))) { - __pyx_t_8 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); - } else { - __pyx_t_8 = PyList_GET_ITEM(sequence, 0); - __pyx_t_3 = PyList_GET_ITEM(sequence, 1); - } - __Pyx_INCREF(__pyx_t_8); - __Pyx_INCREF(__pyx_t_3); - #else - __pyx_t_8 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 171, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 171, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - #endif - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - } else { - Py_ssize_t index = -1; - __pyx_t_1 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 171, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext; - index = 0; __pyx_t_8 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_8)) goto __pyx_L11_unpacking_failed; - __Pyx_GOTREF(__pyx_t_8); - index = 1; __pyx_t_3 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_3)) goto __pyx_L11_unpacking_failed; - __Pyx_GOTREF(__pyx_t_3); - if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_1), 2) < 0) __PYX_ERR(0, 171, __pyx_L1_error) - __pyx_t_9 = NULL; - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - goto __pyx_L12_unpacking_done; - __pyx_L11_unpacking_failed:; - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_9 = NULL; - if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); - __PYX_ERR(0, 171, __pyx_L1_error) - __pyx_L12_unpacking_done:; - } - if (!(likely(PyTuple_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_3)->tp_name), 0))) __PYX_ERR(0, 171, __pyx_L1_error) - __Pyx_XDECREF_SET(__pyx_v_seq2, __pyx_t_8); - __pyx_t_8 = 0; - __Pyx_XDECREF_SET(__pyx_v_info2, ((PyObject*)__pyx_t_3)); - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":172 - * - * for seq2, info2 in all_decomp2.items(): - * seq2_key = hash(seq2) # <<<<<<<<<<<<<< - * head2_key, tail2_key, head_tail2_key = all_decomp2[seq2][5:8] - * _results[(empty1_key, seq2_key)] = base_result - */ - __pyx_t_12 = PyObject_Hash(__pyx_v_seq2); if (unlikely(__pyx_t_12 == ((Py_hash_t)-1))) __PYX_ERR(0, 172, __pyx_L1_error) - __pyx_v_seq2_key = __pyx_t_12; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":173 - * for seq2, info2 in all_decomp2.items(): - * seq2_key = hash(seq2) - * head2_key, tail2_key, head_tail2_key = all_decomp2[seq2][5:8] # <<<<<<<<<<<<<< - * _results[(empty1_key, seq2_key)] = base_result - * _results[(empty1_key, head2_key)] = base_result - */ - if (unlikely(__pyx_v_all_decomp2 == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(0, 173, __pyx_L1_error) - } - __pyx_t_2 = __Pyx_PyDict_GetItem(__pyx_v_all_decomp2, __pyx_v_seq2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 173, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_3 = __Pyx_PyObject_GetSlice(__pyx_t_2, 5, 8, NULL, NULL, &__pyx_slice__2, 1, 1, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 173, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) { - PyObject* sequence = __pyx_t_3; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 3)) { - if (size > 3) __Pyx_RaiseTooManyValuesError(3); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 173, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - if (likely(PyTuple_CheckExact(sequence))) { - __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_8 = PyTuple_GET_ITEM(sequence, 1); - __pyx_t_1 = PyTuple_GET_ITEM(sequence, 2); - } else { - __pyx_t_2 = PyList_GET_ITEM(sequence, 0); - __pyx_t_8 = PyList_GET_ITEM(sequence, 1); - __pyx_t_1 = PyList_GET_ITEM(sequence, 2); - } - __Pyx_INCREF(__pyx_t_2); - __Pyx_INCREF(__pyx_t_8); - __Pyx_INCREF(__pyx_t_1); - #else - __pyx_t_2 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 173, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - __pyx_t_8 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 173, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - __pyx_t_1 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 173, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - #endif - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - } else { - Py_ssize_t index = -1; - __pyx_t_10 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 173, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_10); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_t_9 = Py_TYPE(__pyx_t_10)->tp_iternext; - index = 0; __pyx_t_2 = __pyx_t_9(__pyx_t_10); if (unlikely(!__pyx_t_2)) goto __pyx_L13_unpacking_failed; - __Pyx_GOTREF(__pyx_t_2); - index = 1; __pyx_t_8 = __pyx_t_9(__pyx_t_10); if (unlikely(!__pyx_t_8)) goto __pyx_L13_unpacking_failed; - __Pyx_GOTREF(__pyx_t_8); - index = 2; __pyx_t_1 = __pyx_t_9(__pyx_t_10); if (unlikely(!__pyx_t_1)) goto __pyx_L13_unpacking_failed; - __Pyx_GOTREF(__pyx_t_1); - if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_10), 3) < 0) __PYX_ERR(0, 173, __pyx_L1_error) - __pyx_t_9 = NULL; - __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; - goto __pyx_L14_unpacking_done; - __pyx_L13_unpacking_failed:; - __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; - __pyx_t_9 = NULL; - if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); - __PYX_ERR(0, 173, __pyx_L1_error) - __pyx_L14_unpacking_done:; - } - __pyx_t_12 = __Pyx_PyInt_AsHash_t(__pyx_t_2); if (unlikely((__pyx_t_12 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 173, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_11 = __Pyx_PyInt_AsHash_t(__pyx_t_8); if (unlikely((__pyx_t_11 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 173, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; - __pyx_t_4 = __Pyx_PyInt_AsHash_t(__pyx_t_1); if (unlikely((__pyx_t_4 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 173, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_v_head2_key = __pyx_t_12; - __pyx_v_tail2_key = __pyx_t_11; - __pyx_v_head_tail2_key = __pyx_t_4; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":174 - * seq2_key = hash(seq2) - * head2_key, tail2_key, head_tail2_key = all_decomp2[seq2][5:8] - * _results[(empty1_key, seq2_key)] = base_result # <<<<<<<<<<<<<< - * _results[(empty1_key, head2_key)] = base_result - * _results[(empty1_key, tail2_key)] = base_result - */ - __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_empty1_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 174, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_1 = __Pyx_PyInt_FromHash_t(__pyx_v_seq2_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 174, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 174, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - __Pyx_GIVEREF(__pyx_t_3); - PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_3); - __Pyx_GIVEREF(__pyx_t_1); - PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_1); - __pyx_t_3 = 0; - __pyx_t_1 = 0; - if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_8, __pyx_v_base_result) < 0)) __PYX_ERR(0, 174, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":175 - * head2_key, tail2_key, head_tail2_key = all_decomp2[seq2][5:8] - * _results[(empty1_key, seq2_key)] = base_result - * _results[(empty1_key, head2_key)] = base_result # <<<<<<<<<<<<<< - * _results[(empty1_key, tail2_key)] = base_result - * _results[(empty1_key, head_tail2_key)] = base_result - */ - __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_empty1_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 175, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - __pyx_t_1 = __Pyx_PyInt_FromHash_t(__pyx_v_head2_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 175, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 175, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_GIVEREF(__pyx_t_8); - PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_8); - __Pyx_GIVEREF(__pyx_t_1); - PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_1); - __pyx_t_8 = 0; - __pyx_t_1 = 0; - if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 175, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":176 - * _results[(empty1_key, seq2_key)] = base_result - * _results[(empty1_key, head2_key)] = base_result - * _results[(empty1_key, tail2_key)] = base_result # <<<<<<<<<<<<<< - * _results[(empty1_key, head_tail2_key)] = base_result - * key_decomp2[seq2_key] = info2 - */ - __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_empty1_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 176, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_1 = __Pyx_PyInt_FromHash_t(__pyx_v_tail2_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 176, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 176, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - __Pyx_GIVEREF(__pyx_t_3); - PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_3); - __Pyx_GIVEREF(__pyx_t_1); - PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_1); - __pyx_t_3 = 0; - __pyx_t_1 = 0; - if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_8, __pyx_v_base_result) < 0)) __PYX_ERR(0, 176, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":177 - * _results[(empty1_key, head2_key)] = base_result - * _results[(empty1_key, tail2_key)] = base_result - * _results[(empty1_key, head_tail2_key)] = base_result # <<<<<<<<<<<<<< - * key_decomp2[seq2_key] = info2 - * - */ - __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_empty1_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 177, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - __pyx_t_1 = __Pyx_PyInt_FromHash_t(__pyx_v_head_tail2_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 177, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 177, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_GIVEREF(__pyx_t_8); - PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_8); - __Pyx_GIVEREF(__pyx_t_1); - PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_1); - __pyx_t_8 = 0; - __pyx_t_1 = 0; - if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 177, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":178 - * _results[(empty1_key, tail2_key)] = base_result - * _results[(empty1_key, head_tail2_key)] = base_result - * key_decomp2[seq2_key] = info2 # <<<<<<<<<<<<<< - * - * cdef Py_hash_t full_seq1_key = hash(full_seq1) - */ - __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_seq2_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 178, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - if (unlikely(PyDict_SetItem(__pyx_v_key_decomp2, __pyx_t_3, __pyx_v_info2) < 0)) __PYX_ERR(0, 178, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":171 - * key_decomp1[seq1_key] = info1 - * - * for seq2, info2 in all_decomp2.items(): # <<<<<<<<<<<<<< - * seq2_key = hash(seq2) - * head2_key, tail2_key, head_tail2_key = all_decomp2[seq2][5:8] - */ - } - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":180 - * key_decomp2[seq2_key] = info2 - * - * cdef Py_hash_t full_seq1_key = hash(full_seq1) # <<<<<<<<<<<<<< - * cdef Py_hash_t full_seq2_key = hash(full_seq2) - * - */ - __pyx_t_4 = PyObject_Hash(__pyx_v_full_seq1); if (unlikely(__pyx_t_4 == ((Py_hash_t)-1))) __PYX_ERR(0, 180, __pyx_L1_error) - __pyx_v_full_seq1_key = __pyx_t_4; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":181 - * - * cdef Py_hash_t full_seq1_key = hash(full_seq1) - * cdef Py_hash_t full_seq2_key = hash(full_seq2) # <<<<<<<<<<<<<< - * - * cdef tuple key0 = (full_seq1_key, full_seq2_key) - */ - __pyx_t_4 = PyObject_Hash(__pyx_v_full_seq2); if (unlikely(__pyx_t_4 == ((Py_hash_t)-1))) __PYX_ERR(0, 181, __pyx_L1_error) - __pyx_v_full_seq2_key = __pyx_t_4; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":183 - * cdef Py_hash_t full_seq2_key = hash(full_seq2) - * - * cdef tuple key0 = (full_seq1_key, full_seq2_key) # <<<<<<<<<<<<<< - * cdef tuple frame0 = (key0, full_seq1, full_seq2) - * cdef list stack = [frame0] - */ - __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_full_seq1_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 183, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_full_seq2_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 183, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 183, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_GIVEREF(__pyx_t_7); - PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_7); - __Pyx_GIVEREF(__pyx_t_3); - PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_3); - __pyx_t_7 = 0; - __pyx_t_3 = 0; - __pyx_v_key0 = ((PyObject*)__pyx_t_1); - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":184 - * - * cdef tuple key0 = (full_seq1_key, full_seq2_key) - * cdef tuple frame0 = (key0, full_seq1, full_seq2) # <<<<<<<<<<<<<< - * cdef list stack = [frame0] - * - */ - __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 184, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_INCREF(__pyx_v_key0); - __Pyx_GIVEREF(__pyx_v_key0); - PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_key0); - __Pyx_INCREF(__pyx_v_full_seq1); - __Pyx_GIVEREF(__pyx_v_full_seq1); - PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_full_seq1); - __Pyx_INCREF(__pyx_v_full_seq2); - __Pyx_GIVEREF(__pyx_v_full_seq2); - PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_full_seq2); - __pyx_v_frame0 = ((PyObject*)__pyx_t_1); - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":185 - * cdef tuple key0 = (full_seq1_key, full_seq2_key) - * cdef tuple frame0 = (key0, full_seq1, full_seq2) - * cdef list stack = [frame0] # <<<<<<<<<<<<<< - * - * while stack: - */ - __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 185, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_INCREF(__pyx_v_frame0); - __Pyx_GIVEREF(__pyx_v_frame0); - PyList_SET_ITEM(__pyx_t_1, 0, __pyx_v_frame0); - __pyx_v_stack = ((PyObject*)__pyx_t_1); - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":187 - * cdef list stack = [frame0] - * - * while stack: # <<<<<<<<<<<<<< - * frame = stack[-1] - * key, seq1, seq2 = frame - */ - while (1) { - __pyx_t_13 = (PyList_GET_SIZE(__pyx_v_stack) != 0); - if (!__pyx_t_13) break; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":188 - * - * while stack: - * frame = stack[-1] # <<<<<<<<<<<<<< - * key, seq1, seq2 = frame - * seq1_key, seq2_key = key - */ - __pyx_t_1 = __Pyx_GetItemInt_List(__pyx_v_stack, -1L, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 188, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (!(likely(PyTuple_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(0, 188, __pyx_L1_error) - __Pyx_XDECREF_SET(__pyx_v_frame, ((PyObject*)__pyx_t_1)); - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":189 - * while stack: - * frame = stack[-1] - * key, seq1, seq2 = frame # <<<<<<<<<<<<<< - * seq1_key, seq2_key = key - * if key not in _results: - */ - if (likely(__pyx_v_frame != Py_None)) { - PyObject* sequence = __pyx_v_frame; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 3)) { - if (size > 3) __Pyx_RaiseTooManyValuesError(3); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 189, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_1 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); - __pyx_t_7 = PyTuple_GET_ITEM(sequence, 2); - __Pyx_INCREF(__pyx_t_1); - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(__pyx_t_7); - #else - __pyx_t_1 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 189, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 189, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_7 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 189, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - #endif - } else { - __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 189, __pyx_L1_error) - } - if (!(likely(PyTuple_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(0, 189, __pyx_L1_error) - __Pyx_XDECREF_SET(__pyx_v_key, ((PyObject*)__pyx_t_1)); - __pyx_t_1 = 0; - __Pyx_XDECREF_SET(__pyx_v_seq1, __pyx_t_3); - __pyx_t_3 = 0; - __Pyx_XDECREF_SET(__pyx_v_seq2, __pyx_t_7); - __pyx_t_7 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":190 - * frame = stack[-1] - * key, seq1, seq2 = frame - * seq1_key, seq2_key = key # <<<<<<<<<<<<<< - * if key not in _results: - * info1 = key_decomp1[seq1_key] - */ - if (likely(__pyx_v_key != Py_None)) { - PyObject* sequence = __pyx_v_key; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 2)) { - if (size > 2) __Pyx_RaiseTooManyValuesError(2); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 190, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_7 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); - __Pyx_INCREF(__pyx_t_7); - __Pyx_INCREF(__pyx_t_3); - #else - __pyx_t_7 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 190, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 190, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - #endif - } else { - __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 190, __pyx_L1_error) - } - __pyx_t_4 = __Pyx_PyInt_AsHash_t(__pyx_t_7); if (unlikely((__pyx_t_4 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 190, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - __pyx_t_11 = __Pyx_PyInt_AsHash_t(__pyx_t_3); if (unlikely((__pyx_t_11 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 190, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_v_seq1_key = __pyx_t_4; - __pyx_v_seq2_key = __pyx_t_11; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":191 - * key, seq1, seq2 = frame - * seq1_key, seq2_key = key - * if key not in _results: # <<<<<<<<<<<<<< - * info1 = key_decomp1[seq1_key] - * tok1, seq1, head1, tail1, head_tail1, head1_key, tail1_key, head_tail1_key, a1, b1 = info1 - */ - __pyx_t_13 = (__Pyx_PyDict_ContainsTF(__pyx_v_key, __pyx_v__results, Py_NE)); if (unlikely(__pyx_t_13 < 0)) __PYX_ERR(0, 191, __pyx_L1_error) - __pyx_t_14 = (__pyx_t_13 != 0); - if (__pyx_t_14) { - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":192 - * seq1_key, seq2_key = key - * if key not in _results: - * info1 = key_decomp1[seq1_key] # <<<<<<<<<<<<<< - * tok1, seq1, head1, tail1, head_tail1, head1_key, tail1_key, head_tail1_key, a1, b1 = info1 - * - */ - __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_seq1_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 192, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_7 = __Pyx_PyDict_GetItem(__pyx_v_key_decomp1, __pyx_t_3); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 192, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - if (!(likely(PyTuple_CheckExact(__pyx_t_7))||((__pyx_t_7) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_7)->tp_name), 0))) __PYX_ERR(0, 192, __pyx_L1_error) - __Pyx_XDECREF_SET(__pyx_v_info1, ((PyObject*)__pyx_t_7)); - __pyx_t_7 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":193 - * if key not in _results: - * info1 = key_decomp1[seq1_key] - * tok1, seq1, head1, tail1, head_tail1, head1_key, tail1_key, head_tail1_key, a1, b1 = info1 # <<<<<<<<<<<<<< - * - * info2 = key_decomp2[seq2_key] - */ - if (likely(__pyx_v_info1 != Py_None)) { - PyObject* sequence = __pyx_v_info1; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 10)) { - if (size > 10) __Pyx_RaiseTooManyValuesError(10); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 193, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_7 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); - __pyx_t_1 = PyTuple_GET_ITEM(sequence, 2); - __pyx_t_8 = PyTuple_GET_ITEM(sequence, 3); - __pyx_t_2 = PyTuple_GET_ITEM(sequence, 4); - __pyx_t_10 = PyTuple_GET_ITEM(sequence, 5); - __pyx_t_15 = PyTuple_GET_ITEM(sequence, 6); - __pyx_t_16 = PyTuple_GET_ITEM(sequence, 7); - __pyx_t_17 = PyTuple_GET_ITEM(sequence, 8); - __pyx_t_18 = PyTuple_GET_ITEM(sequence, 9); - __Pyx_INCREF(__pyx_t_7); - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(__pyx_t_1); - __Pyx_INCREF(__pyx_t_8); - __Pyx_INCREF(__pyx_t_2); - __Pyx_INCREF(__pyx_t_10); - __Pyx_INCREF(__pyx_t_15); - __Pyx_INCREF(__pyx_t_16); - __Pyx_INCREF(__pyx_t_17); - __Pyx_INCREF(__pyx_t_18); - #else - { - Py_ssize_t i; - PyObject** temps[10] = {&__pyx_t_7,&__pyx_t_3,&__pyx_t_1,&__pyx_t_8,&__pyx_t_2,&__pyx_t_10,&__pyx_t_15,&__pyx_t_16,&__pyx_t_17,&__pyx_t_18}; - for (i=0; i < 10; i++) { - PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 193, __pyx_L1_error) - __Pyx_GOTREF(item); - *(temps[i]) = item; - } - } - #endif - } else { - __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 193, __pyx_L1_error) - } - __pyx_t_11 = __Pyx_PyInt_AsHash_t(__pyx_t_10); if (unlikely((__pyx_t_11 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 193, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0; - __pyx_t_4 = __Pyx_PyInt_AsHash_t(__pyx_t_15); if (unlikely((__pyx_t_4 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 193, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0; - __pyx_t_12 = __Pyx_PyInt_AsHash_t(__pyx_t_16); if (unlikely((__pyx_t_12 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 193, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0; - __Pyx_XDECREF_SET(__pyx_v_tok1, __pyx_t_7); - __pyx_t_7 = 0; - __Pyx_DECREF_SET(__pyx_v_seq1, __pyx_t_3); - __pyx_t_3 = 0; - __Pyx_XDECREF_SET(__pyx_v_head1, __pyx_t_1); - __pyx_t_1 = 0; - __Pyx_XDECREF_SET(__pyx_v_tail1, __pyx_t_8); - __pyx_t_8 = 0; - __Pyx_XDECREF_SET(__pyx_v_head_tail1, __pyx_t_2); - __pyx_t_2 = 0; - __pyx_v_head1_key = __pyx_t_11; - __pyx_v_tail1_key = __pyx_t_4; - __pyx_v_head_tail1_key = __pyx_t_12; - __Pyx_XDECREF_SET(__pyx_v_a1, __pyx_t_17); - __pyx_t_17 = 0; - __Pyx_XDECREF_SET(__pyx_v_b1, __pyx_t_18); - __pyx_t_18 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":195 - * tok1, seq1, head1, tail1, head_tail1, head1_key, tail1_key, head_tail1_key, a1, b1 = info1 - * - * info2 = key_decomp2[seq2_key] # <<<<<<<<<<<<<< - * tok2, seq2, head2, tail2, head_tail2, head2_key, tail2_key, head_tail2_key, a2, b2 = info2 - * - */ - __pyx_t_18 = __Pyx_PyInt_FromHash_t(__pyx_v_seq2_key); if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 195, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_18); - __pyx_t_17 = __Pyx_PyDict_GetItem(__pyx_v_key_decomp2, __pyx_t_18); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 195, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_17); - __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0; - if (!(likely(PyTuple_CheckExact(__pyx_t_17))||((__pyx_t_17) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_17)->tp_name), 0))) __PYX_ERR(0, 195, __pyx_L1_error) - __Pyx_XDECREF_SET(__pyx_v_info2, ((PyObject*)__pyx_t_17)); - __pyx_t_17 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":196 - * - * info2 = key_decomp2[seq2_key] - * tok2, seq2, head2, tail2, head_tail2, head2_key, tail2_key, head_tail2_key, a2, b2 = info2 # <<<<<<<<<<<<<< - * - * affinity = node_affinity(tok1, tok2) - */ - if (likely(__pyx_v_info2 != Py_None)) { - PyObject* sequence = __pyx_v_info2; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 10)) { - if (size > 10) __Pyx_RaiseTooManyValuesError(10); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 196, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_17 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_18 = PyTuple_GET_ITEM(sequence, 1); - __pyx_t_16 = PyTuple_GET_ITEM(sequence, 2); - __pyx_t_15 = PyTuple_GET_ITEM(sequence, 3); - __pyx_t_10 = PyTuple_GET_ITEM(sequence, 4); - __pyx_t_2 = PyTuple_GET_ITEM(sequence, 5); - __pyx_t_8 = PyTuple_GET_ITEM(sequence, 6); - __pyx_t_1 = PyTuple_GET_ITEM(sequence, 7); - __pyx_t_3 = PyTuple_GET_ITEM(sequence, 8); - __pyx_t_7 = PyTuple_GET_ITEM(sequence, 9); - __Pyx_INCREF(__pyx_t_17); - __Pyx_INCREF(__pyx_t_18); - __Pyx_INCREF(__pyx_t_16); - __Pyx_INCREF(__pyx_t_15); - __Pyx_INCREF(__pyx_t_10); - __Pyx_INCREF(__pyx_t_2); - __Pyx_INCREF(__pyx_t_8); - __Pyx_INCREF(__pyx_t_1); - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(__pyx_t_7); - #else - { - Py_ssize_t i; - PyObject** temps[10] = {&__pyx_t_17,&__pyx_t_18,&__pyx_t_16,&__pyx_t_15,&__pyx_t_10,&__pyx_t_2,&__pyx_t_8,&__pyx_t_1,&__pyx_t_3,&__pyx_t_7}; - for (i=0; i < 10; i++) { - PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 196, __pyx_L1_error) - __Pyx_GOTREF(item); - *(temps[i]) = item; - } - } - #endif - } else { - __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 196, __pyx_L1_error) - } - __pyx_t_12 = __Pyx_PyInt_AsHash_t(__pyx_t_2); if (unlikely((__pyx_t_12 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 196, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __pyx_t_4 = __Pyx_PyInt_AsHash_t(__pyx_t_8); if (unlikely((__pyx_t_4 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 196, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; - __pyx_t_11 = __Pyx_PyInt_AsHash_t(__pyx_t_1); if (unlikely((__pyx_t_11 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 196, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_XDECREF_SET(__pyx_v_tok2, __pyx_t_17); - __pyx_t_17 = 0; - __Pyx_DECREF_SET(__pyx_v_seq2, __pyx_t_18); - __pyx_t_18 = 0; - __Pyx_XDECREF_SET(__pyx_v_head2, __pyx_t_16); - __pyx_t_16 = 0; - __Pyx_XDECREF_SET(__pyx_v_tail2, __pyx_t_15); - __pyx_t_15 = 0; - __Pyx_XDECREF_SET(__pyx_v_head_tail2, __pyx_t_10); - __pyx_t_10 = 0; - __pyx_v_head2_key = __pyx_t_12; - __pyx_v_tail2_key = __pyx_t_4; - __pyx_v_head_tail2_key = __pyx_t_11; - __Pyx_XDECREF_SET(__pyx_v_a2, __pyx_t_3); - __pyx_t_3 = 0; - __Pyx_XDECREF_SET(__pyx_v_b2, __pyx_t_7); - __pyx_t_7 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":198 - * tok2, seq2, head2, tail2, head_tail2, head2_key, tail2_key, head_tail2_key, a2, b2 = info2 - * - * affinity = node_affinity(tok1, tok2) # <<<<<<<<<<<<<< - * - * # Case 2: The current edge in sequence1 is deleted - */ - __Pyx_INCREF(__pyx_v_node_affinity); - __pyx_t_3 = __pyx_v_node_affinity; __pyx_t_1 = NULL; - __pyx_t_19 = 0; - if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) { - __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_3); - if (likely(__pyx_t_1)) { - PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3); - __Pyx_INCREF(__pyx_t_1); - __Pyx_INCREF(function); - __Pyx_DECREF_SET(__pyx_t_3, function); - __pyx_t_19 = 1; - } - } - #if CYTHON_FAST_PYCALL - if (PyFunction_Check(__pyx_t_3)) { - PyObject *__pyx_temp[3] = {__pyx_t_1, __pyx_v_tok1, __pyx_v_tok2}; - __pyx_t_7 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_19, 2+__pyx_t_19); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 198, __pyx_L1_error) - __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_GOTREF(__pyx_t_7); - } else - #endif - #if CYTHON_FAST_PYCCALL - if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) { - PyObject *__pyx_temp[3] = {__pyx_t_1, __pyx_v_tok1, __pyx_v_tok2}; - __pyx_t_7 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_19, 2+__pyx_t_19); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 198, __pyx_L1_error) - __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_GOTREF(__pyx_t_7); - } else - #endif - { - __pyx_t_8 = PyTuple_New(2+__pyx_t_19); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 198, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - if (__pyx_t_1) { - __Pyx_GIVEREF(__pyx_t_1); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_1); __pyx_t_1 = NULL; - } - __Pyx_INCREF(__pyx_v_tok1); - __Pyx_GIVEREF(__pyx_v_tok1); - PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_19, __pyx_v_tok1); - __Pyx_INCREF(__pyx_v_tok2); - __Pyx_GIVEREF(__pyx_v_tok2); - PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_19, __pyx_v_tok2); - __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_8, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 198, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; - } - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __Pyx_XDECREF_SET(__pyx_v_affinity, __pyx_t_7); - __pyx_t_7 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":201 - * - * # Case 2: The current edge in sequence1 is deleted - * try_key = (head_tail1_key, seq2_key) # <<<<<<<<<<<<<< - * if try_key in _results: - * cand1 = _results[try_key] - */ - __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_head_tail1_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 201, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_seq2_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 201, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 201, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - __Pyx_GIVEREF(__pyx_t_7); - PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_7); - __Pyx_GIVEREF(__pyx_t_3); - PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_3); - __pyx_t_7 = 0; - __pyx_t_3 = 0; - __Pyx_XDECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_8)); - __pyx_t_8 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":202 - * # Case 2: The current edge in sequence1 is deleted - * try_key = (head_tail1_key, seq2_key) - * if try_key in _results: # <<<<<<<<<<<<<< - * cand1 = _results[try_key] - * else: - */ - __pyx_t_14 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 202, __pyx_L1_error) - __pyx_t_13 = (__pyx_t_14 != 0); - if (__pyx_t_13) { - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":203 - * try_key = (head_tail1_key, seq2_key) - * if try_key in _results: - * cand1 = _results[try_key] # <<<<<<<<<<<<<< - * else: - * miss_frame = try_key, head_tail1, seq2 - */ - __pyx_t_8 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 203, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - __Pyx_XDECREF_SET(__pyx_v_cand1, __pyx_t_8); - __pyx_t_8 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":202 - * # Case 2: The current edge in sequence1 is deleted - * try_key = (head_tail1_key, seq2_key) - * if try_key in _results: # <<<<<<<<<<<<<< - * cand1 = _results[try_key] - * else: - */ - goto __pyx_L18; - } - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":205 - * cand1 = _results[try_key] - * else: - * miss_frame = try_key, head_tail1, seq2 # <<<<<<<<<<<<<< - * stack.append(miss_frame) - * continue - */ - /*else*/ { - __pyx_t_8 = PyTuple_New(3); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 205, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - __Pyx_INCREF(__pyx_v_try_key); - __Pyx_GIVEREF(__pyx_v_try_key); - PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_v_try_key); - __Pyx_INCREF(__pyx_v_head_tail1); - __Pyx_GIVEREF(__pyx_v_head_tail1); - PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_v_head_tail1); - __Pyx_INCREF(__pyx_v_seq2); - __Pyx_GIVEREF(__pyx_v_seq2); - PyTuple_SET_ITEM(__pyx_t_8, 2, __pyx_v_seq2); - __Pyx_XDECREF_SET(__pyx_v_miss_frame, ((PyObject*)__pyx_t_8)); - __pyx_t_8 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":206 - * else: - * miss_frame = try_key, head_tail1, seq2 - * stack.append(miss_frame) # <<<<<<<<<<<<<< - * continue - * - */ - __pyx_t_20 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_miss_frame); if (unlikely(__pyx_t_20 == ((int)-1))) __PYX_ERR(0, 206, __pyx_L1_error) - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":207 - * miss_frame = try_key, head_tail1, seq2 - * stack.append(miss_frame) - * continue # <<<<<<<<<<<<<< - * - * # Case 3: The current edge in sequence2 is deleted - */ - goto __pyx_L15_continue; - } - __pyx_L18:; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":210 - * - * # Case 3: The current edge in sequence2 is deleted - * try_key = (seq1_key, head_tail2_key) # <<<<<<<<<<<<<< - * if try_key in _results: - * cand2 = _results[try_key] - */ - __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_seq1_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 210, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_head_tail2_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 210, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 210, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __Pyx_GIVEREF(__pyx_t_8); - PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_8); - __Pyx_GIVEREF(__pyx_t_3); - PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_t_3); - __pyx_t_8 = 0; - __pyx_t_3 = 0; - __Pyx_DECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_7)); - __pyx_t_7 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":211 - * # Case 3: The current edge in sequence2 is deleted - * try_key = (seq1_key, head_tail2_key) - * if try_key in _results: # <<<<<<<<<<<<<< - * cand2 = _results[try_key] - * else: - */ - __pyx_t_13 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_13 < 0)) __PYX_ERR(0, 211, __pyx_L1_error) - __pyx_t_14 = (__pyx_t_13 != 0); - if (__pyx_t_14) { - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":212 - * try_key = (seq1_key, head_tail2_key) - * if try_key in _results: - * cand2 = _results[try_key] # <<<<<<<<<<<<<< - * else: - * miss_frame = try_key, seq1, head_tail2 - */ - __pyx_t_7 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 212, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __Pyx_XDECREF_SET(__pyx_v_cand2, __pyx_t_7); - __pyx_t_7 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":211 - * # Case 3: The current edge in sequence2 is deleted - * try_key = (seq1_key, head_tail2_key) - * if try_key in _results: # <<<<<<<<<<<<<< - * cand2 = _results[try_key] - * else: - */ - goto __pyx_L19; - } - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":214 - * cand2 = _results[try_key] - * else: - * miss_frame = try_key, seq1, head_tail2 # <<<<<<<<<<<<<< - * stack.append(miss_frame) - * continue - */ - /*else*/ { - __pyx_t_7 = PyTuple_New(3); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 214, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __Pyx_INCREF(__pyx_v_try_key); - __Pyx_GIVEREF(__pyx_v_try_key); - PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_v_try_key); - __Pyx_INCREF(__pyx_v_seq1); - __Pyx_GIVEREF(__pyx_v_seq1); - PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_v_seq1); - __Pyx_INCREF(__pyx_v_head_tail2); - __Pyx_GIVEREF(__pyx_v_head_tail2); - PyTuple_SET_ITEM(__pyx_t_7, 2, __pyx_v_head_tail2); - __Pyx_XDECREF_SET(__pyx_v_miss_frame, ((PyObject*)__pyx_t_7)); - __pyx_t_7 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":215 - * else: - * miss_frame = try_key, seq1, head_tail2 - * stack.append(miss_frame) # <<<<<<<<<<<<<< - * continue - * - */ - __pyx_t_20 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_miss_frame); if (unlikely(__pyx_t_20 == ((int)-1))) __PYX_ERR(0, 215, __pyx_L1_error) - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":216 - * miss_frame = try_key, seq1, head_tail2 - * stack.append(miss_frame) - * continue # <<<<<<<<<<<<<< - * - * # Case 1: The LCS involves this edge - */ - goto __pyx_L15_continue; - } - __pyx_L19:; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":219 - * - * # Case 1: The LCS involves this edge - * if affinity: # <<<<<<<<<<<<<< - * try_key = (head1_key, head2_key) - * if try_key in _results: - */ - __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_v_affinity); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 219, __pyx_L1_error) - if (__pyx_t_14) { - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":220 - * # Case 1: The LCS involves this edge - * if affinity: - * try_key = (head1_key, head2_key) # <<<<<<<<<<<<<< - * if try_key in _results: - * pval_h, new_heads = _results[try_key] - */ - __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_head1_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 220, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_head2_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 220, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 220, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - __Pyx_GIVEREF(__pyx_t_7); - PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_7); - __Pyx_GIVEREF(__pyx_t_3); - PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_3); - __pyx_t_7 = 0; - __pyx_t_3 = 0; - __Pyx_DECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_8)); - __pyx_t_8 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":221 - * if affinity: - * try_key = (head1_key, head2_key) - * if try_key in _results: # <<<<<<<<<<<<<< - * pval_h, new_heads = _results[try_key] - * else: - */ - __pyx_t_14 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 221, __pyx_L1_error) - __pyx_t_13 = (__pyx_t_14 != 0); - if (__pyx_t_13) { - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":222 - * try_key = (head1_key, head2_key) - * if try_key in _results: - * pval_h, new_heads = _results[try_key] # <<<<<<<<<<<<<< - * else: - * miss_frame = try_key, head1, head2 - */ - __pyx_t_8 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 222, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - if ((likely(PyTuple_CheckExact(__pyx_t_8))) || (PyList_CheckExact(__pyx_t_8))) { - PyObject* sequence = __pyx_t_8; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 2)) { - if (size > 2) __Pyx_RaiseTooManyValuesError(2); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 222, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - if (likely(PyTuple_CheckExact(sequence))) { - __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_7 = PyTuple_GET_ITEM(sequence, 1); - } else { - __pyx_t_3 = PyList_GET_ITEM(sequence, 0); - __pyx_t_7 = PyList_GET_ITEM(sequence, 1); - } - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(__pyx_t_7); - #else - __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 222, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_7 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 222, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - #endif - __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; - } else { - Py_ssize_t index = -1; - __pyx_t_1 = PyObject_GetIter(__pyx_t_8); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 222, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; - __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext; - index = 0; __pyx_t_3 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_3)) goto __pyx_L22_unpacking_failed; - __Pyx_GOTREF(__pyx_t_3); - index = 1; __pyx_t_7 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_7)) goto __pyx_L22_unpacking_failed; - __Pyx_GOTREF(__pyx_t_7); - if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_1), 2) < 0) __PYX_ERR(0, 222, __pyx_L1_error) - __pyx_t_9 = NULL; - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - goto __pyx_L23_unpacking_done; - __pyx_L22_unpacking_failed:; - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_9 = NULL; - if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); - __PYX_ERR(0, 222, __pyx_L1_error) - __pyx_L23_unpacking_done:; - } - __Pyx_XDECREF_SET(__pyx_v_pval_h, __pyx_t_3); - __pyx_t_3 = 0; - __Pyx_XDECREF_SET(__pyx_v_new_heads, __pyx_t_7); - __pyx_t_7 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":221 - * if affinity: - * try_key = (head1_key, head2_key) - * if try_key in _results: # <<<<<<<<<<<<<< - * pval_h, new_heads = _results[try_key] - * else: - */ - goto __pyx_L21; - } - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":224 - * pval_h, new_heads = _results[try_key] - * else: - * miss_frame = try_key, head1, head2 # <<<<<<<<<<<<<< - * stack.append(miss_frame) - * continue - */ - /*else*/ { - __pyx_t_8 = PyTuple_New(3); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 224, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - __Pyx_INCREF(__pyx_v_try_key); - __Pyx_GIVEREF(__pyx_v_try_key); - PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_v_try_key); - __Pyx_INCREF(__pyx_v_head1); - __Pyx_GIVEREF(__pyx_v_head1); - PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_v_head1); - __Pyx_INCREF(__pyx_v_head2); - __Pyx_GIVEREF(__pyx_v_head2); - PyTuple_SET_ITEM(__pyx_t_8, 2, __pyx_v_head2); - __Pyx_XDECREF_SET(__pyx_v_miss_frame, ((PyObject*)__pyx_t_8)); - __pyx_t_8 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":225 - * else: - * miss_frame = try_key, head1, head2 - * stack.append(miss_frame) # <<<<<<<<<<<<<< - * continue - * - */ - __pyx_t_20 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_miss_frame); if (unlikely(__pyx_t_20 == ((int)-1))) __PYX_ERR(0, 225, __pyx_L1_error) - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":226 - * miss_frame = try_key, head1, head2 - * stack.append(miss_frame) - * continue # <<<<<<<<<<<<<< - * - * try_key = (tail1_key, tail2_key) - */ - goto __pyx_L15_continue; - } - __pyx_L21:; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":228 - * continue - * - * try_key = (tail1_key, tail2_key) # <<<<<<<<<<<<<< - * if try_key in _results: - * pval_t, new_tails = _results[try_key] - */ - __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_tail1_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 228, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_tail2_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 228, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 228, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_GIVEREF(__pyx_t_8); - PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_8); - __Pyx_GIVEREF(__pyx_t_7); - PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_7); - __pyx_t_8 = 0; - __pyx_t_7 = 0; - __Pyx_DECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_3)); - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":229 - * - * try_key = (tail1_key, tail2_key) - * if try_key in _results: # <<<<<<<<<<<<<< - * pval_t, new_tails = _results[try_key] - * else: - */ - __pyx_t_13 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_13 < 0)) __PYX_ERR(0, 229, __pyx_L1_error) - __pyx_t_14 = (__pyx_t_13 != 0); - if (__pyx_t_14) { - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":230 - * try_key = (tail1_key, tail2_key) - * if try_key in _results: - * pval_t, new_tails = _results[try_key] # <<<<<<<<<<<<<< - * else: - * miss_frame = try_key, tail1, tail2 - */ - __pyx_t_3 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 230, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) { - PyObject* sequence = __pyx_t_3; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 2)) { - if (size > 2) __Pyx_RaiseTooManyValuesError(2); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 230, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - if (likely(PyTuple_CheckExact(sequence))) { - __pyx_t_7 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_8 = PyTuple_GET_ITEM(sequence, 1); - } else { - __pyx_t_7 = PyList_GET_ITEM(sequence, 0); - __pyx_t_8 = PyList_GET_ITEM(sequence, 1); - } - __Pyx_INCREF(__pyx_t_7); - __Pyx_INCREF(__pyx_t_8); - #else - __pyx_t_7 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 230, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __pyx_t_8 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 230, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - #endif - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - } else { - Py_ssize_t index = -1; - __pyx_t_1 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 230, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext; - index = 0; __pyx_t_7 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_7)) goto __pyx_L25_unpacking_failed; - __Pyx_GOTREF(__pyx_t_7); - index = 1; __pyx_t_8 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_8)) goto __pyx_L25_unpacking_failed; - __Pyx_GOTREF(__pyx_t_8); - if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_1), 2) < 0) __PYX_ERR(0, 230, __pyx_L1_error) - __pyx_t_9 = NULL; - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - goto __pyx_L26_unpacking_done; - __pyx_L25_unpacking_failed:; - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_9 = NULL; - if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); - __PYX_ERR(0, 230, __pyx_L1_error) - __pyx_L26_unpacking_done:; - } - __Pyx_XDECREF_SET(__pyx_v_pval_t, __pyx_t_7); - __pyx_t_7 = 0; - __Pyx_XDECREF_SET(__pyx_v_new_tails, __pyx_t_8); - __pyx_t_8 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":229 - * - * try_key = (tail1_key, tail2_key) - * if try_key in _results: # <<<<<<<<<<<<<< - * pval_t, new_tails = _results[try_key] - * else: - */ - goto __pyx_L24; - } - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":232 - * pval_t, new_tails = _results[try_key] - * else: - * miss_frame = try_key, tail1, tail2 # <<<<<<<<<<<<<< - * stack.append(miss_frame) - * continue - */ - /*else*/ { - __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 232, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_INCREF(__pyx_v_try_key); - __Pyx_GIVEREF(__pyx_v_try_key); - PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_try_key); - __Pyx_INCREF(__pyx_v_tail1); - __Pyx_GIVEREF(__pyx_v_tail1); - PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_tail1); - __Pyx_INCREF(__pyx_v_tail2); - __Pyx_GIVEREF(__pyx_v_tail2); - PyTuple_SET_ITEM(__pyx_t_3, 2, __pyx_v_tail2); - __Pyx_XDECREF_SET(__pyx_v_miss_frame, ((PyObject*)__pyx_t_3)); - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":233 - * else: - * miss_frame = try_key, tail1, tail2 - * stack.append(miss_frame) # <<<<<<<<<<<<<< - * continue - * - */ - __pyx_t_20 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_miss_frame); if (unlikely(__pyx_t_20 == ((int)-1))) __PYX_ERR(0, 233, __pyx_L1_error) - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":234 - * miss_frame = try_key, tail1, tail2 - * stack.append(miss_frame) - * continue # <<<<<<<<<<<<<< - * - * new_head1, new_head2 = new_heads - */ - goto __pyx_L15_continue; - } - __pyx_L24:; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":236 - * continue - * - * new_head1, new_head2 = new_heads # <<<<<<<<<<<<<< - * new_tail1, new_tail2 = new_tails - * - */ - if ((likely(PyTuple_CheckExact(__pyx_v_new_heads))) || (PyList_CheckExact(__pyx_v_new_heads))) { - PyObject* sequence = __pyx_v_new_heads; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 2)) { - if (size > 2) __Pyx_RaiseTooManyValuesError(2); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 236, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - if (likely(PyTuple_CheckExact(sequence))) { - __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_8 = PyTuple_GET_ITEM(sequence, 1); - } else { - __pyx_t_3 = PyList_GET_ITEM(sequence, 0); - __pyx_t_8 = PyList_GET_ITEM(sequence, 1); - } - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(__pyx_t_8); - #else - __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 236, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_8 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 236, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - #endif - } else { - Py_ssize_t index = -1; - __pyx_t_7 = PyObject_GetIter(__pyx_v_new_heads); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 236, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __pyx_t_9 = Py_TYPE(__pyx_t_7)->tp_iternext; - index = 0; __pyx_t_3 = __pyx_t_9(__pyx_t_7); if (unlikely(!__pyx_t_3)) goto __pyx_L27_unpacking_failed; - __Pyx_GOTREF(__pyx_t_3); - index = 1; __pyx_t_8 = __pyx_t_9(__pyx_t_7); if (unlikely(!__pyx_t_8)) goto __pyx_L27_unpacking_failed; - __Pyx_GOTREF(__pyx_t_8); - if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_7), 2) < 0) __PYX_ERR(0, 236, __pyx_L1_error) - __pyx_t_9 = NULL; - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - goto __pyx_L28_unpacking_done; - __pyx_L27_unpacking_failed:; - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - __pyx_t_9 = NULL; - if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); - __PYX_ERR(0, 236, __pyx_L1_error) - __pyx_L28_unpacking_done:; - } - __Pyx_XDECREF_SET(__pyx_v_new_head1, __pyx_t_3); - __pyx_t_3 = 0; - __Pyx_XDECREF_SET(__pyx_v_new_head2, __pyx_t_8); - __pyx_t_8 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":237 - * - * new_head1, new_head2 = new_heads - * new_tail1, new_tail2 = new_tails # <<<<<<<<<<<<<< - * - * subseq1 = a1 + new_head1 + b1 + new_tail1 - */ - if ((likely(PyTuple_CheckExact(__pyx_v_new_tails))) || (PyList_CheckExact(__pyx_v_new_tails))) { - PyObject* sequence = __pyx_v_new_tails; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 2)) { - if (size > 2) __Pyx_RaiseTooManyValuesError(2); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 237, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - if (likely(PyTuple_CheckExact(sequence))) { - __pyx_t_8 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); - } else { - __pyx_t_8 = PyList_GET_ITEM(sequence, 0); - __pyx_t_3 = PyList_GET_ITEM(sequence, 1); - } - __Pyx_INCREF(__pyx_t_8); - __Pyx_INCREF(__pyx_t_3); - #else - __pyx_t_8 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 237, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 237, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - #endif - } else { - Py_ssize_t index = -1; - __pyx_t_7 = PyObject_GetIter(__pyx_v_new_tails); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 237, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __pyx_t_9 = Py_TYPE(__pyx_t_7)->tp_iternext; - index = 0; __pyx_t_8 = __pyx_t_9(__pyx_t_7); if (unlikely(!__pyx_t_8)) goto __pyx_L29_unpacking_failed; - __Pyx_GOTREF(__pyx_t_8); - index = 1; __pyx_t_3 = __pyx_t_9(__pyx_t_7); if (unlikely(!__pyx_t_3)) goto __pyx_L29_unpacking_failed; - __Pyx_GOTREF(__pyx_t_3); - if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_7), 2) < 0) __PYX_ERR(0, 237, __pyx_L1_error) - __pyx_t_9 = NULL; - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - goto __pyx_L30_unpacking_done; - __pyx_L29_unpacking_failed:; - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - __pyx_t_9 = NULL; - if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); - __PYX_ERR(0, 237, __pyx_L1_error) - __pyx_L30_unpacking_done:; - } - __Pyx_XDECREF_SET(__pyx_v_new_tail1, __pyx_t_8); - __pyx_t_8 = 0; - __Pyx_XDECREF_SET(__pyx_v_new_tail2, __pyx_t_3); - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":239 - * new_tail1, new_tail2 = new_tails - * - * subseq1 = a1 + new_head1 + b1 + new_tail1 # <<<<<<<<<<<<<< - * subseq2 = a2 + new_head2 + b2 + new_tail2 - * - */ - __pyx_t_3 = PyNumber_Add(__pyx_v_a1, __pyx_v_new_head1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 239, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_8 = PyNumber_Add(__pyx_t_3, __pyx_v_b1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 239, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_t_3 = PyNumber_Add(__pyx_t_8, __pyx_v_new_tail1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 239, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; - __Pyx_XDECREF_SET(__pyx_v_subseq1, __pyx_t_3); - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":240 - * - * subseq1 = a1 + new_head1 + b1 + new_tail1 - * subseq2 = a2 + new_head2 + b2 + new_tail2 # <<<<<<<<<<<<<< - * - * res3 = (subseq1, subseq2) - */ - __pyx_t_3 = PyNumber_Add(__pyx_v_a2, __pyx_v_new_head2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 240, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_8 = PyNumber_Add(__pyx_t_3, __pyx_v_b2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 240, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __pyx_t_3 = PyNumber_Add(__pyx_t_8, __pyx_v_new_tail2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 240, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; - __Pyx_XDECREF_SET(__pyx_v_subseq2, __pyx_t_3); - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":242 - * subseq2 = a2 + new_head2 + b2 + new_tail2 - * - * res3 = (subseq1, subseq2) # <<<<<<<<<<<<<< - * val3 = pval_h + pval_t + affinity - * cand3 = (val3, res3) - */ - __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 242, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __Pyx_INCREF(__pyx_v_subseq1); - __Pyx_GIVEREF(__pyx_v_subseq1); - PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_subseq1); - __Pyx_INCREF(__pyx_v_subseq2); - __Pyx_GIVEREF(__pyx_v_subseq2); - PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_subseq2); - __Pyx_XDECREF_SET(__pyx_v_res3, ((PyObject*)__pyx_t_3)); - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":243 - * - * res3 = (subseq1, subseq2) - * val3 = pval_h + pval_t + affinity # <<<<<<<<<<<<<< - * cand3 = (val3, res3) - * else: - */ - __pyx_t_3 = PyNumber_Add(__pyx_v_pval_h, __pyx_v_pval_t); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 243, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - __pyx_t_8 = PyNumber_Add(__pyx_t_3, __pyx_v_affinity); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 243, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __Pyx_XDECREF_SET(__pyx_v_val3, __pyx_t_8); - __pyx_t_8 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":244 - * res3 = (subseq1, subseq2) - * val3 = pval_h + pval_t + affinity - * cand3 = (val3, res3) # <<<<<<<<<<<<<< - * else: - * cand3 = (-1, None) - */ - __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 244, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - __Pyx_INCREF(__pyx_v_val3); - __Pyx_GIVEREF(__pyx_v_val3); - PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_v_val3); - __Pyx_INCREF(__pyx_v_res3); - __Pyx_GIVEREF(__pyx_v_res3); - PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_v_res3); - __Pyx_XDECREF_SET(__pyx_v_cand3, ((PyObject*)__pyx_t_8)); - __pyx_t_8 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":219 - * - * # Case 1: The LCS involves this edge - * if affinity: # <<<<<<<<<<<<<< - * try_key = (head1_key, head2_key) - * if try_key in _results: - */ - goto __pyx_L20; - } - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":246 - * cand3 = (val3, res3) - * else: - * cand3 = (-1, None) # <<<<<<<<<<<<<< - * - * # We solved the frame - */ - /*else*/ { - __Pyx_INCREF(__pyx_tuple_); - __Pyx_XDECREF_SET(__pyx_v_cand3, __pyx_tuple_); - } - __pyx_L20:; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":249 - * - * # We solved the frame - * _results[key] = max(cand1, cand2, cand3) # <<<<<<<<<<<<<< - * stack.pop() - * - */ - __Pyx_INCREF(__pyx_v_cand2); - __pyx_t_8 = __pyx_v_cand2; - __Pyx_INCREF(__pyx_v_cand3); - __pyx_t_21 = __pyx_v_cand3; - __Pyx_INCREF(__pyx_v_cand1); - __pyx_t_3 = __pyx_v_cand1; - __pyx_t_1 = PyObject_RichCompare(__pyx_t_8, __pyx_t_3, Py_GT); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 249, __pyx_L1_error) - __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 249, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - if (__pyx_t_14) { - __Pyx_INCREF(__pyx_t_8); - __pyx_t_7 = __pyx_t_8; - } else { - __Pyx_INCREF(__pyx_t_3); - __pyx_t_7 = __pyx_t_3; - } - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __Pyx_INCREF(__pyx_t_7); - __pyx_t_3 = __pyx_t_7; - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - __pyx_t_1 = PyObject_RichCompare(__pyx_t_21, __pyx_t_3, Py_GT); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 249, __pyx_L1_error) - __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 249, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - if (__pyx_t_14) { - __Pyx_INCREF(__pyx_t_21); - __pyx_t_7 = __pyx_t_21; - } else { - __Pyx_INCREF(__pyx_t_3); - __pyx_t_7 = __pyx_t_3; - } - __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; - __Pyx_DECREF(__pyx_t_21); __pyx_t_21 = 0; - __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; - __pyx_t_8 = __pyx_t_7; - __Pyx_INCREF(__pyx_t_8); - __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0; - if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_v_key, __pyx_t_8) < 0)) __PYX_ERR(0, 249, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":191 - * key, seq1, seq2 = frame - * seq1_key, seq2_key = key - * if key not in _results: # <<<<<<<<<<<<<< - * info1 = key_decomp1[seq1_key] - * tok1, seq1, head1, tail1, head_tail1, head1_key, tail1_key, head_tail1_key, a1, b1 = info1 - */ - } - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":250 - * # We solved the frame - * _results[key] = max(cand1, cand2, cand3) - * stack.pop() # <<<<<<<<<<<<<< - * - * # The stack pop is our solution - */ - __pyx_t_8 = __Pyx_PyList_Pop(__pyx_v_stack); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 250, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; - __pyx_L15_continue:; - } - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":253 - * - * # The stack pop is our solution - * (val, best) = _results[key0] # <<<<<<<<<<<<<< - * found = (best, val) - * return found - */ - __pyx_t_8 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_key0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 253, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - if ((likely(PyTuple_CheckExact(__pyx_t_8))) || (PyList_CheckExact(__pyx_t_8))) { - PyObject* sequence = __pyx_t_8; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 2)) { - if (size > 2) __Pyx_RaiseTooManyValuesError(2); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 253, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - if (likely(PyTuple_CheckExact(sequence))) { - __pyx_t_7 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); - } else { - __pyx_t_7 = PyList_GET_ITEM(sequence, 0); - __pyx_t_3 = PyList_GET_ITEM(sequence, 1); - } - __Pyx_INCREF(__pyx_t_7); - __Pyx_INCREF(__pyx_t_3); - #else - __pyx_t_7 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 253, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_7); - __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 253, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_3); - #endif - __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; - } else { - Py_ssize_t index = -1; - __pyx_t_1 = PyObject_GetIter(__pyx_t_8); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 253, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0; - __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext; - index = 0; __pyx_t_7 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_7)) goto __pyx_L31_unpacking_failed; - __Pyx_GOTREF(__pyx_t_7); - index = 1; __pyx_t_3 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_3)) goto __pyx_L31_unpacking_failed; - __Pyx_GOTREF(__pyx_t_3); - if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_1), 2) < 0) __PYX_ERR(0, 253, __pyx_L1_error) - __pyx_t_9 = NULL; - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - goto __pyx_L32_unpacking_done; - __pyx_L31_unpacking_failed:; - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_9 = NULL; - if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index); - __PYX_ERR(0, 253, __pyx_L1_error) - __pyx_L32_unpacking_done:; - } - if (!(likely(PyTuple_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_3)->tp_name), 0))) __PYX_ERR(0, 253, __pyx_L1_error) - __pyx_v_val = __pyx_t_7; - __pyx_t_7 = 0; - __Pyx_DECREF_SET(__pyx_v_best, ((PyObject*)__pyx_t_3)); - __pyx_t_3 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":254 - * # The stack pop is our solution - * (val, best) = _results[key0] - * found = (best, val) # <<<<<<<<<<<<<< - * return found - * - */ - __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 254, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_8); - __Pyx_INCREF(__pyx_v_best); - __Pyx_GIVEREF(__pyx_v_best); - PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_v_best); - __Pyx_INCREF(__pyx_v_val); - __Pyx_GIVEREF(__pyx_v_val); - PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_v_val); - __pyx_v_found = ((PyObject*)__pyx_t_8); - __pyx_t_8 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":255 - * (val, best) = _results[key0] - * found = (best, val) - * return found # <<<<<<<<<<<<<< - * - * - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(__pyx_v_found); - __pyx_r = __pyx_v_found; - goto __pyx_L0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":136 - * - * - * def _lcs_iter_prehash2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node): # <<<<<<<<<<<<<< - * """ - * Version of the lcs iterative algorithm where we precompute hash values - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_XDECREF(__pyx_t_7); - __Pyx_XDECREF(__pyx_t_8); - __Pyx_XDECREF(__pyx_t_10); - __Pyx_XDECREF(__pyx_t_15); - __Pyx_XDECREF(__pyx_t_16); - __Pyx_XDECREF(__pyx_t_17); - __Pyx_XDECREF(__pyx_t_18); - __Pyx_XDECREF(__pyx_t_21); - __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython._lcs_iter_prehash2_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = NULL; - __pyx_L0:; - __Pyx_XDECREF(__pyx_v_all_decomp1); - __Pyx_XDECREF(__pyx_v_all_decomp2); - __Pyx_XDECREF(__pyx_v_key_decomp1); - __Pyx_XDECREF(__pyx_v_key_decomp2); - __Pyx_XDECREF(__pyx_v__results); - __Pyx_XDECREF(__pyx_v_empty1); - __Pyx_XDECREF(__pyx_v_empty2); - __Pyx_XDECREF(__pyx_v_best); - __Pyx_XDECREF(__pyx_v_info1); - __Pyx_XDECREF(__pyx_v_info2); - __Pyx_XDECREF(__pyx_v_try_key); - __Pyx_XDECREF(__pyx_v_key); - __Pyx_XDECREF(__pyx_v_frame); - __Pyx_XDECREF(__pyx_v_miss_frame); - __Pyx_XDECREF(__pyx_v_base_result); - __Pyx_XDECREF(__pyx_v_seq1); - __Pyx_XDECREF(__pyx_v_seq2); - __Pyx_XDECREF(__pyx_v_key0); - __Pyx_XDECREF(__pyx_v_frame0); - __Pyx_XDECREF(__pyx_v_stack); - __Pyx_XDECREF(__pyx_v_tok1); - __Pyx_XDECREF(__pyx_v_head1); - __Pyx_XDECREF(__pyx_v_tail1); - __Pyx_XDECREF(__pyx_v_head_tail1); - __Pyx_XDECREF(__pyx_v_a1); - __Pyx_XDECREF(__pyx_v_b1); - __Pyx_XDECREF(__pyx_v_tok2); - __Pyx_XDECREF(__pyx_v_head2); - __Pyx_XDECREF(__pyx_v_tail2); - __Pyx_XDECREF(__pyx_v_head_tail2); - __Pyx_XDECREF(__pyx_v_a2); - __Pyx_XDECREF(__pyx_v_b2); - __Pyx_XDECREF(__pyx_v_affinity); - __Pyx_XDECREF(__pyx_v_cand1); - __Pyx_XDECREF(__pyx_v_cand2); - __Pyx_XDECREF(__pyx_v_pval_h); - __Pyx_XDECREF(__pyx_v_new_heads); - __Pyx_XDECREF(__pyx_v_pval_t); - __Pyx_XDECREF(__pyx_v_new_tails); - __Pyx_XDECREF(__pyx_v_new_head1); - __Pyx_XDECREF(__pyx_v_new_head2); - __Pyx_XDECREF(__pyx_v_new_tail1); - __Pyx_XDECREF(__pyx_v_new_tail2); - __Pyx_XDECREF(__pyx_v_subseq1); - __Pyx_XDECREF(__pyx_v_subseq2); - __Pyx_XDECREF(__pyx_v_res3); - __Pyx_XDECREF(__pyx_v_val3); - __Pyx_XDECREF(__pyx_v_cand3); - __Pyx_XDECREF(__pyx_v_val); - __Pyx_XDECREF(__pyx_v_found); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":258 - * - * - * cdef tuple balanced_decomp_unsafe_cython(sequence, dict open_to_close): # <<<<<<<<<<<<<< - * cdef int stacklen = 1 # always +1 in the first iteration - * cdef int head_stop = 1 - */ - -static PyObject *__pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_balanced_decomp_unsafe_cython(PyObject *__pyx_v_sequence, PyObject *__pyx_v_open_to_close) { - int __pyx_v_stacklen; - int __pyx_v_head_stop; - PyObject *__pyx_v_tok_curr = NULL; - PyObject *__pyx_v_want_close = NULL; - PyObject *__pyx_v_pop_close = NULL; - PyObject *__pyx_v_pop_open = NULL; - PyObject *__pyx_v_head = NULL; - PyObject *__pyx_v_tail = NULL; - PyObject *__pyx_v_head_tail = NULL; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - Py_ssize_t __pyx_t_2; - Py_ssize_t __pyx_t_3; - int __pyx_t_4; - long __pyx_t_5; - int __pyx_t_6; - int __pyx_t_7; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("balanced_decomp_unsafe_cython", 0); - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":259 - * - * cdef tuple balanced_decomp_unsafe_cython(sequence, dict open_to_close): - * cdef int stacklen = 1 # always +1 in the first iteration # <<<<<<<<<<<<<< - * cdef int head_stop = 1 - * - */ - __pyx_v_stacklen = 1; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":260 - * cdef tuple balanced_decomp_unsafe_cython(sequence, dict open_to_close): - * cdef int stacklen = 1 # always +1 in the first iteration - * cdef int head_stop = 1 # <<<<<<<<<<<<<< - * - * tok_curr = sequence[0] - */ - __pyx_v_head_stop = 1; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":262 - * cdef int head_stop = 1 - * - * tok_curr = sequence[0] # <<<<<<<<<<<<<< - * want_close = open_to_close[tok_curr] - * - */ - __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_sequence, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 262, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_v_tok_curr = __pyx_t_1; - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":263 - * - * tok_curr = sequence[0] - * want_close = open_to_close[tok_curr] # <<<<<<<<<<<<<< - * - * # for tok_curr in sequence[1:]: - */ - if (unlikely(__pyx_v_open_to_close == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(0, 263, __pyx_L1_error) - } - __pyx_t_1 = __Pyx_PyDict_GetItem(__pyx_v_open_to_close, __pyx_v_tok_curr); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 263, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_v_want_close = __pyx_t_1; - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":266 - * - * # for tok_curr in sequence[1:]: - * for head_stop in range(1, len(sequence)): # <<<<<<<<<<<<<< - * tok_curr = sequence[head_stop] - * stacklen += 1 if tok_curr in open_to_close else -1 - */ - __pyx_t_2 = PyObject_Length(__pyx_v_sequence); if (unlikely(__pyx_t_2 == ((Py_ssize_t)-1))) __PYX_ERR(0, 266, __pyx_L1_error) - __pyx_t_3 = __pyx_t_2; - for (__pyx_t_4 = 1; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) { - __pyx_v_head_stop = __pyx_t_4; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":267 - * # for tok_curr in sequence[1:]: - * for head_stop in range(1, len(sequence)): - * tok_curr = sequence[head_stop] # <<<<<<<<<<<<<< - * stacklen += 1 if tok_curr in open_to_close else -1 - * if stacklen == 0 and tok_curr == want_close: - */ - __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_sequence, __pyx_v_head_stop, int, 1, __Pyx_PyInt_From_int, 0, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 267, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF_SET(__pyx_v_tok_curr, __pyx_t_1); - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":268 - * for head_stop in range(1, len(sequence)): - * tok_curr = sequence[head_stop] - * stacklen += 1 if tok_curr in open_to_close else -1 # <<<<<<<<<<<<<< - * if stacklen == 0 and tok_curr == want_close: - * pop_close = sequence[head_stop:head_stop + 1] - */ - if (unlikely(__pyx_v_open_to_close == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); - __PYX_ERR(0, 268, __pyx_L1_error) - } - __pyx_t_6 = (__Pyx_PyDict_ContainsTF(__pyx_v_tok_curr, __pyx_v_open_to_close, Py_EQ)); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(0, 268, __pyx_L1_error) - if ((__pyx_t_6 != 0)) { - __pyx_t_5 = 1; - } else { - __pyx_t_5 = -1L; - } - __pyx_v_stacklen = (__pyx_v_stacklen + __pyx_t_5); - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":269 - * tok_curr = sequence[head_stop] - * stacklen += 1 if tok_curr in open_to_close else -1 - * if stacklen == 0 and tok_curr == want_close: # <<<<<<<<<<<<<< - * pop_close = sequence[head_stop:head_stop + 1] - * break - */ - __pyx_t_7 = ((__pyx_v_stacklen == 0) != 0); - if (__pyx_t_7) { - } else { - __pyx_t_6 = __pyx_t_7; - goto __pyx_L6_bool_binop_done; - } - __pyx_t_1 = PyObject_RichCompare(__pyx_v_tok_curr, __pyx_v_want_close, Py_EQ); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 269, __pyx_L1_error) - __pyx_t_7 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 269, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_t_6 = __pyx_t_7; - __pyx_L6_bool_binop_done:; - if (__pyx_t_6) { - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":270 - * stacklen += 1 if tok_curr in open_to_close else -1 - * if stacklen == 0 and tok_curr == want_close: - * pop_close = sequence[head_stop:head_stop + 1] # <<<<<<<<<<<<<< - * break - * - */ - __pyx_t_1 = __Pyx_PyObject_GetSlice(__pyx_v_sequence, __pyx_v_head_stop, (__pyx_v_head_stop + 1), NULL, NULL, NULL, 1, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 270, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_v_pop_close = __pyx_t_1; - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":271 - * if stacklen == 0 and tok_curr == want_close: - * pop_close = sequence[head_stop:head_stop + 1] - * break # <<<<<<<<<<<<<< - * - * pop_open = sequence[0:1] - */ - goto __pyx_L4_break; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":269 - * tok_curr = sequence[head_stop] - * stacklen += 1 if tok_curr in open_to_close else -1 - * if stacklen == 0 and tok_curr == want_close: # <<<<<<<<<<<<<< - * pop_close = sequence[head_stop:head_stop + 1] - * break - */ - } - } - __pyx_L4_break:; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":273 - * break - * - * pop_open = sequence[0:1] # <<<<<<<<<<<<<< - * head = sequence[1:head_stop] - * tail = sequence[head_stop + 1:] - */ - __pyx_t_1 = __Pyx_PyObject_GetSlice(__pyx_v_sequence, 0, 1, NULL, NULL, &__pyx_slice__3, 1, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 273, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_v_pop_open = __pyx_t_1; - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":274 - * - * pop_open = sequence[0:1] - * head = sequence[1:head_stop] # <<<<<<<<<<<<<< - * tail = sequence[head_stop + 1:] - * head_tail = head + tail - */ - __pyx_t_1 = __Pyx_PyObject_GetSlice(__pyx_v_sequence, 1, __pyx_v_head_stop, NULL, NULL, NULL, 1, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 274, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_v_head = __pyx_t_1; - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":275 - * pop_open = sequence[0:1] - * head = sequence[1:head_stop] - * tail = sequence[head_stop + 1:] # <<<<<<<<<<<<<< - * head_tail = head + tail - * return pop_open, pop_close, head, tail, head_tail - */ - __pyx_t_1 = __Pyx_PyObject_GetSlice(__pyx_v_sequence, (__pyx_v_head_stop + 1), 0, NULL, NULL, NULL, 1, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 275, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_v_tail = __pyx_t_1; - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":276 - * head = sequence[1:head_stop] - * tail = sequence[head_stop + 1:] - * head_tail = head + tail # <<<<<<<<<<<<<< - * return pop_open, pop_close, head, tail, head_tail - * - */ - __pyx_t_1 = PyNumber_Add(__pyx_v_head, __pyx_v_tail); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 276, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_v_head_tail = __pyx_t_1; - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":277 - * tail = sequence[head_stop + 1:] - * head_tail = head + tail - * return pop_open, pop_close, head, tail, head_tail # <<<<<<<<<<<<<< - * - * - */ - __Pyx_XDECREF(__pyx_r); - if (unlikely(!__pyx_v_pop_close)) { __Pyx_RaiseUnboundLocalError("pop_close"); __PYX_ERR(0, 277, __pyx_L1_error) } - __pyx_t_1 = PyTuple_New(5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 277, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_INCREF(__pyx_v_pop_open); - __Pyx_GIVEREF(__pyx_v_pop_open); - PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_pop_open); - __Pyx_INCREF(__pyx_v_pop_close); - __Pyx_GIVEREF(__pyx_v_pop_close); - PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_pop_close); - __Pyx_INCREF(__pyx_v_head); - __Pyx_GIVEREF(__pyx_v_head); - PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_head); - __Pyx_INCREF(__pyx_v_tail); - __Pyx_GIVEREF(__pyx_v_tail); - PyTuple_SET_ITEM(__pyx_t_1, 3, __pyx_v_tail); - __Pyx_INCREF(__pyx_v_head_tail); - __Pyx_GIVEREF(__pyx_v_head_tail); - PyTuple_SET_ITEM(__pyx_t_1, 4, __pyx_v_head_tail); - __pyx_r = ((PyObject*)__pyx_t_1); - __pyx_t_1 = 0; - goto __pyx_L0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":258 - * - * - * cdef tuple balanced_decomp_unsafe_cython(sequence, dict open_to_close): # <<<<<<<<<<<<<< - * cdef int stacklen = 1 # always +1 in the first iteration - * cdef int head_stop = 1 - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython.balanced_decomp_unsafe_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XDECREF(__pyx_v_tok_curr); - __Pyx_XDECREF(__pyx_v_want_close); - __Pyx_XDECREF(__pyx_v_pop_close); - __Pyx_XDECREF(__pyx_v_pop_open); - __Pyx_XDECREF(__pyx_v_head); - __Pyx_XDECREF(__pyx_v_tail); - __Pyx_XDECREF(__pyx_v_head_tail); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":280 - * - * - * cdef generate_all_decomp_cython(seq, open_to_close, open_to_node=None): # <<<<<<<<<<<<<< - * """ - * Cython version of :func:`generate_all_decomp`. - */ - -static PyObject *__pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython(PyObject *__pyx_v_seq, PyObject *__pyx_v_open_to_close, struct __pyx_opt_args_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython *__pyx_optional_args) { - PyObject *__pyx_v_open_to_node = ((PyObject *)Py_None); - PyObject *__pyx_v_all_decomp = NULL; - PyObject *__pyx_v_stack = NULL; - PyObject *__pyx_v_pop_open = NULL; - PyObject *__pyx_v_pop_close = NULL; - PyObject *__pyx_v_head = NULL; - PyObject *__pyx_v_tail = NULL; - PyObject *__pyx_v_head_tail = NULL; - PyObject *__pyx_v_node = NULL; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_t_2; - int __pyx_t_3; - int __pyx_t_4; - PyObject *__pyx_t_5 = NULL; - PyObject *__pyx_t_6 = NULL; - PyObject *__pyx_t_7 = NULL; - PyObject *__pyx_t_8 = NULL; - PyObject *__pyx_t_9 = NULL; - int __pyx_t_10; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("generate_all_decomp_cython", 0); - if (__pyx_optional_args) { - if (__pyx_optional_args->__pyx_n > 0) { - __pyx_v_open_to_node = __pyx_optional_args->open_to_node; - } - } - __Pyx_INCREF(__pyx_v_seq); - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":288 - * >>> all_decomp = generate_all_decomp_cython(seq, open_to_close) - * """ - * all_decomp = {} # <<<<<<<<<<<<<< - * stack = [seq] - * while stack: - */ - __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 288, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_v_all_decomp = ((PyObject*)__pyx_t_1); - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":289 - * """ - * all_decomp = {} - * stack = [seq] # <<<<<<<<<<<<<< - * while stack: - * seq = stack.pop() - */ - __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 289, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_INCREF(__pyx_v_seq); - __Pyx_GIVEREF(__pyx_v_seq); - PyList_SET_ITEM(__pyx_t_1, 0, __pyx_v_seq); - __pyx_v_stack = ((PyObject*)__pyx_t_1); - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":290 - * all_decomp = {} - * stack = [seq] - * while stack: # <<<<<<<<<<<<<< - * seq = stack.pop() - * if seq not in all_decomp and seq: - */ - while (1) { - __pyx_t_2 = (PyList_GET_SIZE(__pyx_v_stack) != 0); - if (!__pyx_t_2) break; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":291 - * stack = [seq] - * while stack: - * seq = stack.pop() # <<<<<<<<<<<<<< - * if seq not in all_decomp and seq: - * pop_open, pop_close, head, tail, head_tail = balanced_decomp_unsafe_cython(seq, open_to_close) - */ - __pyx_t_1 = __Pyx_PyList_Pop(__pyx_v_stack); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 291, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF_SET(__pyx_v_seq, __pyx_t_1); - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":292 - * while stack: - * seq = stack.pop() - * if seq not in all_decomp and seq: # <<<<<<<<<<<<<< - * pop_open, pop_close, head, tail, head_tail = balanced_decomp_unsafe_cython(seq, open_to_close) - * node = open_to_node[pop_open[0]] - */ - __pyx_t_3 = (__Pyx_PyDict_ContainsTF(__pyx_v_seq, __pyx_v_all_decomp, Py_NE)); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 292, __pyx_L1_error) - __pyx_t_4 = (__pyx_t_3 != 0); - if (__pyx_t_4) { - } else { - __pyx_t_2 = __pyx_t_4; - goto __pyx_L6_bool_binop_done; - } - __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_v_seq); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 292, __pyx_L1_error) - __pyx_t_2 = __pyx_t_4; - __pyx_L6_bool_binop_done:; - if (__pyx_t_2) { - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":293 - * seq = stack.pop() - * if seq not in all_decomp and seq: - * pop_open, pop_close, head, tail, head_tail = balanced_decomp_unsafe_cython(seq, open_to_close) # <<<<<<<<<<<<<< - * node = open_to_node[pop_open[0]] - * all_decomp[seq] = (node, pop_open, pop_close, head, tail, head_tail) - */ - if (!(likely(PyDict_CheckExact(__pyx_v_open_to_close))||((__pyx_v_open_to_close) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "dict", Py_TYPE(__pyx_v_open_to_close)->tp_name), 0))) __PYX_ERR(0, 293, __pyx_L1_error) - __pyx_t_1 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_balanced_decomp_unsafe_cython(__pyx_v_seq, ((PyObject*)__pyx_v_open_to_close)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 293, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (likely(__pyx_t_1 != Py_None)) { - PyObject* sequence = __pyx_t_1; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 5)) { - if (size > 5) __Pyx_RaiseTooManyValuesError(5); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 293, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_5 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_6 = PyTuple_GET_ITEM(sequence, 1); - __pyx_t_7 = PyTuple_GET_ITEM(sequence, 2); - __pyx_t_8 = PyTuple_GET_ITEM(sequence, 3); - __pyx_t_9 = PyTuple_GET_ITEM(sequence, 4); - __Pyx_INCREF(__pyx_t_5); - __Pyx_INCREF(__pyx_t_6); - __Pyx_INCREF(__pyx_t_7); - __Pyx_INCREF(__pyx_t_8); - __Pyx_INCREF(__pyx_t_9); - #else - { - Py_ssize_t i; - PyObject** temps[5] = {&__pyx_t_5,&__pyx_t_6,&__pyx_t_7,&__pyx_t_8,&__pyx_t_9}; - for (i=0; i < 5; i++) { - PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 293, __pyx_L1_error) - __Pyx_GOTREF(item); - *(temps[i]) = item; - } - } - #endif - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - } else { - __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 293, __pyx_L1_error) - } - __Pyx_XDECREF_SET(__pyx_v_pop_open, __pyx_t_5); - __pyx_t_5 = 0; - __Pyx_XDECREF_SET(__pyx_v_pop_close, __pyx_t_6); - __pyx_t_6 = 0; - __Pyx_XDECREF_SET(__pyx_v_head, __pyx_t_7); - __pyx_t_7 = 0; - __Pyx_XDECREF_SET(__pyx_v_tail, __pyx_t_8); - __pyx_t_8 = 0; - __Pyx_XDECREF_SET(__pyx_v_head_tail, __pyx_t_9); - __pyx_t_9 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":294 - * if seq not in all_decomp and seq: - * pop_open, pop_close, head, tail, head_tail = balanced_decomp_unsafe_cython(seq, open_to_close) - * node = open_to_node[pop_open[0]] # <<<<<<<<<<<<<< - * all_decomp[seq] = (node, pop_open, pop_close, head, tail, head_tail) - * stack.append(head_tail) - */ - __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_pop_open, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 294, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_9 = __Pyx_PyObject_GetItem(__pyx_v_open_to_node, __pyx_t_1); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 294, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_9); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __Pyx_XDECREF_SET(__pyx_v_node, __pyx_t_9); - __pyx_t_9 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":295 - * pop_open, pop_close, head, tail, head_tail = balanced_decomp_unsafe_cython(seq, open_to_close) - * node = open_to_node[pop_open[0]] - * all_decomp[seq] = (node, pop_open, pop_close, head, tail, head_tail) # <<<<<<<<<<<<<< - * stack.append(head_tail) - * stack.append(head) - */ - __pyx_t_9 = PyTuple_New(6); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 295, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_9); - __Pyx_INCREF(__pyx_v_node); - __Pyx_GIVEREF(__pyx_v_node); - PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_v_node); - __Pyx_INCREF(__pyx_v_pop_open); - __Pyx_GIVEREF(__pyx_v_pop_open); - PyTuple_SET_ITEM(__pyx_t_9, 1, __pyx_v_pop_open); - __Pyx_INCREF(__pyx_v_pop_close); - __Pyx_GIVEREF(__pyx_v_pop_close); - PyTuple_SET_ITEM(__pyx_t_9, 2, __pyx_v_pop_close); - __Pyx_INCREF(__pyx_v_head); - __Pyx_GIVEREF(__pyx_v_head); - PyTuple_SET_ITEM(__pyx_t_9, 3, __pyx_v_head); - __Pyx_INCREF(__pyx_v_tail); - __Pyx_GIVEREF(__pyx_v_tail); - PyTuple_SET_ITEM(__pyx_t_9, 4, __pyx_v_tail); - __Pyx_INCREF(__pyx_v_head_tail); - __Pyx_GIVEREF(__pyx_v_head_tail); - PyTuple_SET_ITEM(__pyx_t_9, 5, __pyx_v_head_tail); - if (unlikely(PyDict_SetItem(__pyx_v_all_decomp, __pyx_v_seq, __pyx_t_9) < 0)) __PYX_ERR(0, 295, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":296 - * node = open_to_node[pop_open[0]] - * all_decomp[seq] = (node, pop_open, pop_close, head, tail, head_tail) - * stack.append(head_tail) # <<<<<<<<<<<<<< - * stack.append(head) - * stack.append(tail) - */ - __pyx_t_10 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_head_tail); if (unlikely(__pyx_t_10 == ((int)-1))) __PYX_ERR(0, 296, __pyx_L1_error) - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":297 - * all_decomp[seq] = (node, pop_open, pop_close, head, tail, head_tail) - * stack.append(head_tail) - * stack.append(head) # <<<<<<<<<<<<<< - * stack.append(tail) - * return all_decomp - */ - __pyx_t_10 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_head); if (unlikely(__pyx_t_10 == ((int)-1))) __PYX_ERR(0, 297, __pyx_L1_error) - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":298 - * stack.append(head_tail) - * stack.append(head) - * stack.append(tail) # <<<<<<<<<<<<<< - * return all_decomp - * - */ - __pyx_t_10 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_tail); if (unlikely(__pyx_t_10 == ((int)-1))) __PYX_ERR(0, 298, __pyx_L1_error) - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":292 - * while stack: - * seq = stack.pop() - * if seq not in all_decomp and seq: # <<<<<<<<<<<<<< - * pop_open, pop_close, head, tail, head_tail = balanced_decomp_unsafe_cython(seq, open_to_close) - * node = open_to_node[pop_open[0]] - */ - } - } - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":299 - * stack.append(head) - * stack.append(tail) - * return all_decomp # <<<<<<<<<<<<<< - * - * - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(__pyx_v_all_decomp); - __pyx_r = __pyx_v_all_decomp; - goto __pyx_L0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":280 - * - * - * cdef generate_all_decomp_cython(seq, open_to_close, open_to_node=None): # <<<<<<<<<<<<<< - * """ - * Cython version of :func:`generate_all_decomp`. - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_5); - __Pyx_XDECREF(__pyx_t_6); - __Pyx_XDECREF(__pyx_t_7); - __Pyx_XDECREF(__pyx_t_8); - __Pyx_XDECREF(__pyx_t_9); - __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython.generate_all_decomp_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XDECREF(__pyx_v_all_decomp); - __Pyx_XDECREF(__pyx_v_stack); - __Pyx_XDECREF(__pyx_v_pop_open); - __Pyx_XDECREF(__pyx_v_pop_close); - __Pyx_XDECREF(__pyx_v_head); - __Pyx_XDECREF(__pyx_v_tail); - __Pyx_XDECREF(__pyx_v_head_tail); - __Pyx_XDECREF(__pyx_v_node); - __Pyx_XDECREF(__pyx_v_seq); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":302 - * - * - * cdef tuple balanced_decomp_prehash_cython(seq, dict open_to_close, open_to_node): # <<<<<<<<<<<<<< - * """ - * Cython version of :func:`balanced_decomp_unsafe`. - */ - -static PyObject *__pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_balanced_decomp_prehash_cython(PyObject *__pyx_v_seq, PyObject *__pyx_v_open_to_close, PyObject *__pyx_v_open_to_node) { - PyObject *__pyx_v_info = 0; - PyObject *__pyx_v_pop_open = NULL; - PyObject *__pyx_v_pop_close = NULL; - PyObject *__pyx_v_head = NULL; - PyObject *__pyx_v_tail = NULL; - PyObject *__pyx_v_head_tail = NULL; - Py_hash_t __pyx_v_head_key; - Py_hash_t __pyx_v_tail_key; - Py_hash_t __pyx_v_head_tail_key; - PyObject *__pyx_v_node = NULL; - PyObject *__pyx_v_a = NULL; - PyObject *__pyx_v_b = NULL; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - PyObject *__pyx_t_3 = NULL; - PyObject *__pyx_t_4 = NULL; - PyObject *__pyx_t_5 = NULL; - PyObject *__pyx_t_6 = NULL; - Py_hash_t __pyx_t_7; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("balanced_decomp_prehash_cython", 0); - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":307 - * """ - * cdef tuple info - * pop_open, pop_close, head, tail, head_tail = balanced_decomp_unsafe_cython(seq, open_to_close) # <<<<<<<<<<<<<< - * cdef Py_hash_t head_key = hash(head) - * cdef Py_hash_t tail_key = hash(tail) - */ - __pyx_t_1 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_balanced_decomp_unsafe_cython(__pyx_v_seq, __pyx_v_open_to_close); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 307, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (likely(__pyx_t_1 != Py_None)) { - PyObject* sequence = __pyx_t_1; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 5)) { - if (size > 5) __Pyx_RaiseTooManyValuesError(5); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 307, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); - __pyx_t_4 = PyTuple_GET_ITEM(sequence, 2); - __pyx_t_5 = PyTuple_GET_ITEM(sequence, 3); - __pyx_t_6 = PyTuple_GET_ITEM(sequence, 4); - __Pyx_INCREF(__pyx_t_2); - __Pyx_INCREF(__pyx_t_3); - __Pyx_INCREF(__pyx_t_4); - __Pyx_INCREF(__pyx_t_5); - __Pyx_INCREF(__pyx_t_6); - #else - { - Py_ssize_t i; - PyObject** temps[5] = {&__pyx_t_2,&__pyx_t_3,&__pyx_t_4,&__pyx_t_5,&__pyx_t_6}; - for (i=0; i < 5; i++) { - PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 307, __pyx_L1_error) - __Pyx_GOTREF(item); - *(temps[i]) = item; - } - } - #endif - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - } else { - __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 307, __pyx_L1_error) - } - __pyx_v_pop_open = __pyx_t_2; - __pyx_t_2 = 0; - __pyx_v_pop_close = __pyx_t_3; - __pyx_t_3 = 0; - __pyx_v_head = __pyx_t_4; - __pyx_t_4 = 0; - __pyx_v_tail = __pyx_t_5; - __pyx_t_5 = 0; - __pyx_v_head_tail = __pyx_t_6; - __pyx_t_6 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":308 - * cdef tuple info - * pop_open, pop_close, head, tail, head_tail = balanced_decomp_unsafe_cython(seq, open_to_close) - * cdef Py_hash_t head_key = hash(head) # <<<<<<<<<<<<<< - * cdef Py_hash_t tail_key = hash(tail) - * cdef Py_hash_t head_tail_key = hash(head_tail) - */ - __pyx_t_7 = PyObject_Hash(__pyx_v_head); if (unlikely(__pyx_t_7 == ((Py_hash_t)-1))) __PYX_ERR(0, 308, __pyx_L1_error) - __pyx_v_head_key = __pyx_t_7; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":309 - * pop_open, pop_close, head, tail, head_tail = balanced_decomp_unsafe_cython(seq, open_to_close) - * cdef Py_hash_t head_key = hash(head) - * cdef Py_hash_t tail_key = hash(tail) # <<<<<<<<<<<<<< - * cdef Py_hash_t head_tail_key = hash(head_tail) - * node = open_to_node[pop_open[0]] - */ - __pyx_t_7 = PyObject_Hash(__pyx_v_tail); if (unlikely(__pyx_t_7 == ((Py_hash_t)-1))) __PYX_ERR(0, 309, __pyx_L1_error) - __pyx_v_tail_key = __pyx_t_7; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":310 - * cdef Py_hash_t head_key = hash(head) - * cdef Py_hash_t tail_key = hash(tail) - * cdef Py_hash_t head_tail_key = hash(head_tail) # <<<<<<<<<<<<<< - * node = open_to_node[pop_open[0]] - * a = pop_open - */ - __pyx_t_7 = PyObject_Hash(__pyx_v_head_tail); if (unlikely(__pyx_t_7 == ((Py_hash_t)-1))) __PYX_ERR(0, 310, __pyx_L1_error) - __pyx_v_head_tail_key = __pyx_t_7; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":311 - * cdef Py_hash_t tail_key = hash(tail) - * cdef Py_hash_t head_tail_key = hash(head_tail) - * node = open_to_node[pop_open[0]] # <<<<<<<<<<<<<< - * a = pop_open - * b = pop_close - */ - __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_pop_open, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 311, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_6 = __Pyx_PyObject_GetItem(__pyx_v_open_to_node, __pyx_t_1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 311, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - __pyx_v_node = __pyx_t_6; - __pyx_t_6 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":312 - * cdef Py_hash_t head_tail_key = hash(head_tail) - * node = open_to_node[pop_open[0]] - * a = pop_open # <<<<<<<<<<<<<< - * b = pop_close - * info = (node, seq, head, tail, head_tail, head_key, tail_key, head_tail_key, a, b) - */ - __Pyx_INCREF(__pyx_v_pop_open); - __pyx_v_a = __pyx_v_pop_open; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":313 - * node = open_to_node[pop_open[0]] - * a = pop_open - * b = pop_close # <<<<<<<<<<<<<< - * info = (node, seq, head, tail, head_tail, head_key, tail_key, head_tail_key, a, b) - * return info - */ - __Pyx_INCREF(__pyx_v_pop_close); - __pyx_v_b = __pyx_v_pop_close; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":314 - * a = pop_open - * b = pop_close - * info = (node, seq, head, tail, head_tail, head_key, tail_key, head_tail_key, a, b) # <<<<<<<<<<<<<< - * return info - * - */ - __pyx_t_6 = __Pyx_PyInt_FromHash_t(__pyx_v_head_key); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 314, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - __pyx_t_1 = __Pyx_PyInt_FromHash_t(__pyx_v_tail_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 314, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_t_5 = __Pyx_PyInt_FromHash_t(__pyx_v_head_tail_key); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 314, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __pyx_t_4 = PyTuple_New(10); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 314, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __Pyx_INCREF(__pyx_v_node); - __Pyx_GIVEREF(__pyx_v_node); - PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_node); - __Pyx_INCREF(__pyx_v_seq); - __Pyx_GIVEREF(__pyx_v_seq); - PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_seq); - __Pyx_INCREF(__pyx_v_head); - __Pyx_GIVEREF(__pyx_v_head); - PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_v_head); - __Pyx_INCREF(__pyx_v_tail); - __Pyx_GIVEREF(__pyx_v_tail); - PyTuple_SET_ITEM(__pyx_t_4, 3, __pyx_v_tail); - __Pyx_INCREF(__pyx_v_head_tail); - __Pyx_GIVEREF(__pyx_v_head_tail); - PyTuple_SET_ITEM(__pyx_t_4, 4, __pyx_v_head_tail); - __Pyx_GIVEREF(__pyx_t_6); - PyTuple_SET_ITEM(__pyx_t_4, 5, __pyx_t_6); - __Pyx_GIVEREF(__pyx_t_1); - PyTuple_SET_ITEM(__pyx_t_4, 6, __pyx_t_1); - __Pyx_GIVEREF(__pyx_t_5); - PyTuple_SET_ITEM(__pyx_t_4, 7, __pyx_t_5); - __Pyx_INCREF(__pyx_v_a); - __Pyx_GIVEREF(__pyx_v_a); - PyTuple_SET_ITEM(__pyx_t_4, 8, __pyx_v_a); - __Pyx_INCREF(__pyx_v_b); - __Pyx_GIVEREF(__pyx_v_b); - PyTuple_SET_ITEM(__pyx_t_4, 9, __pyx_v_b); - __pyx_t_6 = 0; - __pyx_t_1 = 0; - __pyx_t_5 = 0; - __pyx_v_info = ((PyObject*)__pyx_t_4); - __pyx_t_4 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":315 - * b = pop_close - * info = (node, seq, head, tail, head_tail, head_key, tail_key, head_tail_key, a, b) - * return info # <<<<<<<<<<<<<< - * - * - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(__pyx_v_info); - __pyx_r = __pyx_v_info; - goto __pyx_L0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":302 - * - * - * cdef tuple balanced_decomp_prehash_cython(seq, dict open_to_close, open_to_node): # <<<<<<<<<<<<<< - * """ - * Cython version of :func:`balanced_decomp_unsafe`. - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - __Pyx_XDECREF(__pyx_t_3); - __Pyx_XDECREF(__pyx_t_4); - __Pyx_XDECREF(__pyx_t_5); - __Pyx_XDECREF(__pyx_t_6); - __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython.balanced_decomp_prehash_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XDECREF(__pyx_v_info); - __Pyx_XDECREF(__pyx_v_pop_open); - __Pyx_XDECREF(__pyx_v_pop_close); - __Pyx_XDECREF(__pyx_v_head); - __Pyx_XDECREF(__pyx_v_tail); - __Pyx_XDECREF(__pyx_v_head_tail); - __Pyx_XDECREF(__pyx_v_node); - __Pyx_XDECREF(__pyx_v_a); - __Pyx_XDECREF(__pyx_v_b); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":318 - * - * - * cdef dict generate_all_decomp_prehash_cython(seq, dict open_to_close, open_to_node): # <<<<<<<<<<<<<< - * """ - * Cython version of :func:`generate_all_decomp_prehash`. - */ - -static PyObject *__pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_prehash_cython(PyObject *__pyx_v_seq, PyObject *__pyx_v_open_to_close, PyObject *__pyx_v_open_to_node) { - PyObject *__pyx_v_all_decomp = 0; - PyObject *__pyx_v_stack = 0; - PyObject *__pyx_v_info = 0; - PyObject *__pyx_v_key = NULL; - PyObject *__pyx_v_head = NULL; - PyObject *__pyx_v_tail = NULL; - PyObject *__pyx_v_head_tail = NULL; - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - PyObject *__pyx_t_1 = NULL; - int __pyx_t_2; - int __pyx_t_3; - PyObject *__pyx_t_4 = NULL; - PyObject *__pyx_t_5 = NULL; - PyObject *__pyx_t_6 = NULL; - int __pyx_t_7; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("generate_all_decomp_prehash_cython", 0); - __Pyx_INCREF(__pyx_v_seq); - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":322 - * Cython version of :func:`generate_all_decomp_prehash`. - * """ - * cdef dict all_decomp = {} # <<<<<<<<<<<<<< - * cdef list stack = [seq] - * cdef tuple info - */ - __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 322, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __pyx_v_all_decomp = ((PyObject*)__pyx_t_1); - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":323 - * """ - * cdef dict all_decomp = {} - * cdef list stack = [seq] # <<<<<<<<<<<<<< - * cdef tuple info - * while stack: - */ - __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 323, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_INCREF(__pyx_v_seq); - __Pyx_GIVEREF(__pyx_v_seq); - PyList_SET_ITEM(__pyx_t_1, 0, __pyx_v_seq); - __pyx_v_stack = ((PyObject*)__pyx_t_1); - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":325 - * cdef list stack = [seq] - * cdef tuple info - * while stack: # <<<<<<<<<<<<<< - * seq = stack.pop() - * if seq: - */ - while (1) { - __pyx_t_2 = (PyList_GET_SIZE(__pyx_v_stack) != 0); - if (!__pyx_t_2) break; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":326 - * cdef tuple info - * while stack: - * seq = stack.pop() # <<<<<<<<<<<<<< - * if seq: - * # key = hash(seq) - */ - __pyx_t_1 = __Pyx_PyList_Pop(__pyx_v_stack); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 326, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_DECREF_SET(__pyx_v_seq, __pyx_t_1); - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":327 - * while stack: - * seq = stack.pop() - * if seq: # <<<<<<<<<<<<<< - * # key = hash(seq) - * key = seq - */ - __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_seq); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 327, __pyx_L1_error) - if (__pyx_t_2) { - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":329 - * if seq: - * # key = hash(seq) - * key = seq # <<<<<<<<<<<<<< - * if key not in all_decomp: - * info = balanced_decomp_prehash_cython(seq, open_to_close, open_to_node) - */ - __Pyx_INCREF(__pyx_v_seq); - __Pyx_XDECREF_SET(__pyx_v_key, __pyx_v_seq); - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":330 - * # key = hash(seq) - * key = seq - * if key not in all_decomp: # <<<<<<<<<<<<<< - * info = balanced_decomp_prehash_cython(seq, open_to_close, open_to_node) - * head, tail, head_tail = info[2:5] - */ - __pyx_t_2 = (__Pyx_PyDict_ContainsTF(__pyx_v_key, __pyx_v_all_decomp, Py_NE)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 330, __pyx_L1_error) - __pyx_t_3 = (__pyx_t_2 != 0); - if (__pyx_t_3) { - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":331 - * key = seq - * if key not in all_decomp: - * info = balanced_decomp_prehash_cython(seq, open_to_close, open_to_node) # <<<<<<<<<<<<<< - * head, tail, head_tail = info[2:5] - * all_decomp[key] = info - */ - __pyx_t_1 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_balanced_decomp_prehash_cython(__pyx_v_seq, __pyx_v_open_to_close, __pyx_v_open_to_node); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 331, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - __Pyx_XDECREF_SET(__pyx_v_info, ((PyObject*)__pyx_t_1)); - __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":332 - * if key not in all_decomp: - * info = balanced_decomp_prehash_cython(seq, open_to_close, open_to_node) - * head, tail, head_tail = info[2:5] # <<<<<<<<<<<<<< - * all_decomp[key] = info - * stack.append(head_tail) - */ - if (unlikely(__pyx_v_info == Py_None)) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable"); - __PYX_ERR(0, 332, __pyx_L1_error) - } - __pyx_t_1 = __Pyx_PyTuple_GetSlice(__pyx_v_info, 2, 5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 332, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (1) { - PyObject* sequence = __pyx_t_1; - Py_ssize_t size = __Pyx_PySequence_SIZE(sequence); - if (unlikely(size != 3)) { - if (size > 3) __Pyx_RaiseTooManyValuesError(3); - else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size); - __PYX_ERR(0, 332, __pyx_L1_error) - } - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - __pyx_t_4 = PyTuple_GET_ITEM(sequence, 0); - __pyx_t_5 = PyTuple_GET_ITEM(sequence, 1); - __pyx_t_6 = PyTuple_GET_ITEM(sequence, 2); - __Pyx_INCREF(__pyx_t_4); - __Pyx_INCREF(__pyx_t_5); - __Pyx_INCREF(__pyx_t_6); - #else - __pyx_t_4 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 332, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_4); - __pyx_t_5 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 332, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_5); - __pyx_t_6 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 332, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_6); - #endif - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - } - __Pyx_XDECREF_SET(__pyx_v_head, __pyx_t_4); - __pyx_t_4 = 0; - __Pyx_XDECREF_SET(__pyx_v_tail, __pyx_t_5); - __pyx_t_5 = 0; - __Pyx_XDECREF_SET(__pyx_v_head_tail, __pyx_t_6); - __pyx_t_6 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":333 - * info = balanced_decomp_prehash_cython(seq, open_to_close, open_to_node) - * head, tail, head_tail = info[2:5] - * all_decomp[key] = info # <<<<<<<<<<<<<< - * stack.append(head_tail) - * stack.append(head) - */ - if (unlikely(PyDict_SetItem(__pyx_v_all_decomp, __pyx_v_key, __pyx_v_info) < 0)) __PYX_ERR(0, 333, __pyx_L1_error) - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":334 - * head, tail, head_tail = info[2:5] - * all_decomp[key] = info - * stack.append(head_tail) # <<<<<<<<<<<<<< - * stack.append(head) - * stack.append(tail) - */ - __pyx_t_7 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_head_tail); if (unlikely(__pyx_t_7 == ((int)-1))) __PYX_ERR(0, 334, __pyx_L1_error) - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":335 - * all_decomp[key] = info - * stack.append(head_tail) - * stack.append(head) # <<<<<<<<<<<<<< - * stack.append(tail) - * return all_decomp - */ - __pyx_t_7 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_head); if (unlikely(__pyx_t_7 == ((int)-1))) __PYX_ERR(0, 335, __pyx_L1_error) - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":336 - * stack.append(head_tail) - * stack.append(head) - * stack.append(tail) # <<<<<<<<<<<<<< - * return all_decomp - * - */ - __pyx_t_7 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_tail); if (unlikely(__pyx_t_7 == ((int)-1))) __PYX_ERR(0, 336, __pyx_L1_error) - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":330 - * # key = hash(seq) - * key = seq - * if key not in all_decomp: # <<<<<<<<<<<<<< - * info = balanced_decomp_prehash_cython(seq, open_to_close, open_to_node) - * head, tail, head_tail = info[2:5] - */ - } - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":327 - * while stack: - * seq = stack.pop() - * if seq: # <<<<<<<<<<<<<< - * # key = hash(seq) - * key = seq - */ - } - } - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":337 - * stack.append(head) - * stack.append(tail) - * return all_decomp # <<<<<<<<<<<<<< - * - * - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(__pyx_v_all_decomp); - __pyx_r = __pyx_v_all_decomp; - goto __pyx_L0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":318 - * - * - * cdef dict generate_all_decomp_prehash_cython(seq, dict open_to_close, open_to_node): # <<<<<<<<<<<<<< - * """ - * Cython version of :func:`generate_all_decomp_prehash`. - */ - - /* function exit code */ - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_4); - __Pyx_XDECREF(__pyx_t_5); - __Pyx_XDECREF(__pyx_t_6); - __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython.generate_all_decomp_prehash_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); - __pyx_r = 0; - __pyx_L0:; - __Pyx_XDECREF(__pyx_v_all_decomp); - __Pyx_XDECREF(__pyx_v_stack); - __Pyx_XDECREF(__pyx_v_info); - __Pyx_XDECREF(__pyx_v_key); - __Pyx_XDECREF(__pyx_v_head); - __Pyx_XDECREF(__pyx_v_tail); - __Pyx_XDECREF(__pyx_v_head_tail); - __Pyx_XDECREF(__pyx_v_seq); - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -/* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":342 - * class IdentityDict: - * """ Used when ``open_to_node`` is unspecified """ - * def __getitem__(self, key): # <<<<<<<<<<<<<< - * return key - */ - -/* Python wrapper */ -static PyObject *__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict_1__getitem__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ -static PyMethodDef __pyx_mdef_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict_1__getitem__ = {"__getitem__", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict_1__getitem__, METH_VARARGS|METH_KEYWORDS, 0}; -static PyObject *__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict_1__getitem__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { - CYTHON_UNUSED PyObject *__pyx_v_self = 0; - PyObject *__pyx_v_key = 0; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - PyObject *__pyx_r = 0; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__getitem__ (wrapper)", 0); - { - static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_self,&__pyx_n_s_key,0}; - PyObject* values[2] = {0,0}; - if (unlikely(__pyx_kwds)) { - Py_ssize_t kw_args; - const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); - switch (pos_args) { - case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - CYTHON_FALLTHROUGH; - case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - CYTHON_FALLTHROUGH; - case 0: break; - default: goto __pyx_L5_argtuple_error; - } - kw_args = PyDict_Size(__pyx_kwds); - switch (pos_args) { - case 0: - if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_self)) != 0)) kw_args--; - else goto __pyx_L5_argtuple_error; - CYTHON_FALLTHROUGH; - case 1: - if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_key)) != 0)) kw_args--; - else { - __Pyx_RaiseArgtupleInvalid("__getitem__", 1, 2, 2, 1); __PYX_ERR(0, 342, __pyx_L3_error) - } - } - if (unlikely(kw_args > 0)) { - if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__getitem__") < 0)) __PYX_ERR(0, 342, __pyx_L3_error) - } - } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { - goto __pyx_L5_argtuple_error; - } else { - values[0] = PyTuple_GET_ITEM(__pyx_args, 0); - values[1] = PyTuple_GET_ITEM(__pyx_args, 1); - } - __pyx_v_self = values[0]; - __pyx_v_key = values[1]; - } - goto __pyx_L4_argument_unpacking_done; - __pyx_L5_argtuple_error:; - __Pyx_RaiseArgtupleInvalid("__getitem__", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 342, __pyx_L3_error) - __pyx_L3_error:; - __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython.IdentityDict.__getitem__", __pyx_clineno, __pyx_lineno, __pyx_filename); - __Pyx_RefNannyFinishContext(); - return NULL; - __pyx_L4_argument_unpacking_done:; - __pyx_r = __pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict___getitem__(__pyx_self, __pyx_v_self, __pyx_v_key); - - /* function exit code */ - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyObject *__pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict___getitem__(CYTHON_UNUSED PyObject *__pyx_self, CYTHON_UNUSED PyObject *__pyx_v_self, PyObject *__pyx_v_key) { - PyObject *__pyx_r = NULL; - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__getitem__", 0); - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":343 - * """ Used when ``open_to_node`` is unspecified """ - * def __getitem__(self, key): - * return key # <<<<<<<<<<<<<< - */ - __Pyx_XDECREF(__pyx_r); - __Pyx_INCREF(__pyx_v_key); - __pyx_r = __pyx_v_key; - goto __pyx_L0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":342 - * class IdentityDict: - * """ Used when ``open_to_node`` is unspecified """ - * def __getitem__(self, key): # <<<<<<<<<<<<<< - * return key - */ - - /* function exit code */ - __pyx_L0:; - __Pyx_XGIVEREF(__pyx_r); - __Pyx_RefNannyFinishContext(); - return __pyx_r; -} - -static PyMethodDef __pyx_methods[] = { - {0, 0, 0, 0} -}; - -#if PY_MAJOR_VERSION >= 3 -#if CYTHON_PEP489_MULTI_PHASE_INIT -static PyObject* __pyx_pymod_create(PyObject *spec, PyModuleDef *def); /*proto*/ -static int __pyx_pymod_exec_balanced_sequence_cython(PyObject* module); /*proto*/ -static PyModuleDef_Slot __pyx_moduledef_slots[] = { - {Py_mod_create, (void*)__pyx_pymod_create}, - {Py_mod_exec, (void*)__pyx_pymod_exec_balanced_sequence_cython}, - {0, NULL} -}; -#endif - -static struct PyModuleDef __pyx_moduledef = { - PyModuleDef_HEAD_INIT, - "balanced_sequence_cython", - __pyx_k_This_module_re_implements_funct, /* m_doc */ - #if CYTHON_PEP489_MULTI_PHASE_INIT - 0, /* m_size */ - #else - -1, /* m_size */ - #endif - __pyx_methods /* m_methods */, - #if CYTHON_PEP489_MULTI_PHASE_INIT - __pyx_moduledef_slots, /* m_slots */ - #else - NULL, /* m_reload */ - #endif - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL /* m_free */ -}; -#endif -#ifndef CYTHON_SMALL_CODE -#if defined(__clang__) - #define CYTHON_SMALL_CODE -#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) - #define CYTHON_SMALL_CODE __attribute__((cold)) -#else - #define CYTHON_SMALL_CODE -#endif -#endif - -static __Pyx_StringTabEntry __pyx_string_tab[] = { - {&__pyx_n_s_IdentityDict, __pyx_k_IdentityDict, sizeof(__pyx_k_IdentityDict), 0, 0, 1, 1}, - {&__pyx_n_s_IdentityDict___getitem, __pyx_k_IdentityDict___getitem, sizeof(__pyx_k_IdentityDict___getitem), 0, 0, 1, 1}, - {&__pyx_kp_s_Used_when_open_to_node_is_unspe, __pyx_k_Used_when_open_to_node_is_unspe, sizeof(__pyx_k_Used_when_open_to_node_is_unspe), 0, 0, 1, 0}, - {&__pyx_n_s_a1, __pyx_k_a1, sizeof(__pyx_k_a1), 0, 0, 1, 1}, - {&__pyx_n_s_a2, __pyx_k_a2, sizeof(__pyx_k_a2), 0, 0, 1, 1}, - {&__pyx_n_s_affinity, __pyx_k_affinity, sizeof(__pyx_k_affinity), 0, 0, 1, 1}, - {&__pyx_n_s_all_decomp1, __pyx_k_all_decomp1, sizeof(__pyx_k_all_decomp1), 0, 0, 1, 1}, - {&__pyx_n_s_all_decomp2, __pyx_k_all_decomp2, sizeof(__pyx_k_all_decomp2), 0, 0, 1, 1}, - {&__pyx_n_s_b1, __pyx_k_b1, sizeof(__pyx_k_b1), 0, 0, 1, 1}, - {&__pyx_n_s_b2, __pyx_k_b2, sizeof(__pyx_k_b2), 0, 0, 1, 1}, - {&__pyx_n_s_base_result, __pyx_k_base_result, sizeof(__pyx_k_base_result), 0, 0, 1, 1}, - {&__pyx_n_s_best, __pyx_k_best, sizeof(__pyx_k_best), 0, 0, 1, 1}, - {&__pyx_n_s_cand1, __pyx_k_cand1, sizeof(__pyx_k_cand1), 0, 0, 1, 1}, - {&__pyx_n_s_cand2, __pyx_k_cand2, sizeof(__pyx_k_cand2), 0, 0, 1, 1}, - {&__pyx_n_s_cand3, __pyx_k_cand3, sizeof(__pyx_k_cand3), 0, 0, 1, 1}, - {&__pyx_n_s_cline_in_traceback, __pyx_k_cline_in_traceback, sizeof(__pyx_k_cline_in_traceback), 0, 0, 1, 1}, - {&__pyx_n_s_doc, __pyx_k_doc, sizeof(__pyx_k_doc), 0, 0, 1, 1}, - {&__pyx_kp_s_embedding_balanced_sequence_cyt, __pyx_k_embedding_balanced_sequence_cyt, sizeof(__pyx_k_embedding_balanced_sequence_cyt), 0, 0, 1, 0}, - {&__pyx_n_s_empty1, __pyx_k_empty1, sizeof(__pyx_k_empty1), 0, 0, 1, 1}, - {&__pyx_n_s_empty1_key, __pyx_k_empty1_key, sizeof(__pyx_k_empty1_key), 0, 0, 1, 1}, - {&__pyx_n_s_empty2, __pyx_k_empty2, sizeof(__pyx_k_empty2), 0, 0, 1, 1}, - {&__pyx_n_s_empty2_key, __pyx_k_empty2_key, sizeof(__pyx_k_empty2_key), 0, 0, 1, 1}, - {&__pyx_n_s_found, __pyx_k_found, sizeof(__pyx_k_found), 0, 0, 1, 1}, - {&__pyx_n_s_frame, __pyx_k_frame, sizeof(__pyx_k_frame), 0, 0, 1, 1}, - {&__pyx_n_s_frame0, __pyx_k_frame0, sizeof(__pyx_k_frame0), 0, 0, 1, 1}, - {&__pyx_n_s_full_seq1, __pyx_k_full_seq1, sizeof(__pyx_k_full_seq1), 0, 0, 1, 1}, - {&__pyx_n_s_full_seq1_key, __pyx_k_full_seq1_key, sizeof(__pyx_k_full_seq1_key), 0, 0, 1, 1}, - {&__pyx_n_s_full_seq2, __pyx_k_full_seq2, sizeof(__pyx_k_full_seq2), 0, 0, 1, 1}, - {&__pyx_n_s_full_seq2_key, __pyx_k_full_seq2_key, sizeof(__pyx_k_full_seq2_key), 0, 0, 1, 1}, - {&__pyx_n_s_getitem, __pyx_k_getitem, sizeof(__pyx_k_getitem), 0, 0, 1, 1}, - {&__pyx_n_s_head1, __pyx_k_head1, sizeof(__pyx_k_head1), 0, 0, 1, 1}, - {&__pyx_n_s_head1_key, __pyx_k_head1_key, sizeof(__pyx_k_head1_key), 0, 0, 1, 1}, - {&__pyx_n_s_head2, __pyx_k_head2, sizeof(__pyx_k_head2), 0, 0, 1, 1}, - {&__pyx_n_s_head2_key, __pyx_k_head2_key, sizeof(__pyx_k_head2_key), 0, 0, 1, 1}, - {&__pyx_n_s_head_tail1, __pyx_k_head_tail1, sizeof(__pyx_k_head_tail1), 0, 0, 1, 1}, - {&__pyx_n_s_head_tail1_key, __pyx_k_head_tail1_key, sizeof(__pyx_k_head_tail1_key), 0, 0, 1, 1}, - {&__pyx_n_s_head_tail2, __pyx_k_head_tail2, sizeof(__pyx_k_head_tail2), 0, 0, 1, 1}, - {&__pyx_n_s_head_tail2_key, __pyx_k_head_tail2_key, sizeof(__pyx_k_head_tail2_key), 0, 0, 1, 1}, - {&__pyx_n_s_info1, __pyx_k_info1, sizeof(__pyx_k_info1), 0, 0, 1, 1}, - {&__pyx_n_s_info2, __pyx_k_info2, sizeof(__pyx_k_info2), 0, 0, 1, 1}, - {&__pyx_n_s_items, __pyx_k_items, sizeof(__pyx_k_items), 0, 0, 1, 1}, - {&__pyx_n_s_key, __pyx_k_key, sizeof(__pyx_k_key), 0, 0, 1, 1}, - {&__pyx_n_s_key0, __pyx_k_key0, sizeof(__pyx_k_key0), 0, 0, 1, 1}, - {&__pyx_n_s_key1, __pyx_k_key1, sizeof(__pyx_k_key1), 0, 0, 1, 1}, - {&__pyx_n_s_key2, __pyx_k_key2, sizeof(__pyx_k_key2), 0, 0, 1, 1}, - {&__pyx_n_s_key_decomp1, __pyx_k_key_decomp1, sizeof(__pyx_k_key_decomp1), 0, 0, 1, 1}, - {&__pyx_n_s_key_decomp2, __pyx_k_key_decomp2, sizeof(__pyx_k_key_decomp2), 0, 0, 1, 1}, - {&__pyx_n_s_keys, __pyx_k_keys, sizeof(__pyx_k_keys), 0, 0, 1, 1}, - {&__pyx_n_s_lcs_iter_prehash2_cython, __pyx_k_lcs_iter_prehash2_cython, sizeof(__pyx_k_lcs_iter_prehash2_cython), 0, 0, 1, 1}, - {&__pyx_n_s_lcs_iter_simple_alt2_cython, __pyx_k_lcs_iter_simple_alt2_cython, sizeof(__pyx_k_lcs_iter_simple_alt2_cython), 0, 0, 1, 1}, - {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1}, - {&__pyx_n_s_metaclass, __pyx_k_metaclass, sizeof(__pyx_k_metaclass), 0, 0, 1, 1}, - {&__pyx_n_s_miss_frame, __pyx_k_miss_frame, sizeof(__pyx_k_miss_frame), 0, 0, 1, 1}, - {&__pyx_n_s_module, __pyx_k_module, sizeof(__pyx_k_module), 0, 0, 1, 1}, - {&__pyx_n_s_name, __pyx_k_name, sizeof(__pyx_k_name), 0, 0, 1, 1}, - {&__pyx_n_s_networkx_algorithms_isomorphism, __pyx_k_networkx_algorithms_isomorphism, sizeof(__pyx_k_networkx_algorithms_isomorphism), 0, 0, 1, 1}, - {&__pyx_n_s_new_head1, __pyx_k_new_head1, sizeof(__pyx_k_new_head1), 0, 0, 1, 1}, - {&__pyx_n_s_new_head2, __pyx_k_new_head2, sizeof(__pyx_k_new_head2), 0, 0, 1, 1}, - {&__pyx_n_s_new_heads, __pyx_k_new_heads, sizeof(__pyx_k_new_heads), 0, 0, 1, 1}, - {&__pyx_n_s_new_tail1, __pyx_k_new_tail1, sizeof(__pyx_k_new_tail1), 0, 0, 1, 1}, - {&__pyx_n_s_new_tail2, __pyx_k_new_tail2, sizeof(__pyx_k_new_tail2), 0, 0, 1, 1}, - {&__pyx_n_s_new_tails, __pyx_k_new_tails, sizeof(__pyx_k_new_tails), 0, 0, 1, 1}, - {&__pyx_n_s_node_affinity, __pyx_k_node_affinity, sizeof(__pyx_k_node_affinity), 0, 0, 1, 1}, - {&__pyx_n_s_open_to_close, __pyx_k_open_to_close, sizeof(__pyx_k_open_to_close), 0, 0, 1, 1}, - {&__pyx_n_s_open_to_node, __pyx_k_open_to_node, sizeof(__pyx_k_open_to_node), 0, 0, 1, 1}, - {&__pyx_n_s_pop, __pyx_k_pop, sizeof(__pyx_k_pop), 0, 0, 1, 1}, - {&__pyx_n_s_prepare, __pyx_k_prepare, sizeof(__pyx_k_prepare), 0, 0, 1, 1}, - {&__pyx_n_s_pval_h, __pyx_k_pval_h, sizeof(__pyx_k_pval_h), 0, 0, 1, 1}, - {&__pyx_n_s_pval_t, __pyx_k_pval_t, sizeof(__pyx_k_pval_t), 0, 0, 1, 1}, - {&__pyx_n_s_qualname, __pyx_k_qualname, sizeof(__pyx_k_qualname), 0, 0, 1, 1}, - {&__pyx_n_s_range, __pyx_k_range, sizeof(__pyx_k_range), 0, 0, 1, 1}, - {&__pyx_n_s_res3, __pyx_k_res3, sizeof(__pyx_k_res3), 0, 0, 1, 1}, - {&__pyx_n_s_results, __pyx_k_results, sizeof(__pyx_k_results), 0, 0, 1, 1}, - {&__pyx_n_s_self, __pyx_k_self, sizeof(__pyx_k_self), 0, 0, 1, 1}, - {&__pyx_n_s_seq1, __pyx_k_seq1, sizeof(__pyx_k_seq1), 0, 0, 1, 1}, - {&__pyx_n_s_seq1_key, __pyx_k_seq1_key, sizeof(__pyx_k_seq1_key), 0, 0, 1, 1}, - {&__pyx_n_s_seq2, __pyx_k_seq2, sizeof(__pyx_k_seq2), 0, 0, 1, 1}, - {&__pyx_n_s_seq2_key, __pyx_k_seq2_key, sizeof(__pyx_k_seq2_key), 0, 0, 1, 1}, - {&__pyx_n_s_stack, __pyx_k_stack, sizeof(__pyx_k_stack), 0, 0, 1, 1}, - {&__pyx_n_s_subseq1, __pyx_k_subseq1, sizeof(__pyx_k_subseq1), 0, 0, 1, 1}, - {&__pyx_n_s_subseq2, __pyx_k_subseq2, sizeof(__pyx_k_subseq2), 0, 0, 1, 1}, - {&__pyx_n_s_t1, __pyx_k_t1, sizeof(__pyx_k_t1), 0, 0, 1, 1}, - {&__pyx_n_s_t2, __pyx_k_t2, sizeof(__pyx_k_t2), 0, 0, 1, 1}, - {&__pyx_n_s_tail1, __pyx_k_tail1, sizeof(__pyx_k_tail1), 0, 0, 1, 1}, - {&__pyx_n_s_tail1_key, __pyx_k_tail1_key, sizeof(__pyx_k_tail1_key), 0, 0, 1, 1}, - {&__pyx_n_s_tail2, __pyx_k_tail2, sizeof(__pyx_k_tail2), 0, 0, 1, 1}, - {&__pyx_n_s_tail2_key, __pyx_k_tail2_key, sizeof(__pyx_k_tail2_key), 0, 0, 1, 1}, - {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1}, - {&__pyx_n_s_tok1, __pyx_k_tok1, sizeof(__pyx_k_tok1), 0, 0, 1, 1}, - {&__pyx_n_s_tok2, __pyx_k_tok2, sizeof(__pyx_k_tok2), 0, 0, 1, 1}, - {&__pyx_n_s_try_key, __pyx_k_try_key, sizeof(__pyx_k_try_key), 0, 0, 1, 1}, - {&__pyx_n_s_val, __pyx_k_val, sizeof(__pyx_k_val), 0, 0, 1, 1}, - {&__pyx_n_s_val3, __pyx_k_val3, sizeof(__pyx_k_val3), 0, 0, 1, 1}, - {0, 0, 0, 0, 0, 0, 0} -}; -static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) { - __pyx_builtin_range = __Pyx_GetBuiltinName(__pyx_n_s_range); if (!__pyx_builtin_range) __PYX_ERR(0, 266, __pyx_L1_error) - return 0; - __pyx_L1_error:; - return -1; -} - -static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":125 - * cand3 = (val3, res3) - * else: - * cand3 = (-1, None) # <<<<<<<<<<<<<< - * - * # We solved the frame - */ - __pyx_tuple_ = PyTuple_Pack(2, __pyx_int_neg_1, Py_None); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 125, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple_); - __Pyx_GIVEREF(__pyx_tuple_); - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":164 - * for seq1, info1 in all_decomp1.items(): - * seq1_key = hash(seq1) - * head1_key, tail1_key, head_tail1_key = all_decomp1[seq1][5:8] # <<<<<<<<<<<<<< - * _results[(seq1_key, empty2_key)] = base_result - * _results[(head1_key, empty2_key)] = base_result - */ - __pyx_slice__2 = PySlice_New(__pyx_int_5, __pyx_int_8, Py_None); if (unlikely(!__pyx_slice__2)) __PYX_ERR(0, 164, __pyx_L1_error) - __Pyx_GOTREF(__pyx_slice__2); - __Pyx_GIVEREF(__pyx_slice__2); - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":273 - * break - * - * pop_open = sequence[0:1] # <<<<<<<<<<<<<< - * head = sequence[1:head_stop] - * tail = sequence[head_stop + 1:] - */ - __pyx_slice__3 = PySlice_New(__pyx_int_0, __pyx_int_1, Py_None); if (unlikely(!__pyx_slice__3)) __PYX_ERR(0, 273, __pyx_L1_error) - __Pyx_GOTREF(__pyx_slice__3); - __Pyx_GIVEREF(__pyx_slice__3); - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":35 - * - * - * def _lcs_iter_simple_alt2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node): # <<<<<<<<<<<<<< - * """ - * Depth first stack trajectory and replace try except statements with ifs - */ - __pyx_tuple__4 = PyTuple_Pack(51, __pyx_n_s_full_seq1, __pyx_n_s_full_seq2, __pyx_n_s_open_to_close, __pyx_n_s_node_affinity, __pyx_n_s_open_to_node, __pyx_n_s_all_decomp1, __pyx_n_s_all_decomp2, __pyx_n_s_key0, __pyx_n_s_frame0, __pyx_n_s_stack, __pyx_n_s_results, __pyx_n_s_empty1, __pyx_n_s_empty2, __pyx_n_s_best, __pyx_n_s_base_result, __pyx_n_s_seq1, __pyx_n_s_key1, __pyx_n_s_t1, __pyx_n_s_a1, __pyx_n_s_b1, __pyx_n_s_head1, __pyx_n_s_tail1, __pyx_n_s_head_tail1, __pyx_n_s_seq2, __pyx_n_s_key2, __pyx_n_s_t2, __pyx_n_s_a2, __pyx_n_s_b2, __pyx_n_s_head2, __pyx_n_s_tail2, __pyx_n_s_head_tail2, __pyx_n_s_key, __pyx_n_s_try_key, __pyx_n_s_cand1, __pyx_n_s_cand2, __pyx_n_s_affinity, __pyx_n_s_pval_h, __pyx_n_s_new_heads, __pyx_n_s_pval_t, __pyx_n_s_new_tails, __pyx_n_s_new_head1, __pyx_n_s_new_head2, __pyx_n_s_new_tail1, __pyx_n_s_new_tail2, __pyx_n_s_subseq1, __pyx_n_s_subseq2, __pyx_n_s_res3, __pyx_n_s_val3, __pyx_n_s_cand3, __pyx_n_s_val, __pyx_n_s_found); if (unlikely(!__pyx_tuple__4)) __PYX_ERR(0, 35, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__4); - __Pyx_GIVEREF(__pyx_tuple__4); - __pyx_codeobj__5 = (PyObject*)__Pyx_PyCode_New(5, 0, 51, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__4, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_embedding_balanced_sequence_cyt, __pyx_n_s_lcs_iter_simple_alt2_cython, 35, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__5)) __PYX_ERR(0, 35, __pyx_L1_error) - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":136 - * - * - * def _lcs_iter_prehash2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node): # <<<<<<<<<<<<<< - * """ - * Version of the lcs iterative algorithm where we precompute hash values - */ - __pyx_tuple__6 = PyTuple_Pack(67, __pyx_n_s_full_seq1, __pyx_n_s_full_seq2, __pyx_n_s_open_to_close, __pyx_n_s_node_affinity, __pyx_n_s_open_to_node, __pyx_n_s_all_decomp1, __pyx_n_s_all_decomp2, __pyx_n_s_key_decomp1, __pyx_n_s_key_decomp2, __pyx_n_s_results, __pyx_n_s_empty1, __pyx_n_s_empty2, __pyx_n_s_empty1_key, __pyx_n_s_empty2_key, __pyx_n_s_best, __pyx_n_s_info1, __pyx_n_s_info2, __pyx_n_s_try_key, __pyx_n_s_key, __pyx_n_s_seq1_key, __pyx_n_s_seq2_key, __pyx_n_s_head1_key, __pyx_n_s_tail1_key, __pyx_n_s_head_tail1_key, __pyx_n_s_head2_key, __pyx_n_s_tail2_key, __pyx_n_s_head_tail2_key, __pyx_n_s_frame, __pyx_n_s_miss_frame, __pyx_n_s_base_result, __pyx_n_s_seq1, __pyx_n_s_seq2, __pyx_n_s_full_seq1_key, __pyx_n_s_full_seq2_key, __pyx_n_s_key0, __pyx_n_s_frame0, __pyx_n_s_stack, __pyx_n_s_tok1, __pyx_n_s_head1, __pyx_n_s_tail1, __pyx_n_s_head_tail1, __pyx_n_s_a1, __pyx_n_s_b1, __pyx_n_s_tok2, __pyx_n_s_head2, __pyx_n_s_tail2, __pyx_n_s_head_tail2, __pyx_n_s_a2, __pyx_n_s_b2, __pyx_n_s_affinity, __pyx_n_s_cand1, __pyx_n_s_cand2, __pyx_n_s_pval_h, __pyx_n_s_new_heads, __pyx_n_s_pval_t, __pyx_n_s_new_tails, __pyx_n_s_new_head1, __pyx_n_s_new_head2, __pyx_n_s_new_tail1, __pyx_n_s_new_tail2, __pyx_n_s_subseq1, __pyx_n_s_subseq2, __pyx_n_s_res3, __pyx_n_s_val3, __pyx_n_s_cand3, __pyx_n_s_val, __pyx_n_s_found); if (unlikely(!__pyx_tuple__6)) __PYX_ERR(0, 136, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__6); - __Pyx_GIVEREF(__pyx_tuple__6); - __pyx_codeobj__7 = (PyObject*)__Pyx_PyCode_New(5, 0, 67, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__6, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_embedding_balanced_sequence_cyt, __pyx_n_s_lcs_iter_prehash2_cython, 136, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__7)) __PYX_ERR(0, 136, __pyx_L1_error) - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":342 - * class IdentityDict: - * """ Used when ``open_to_node`` is unspecified """ - * def __getitem__(self, key): # <<<<<<<<<<<<<< - * return key - */ - __pyx_tuple__8 = PyTuple_Pack(2, __pyx_n_s_self, __pyx_n_s_key); if (unlikely(!__pyx_tuple__8)) __PYX_ERR(0, 342, __pyx_L1_error) - __Pyx_GOTREF(__pyx_tuple__8); - __Pyx_GIVEREF(__pyx_tuple__8); - __pyx_codeobj__9 = (PyObject*)__Pyx_PyCode_New(2, 0, 2, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__8, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_embedding_balanced_sequence_cyt, __pyx_n_s_getitem, 342, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__9)) __PYX_ERR(0, 342, __pyx_L1_error) - __Pyx_RefNannyFinishContext(); - return 0; - __pyx_L1_error:; - __Pyx_RefNannyFinishContext(); - return -1; -} - -static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) { - __pyx_umethod_PyDict_Type_items.type = (PyObject*)&PyDict_Type; - __pyx_umethod_PyDict_Type_keys.type = (PyObject*)&PyDict_Type; - __pyx_umethod_PyList_Type_pop.type = (PyObject*)&PyList_Type; - if (__Pyx_InitStrings(__pyx_string_tab) < 0) __PYX_ERR(0, 1, __pyx_L1_error); - __pyx_int_0 = PyInt_FromLong(0); if (unlikely(!__pyx_int_0)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_int_1 = PyInt_FromLong(1); if (unlikely(!__pyx_int_1)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_int_5 = PyInt_FromLong(5); if (unlikely(!__pyx_int_5)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_int_8 = PyInt_FromLong(8); if (unlikely(!__pyx_int_8)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_int_neg_1 = PyInt_FromLong(-1); if (unlikely(!__pyx_int_neg_1)) __PYX_ERR(0, 1, __pyx_L1_error) - return 0; - __pyx_L1_error:; - return -1; -} - -static CYTHON_SMALL_CODE int __Pyx_modinit_global_init_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_variable_export_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_function_export_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_type_init_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_type_import_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_variable_import_code(void); /*proto*/ -static CYTHON_SMALL_CODE int __Pyx_modinit_function_import_code(void); /*proto*/ - -static int __Pyx_modinit_global_init_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_global_init_code", 0); - /*--- Global init code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - -static int __Pyx_modinit_variable_export_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_variable_export_code", 0); - /*--- Variable export code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - -static int __Pyx_modinit_function_export_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_function_export_code", 0); - /*--- Function export code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - -static int __Pyx_modinit_type_init_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_type_init_code", 0); - /*--- Type init code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - -static int __Pyx_modinit_type_import_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_type_import_code", 0); - /*--- Type import code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - -static int __Pyx_modinit_variable_import_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_variable_import_code", 0); - /*--- Variable import code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - -static int __Pyx_modinit_function_import_code(void) { - __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_modinit_function_import_code", 0); - /*--- Function import code ---*/ - __Pyx_RefNannyFinishContext(); - return 0; -} - - -#ifndef CYTHON_NO_PYINIT_EXPORT -#define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC -#elif PY_MAJOR_VERSION < 3 -#ifdef __cplusplus -#define __Pyx_PyMODINIT_FUNC extern "C" void -#else -#define __Pyx_PyMODINIT_FUNC void -#endif -#else -#ifdef __cplusplus -#define __Pyx_PyMODINIT_FUNC extern "C" PyObject * -#else -#define __Pyx_PyMODINIT_FUNC PyObject * -#endif -#endif - - -#if PY_MAJOR_VERSION < 3 -__Pyx_PyMODINIT_FUNC initbalanced_sequence_cython(void) CYTHON_SMALL_CODE; /*proto*/ -__Pyx_PyMODINIT_FUNC initbalanced_sequence_cython(void) -#else -__Pyx_PyMODINIT_FUNC PyInit_balanced_sequence_cython(void) CYTHON_SMALL_CODE; /*proto*/ -__Pyx_PyMODINIT_FUNC PyInit_balanced_sequence_cython(void) -#if CYTHON_PEP489_MULTI_PHASE_INIT -{ - return PyModuleDef_Init(&__pyx_moduledef); -} -static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) { - #if PY_VERSION_HEX >= 0x030700A1 - static PY_INT64_T main_interpreter_id = -1; - PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()->interp); - if (main_interpreter_id == -1) { - main_interpreter_id = current_id; - return (unlikely(current_id == -1)) ? -1 : 0; - } else if (unlikely(main_interpreter_id != current_id)) - #else - static PyInterpreterState *main_interpreter = NULL; - PyInterpreterState *current_interpreter = PyThreadState_Get()->interp; - if (!main_interpreter) { - main_interpreter = current_interpreter; - } else if (unlikely(main_interpreter != current_interpreter)) - #endif - { - PyErr_SetString( - PyExc_ImportError, - "Interpreter change detected - this module can only be loaded into one interpreter per process."); - return -1; - } - return 0; -} -static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name, int allow_none) { - PyObject *value = PyObject_GetAttrString(spec, from_name); - int result = 0; - if (likely(value)) { - if (allow_none || value != Py_None) { - result = PyDict_SetItemString(moddict, to_name, value); - } - Py_DECREF(value); - } else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { - PyErr_Clear(); - } else { - result = -1; - } - return result; -} -static CYTHON_SMALL_CODE PyObject* __pyx_pymod_create(PyObject *spec, CYTHON_UNUSED PyModuleDef *def) { - PyObject *module = NULL, *moddict, *modname; - if (__Pyx_check_single_interpreter()) - return NULL; - if (__pyx_m) - return __Pyx_NewRef(__pyx_m); - modname = PyObject_GetAttrString(spec, "name"); - if (unlikely(!modname)) goto bad; - module = PyModule_NewObject(modname); - Py_DECREF(modname); - if (unlikely(!module)) goto bad; - moddict = PyModule_GetDict(module); - if (unlikely(!moddict)) goto bad; - if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "loader", "__loader__", 1) < 0)) goto bad; - if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "origin", "__file__", 1) < 0)) goto bad; - if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "parent", "__package__", 1) < 0)) goto bad; - if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "submodule_search_locations", "__path__", 0) < 0)) goto bad; - return module; -bad: - Py_XDECREF(module); - return NULL; -} - - -static CYTHON_SMALL_CODE int __pyx_pymod_exec_balanced_sequence_cython(PyObject *__pyx_pyinit_module) -#endif -#endif -{ - PyObject *__pyx_t_1 = NULL; - PyObject *__pyx_t_2 = NULL; - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannyDeclarations - #if CYTHON_PEP489_MULTI_PHASE_INIT - if (__pyx_m) { - if (__pyx_m == __pyx_pyinit_module) return 0; - PyErr_SetString(PyExc_RuntimeError, "Module 'balanced_sequence_cython' has already been imported. Re-initialisation is not supported."); - return -1; - } - #elif PY_MAJOR_VERSION >= 3 - if (__pyx_m) return __Pyx_NewRef(__pyx_m); - #endif - #if CYTHON_REFNANNY -__Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); -if (!__Pyx_RefNanny) { - PyErr_Clear(); - __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); - if (!__Pyx_RefNanny) - Py_FatalError("failed to import 'refnanny' module"); -} -#endif - __Pyx_RefNannySetupContext("__Pyx_PyMODINIT_FUNC PyInit_balanced_sequence_cython(void)", 0); - if (__Pyx_check_binary_version() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #ifdef __Pxy_PyFrame_Initialize_Offsets - __Pxy_PyFrame_Initialize_Offsets(); - #endif - __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) __PYX_ERR(0, 1, __pyx_L1_error) - __pyx_empty_unicode = PyUnicode_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_unicode)) __PYX_ERR(0, 1, __pyx_L1_error) - #ifdef __Pyx_CyFunction_USED - if (__pyx_CyFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - #ifdef __Pyx_FusedFunction_USED - if (__pyx_FusedFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - #ifdef __Pyx_Coroutine_USED - if (__pyx_Coroutine_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - #ifdef __Pyx_Generator_USED - if (__pyx_Generator_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - #ifdef __Pyx_AsyncGen_USED - if (__pyx_AsyncGen_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - #ifdef __Pyx_StopAsyncIteration_USED - if (__pyx_StopAsyncIteration_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - /*--- Library function declarations ---*/ - /*--- Threads initialization code ---*/ - #if defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_THREADS - #ifdef WITH_THREAD /* Python build with threading support? */ - PyEval_InitThreads(); - #endif - #endif - /*--- Module creation code ---*/ - #if CYTHON_PEP489_MULTI_PHASE_INIT - __pyx_m = __pyx_pyinit_module; - Py_INCREF(__pyx_m); - #else - #if PY_MAJOR_VERSION < 3 - __pyx_m = Py_InitModule4("balanced_sequence_cython", __pyx_methods, __pyx_k_This_module_re_implements_funct, 0, PYTHON_API_VERSION); Py_XINCREF(__pyx_m); - #else - __pyx_m = PyModule_Create(&__pyx_moduledef); - #endif - if (unlikely(!__pyx_m)) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - __pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) __PYX_ERR(0, 1, __pyx_L1_error) - Py_INCREF(__pyx_d); - __pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_b)) __PYX_ERR(0, 1, __pyx_L1_error) - Py_INCREF(__pyx_b); - __pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error) - Py_INCREF(__pyx_cython_runtime); - if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) __PYX_ERR(0, 1, __pyx_L1_error); - /*--- Initialize various global constants etc. ---*/ - if (__Pyx_InitGlobals() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #if PY_MAJOR_VERSION < 3 && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT) - if (__Pyx_init_sys_getdefaultencoding_params() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - if (__pyx_module_is_main_networkx__algorithms__isomorphism___embedding__balanced_sequence_cython) { - if (PyObject_SetAttr(__pyx_m, __pyx_n_s_name, __pyx_n_s_main) < 0) __PYX_ERR(0, 1, __pyx_L1_error) - } - #if PY_MAJOR_VERSION >= 3 - { - PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) __PYX_ERR(0, 1, __pyx_L1_error) - if (!PyDict_GetItemString(modules, "networkx.algorithms.isomorphism._embedding.balanced_sequence_cython")) { - if (unlikely(PyDict_SetItemString(modules, "networkx.algorithms.isomorphism._embedding.balanced_sequence_cython", __pyx_m) < 0)) __PYX_ERR(0, 1, __pyx_L1_error) - } - } - #endif - /*--- Builtin init code ---*/ - if (__Pyx_InitCachedBuiltins() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - /*--- Constants init code ---*/ - if (__Pyx_InitCachedConstants() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - /*--- Global type/function init code ---*/ - (void)__Pyx_modinit_global_init_code(); - (void)__Pyx_modinit_variable_export_code(); - (void)__Pyx_modinit_function_export_code(); - (void)__Pyx_modinit_type_init_code(); - (void)__Pyx_modinit_type_import_code(); - (void)__Pyx_modinit_variable_import_code(); - (void)__Pyx_modinit_function_import_code(); - /*--- Execution code ---*/ - #if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED) - if (__Pyx_patch_abc() < 0) __PYX_ERR(0, 1, __pyx_L1_error) - #endif - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":35 - * - * - * def _lcs_iter_simple_alt2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node): # <<<<<<<<<<<<<< - * """ - * Depth first stack trajectory and replace try except statements with ifs - */ - __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_1_lcs_iter_simple_alt2_cython, NULL, __pyx_n_s_networkx_algorithms_isomorphism); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 35, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_lcs_iter_simple_alt2_cython, __pyx_t_1) < 0) __PYX_ERR(0, 35, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":136 - * - * - * def _lcs_iter_prehash2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node): # <<<<<<<<<<<<<< - * """ - * Version of the lcs iterative algorithm where we precompute hash values - */ - __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_3_lcs_iter_prehash2_cython, NULL, __pyx_n_s_networkx_algorithms_isomorphism); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 136, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_lcs_iter_prehash2_cython, __pyx_t_1) < 0) __PYX_ERR(0, 136, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":340 - * - * - * class IdentityDict: # <<<<<<<<<<<<<< - * """ Used when ``open_to_node`` is unspecified """ - * def __getitem__(self, key): - */ - __pyx_t_1 = __Pyx_Py3MetaclassPrepare((PyObject *) NULL, __pyx_empty_tuple, __pyx_n_s_IdentityDict, __pyx_n_s_IdentityDict, (PyObject *) NULL, __pyx_n_s_networkx_algorithms_isomorphism, __pyx_kp_s_Used_when_open_to_node_is_unspe); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 340, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":342 - * class IdentityDict: - * """ Used when ``open_to_node`` is unspecified """ - * def __getitem__(self, key): # <<<<<<<<<<<<<< - * return key - */ - __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict_1__getitem__, 0, __pyx_n_s_IdentityDict___getitem, NULL, __pyx_n_s_networkx_algorithms_isomorphism, __pyx_d, ((PyObject *)__pyx_codeobj__9)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 342, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - if (__Pyx_SetNameInClass(__pyx_t_1, __pyx_n_s_getitem, __pyx_t_2) < 0) __PYX_ERR(0, 342, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":340 - * - * - * class IdentityDict: # <<<<<<<<<<<<<< - * """ Used when ``open_to_node`` is unspecified """ - * def __getitem__(self, key): - */ - __pyx_t_2 = __Pyx_Py3ClassCreate(((PyObject*)&__Pyx_DefaultClassType), __pyx_n_s_IdentityDict, __pyx_empty_tuple, __pyx_t_1, NULL, 0, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 340, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_2); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_IdentityDict, __pyx_t_2) < 0) __PYX_ERR(0, 340, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /* "networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx":1 - * # distutils: language = c++ # <<<<<<<<<<<<<< - * """ - * This module re-implements functions in :module:`balanced_sequence` in cython - */ - __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error) - __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error) - __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; - - /*--- Wrapped vars code ---*/ - - goto __pyx_L0; - __pyx_L1_error:; - __Pyx_XDECREF(__pyx_t_1); - __Pyx_XDECREF(__pyx_t_2); - if (__pyx_m) { - if (__pyx_d) { - __Pyx_AddTraceback("init networkx.algorithms.isomorphism._embedding.balanced_sequence_cython", __pyx_clineno, __pyx_lineno, __pyx_filename); - } - Py_CLEAR(__pyx_m); - } else if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_ImportError, "init networkx.algorithms.isomorphism._embedding.balanced_sequence_cython"); - } - __pyx_L0:; - __Pyx_RefNannyFinishContext(); - #if CYTHON_PEP489_MULTI_PHASE_INIT - return (__pyx_m != NULL) ? 0 : -1; - #elif PY_MAJOR_VERSION >= 3 - return __pyx_m; - #else - return; - #endif -} - -/* --- Runtime support code --- */ -/* Refnanny */ -#if CYTHON_REFNANNY -static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { - PyObject *m = NULL, *p = NULL; - void *r = NULL; - m = PyImport_ImportModule(modname); - if (!m) goto end; - p = PyObject_GetAttrString(m, "RefNannyAPI"); - if (!p) goto end; - r = PyLong_AsVoidPtr(p); -end: - Py_XDECREF(p); - Py_XDECREF(m); - return (__Pyx_RefNannyAPIStruct *)r; -} -#endif - -/* PyObjectGetAttrStr */ -#if CYTHON_USE_TYPE_SLOTS -static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) { - PyTypeObject* tp = Py_TYPE(obj); - if (likely(tp->tp_getattro)) - return tp->tp_getattro(obj, attr_name); -#if PY_MAJOR_VERSION < 3 - if (likely(tp->tp_getattr)) - return tp->tp_getattr(obj, PyString_AS_STRING(attr_name)); -#endif - return PyObject_GetAttr(obj, attr_name); -} -#endif - -/* GetBuiltinName */ -static PyObject *__Pyx_GetBuiltinName(PyObject *name) { - PyObject* result = __Pyx_PyObject_GetAttrStr(__pyx_b, name); - if (unlikely(!result)) { - PyErr_Format(PyExc_NameError, -#if PY_MAJOR_VERSION >= 3 - "name '%U' is not defined", name); -#else - "name '%.200s' is not defined", PyString_AS_STRING(name)); -#endif - } - return result; -} - -/* RaiseArgTupleInvalid */ -static void __Pyx_RaiseArgtupleInvalid( - const char* func_name, - int exact, - Py_ssize_t num_min, - Py_ssize_t num_max, - Py_ssize_t num_found) -{ - Py_ssize_t num_expected; - const char *more_or_less; - if (num_found < num_min) { - num_expected = num_min; - more_or_less = "at least"; - } else { - num_expected = num_max; - more_or_less = "at most"; - } - if (exact) { - more_or_less = "exactly"; - } - PyErr_Format(PyExc_TypeError, - "%.200s() takes %.8s %" CYTHON_FORMAT_SSIZE_T "d positional argument%.1s (%" CYTHON_FORMAT_SSIZE_T "d given)", - func_name, more_or_less, num_expected, - (num_expected == 1) ? "" : "s", num_found); -} - -/* RaiseDoubleKeywords */ -static void __Pyx_RaiseDoubleKeywordsError( - const char* func_name, - PyObject* kw_name) -{ - PyErr_Format(PyExc_TypeError, - #if PY_MAJOR_VERSION >= 3 - "%s() got multiple values for keyword argument '%U'", func_name, kw_name); - #else - "%s() got multiple values for keyword argument '%s'", func_name, - PyString_AsString(kw_name)); - #endif -} - -/* ParseKeywords */ -static int __Pyx_ParseOptionalKeywords( - PyObject *kwds, - PyObject **argnames[], - PyObject *kwds2, - PyObject *values[], - Py_ssize_t num_pos_args, - const char* function_name) -{ - PyObject *key = 0, *value = 0; - Py_ssize_t pos = 0; - PyObject*** name; - PyObject*** first_kw_arg = argnames + num_pos_args; - while (PyDict_Next(kwds, &pos, &key, &value)) { - name = first_kw_arg; - while (*name && (**name != key)) name++; - if (*name) { - values[name-argnames] = value; - continue; - } - name = first_kw_arg; - #if PY_MAJOR_VERSION < 3 - if (likely(PyString_Check(key))) { - while (*name) { - if ((CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**name) == PyString_GET_SIZE(key)) - && _PyString_Eq(**name, key)) { - values[name-argnames] = value; - break; - } - name++; - } - if (*name) continue; - else { - PyObject*** argname = argnames; - while (argname != first_kw_arg) { - if ((**argname == key) || ( - (CYTHON_COMPILING_IN_PYPY || PyString_GET_SIZE(**argname) == PyString_GET_SIZE(key)) - && _PyString_Eq(**argname, key))) { - goto arg_passed_twice; - } - argname++; - } - } - } else - #endif - if (likely(PyUnicode_Check(key))) { - while (*name) { - int cmp = (**name == key) ? 0 : - #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 - (__Pyx_PyUnicode_GET_LENGTH(**name) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 : - #endif - PyUnicode_Compare(**name, key); - if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; - if (cmp == 0) { - values[name-argnames] = value; - break; - } - name++; - } - if (*name) continue; - else { - PyObject*** argname = argnames; - while (argname != first_kw_arg) { - int cmp = (**argname == key) ? 0 : - #if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION >= 3 - (__Pyx_PyUnicode_GET_LENGTH(**argname) != __Pyx_PyUnicode_GET_LENGTH(key)) ? 1 : - #endif - PyUnicode_Compare(**argname, key); - if (cmp < 0 && unlikely(PyErr_Occurred())) goto bad; - if (cmp == 0) goto arg_passed_twice; - argname++; - } - } - } else - goto invalid_keyword_type; - if (kwds2) { - if (unlikely(PyDict_SetItem(kwds2, key, value))) goto bad; - } else { - goto invalid_keyword; - } - } - return 0; -arg_passed_twice: - __Pyx_RaiseDoubleKeywordsError(function_name, key); - goto bad; -invalid_keyword_type: - PyErr_Format(PyExc_TypeError, - "%.200s() keywords must be strings", function_name); - goto bad; -invalid_keyword: - PyErr_Format(PyExc_TypeError, - #if PY_MAJOR_VERSION < 3 - "%.200s() got an unexpected keyword argument '%.200s'", - function_name, PyString_AsString(key)); - #else - "%s() got an unexpected keyword argument '%U'", - function_name, key); - #endif -bad: - return -1; -} - -/* PyDictVersioning */ -#if CYTHON_USE_DICT_VERSIONS && CYTHON_USE_TYPE_SLOTS -static CYTHON_INLINE PY_UINT64_T __Pyx_get_tp_dict_version(PyObject *obj) { - PyObject *dict = Py_TYPE(obj)->tp_dict; - return likely(dict) ? __PYX_GET_DICT_VERSION(dict) : 0; -} -static CYTHON_INLINE PY_UINT64_T __Pyx_get_object_dict_version(PyObject *obj) { - PyObject **dictptr = NULL; - Py_ssize_t offset = Py_TYPE(obj)->tp_dictoffset; - if (offset) { -#if CYTHON_COMPILING_IN_CPYTHON - dictptr = (likely(offset > 0)) ? (PyObject **) ((char *)obj + offset) : _PyObject_GetDictPtr(obj); -#else - dictptr = _PyObject_GetDictPtr(obj); -#endif - } - return (dictptr && *dictptr) ? __PYX_GET_DICT_VERSION(*dictptr) : 0; -} -static CYTHON_INLINE int __Pyx_object_dict_version_matches(PyObject* obj, PY_UINT64_T tp_dict_version, PY_UINT64_T obj_dict_version) { - PyObject *dict = Py_TYPE(obj)->tp_dict; - if (unlikely(!dict) || unlikely(tp_dict_version != __PYX_GET_DICT_VERSION(dict))) - return 0; - return obj_dict_version == __Pyx_get_object_dict_version(obj); -} -#endif - -/* GetModuleGlobalName */ -#if CYTHON_USE_DICT_VERSIONS -static PyObject *__Pyx__GetModuleGlobalName(PyObject *name, PY_UINT64_T *dict_version, PyObject **dict_cached_value) -#else -static CYTHON_INLINE PyObject *__Pyx__GetModuleGlobalName(PyObject *name) -#endif -{ - PyObject *result; -#if !CYTHON_AVOID_BORROWED_REFS -#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 - result = _PyDict_GetItem_KnownHash(__pyx_d, name, ((PyASCIIObject *) name)->hash); - __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) - if (likely(result)) { - return __Pyx_NewRef(result); - } else if (unlikely(PyErr_Occurred())) { - return NULL; - } -#else - result = PyDict_GetItem(__pyx_d, name); - __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) - if (likely(result)) { - return __Pyx_NewRef(result); - } -#endif -#else - result = PyObject_GetItem(__pyx_d, name); - __PYX_UPDATE_DICT_CACHE(__pyx_d, result, *dict_cached_value, *dict_version) - if (likely(result)) { - return __Pyx_NewRef(result); - } - PyErr_Clear(); -#endif - return __Pyx_GetBuiltinName(name); -} - -/* PyFunctionFastCall */ -#if CYTHON_FAST_PYCALL -static PyObject* __Pyx_PyFunction_FastCallNoKw(PyCodeObject *co, PyObject **args, Py_ssize_t na, - PyObject *globals) { - PyFrameObject *f; - PyThreadState *tstate = __Pyx_PyThreadState_Current; - PyObject **fastlocals; - Py_ssize_t i; - PyObject *result; - assert(globals != NULL); - /* XXX Perhaps we should create a specialized - PyFrame_New() that doesn't take locals, but does - take builtins without sanity checking them. - */ - assert(tstate != NULL); - f = PyFrame_New(tstate, co, globals, NULL); - if (f == NULL) { - return NULL; - } - fastlocals = __Pyx_PyFrame_GetLocalsplus(f); - for (i = 0; i < na; i++) { - Py_INCREF(*args); - fastlocals[i] = *args++; - } - result = PyEval_EvalFrameEx(f,0); - ++tstate->recursion_depth; - Py_DECREF(f); - --tstate->recursion_depth; - return result; -} -#if 1 || PY_VERSION_HEX < 0x030600B1 -static PyObject *__Pyx_PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) { - PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); - PyObject *globals = PyFunction_GET_GLOBALS(func); - PyObject *argdefs = PyFunction_GET_DEFAULTS(func); - PyObject *closure; -#if PY_MAJOR_VERSION >= 3 - PyObject *kwdefs; -#endif - PyObject *kwtuple, **k; - PyObject **d; - Py_ssize_t nd; - Py_ssize_t nk; - PyObject *result; - assert(kwargs == NULL || PyDict_Check(kwargs)); - nk = kwargs ? PyDict_Size(kwargs) : 0; - if (Py_EnterRecursiveCall((char*)" while calling a Python object")) { - return NULL; - } - if ( -#if PY_MAJOR_VERSION >= 3 - co->co_kwonlyargcount == 0 && -#endif - likely(kwargs == NULL || nk == 0) && - co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) { - if (argdefs == NULL && co->co_argcount == nargs) { - result = __Pyx_PyFunction_FastCallNoKw(co, args, nargs, globals); - goto done; - } - else if (nargs == 0 && argdefs != NULL - && co->co_argcount == Py_SIZE(argdefs)) { - /* function called with no arguments, but all parameters have - a default value: use default values as arguments .*/ - args = &PyTuple_GET_ITEM(argdefs, 0); - result =__Pyx_PyFunction_FastCallNoKw(co, args, Py_SIZE(argdefs), globals); - goto done; - } - } - if (kwargs != NULL) { - Py_ssize_t pos, i; - kwtuple = PyTuple_New(2 * nk); - if (kwtuple == NULL) { - result = NULL; - goto done; - } - k = &PyTuple_GET_ITEM(kwtuple, 0); - pos = i = 0; - while (PyDict_Next(kwargs, &pos, &k[i], &k[i+1])) { - Py_INCREF(k[i]); - Py_INCREF(k[i+1]); - i += 2; - } - nk = i / 2; - } - else { - kwtuple = NULL; - k = NULL; - } - closure = PyFunction_GET_CLOSURE(func); -#if PY_MAJOR_VERSION >= 3 - kwdefs = PyFunction_GET_KW_DEFAULTS(func); -#endif - if (argdefs != NULL) { - d = &PyTuple_GET_ITEM(argdefs, 0); - nd = Py_SIZE(argdefs); - } - else { - d = NULL; - nd = 0; - } -#if PY_MAJOR_VERSION >= 3 - result = PyEval_EvalCodeEx((PyObject*)co, globals, (PyObject *)NULL, - args, (int)nargs, - k, (int)nk, - d, (int)nd, kwdefs, closure); -#else - result = PyEval_EvalCodeEx(co, globals, (PyObject *)NULL, - args, (int)nargs, - k, (int)nk, - d, (int)nd, closure); -#endif - Py_XDECREF(kwtuple); -done: - Py_LeaveRecursiveCall(); - return result; -} -#endif -#endif - -/* PyObjectCall */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw) { - PyObject *result; - ternaryfunc call = func->ob_type->tp_call; - if (unlikely(!call)) - return PyObject_Call(func, arg, kw); - if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) - return NULL; - result = (*call)(func, arg, kw); - Py_LeaveRecursiveCall(); - if (unlikely(!result) && unlikely(!PyErr_Occurred())) { - PyErr_SetString( - PyExc_SystemError, - "NULL result without error in PyObject_Call"); - } - return result; -} -#endif - -/* PyObjectCallMethO */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallMethO(PyObject *func, PyObject *arg) { - PyObject *self, *result; - PyCFunction cfunc; - cfunc = PyCFunction_GET_FUNCTION(func); - self = PyCFunction_GET_SELF(func); - if (unlikely(Py_EnterRecursiveCall((char*)" while calling a Python object"))) - return NULL; - result = cfunc(self, arg); - Py_LeaveRecursiveCall(); - if (unlikely(!result) && unlikely(!PyErr_Occurred())) { - PyErr_SetString( - PyExc_SystemError, - "NULL result without error in PyObject_Call"); - } - return result; -} -#endif - -/* PyObjectCallNoArg */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallNoArg(PyObject *func) { -#if CYTHON_FAST_PYCALL - if (PyFunction_Check(func)) { - return __Pyx_PyFunction_FastCall(func, NULL, 0); - } -#endif -#ifdef __Pyx_CyFunction_USED - if (likely(PyCFunction_Check(func) || __Pyx_CyFunction_Check(func))) -#else - if (likely(PyCFunction_Check(func))) -#endif - { - if (likely(PyCFunction_GET_FLAGS(func) & METH_NOARGS)) { - return __Pyx_PyObject_CallMethO(func, NULL); - } - } - return __Pyx_PyObject_Call(func, __pyx_empty_tuple, NULL); -} -#endif - -/* PyCFunctionFastCall */ -#if CYTHON_FAST_PYCCALL -static CYTHON_INLINE PyObject * __Pyx_PyCFunction_FastCall(PyObject *func_obj, PyObject **args, Py_ssize_t nargs) { - PyCFunctionObject *func = (PyCFunctionObject*)func_obj; - PyCFunction meth = PyCFunction_GET_FUNCTION(func); - PyObject *self = PyCFunction_GET_SELF(func); - int flags = PyCFunction_GET_FLAGS(func); - assert(PyCFunction_Check(func)); - assert(METH_FASTCALL == (flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))); - assert(nargs >= 0); - assert(nargs == 0 || args != NULL); - /* _PyCFunction_FastCallDict() must not be called with an exception set, - because it may clear it (directly or indirectly) and so the - caller loses its exception */ - assert(!PyErr_Occurred()); - if ((PY_VERSION_HEX < 0x030700A0) || unlikely(flags & METH_KEYWORDS)) { - return (*((__Pyx_PyCFunctionFastWithKeywords)(void*)meth)) (self, args, nargs, NULL); - } else { - return (*((__Pyx_PyCFunctionFast)(void*)meth)) (self, args, nargs); - } -} -#endif - -/* PyObjectCallOneArg */ -#if CYTHON_COMPILING_IN_CPYTHON -static PyObject* __Pyx__PyObject_CallOneArg(PyObject *func, PyObject *arg) { - PyObject *result; - PyObject *args = PyTuple_New(1); - if (unlikely(!args)) return NULL; - Py_INCREF(arg); - PyTuple_SET_ITEM(args, 0, arg); - result = __Pyx_PyObject_Call(func, args, NULL); - Py_DECREF(args); - return result; -} -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { -#if CYTHON_FAST_PYCALL - if (PyFunction_Check(func)) { - return __Pyx_PyFunction_FastCall(func, &arg, 1); - } -#endif - if (likely(PyCFunction_Check(func))) { - if (likely(PyCFunction_GET_FLAGS(func) & METH_O)) { - return __Pyx_PyObject_CallMethO(func, arg); -#if CYTHON_FAST_PYCCALL - } else if (PyCFunction_GET_FLAGS(func) & METH_FASTCALL) { - return __Pyx_PyCFunction_FastCall(func, &arg, 1); -#endif - } - } - return __Pyx__PyObject_CallOneArg(func, arg); -} -#else -static CYTHON_INLINE PyObject* __Pyx_PyObject_CallOneArg(PyObject *func, PyObject *arg) { - PyObject *result; - PyObject *args = PyTuple_Pack(1, arg); - if (unlikely(!args)) return NULL; - result = __Pyx_PyObject_Call(func, args, NULL); - Py_DECREF(args); - return result; -} -#endif - -/* PyErrFetchRestore */ -#if CYTHON_FAST_THREAD_STATE -static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { - PyObject *tmp_type, *tmp_value, *tmp_tb; - tmp_type = tstate->curexc_type; - tmp_value = tstate->curexc_value; - tmp_tb = tstate->curexc_traceback; - tstate->curexc_type = type; - tstate->curexc_value = value; - tstate->curexc_traceback = tb; - Py_XDECREF(tmp_type); - Py_XDECREF(tmp_value); - Py_XDECREF(tmp_tb); -} -static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { - *type = tstate->curexc_type; - *value = tstate->curexc_value; - *tb = tstate->curexc_traceback; - tstate->curexc_type = 0; - tstate->curexc_value = 0; - tstate->curexc_traceback = 0; -} -#endif - -/* IterNext */ -static PyObject *__Pyx_PyIter_Next2Default(PyObject* defval) { - PyObject* exc_type; - __Pyx_PyThreadState_declare - __Pyx_PyThreadState_assign - exc_type = __Pyx_PyErr_Occurred(); - if (unlikely(exc_type)) { - if (!defval || unlikely(!__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) - return NULL; - __Pyx_PyErr_Clear(); - Py_INCREF(defval); - return defval; - } - if (defval) { - Py_INCREF(defval); - return defval; - } - __Pyx_PyErr_SetNone(PyExc_StopIteration); - return NULL; -} -static void __Pyx_PyIter_Next_ErrorNoIterator(PyObject *iterator) { - PyErr_Format(PyExc_TypeError, - "%.200s object is not an iterator", Py_TYPE(iterator)->tp_name); -} -static CYTHON_INLINE PyObject *__Pyx_PyIter_Next2(PyObject* iterator, PyObject* defval) { - PyObject* next; - iternextfunc iternext = Py_TYPE(iterator)->tp_iternext; - if (likely(iternext)) { -#if CYTHON_USE_TYPE_SLOTS - next = iternext(iterator); - if (likely(next)) - return next; - #if PY_VERSION_HEX >= 0x02070000 - if (unlikely(iternext == &_PyObject_NextNotImplemented)) - return NULL; - #endif -#else - next = PyIter_Next(iterator); - if (likely(next)) - return next; -#endif - } else if (CYTHON_USE_TYPE_SLOTS || unlikely(!PyIter_Check(iterator))) { - __Pyx_PyIter_Next_ErrorNoIterator(iterator); - return NULL; - } -#if !CYTHON_USE_TYPE_SLOTS - else { - next = PyIter_Next(iterator); - if (likely(next)) - return next; - } -#endif - return __Pyx_PyIter_Next2Default(defval); -} - -/* GetItemInt */ -static PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) { - PyObject *r; - if (!j) return NULL; - r = PyObject_GetItem(o, j); - Py_DECREF(j); - return r; -} -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i, - CYTHON_NCP_UNUSED int wraparound, - CYTHON_NCP_UNUSED int boundscheck) { -#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - Py_ssize_t wrapped_i = i; - if (wraparound & unlikely(i < 0)) { - wrapped_i += PyList_GET_SIZE(o); - } - if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyList_GET_SIZE(o)))) { - PyObject *r = PyList_GET_ITEM(o, wrapped_i); - Py_INCREF(r); - return r; - } - return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); -#else - return PySequence_GetItem(o, i); -#endif -} -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i, - CYTHON_NCP_UNUSED int wraparound, - CYTHON_NCP_UNUSED int boundscheck) { -#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - Py_ssize_t wrapped_i = i; - if (wraparound & unlikely(i < 0)) { - wrapped_i += PyTuple_GET_SIZE(o); - } - if ((!boundscheck) || likely(__Pyx_is_valid_index(wrapped_i, PyTuple_GET_SIZE(o)))) { - PyObject *r = PyTuple_GET_ITEM(o, wrapped_i); - Py_INCREF(r); - return r; - } - return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); -#else - return PySequence_GetItem(o, i); -#endif -} -static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i, int is_list, - CYTHON_NCP_UNUSED int wraparound, - CYTHON_NCP_UNUSED int boundscheck) { -#if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS && CYTHON_USE_TYPE_SLOTS - if (is_list || PyList_CheckExact(o)) { - Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyList_GET_SIZE(o); - if ((!boundscheck) || (likely(__Pyx_is_valid_index(n, PyList_GET_SIZE(o))))) { - PyObject *r = PyList_GET_ITEM(o, n); - Py_INCREF(r); - return r; - } - } - else if (PyTuple_CheckExact(o)) { - Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyTuple_GET_SIZE(o); - if ((!boundscheck) || likely(__Pyx_is_valid_index(n, PyTuple_GET_SIZE(o)))) { - PyObject *r = PyTuple_GET_ITEM(o, n); - Py_INCREF(r); - return r; - } - } else { - PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence; - if (likely(m && m->sq_item)) { - if (wraparound && unlikely(i < 0) && likely(m->sq_length)) { - Py_ssize_t l = m->sq_length(o); - if (likely(l >= 0)) { - i += l; - } else { - if (!PyErr_ExceptionMatches(PyExc_OverflowError)) - return NULL; - PyErr_Clear(); - } - } - return m->sq_item(o, i); - } - } -#else - if (is_list || PySequence_Check(o)) { - return PySequence_GetItem(o, i); - } -#endif - return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i)); -} - -/* ObjectGetItem */ -#if CYTHON_USE_TYPE_SLOTS -static PyObject *__Pyx_PyObject_GetIndex(PyObject *obj, PyObject* index) { - PyObject *runerr; - Py_ssize_t key_value; - PySequenceMethods *m = Py_TYPE(obj)->tp_as_sequence; - if (unlikely(!(m && m->sq_item))) { - PyErr_Format(PyExc_TypeError, "'%.200s' object is not subscriptable", Py_TYPE(obj)->tp_name); - return NULL; - } - key_value = __Pyx_PyIndex_AsSsize_t(index); - if (likely(key_value != -1 || !(runerr = PyErr_Occurred()))) { - return __Pyx_GetItemInt_Fast(obj, key_value, 0, 1, 1); - } - if (PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError)) { - PyErr_Clear(); - PyErr_Format(PyExc_IndexError, "cannot fit '%.200s' into an index-sized integer", Py_TYPE(index)->tp_name); - } - return NULL; -} -static PyObject *__Pyx_PyObject_GetItem(PyObject *obj, PyObject* key) { - PyMappingMethods *m = Py_TYPE(obj)->tp_as_mapping; - if (likely(m && m->mp_subscript)) { - return m->mp_subscript(obj, key); - } - return __Pyx_PyObject_GetIndex(obj, key); -} -#endif - -/* RaiseTooManyValuesToUnpack */ -static CYTHON_INLINE void __Pyx_RaiseTooManyValuesError(Py_ssize_t expected) { - PyErr_Format(PyExc_ValueError, - "too many values to unpack (expected %" CYTHON_FORMAT_SSIZE_T "d)", expected); -} - -/* RaiseNeedMoreValuesToUnpack */ -static CYTHON_INLINE void __Pyx_RaiseNeedMoreValuesError(Py_ssize_t index) { - PyErr_Format(PyExc_ValueError, - "need more than %" CYTHON_FORMAT_SSIZE_T "d value%.1s to unpack", - index, (index == 1) ? "" : "s"); -} - -/* IterFinish */ -static CYTHON_INLINE int __Pyx_IterFinish(void) { -#if CYTHON_FAST_THREAD_STATE - PyThreadState *tstate = __Pyx_PyThreadState_Current; - PyObject* exc_type = tstate->curexc_type; - if (unlikely(exc_type)) { - if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) { - PyObject *exc_value, *exc_tb; - exc_value = tstate->curexc_value; - exc_tb = tstate->curexc_traceback; - tstate->curexc_type = 0; - tstate->curexc_value = 0; - tstate->curexc_traceback = 0; - Py_DECREF(exc_type); - Py_XDECREF(exc_value); - Py_XDECREF(exc_tb); - return 0; - } else { - return -1; - } - } - return 0; -#else - if (unlikely(PyErr_Occurred())) { - if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) { - PyErr_Clear(); - return 0; - } else { - return -1; - } - } - return 0; -#endif -} - -/* UnpackItemEndCheck */ -static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected) { - if (unlikely(retval)) { - Py_DECREF(retval); - __Pyx_RaiseTooManyValuesError(expected); - return -1; - } else { - return __Pyx_IterFinish(); - } - return 0; -} - -/* DictGetItem */ -#if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY -static PyObject *__Pyx_PyDict_GetItem(PyObject *d, PyObject* key) { - PyObject *value; - value = PyDict_GetItemWithError(d, key); - if (unlikely(!value)) { - if (!PyErr_Occurred()) { - if (unlikely(PyTuple_Check(key))) { - PyObject* args = PyTuple_Pack(1, key); - if (likely(args)) { - PyErr_SetObject(PyExc_KeyError, args); - Py_DECREF(args); - } - } else { - PyErr_SetObject(PyExc_KeyError, key); - } - } - return NULL; - } - Py_INCREF(value); - return value; -} -#endif - -/* PyObjectGetMethod */ -static int __Pyx_PyObject_GetMethod(PyObject *obj, PyObject *name, PyObject **method) { - PyObject *attr; -#if CYTHON_UNPACK_METHODS && CYTHON_COMPILING_IN_CPYTHON && CYTHON_USE_PYTYPE_LOOKUP - PyTypeObject *tp = Py_TYPE(obj); - PyObject *descr; - descrgetfunc f = NULL; - PyObject **dictptr, *dict; - int meth_found = 0; - assert (*method == NULL); - if (unlikely(tp->tp_getattro != PyObject_GenericGetAttr)) { - attr = __Pyx_PyObject_GetAttrStr(obj, name); - goto try_unpack; - } - if (unlikely(tp->tp_dict == NULL) && unlikely(PyType_Ready(tp) < 0)) { - return 0; - } - descr = _PyType_Lookup(tp, name); - if (likely(descr != NULL)) { - Py_INCREF(descr); -#if PY_MAJOR_VERSION >= 3 - #ifdef __Pyx_CyFunction_USED - if (likely(PyFunction_Check(descr) || (Py_TYPE(descr) == &PyMethodDescr_Type) || __Pyx_CyFunction_Check(descr))) - #else - if (likely(PyFunction_Check(descr) || (Py_TYPE(descr) == &PyMethodDescr_Type))) - #endif -#else - #ifdef __Pyx_CyFunction_USED - if (likely(PyFunction_Check(descr) || __Pyx_CyFunction_Check(descr))) - #else - if (likely(PyFunction_Check(descr))) - #endif -#endif - { - meth_found = 1; - } else { - f = Py_TYPE(descr)->tp_descr_get; - if (f != NULL && PyDescr_IsData(descr)) { - attr = f(descr, obj, (PyObject *)Py_TYPE(obj)); - Py_DECREF(descr); - goto try_unpack; - } - } - } - dictptr = _PyObject_GetDictPtr(obj); - if (dictptr != NULL && (dict = *dictptr) != NULL) { - Py_INCREF(dict); - attr = __Pyx_PyDict_GetItemStr(dict, name); - if (attr != NULL) { - Py_INCREF(attr); - Py_DECREF(dict); - Py_XDECREF(descr); - goto try_unpack; - } - Py_DECREF(dict); - } - if (meth_found) { - *method = descr; - return 1; - } - if (f != NULL) { - attr = f(descr, obj, (PyObject *)Py_TYPE(obj)); - Py_DECREF(descr); - goto try_unpack; - } - if (descr != NULL) { - *method = descr; - return 0; - } - PyErr_Format(PyExc_AttributeError, -#if PY_MAJOR_VERSION >= 3 - "'%.50s' object has no attribute '%U'", - tp->tp_name, name); -#else - "'%.50s' object has no attribute '%.400s'", - tp->tp_name, PyString_AS_STRING(name)); -#endif - return 0; -#else - attr = __Pyx_PyObject_GetAttrStr(obj, name); - goto try_unpack; -#endif -try_unpack: -#if CYTHON_UNPACK_METHODS - if (likely(attr) && PyMethod_Check(attr) && likely(PyMethod_GET_SELF(attr) == obj)) { - PyObject *function = PyMethod_GET_FUNCTION(attr); - Py_INCREF(function); - Py_DECREF(attr); - *method = function; - return 1; - } -#endif - *method = attr; - return 0; -} - -/* PyObjectCallMethod0 */ -static PyObject* __Pyx_PyObject_CallMethod0(PyObject* obj, PyObject* method_name) { - PyObject *method = NULL, *result = NULL; - int is_method = __Pyx_PyObject_GetMethod(obj, method_name, &method); - if (likely(is_method)) { - result = __Pyx_PyObject_CallOneArg(method, obj); - Py_DECREF(method); - return result; - } - if (unlikely(!method)) goto bad; - result = __Pyx_PyObject_CallNoArg(method); - Py_DECREF(method); -bad: - return result; -} - -/* UnpackUnboundCMethod */ -static int __Pyx_TryUnpackUnboundCMethod(__Pyx_CachedCFunction* target) { - PyObject *method; - method = __Pyx_PyObject_GetAttrStr(target->type, *target->method_name); - if (unlikely(!method)) - return -1; - target->method = method; -#if CYTHON_COMPILING_IN_CPYTHON - #if PY_MAJOR_VERSION >= 3 - if (likely(__Pyx_TypeCheck(method, &PyMethodDescr_Type))) - #endif - { - PyMethodDescrObject *descr = (PyMethodDescrObject*) method; - target->func = descr->d_method->ml_meth; - target->flag = descr->d_method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_STACKLESS); - } -#endif - return 0; -} - -/* CallUnboundCMethod0 */ -static PyObject* __Pyx__CallUnboundCMethod0(__Pyx_CachedCFunction* cfunc, PyObject* self) { - PyObject *args, *result = NULL; - if (unlikely(!cfunc->method) && unlikely(__Pyx_TryUnpackUnboundCMethod(cfunc) < 0)) return NULL; -#if CYTHON_ASSUME_SAFE_MACROS - args = PyTuple_New(1); - if (unlikely(!args)) goto bad; - Py_INCREF(self); - PyTuple_SET_ITEM(args, 0, self); -#else - args = PyTuple_Pack(1, self); - if (unlikely(!args)) goto bad; -#endif - result = __Pyx_PyObject_Call(cfunc->method, args, NULL); - Py_DECREF(args); -bad: - return result; -} - -/* pop */ -static CYTHON_INLINE PyObject* __Pyx__PyObject_Pop(PyObject* L) { - if (Py_TYPE(L) == &PySet_Type) { - return PySet_Pop(L); - } - return __Pyx_PyObject_CallMethod0(L, __pyx_n_s_pop); -} -#if CYTHON_USE_PYLIST_INTERNALS && CYTHON_ASSUME_SAFE_MACROS -static CYTHON_INLINE PyObject* __Pyx_PyList_Pop(PyObject* L) { - if (likely(PyList_GET_SIZE(L) > (((PyListObject*)L)->allocated >> 1))) { - __Pyx_SET_SIZE(L, Py_SIZE(L) - 1); - return PyList_GET_ITEM(L, PyList_GET_SIZE(L)); - } - return __Pyx_CallUnboundCMethod0(&__pyx_umethod_PyList_Type_pop, L); -} -#endif - -/* py_dict_keys */ -static CYTHON_INLINE PyObject* __Pyx_PyDict_Keys(PyObject* d) { - if (PY_MAJOR_VERSION >= 3) - return __Pyx_CallUnboundCMethod0(&__pyx_umethod_PyDict_Type_keys, d); - else - return PyDict_Keys(d); -} - -/* py_dict_items */ -static CYTHON_INLINE PyObject* __Pyx_PyDict_Items(PyObject* d) { - if (PY_MAJOR_VERSION >= 3) - return __Pyx_CallUnboundCMethod0(&__pyx_umethod_PyDict_Type_items, d); - else - return PyDict_Items(d); -} - -/* SliceObject */ -static CYTHON_INLINE PyObject* __Pyx_PyObject_GetSlice(PyObject* obj, - Py_ssize_t cstart, Py_ssize_t cstop, - PyObject** _py_start, PyObject** _py_stop, PyObject** _py_slice, - int has_cstart, int has_cstop, CYTHON_UNUSED int wraparound) { -#if CYTHON_USE_TYPE_SLOTS - PyMappingMethods* mp; -#if PY_MAJOR_VERSION < 3 - PySequenceMethods* ms = Py_TYPE(obj)->tp_as_sequence; - if (likely(ms && ms->sq_slice)) { - if (!has_cstart) { - if (_py_start && (*_py_start != Py_None)) { - cstart = __Pyx_PyIndex_AsSsize_t(*_py_start); - if ((cstart == (Py_ssize_t)-1) && PyErr_Occurred()) goto bad; - } else - cstart = 0; - } - if (!has_cstop) { - if (_py_stop && (*_py_stop != Py_None)) { - cstop = __Pyx_PyIndex_AsSsize_t(*_py_stop); - if ((cstop == (Py_ssize_t)-1) && PyErr_Occurred()) goto bad; - } else - cstop = PY_SSIZE_T_MAX; - } - if (wraparound && unlikely((cstart < 0) | (cstop < 0)) && likely(ms->sq_length)) { - Py_ssize_t l = ms->sq_length(obj); - if (likely(l >= 0)) { - if (cstop < 0) { - cstop += l; - if (cstop < 0) cstop = 0; - } - if (cstart < 0) { - cstart += l; - if (cstart < 0) cstart = 0; - } - } else { - if (!PyErr_ExceptionMatches(PyExc_OverflowError)) - goto bad; - PyErr_Clear(); - } - } - return ms->sq_slice(obj, cstart, cstop); - } -#endif - mp = Py_TYPE(obj)->tp_as_mapping; - if (likely(mp && mp->mp_subscript)) -#endif - { - PyObject* result; - PyObject *py_slice, *py_start, *py_stop; - if (_py_slice) { - py_slice = *_py_slice; - } else { - PyObject* owned_start = NULL; - PyObject* owned_stop = NULL; - if (_py_start) { - py_start = *_py_start; - } else { - if (has_cstart) { - owned_start = py_start = PyInt_FromSsize_t(cstart); - if (unlikely(!py_start)) goto bad; - } else - py_start = Py_None; - } - if (_py_stop) { - py_stop = *_py_stop; - } else { - if (has_cstop) { - owned_stop = py_stop = PyInt_FromSsize_t(cstop); - if (unlikely(!py_stop)) { - Py_XDECREF(owned_start); - goto bad; - } - } else - py_stop = Py_None; - } - py_slice = PySlice_New(py_start, py_stop, Py_None); - Py_XDECREF(owned_start); - Py_XDECREF(owned_stop); - if (unlikely(!py_slice)) goto bad; - } -#if CYTHON_USE_TYPE_SLOTS - result = mp->mp_subscript(obj, py_slice); -#else - result = PyObject_GetItem(obj, py_slice); -#endif - if (!_py_slice) { - Py_DECREF(py_slice); - } - return result; - } - PyErr_Format(PyExc_TypeError, - "'%.200s' object is unsliceable", Py_TYPE(obj)->tp_name); -bad: - return NULL; -} - -/* RaiseNoneIterError */ -static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void) { - PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable"); -} - -/* None */ -static CYTHON_INLINE void __Pyx_RaiseUnboundLocalError(const char *varname) { - PyErr_Format(PyExc_UnboundLocalError, "local variable '%s' referenced before assignment", varname); -} - -/* SliceTupleAndList */ -#if CYTHON_COMPILING_IN_CPYTHON -static CYTHON_INLINE void __Pyx_crop_slice(Py_ssize_t* _start, Py_ssize_t* _stop, Py_ssize_t* _length) { - Py_ssize_t start = *_start, stop = *_stop, length = *_length; - if (start < 0) { - start += length; - if (start < 0) - start = 0; - } - if (stop < 0) - stop += length; - else if (stop > length) - stop = length; - *_length = stop - start; - *_start = start; - *_stop = stop; -} -static CYTHON_INLINE void __Pyx_copy_object_array(PyObject** CYTHON_RESTRICT src, PyObject** CYTHON_RESTRICT dest, Py_ssize_t length) { - PyObject *v; - Py_ssize_t i; - for (i = 0; i < length; i++) { - v = dest[i] = src[i]; - Py_INCREF(v); - } -} -static CYTHON_INLINE PyObject* __Pyx_PyList_GetSlice( - PyObject* src, Py_ssize_t start, Py_ssize_t stop) { - PyObject* dest; - Py_ssize_t length = PyList_GET_SIZE(src); - __Pyx_crop_slice(&start, &stop, &length); - if (unlikely(length <= 0)) - return PyList_New(0); - dest = PyList_New(length); - if (unlikely(!dest)) - return NULL; - __Pyx_copy_object_array( - ((PyListObject*)src)->ob_item + start, - ((PyListObject*)dest)->ob_item, - length); - return dest; -} -static CYTHON_INLINE PyObject* __Pyx_PyTuple_GetSlice( - PyObject* src, Py_ssize_t start, Py_ssize_t stop) { - PyObject* dest; - Py_ssize_t length = PyTuple_GET_SIZE(src); - __Pyx_crop_slice(&start, &stop, &length); - if (unlikely(length <= 0)) - return PyTuple_New(0); - dest = PyTuple_New(length); - if (unlikely(!dest)) - return NULL; - __Pyx_copy_object_array( - ((PyTupleObject*)src)->ob_item + start, - ((PyTupleObject*)dest)->ob_item, - length); - return dest; -} -#endif - -/* FetchCommonType */ -static PyTypeObject* __Pyx_FetchCommonType(PyTypeObject* type) { - PyObject* fake_module; - PyTypeObject* cached_type = NULL; - fake_module = PyImport_AddModule((char*) "_cython_" CYTHON_ABI); - if (!fake_module) return NULL; - Py_INCREF(fake_module); - cached_type = (PyTypeObject*) PyObject_GetAttrString(fake_module, type->tp_name); - if (cached_type) { - if (!PyType_Check((PyObject*)cached_type)) { - PyErr_Format(PyExc_TypeError, - "Shared Cython type %.200s is not a type object", - type->tp_name); - goto bad; - } - if (cached_type->tp_basicsize != type->tp_basicsize) { - PyErr_Format(PyExc_TypeError, - "Shared Cython type %.200s has the wrong size, try recompiling", - type->tp_name); - goto bad; - } - } else { - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto bad; - PyErr_Clear(); - if (PyType_Ready(type) < 0) goto bad; - if (PyObject_SetAttrString(fake_module, type->tp_name, (PyObject*) type) < 0) - goto bad; - Py_INCREF(type); - cached_type = type; - } -done: - Py_DECREF(fake_module); - return cached_type; -bad: - Py_XDECREF(cached_type); - cached_type = NULL; - goto done; -} - -/* CythonFunctionShared */ -#include -static PyObject * -__Pyx_CyFunction_get_doc(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *closure) -{ - if (unlikely(op->func_doc == NULL)) { - if (op->func.m_ml->ml_doc) { -#if PY_MAJOR_VERSION >= 3 - op->func_doc = PyUnicode_FromString(op->func.m_ml->ml_doc); -#else - op->func_doc = PyString_FromString(op->func.m_ml->ml_doc); -#endif - if (unlikely(op->func_doc == NULL)) - return NULL; - } else { - Py_INCREF(Py_None); - return Py_None; - } - } - Py_INCREF(op->func_doc); - return op->func_doc; -} -static int -__Pyx_CyFunction_set_doc(__pyx_CyFunctionObject *op, PyObject *value, CYTHON_UNUSED void *context) -{ - PyObject *tmp = op->func_doc; - if (value == NULL) { - value = Py_None; - } - Py_INCREF(value); - op->func_doc = value; - Py_XDECREF(tmp); - return 0; -} -static PyObject * -__Pyx_CyFunction_get_name(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) -{ - if (unlikely(op->func_name == NULL)) { -#if PY_MAJOR_VERSION >= 3 - op->func_name = PyUnicode_InternFromString(op->func.m_ml->ml_name); -#else - op->func_name = PyString_InternFromString(op->func.m_ml->ml_name); -#endif - if (unlikely(op->func_name == NULL)) - return NULL; - } - Py_INCREF(op->func_name); - return op->func_name; -} -static int -__Pyx_CyFunction_set_name(__pyx_CyFunctionObject *op, PyObject *value, CYTHON_UNUSED void *context) -{ - PyObject *tmp; -#if PY_MAJOR_VERSION >= 3 - if (unlikely(value == NULL || !PyUnicode_Check(value))) -#else - if (unlikely(value == NULL || !PyString_Check(value))) -#endif - { - PyErr_SetString(PyExc_TypeError, - "__name__ must be set to a string object"); - return -1; - } - tmp = op->func_name; - Py_INCREF(value); - op->func_name = value; - Py_XDECREF(tmp); - return 0; -} -static PyObject * -__Pyx_CyFunction_get_qualname(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) -{ - Py_INCREF(op->func_qualname); - return op->func_qualname; -} -static int -__Pyx_CyFunction_set_qualname(__pyx_CyFunctionObject *op, PyObject *value, CYTHON_UNUSED void *context) -{ - PyObject *tmp; -#if PY_MAJOR_VERSION >= 3 - if (unlikely(value == NULL || !PyUnicode_Check(value))) -#else - if (unlikely(value == NULL || !PyString_Check(value))) -#endif - { - PyErr_SetString(PyExc_TypeError, - "__qualname__ must be set to a string object"); - return -1; - } - tmp = op->func_qualname; - Py_INCREF(value); - op->func_qualname = value; - Py_XDECREF(tmp); - return 0; -} -static PyObject * -__Pyx_CyFunction_get_self(__pyx_CyFunctionObject *m, CYTHON_UNUSED void *closure) -{ - PyObject *self; - self = m->func_closure; - if (self == NULL) - self = Py_None; - Py_INCREF(self); - return self; -} -static PyObject * -__Pyx_CyFunction_get_dict(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) -{ - if (unlikely(op->func_dict == NULL)) { - op->func_dict = PyDict_New(); - if (unlikely(op->func_dict == NULL)) - return NULL; - } - Py_INCREF(op->func_dict); - return op->func_dict; -} -static int -__Pyx_CyFunction_set_dict(__pyx_CyFunctionObject *op, PyObject *value, CYTHON_UNUSED void *context) -{ - PyObject *tmp; - if (unlikely(value == NULL)) { - PyErr_SetString(PyExc_TypeError, - "function's dictionary may not be deleted"); - return -1; - } - if (unlikely(!PyDict_Check(value))) { - PyErr_SetString(PyExc_TypeError, - "setting function's dictionary to a non-dict"); - return -1; - } - tmp = op->func_dict; - Py_INCREF(value); - op->func_dict = value; - Py_XDECREF(tmp); - return 0; -} -static PyObject * -__Pyx_CyFunction_get_globals(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) -{ - Py_INCREF(op->func_globals); - return op->func_globals; -} -static PyObject * -__Pyx_CyFunction_get_closure(CYTHON_UNUSED __pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) -{ - Py_INCREF(Py_None); - return Py_None; -} -static PyObject * -__Pyx_CyFunction_get_code(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) -{ - PyObject* result = (op->func_code) ? op->func_code : Py_None; - Py_INCREF(result); - return result; -} -static int -__Pyx_CyFunction_init_defaults(__pyx_CyFunctionObject *op) { - int result = 0; - PyObject *res = op->defaults_getter((PyObject *) op); - if (unlikely(!res)) - return -1; - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - op->defaults_tuple = PyTuple_GET_ITEM(res, 0); - Py_INCREF(op->defaults_tuple); - op->defaults_kwdict = PyTuple_GET_ITEM(res, 1); - Py_INCREF(op->defaults_kwdict); - #else - op->defaults_tuple = PySequence_ITEM(res, 0); - if (unlikely(!op->defaults_tuple)) result = -1; - else { - op->defaults_kwdict = PySequence_ITEM(res, 1); - if (unlikely(!op->defaults_kwdict)) result = -1; - } - #endif - Py_DECREF(res); - return result; -} -static int -__Pyx_CyFunction_set_defaults(__pyx_CyFunctionObject *op, PyObject* value, CYTHON_UNUSED void *context) { - PyObject* tmp; - if (!value) { - value = Py_None; - } else if (value != Py_None && !PyTuple_Check(value)) { - PyErr_SetString(PyExc_TypeError, - "__defaults__ must be set to a tuple object"); - return -1; - } - Py_INCREF(value); - tmp = op->defaults_tuple; - op->defaults_tuple = value; - Py_XDECREF(tmp); - return 0; -} -static PyObject * -__Pyx_CyFunction_get_defaults(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) { - PyObject* result = op->defaults_tuple; - if (unlikely(!result)) { - if (op->defaults_getter) { - if (__Pyx_CyFunction_init_defaults(op) < 0) return NULL; - result = op->defaults_tuple; - } else { - result = Py_None; - } - } - Py_INCREF(result); - return result; -} -static int -__Pyx_CyFunction_set_kwdefaults(__pyx_CyFunctionObject *op, PyObject* value, CYTHON_UNUSED void *context) { - PyObject* tmp; - if (!value) { - value = Py_None; - } else if (value != Py_None && !PyDict_Check(value)) { - PyErr_SetString(PyExc_TypeError, - "__kwdefaults__ must be set to a dict object"); - return -1; - } - Py_INCREF(value); - tmp = op->defaults_kwdict; - op->defaults_kwdict = value; - Py_XDECREF(tmp); - return 0; -} -static PyObject * -__Pyx_CyFunction_get_kwdefaults(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) { - PyObject* result = op->defaults_kwdict; - if (unlikely(!result)) { - if (op->defaults_getter) { - if (__Pyx_CyFunction_init_defaults(op) < 0) return NULL; - result = op->defaults_kwdict; - } else { - result = Py_None; - } - } - Py_INCREF(result); - return result; -} -static int -__Pyx_CyFunction_set_annotations(__pyx_CyFunctionObject *op, PyObject* value, CYTHON_UNUSED void *context) { - PyObject* tmp; - if (!value || value == Py_None) { - value = NULL; - } else if (!PyDict_Check(value)) { - PyErr_SetString(PyExc_TypeError, - "__annotations__ must be set to a dict object"); - return -1; - } - Py_XINCREF(value); - tmp = op->func_annotations; - op->func_annotations = value; - Py_XDECREF(tmp); - return 0; -} -static PyObject * -__Pyx_CyFunction_get_annotations(__pyx_CyFunctionObject *op, CYTHON_UNUSED void *context) { - PyObject* result = op->func_annotations; - if (unlikely(!result)) { - result = PyDict_New(); - if (unlikely(!result)) return NULL; - op->func_annotations = result; - } - Py_INCREF(result); - return result; -} -static PyGetSetDef __pyx_CyFunction_getsets[] = { - {(char *) "func_doc", (getter)__Pyx_CyFunction_get_doc, (setter)__Pyx_CyFunction_set_doc, 0, 0}, - {(char *) "__doc__", (getter)__Pyx_CyFunction_get_doc, (setter)__Pyx_CyFunction_set_doc, 0, 0}, - {(char *) "func_name", (getter)__Pyx_CyFunction_get_name, (setter)__Pyx_CyFunction_set_name, 0, 0}, - {(char *) "__name__", (getter)__Pyx_CyFunction_get_name, (setter)__Pyx_CyFunction_set_name, 0, 0}, - {(char *) "__qualname__", (getter)__Pyx_CyFunction_get_qualname, (setter)__Pyx_CyFunction_set_qualname, 0, 0}, - {(char *) "__self__", (getter)__Pyx_CyFunction_get_self, 0, 0, 0}, - {(char *) "func_dict", (getter)__Pyx_CyFunction_get_dict, (setter)__Pyx_CyFunction_set_dict, 0, 0}, - {(char *) "__dict__", (getter)__Pyx_CyFunction_get_dict, (setter)__Pyx_CyFunction_set_dict, 0, 0}, - {(char *) "func_globals", (getter)__Pyx_CyFunction_get_globals, 0, 0, 0}, - {(char *) "__globals__", (getter)__Pyx_CyFunction_get_globals, 0, 0, 0}, - {(char *) "func_closure", (getter)__Pyx_CyFunction_get_closure, 0, 0, 0}, - {(char *) "__closure__", (getter)__Pyx_CyFunction_get_closure, 0, 0, 0}, - {(char *) "func_code", (getter)__Pyx_CyFunction_get_code, 0, 0, 0}, - {(char *) "__code__", (getter)__Pyx_CyFunction_get_code, 0, 0, 0}, - {(char *) "func_defaults", (getter)__Pyx_CyFunction_get_defaults, (setter)__Pyx_CyFunction_set_defaults, 0, 0}, - {(char *) "__defaults__", (getter)__Pyx_CyFunction_get_defaults, (setter)__Pyx_CyFunction_set_defaults, 0, 0}, - {(char *) "__kwdefaults__", (getter)__Pyx_CyFunction_get_kwdefaults, (setter)__Pyx_CyFunction_set_kwdefaults, 0, 0}, - {(char *) "__annotations__", (getter)__Pyx_CyFunction_get_annotations, (setter)__Pyx_CyFunction_set_annotations, 0, 0}, - {0, 0, 0, 0, 0} -}; -static PyMemberDef __pyx_CyFunction_members[] = { - {(char *) "__module__", T_OBJECT, offsetof(PyCFunctionObject, m_module), PY_WRITE_RESTRICTED, 0}, - {0, 0, 0, 0, 0} -}; -static PyObject * -__Pyx_CyFunction_reduce(__pyx_CyFunctionObject *m, CYTHON_UNUSED PyObject *args) -{ -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromString(m->func.m_ml->ml_name); -#else - return PyString_FromString(m->func.m_ml->ml_name); -#endif -} -static PyMethodDef __pyx_CyFunction_methods[] = { - {"__reduce__", (PyCFunction)__Pyx_CyFunction_reduce, METH_VARARGS, 0}, - {0, 0, 0, 0} -}; -#if PY_VERSION_HEX < 0x030500A0 -#define __Pyx_CyFunction_weakreflist(cyfunc) ((cyfunc)->func_weakreflist) -#else -#define __Pyx_CyFunction_weakreflist(cyfunc) ((cyfunc)->func.m_weakreflist) -#endif -static PyObject *__Pyx_CyFunction_Init(__pyx_CyFunctionObject *op, PyMethodDef *ml, int flags, PyObject* qualname, - PyObject *closure, PyObject *module, PyObject* globals, PyObject* code) { - if (unlikely(op == NULL)) - return NULL; - op->flags = flags; - __Pyx_CyFunction_weakreflist(op) = NULL; - op->func.m_ml = ml; - op->func.m_self = (PyObject *) op; - Py_XINCREF(closure); - op->func_closure = closure; - Py_XINCREF(module); - op->func.m_module = module; - op->func_dict = NULL; - op->func_name = NULL; - Py_INCREF(qualname); - op->func_qualname = qualname; - op->func_doc = NULL; - op->func_classobj = NULL; - op->func_globals = globals; - Py_INCREF(op->func_globals); - Py_XINCREF(code); - op->func_code = code; - op->defaults_pyobjects = 0; - op->defaults_size = 0; - op->defaults = NULL; - op->defaults_tuple = NULL; - op->defaults_kwdict = NULL; - op->defaults_getter = NULL; - op->func_annotations = NULL; - return (PyObject *) op; -} -static int -__Pyx_CyFunction_clear(__pyx_CyFunctionObject *m) -{ - Py_CLEAR(m->func_closure); - Py_CLEAR(m->func.m_module); - Py_CLEAR(m->func_dict); - Py_CLEAR(m->func_name); - Py_CLEAR(m->func_qualname); - Py_CLEAR(m->func_doc); - Py_CLEAR(m->func_globals); - Py_CLEAR(m->func_code); - Py_CLEAR(m->func_classobj); - Py_CLEAR(m->defaults_tuple); - Py_CLEAR(m->defaults_kwdict); - Py_CLEAR(m->func_annotations); - if (m->defaults) { - PyObject **pydefaults = __Pyx_CyFunction_Defaults(PyObject *, m); - int i; - for (i = 0; i < m->defaults_pyobjects; i++) - Py_XDECREF(pydefaults[i]); - PyObject_Free(m->defaults); - m->defaults = NULL; - } - return 0; -} -static void __Pyx__CyFunction_dealloc(__pyx_CyFunctionObject *m) -{ - if (__Pyx_CyFunction_weakreflist(m) != NULL) - PyObject_ClearWeakRefs((PyObject *) m); - __Pyx_CyFunction_clear(m); - PyObject_GC_Del(m); -} -static void __Pyx_CyFunction_dealloc(__pyx_CyFunctionObject *m) -{ - PyObject_GC_UnTrack(m); - __Pyx__CyFunction_dealloc(m); -} -static int __Pyx_CyFunction_traverse(__pyx_CyFunctionObject *m, visitproc visit, void *arg) -{ - Py_VISIT(m->func_closure); - Py_VISIT(m->func.m_module); - Py_VISIT(m->func_dict); - Py_VISIT(m->func_name); - Py_VISIT(m->func_qualname); - Py_VISIT(m->func_doc); - Py_VISIT(m->func_globals); - Py_VISIT(m->func_code); - Py_VISIT(m->func_classobj); - Py_VISIT(m->defaults_tuple); - Py_VISIT(m->defaults_kwdict); - if (m->defaults) { - PyObject **pydefaults = __Pyx_CyFunction_Defaults(PyObject *, m); - int i; - for (i = 0; i < m->defaults_pyobjects; i++) - Py_VISIT(pydefaults[i]); - } - return 0; -} -static PyObject *__Pyx_CyFunction_descr_get(PyObject *func, PyObject *obj, PyObject *type) -{ - __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func; - if (m->flags & __Pyx_CYFUNCTION_STATICMETHOD) { - Py_INCREF(func); - return func; - } - if (m->flags & __Pyx_CYFUNCTION_CLASSMETHOD) { - if (type == NULL) - type = (PyObject *)(Py_TYPE(obj)); - return __Pyx_PyMethod_New(func, type, (PyObject *)(Py_TYPE(type))); - } - if (obj == Py_None) - obj = NULL; - return __Pyx_PyMethod_New(func, obj, type); -} -static PyObject* -__Pyx_CyFunction_repr(__pyx_CyFunctionObject *op) -{ -#if PY_MAJOR_VERSION >= 3 - return PyUnicode_FromFormat("", - op->func_qualname, (void *)op); -#else - return PyString_FromFormat("", - PyString_AsString(op->func_qualname), (void *)op); -#endif -} -static PyObject * __Pyx_CyFunction_CallMethod(PyObject *func, PyObject *self, PyObject *arg, PyObject *kw) { - PyCFunctionObject* f = (PyCFunctionObject*)func; - PyCFunction meth = f->m_ml->ml_meth; - Py_ssize_t size; - switch (f->m_ml->ml_flags & (METH_VARARGS | METH_KEYWORDS | METH_NOARGS | METH_O)) { - case METH_VARARGS: - if (likely(kw == NULL || PyDict_Size(kw) == 0)) - return (*meth)(self, arg); - break; - case METH_VARARGS | METH_KEYWORDS: - return (*(PyCFunctionWithKeywords)(void*)meth)(self, arg, kw); - case METH_NOARGS: - if (likely(kw == NULL || PyDict_Size(kw) == 0)) { - size = PyTuple_GET_SIZE(arg); - if (likely(size == 0)) - return (*meth)(self, NULL); - PyErr_Format(PyExc_TypeError, - "%.200s() takes no arguments (%" CYTHON_FORMAT_SSIZE_T "d given)", - f->m_ml->ml_name, size); - return NULL; - } - break; - case METH_O: - if (likely(kw == NULL || PyDict_Size(kw) == 0)) { - size = PyTuple_GET_SIZE(arg); - if (likely(size == 1)) { - PyObject *result, *arg0; - #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS - arg0 = PyTuple_GET_ITEM(arg, 0); - #else - arg0 = PySequence_ITEM(arg, 0); if (unlikely(!arg0)) return NULL; - #endif - result = (*meth)(self, arg0); - #if !(CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS) - Py_DECREF(arg0); - #endif - return result; - } - PyErr_Format(PyExc_TypeError, - "%.200s() takes exactly one argument (%" CYTHON_FORMAT_SSIZE_T "d given)", - f->m_ml->ml_name, size); - return NULL; - } - break; - default: - PyErr_SetString(PyExc_SystemError, "Bad call flags in " - "__Pyx_CyFunction_Call. METH_OLDARGS is no " - "longer supported!"); - return NULL; - } - PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", - f->m_ml->ml_name); - return NULL; -} -static CYTHON_INLINE PyObject *__Pyx_CyFunction_Call(PyObject *func, PyObject *arg, PyObject *kw) { - return __Pyx_CyFunction_CallMethod(func, ((PyCFunctionObject*)func)->m_self, arg, kw); -} -static PyObject *__Pyx_CyFunction_CallAsMethod(PyObject *func, PyObject *args, PyObject *kw) { - PyObject *result; - __pyx_CyFunctionObject *cyfunc = (__pyx_CyFunctionObject *) func; - if ((cyfunc->flags & __Pyx_CYFUNCTION_CCLASS) && !(cyfunc->flags & __Pyx_CYFUNCTION_STATICMETHOD)) { - Py_ssize_t argc; - PyObject *new_args; - PyObject *self; - argc = PyTuple_GET_SIZE(args); - new_args = PyTuple_GetSlice(args, 1, argc); - if (unlikely(!new_args)) - return NULL; - self = PyTuple_GetItem(args, 0); - if (unlikely(!self)) { - Py_DECREF(new_args); - return NULL; - } - result = __Pyx_CyFunction_CallMethod(func, self, new_args, kw); - Py_DECREF(new_args); - } else { - result = __Pyx_CyFunction_Call(func, args, kw); - } - return result; -} -static PyTypeObject __pyx_CyFunctionType_type = { - PyVarObject_HEAD_INIT(0, 0) - "cython_function_or_method", - sizeof(__pyx_CyFunctionObject), - 0, - (destructor) __Pyx_CyFunction_dealloc, - 0, - 0, - 0, -#if PY_MAJOR_VERSION < 3 - 0, -#else - 0, -#endif - (reprfunc) __Pyx_CyFunction_repr, - 0, - 0, - 0, - 0, - __Pyx_CyFunction_CallAsMethod, - 0, - 0, - 0, - 0, - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, - 0, - (traverseproc) __Pyx_CyFunction_traverse, - (inquiry) __Pyx_CyFunction_clear, - 0, -#if PY_VERSION_HEX < 0x030500A0 - offsetof(__pyx_CyFunctionObject, func_weakreflist), -#else - offsetof(PyCFunctionObject, m_weakreflist), -#endif - 0, - 0, - __pyx_CyFunction_methods, - __pyx_CyFunction_members, - __pyx_CyFunction_getsets, - 0, - 0, - __Pyx_CyFunction_descr_get, - 0, - offsetof(__pyx_CyFunctionObject, func_dict), - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, -#if PY_VERSION_HEX >= 0x030400a1 - 0, -#endif -#if PY_VERSION_HEX >= 0x030800b1 - 0, -#endif -#if PY_VERSION_HEX >= 0x030800b4 && PY_VERSION_HEX < 0x03090000 - 0, -#endif -}; -static int __pyx_CyFunction_init(void) { - __pyx_CyFunctionType = __Pyx_FetchCommonType(&__pyx_CyFunctionType_type); - if (unlikely(__pyx_CyFunctionType == NULL)) { - return -1; - } - return 0; -} -static CYTHON_INLINE void *__Pyx_CyFunction_InitDefaults(PyObject *func, size_t size, int pyobjects) { - __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func; - m->defaults = PyObject_Malloc(size); - if (unlikely(!m->defaults)) - return PyErr_NoMemory(); - memset(m->defaults, 0, size); - m->defaults_pyobjects = pyobjects; - m->defaults_size = size; - return m->defaults; -} -static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsTuple(PyObject *func, PyObject *tuple) { - __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func; - m->defaults_tuple = tuple; - Py_INCREF(tuple); -} -static CYTHON_INLINE void __Pyx_CyFunction_SetDefaultsKwDict(PyObject *func, PyObject *dict) { - __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func; - m->defaults_kwdict = dict; - Py_INCREF(dict); -} -static CYTHON_INLINE void __Pyx_CyFunction_SetAnnotationsDict(PyObject *func, PyObject *dict) { - __pyx_CyFunctionObject *m = (__pyx_CyFunctionObject *) func; - m->func_annotations = dict; - Py_INCREF(dict); -} - -/* CythonFunction */ -static PyObject *__Pyx_CyFunction_New(PyMethodDef *ml, int flags, PyObject* qualname, - PyObject *closure, PyObject *module, PyObject* globals, PyObject* code) { - PyObject *op = __Pyx_CyFunction_Init( - PyObject_GC_New(__pyx_CyFunctionObject, __pyx_CyFunctionType), - ml, flags, qualname, closure, module, globals, code - ); - if (likely(op)) { - PyObject_GC_Track(op); - } - return op; -} - -/* CalculateMetaclass */ -static PyObject *__Pyx_CalculateMetaclass(PyTypeObject *metaclass, PyObject *bases) { - Py_ssize_t i, nbases = PyTuple_GET_SIZE(bases); - for (i=0; i < nbases; i++) { - PyTypeObject *tmptype; - PyObject *tmp = PyTuple_GET_ITEM(bases, i); - tmptype = Py_TYPE(tmp); -#if PY_MAJOR_VERSION < 3 - if (tmptype == &PyClass_Type) - continue; -#endif - if (!metaclass) { - metaclass = tmptype; - continue; - } - if (PyType_IsSubtype(metaclass, tmptype)) - continue; - if (PyType_IsSubtype(tmptype, metaclass)) { - metaclass = tmptype; - continue; - } - PyErr_SetString(PyExc_TypeError, - "metaclass conflict: " - "the metaclass of a derived class " - "must be a (non-strict) subclass " - "of the metaclasses of all its bases"); - return NULL; - } - if (!metaclass) { -#if PY_MAJOR_VERSION < 3 - metaclass = &PyClass_Type; -#else - metaclass = &PyType_Type; -#endif - } - Py_INCREF((PyObject*) metaclass); - return (PyObject*) metaclass; -} - -/* Py3ClassCreate */ -static PyObject *__Pyx_Py3MetaclassPrepare(PyObject *metaclass, PyObject *bases, PyObject *name, - PyObject *qualname, PyObject *mkw, PyObject *modname, PyObject *doc) { - PyObject *ns; - if (metaclass) { - PyObject *prep = __Pyx_PyObject_GetAttrStr(metaclass, __pyx_n_s_prepare); - if (prep) { - PyObject *pargs = PyTuple_Pack(2, name, bases); - if (unlikely(!pargs)) { - Py_DECREF(prep); - return NULL; - } - ns = PyObject_Call(prep, pargs, mkw); - Py_DECREF(prep); - Py_DECREF(pargs); - } else { - if (unlikely(!PyErr_ExceptionMatches(PyExc_AttributeError))) - return NULL; - PyErr_Clear(); - ns = PyDict_New(); - } - } else { - ns = PyDict_New(); - } - if (unlikely(!ns)) - return NULL; - if (unlikely(PyObject_SetItem(ns, __pyx_n_s_module, modname) < 0)) goto bad; - if (unlikely(PyObject_SetItem(ns, __pyx_n_s_qualname, qualname) < 0)) goto bad; - if (unlikely(doc && PyObject_SetItem(ns, __pyx_n_s_doc, doc) < 0)) goto bad; - return ns; -bad: - Py_DECREF(ns); - return NULL; -} -static PyObject *__Pyx_Py3ClassCreate(PyObject *metaclass, PyObject *name, PyObject *bases, - PyObject *dict, PyObject *mkw, - int calculate_metaclass, int allow_py2_metaclass) { - PyObject *result, *margs; - PyObject *owned_metaclass = NULL; - if (allow_py2_metaclass) { - owned_metaclass = PyObject_GetItem(dict, __pyx_n_s_metaclass); - if (owned_metaclass) { - metaclass = owned_metaclass; - } else if (likely(PyErr_ExceptionMatches(PyExc_KeyError))) { - PyErr_Clear(); - } else { - return NULL; - } - } - if (calculate_metaclass && (!metaclass || PyType_Check(metaclass))) { - metaclass = __Pyx_CalculateMetaclass((PyTypeObject*) metaclass, bases); - Py_XDECREF(owned_metaclass); - if (unlikely(!metaclass)) - return NULL; - owned_metaclass = metaclass; - } - margs = PyTuple_Pack(3, name, bases, dict); - if (unlikely(!margs)) { - result = NULL; - } else { - result = PyObject_Call(metaclass, margs, mkw); - Py_DECREF(margs); - } - Py_XDECREF(owned_metaclass); - return result; -} - -/* CLineInTraceback */ -#ifndef CYTHON_CLINE_IN_TRACEBACK -static int __Pyx_CLineForTraceback(CYTHON_NCP_UNUSED PyThreadState *tstate, int c_line) { - PyObject *use_cline; - PyObject *ptype, *pvalue, *ptraceback; -#if CYTHON_COMPILING_IN_CPYTHON - PyObject **cython_runtime_dict; -#endif - if (unlikely(!__pyx_cython_runtime)) { - return c_line; - } - __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); -#if CYTHON_COMPILING_IN_CPYTHON - cython_runtime_dict = _PyObject_GetDictPtr(__pyx_cython_runtime); - if (likely(cython_runtime_dict)) { - __PYX_PY_DICT_LOOKUP_IF_MODIFIED( - use_cline, *cython_runtime_dict, - __Pyx_PyDict_GetItemStr(*cython_runtime_dict, __pyx_n_s_cline_in_traceback)) - } else -#endif - { - PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback); - if (use_cline_obj) { - use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True; - Py_DECREF(use_cline_obj); - } else { - PyErr_Clear(); - use_cline = NULL; - } - } - if (!use_cline) { - c_line = 0; - PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); - } - else if (use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { - c_line = 0; - } - __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); - return c_line; -} -#endif - -/* CodeObjectCache */ -static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) { - int start = 0, mid = 0, end = count - 1; - if (end >= 0 && code_line > entries[end].code_line) { - return count; - } - while (start < end) { - mid = start + (end - start) / 2; - if (code_line < entries[mid].code_line) { - end = mid; - } else if (code_line > entries[mid].code_line) { - start = mid + 1; - } else { - return mid; - } - } - if (code_line <= entries[mid].code_line) { - return mid; - } else { - return mid + 1; - } -} -static PyCodeObject *__pyx_find_code_object(int code_line) { - PyCodeObject* code_object; - int pos; - if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) { - return NULL; - } - pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); - if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) { - return NULL; - } - code_object = __pyx_code_cache.entries[pos].code_object; - Py_INCREF(code_object); - return code_object; -} -static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) { - int pos, i; - __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries; - if (unlikely(!code_line)) { - return; - } - if (unlikely(!entries)) { - entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry)); - if (likely(entries)) { - __pyx_code_cache.entries = entries; - __pyx_code_cache.max_count = 64; - __pyx_code_cache.count = 1; - entries[0].code_line = code_line; - entries[0].code_object = code_object; - Py_INCREF(code_object); - } - return; - } - pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); - if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) { - PyCodeObject* tmp = entries[pos].code_object; - entries[pos].code_object = code_object; - Py_DECREF(tmp); - return; - } - if (__pyx_code_cache.count == __pyx_code_cache.max_count) { - int new_max = __pyx_code_cache.max_count + 64; - entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc( - __pyx_code_cache.entries, ((size_t)new_max) * sizeof(__Pyx_CodeObjectCacheEntry)); - if (unlikely(!entries)) { - return; - } - __pyx_code_cache.entries = entries; - __pyx_code_cache.max_count = new_max; - } - for (i=__pyx_code_cache.count; i>pos; i--) { - entries[i] = entries[i-1]; - } - entries[pos].code_line = code_line; - entries[pos].code_object = code_object; - __pyx_code_cache.count++; - Py_INCREF(code_object); -} - -/* AddTraceback */ -#include "compile.h" -#include "frameobject.h" -#include "traceback.h" -static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( - const char *funcname, int c_line, - int py_line, const char *filename) { - PyCodeObject *py_code = 0; - PyObject *py_srcfile = 0; - PyObject *py_funcname = 0; - #if PY_MAJOR_VERSION < 3 - py_srcfile = PyString_FromString(filename); - #else - py_srcfile = PyUnicode_FromString(filename); - #endif - if (!py_srcfile) goto bad; - if (c_line) { - #if PY_MAJOR_VERSION < 3 - py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); - #else - py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); - #endif - } - else { - #if PY_MAJOR_VERSION < 3 - py_funcname = PyString_FromString(funcname); - #else - py_funcname = PyUnicode_FromString(funcname); - #endif - } - if (!py_funcname) goto bad; - py_code = __Pyx_PyCode_New( - 0, - 0, - 0, - 0, - 0, - __pyx_empty_bytes, /*PyObject *code,*/ - __pyx_empty_tuple, /*PyObject *consts,*/ - __pyx_empty_tuple, /*PyObject *names,*/ - __pyx_empty_tuple, /*PyObject *varnames,*/ - __pyx_empty_tuple, /*PyObject *freevars,*/ - __pyx_empty_tuple, /*PyObject *cellvars,*/ - py_srcfile, /*PyObject *filename,*/ - py_funcname, /*PyObject *name,*/ - py_line, - __pyx_empty_bytes /*PyObject *lnotab*/ - ); - Py_DECREF(py_srcfile); - Py_DECREF(py_funcname); - return py_code; -bad: - Py_XDECREF(py_srcfile); - Py_XDECREF(py_funcname); - return NULL; -} -static void __Pyx_AddTraceback(const char *funcname, int c_line, - int py_line, const char *filename) { - PyCodeObject *py_code = 0; - PyFrameObject *py_frame = 0; - PyThreadState *tstate = __Pyx_PyThreadState_Current; - if (c_line) { - c_line = __Pyx_CLineForTraceback(tstate, c_line); - } - py_code = __pyx_find_code_object(c_line ? -c_line : py_line); - if (!py_code) { - py_code = __Pyx_CreateCodeObjectForTraceback( - funcname, c_line, py_line, filename); - if (!py_code) goto bad; - __pyx_insert_code_object(c_line ? -c_line : py_line, py_code); - } - py_frame = PyFrame_New( - tstate, /*PyThreadState *tstate,*/ - py_code, /*PyCodeObject *code,*/ - __pyx_d, /*PyObject *globals,*/ - 0 /*PyObject *locals*/ - ); - if (!py_frame) goto bad; - __Pyx_PyFrame_SetLineNumber(py_frame, py_line); - PyTraceBack_Here(py_frame); -bad: - Py_XDECREF(py_code); - Py_XDECREF(py_frame); -} - -/* CIntToPy */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { - const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; - const int is_unsigned = neg_one > const_zero; - if (is_unsigned) { - if (sizeof(long) < sizeof(long)) { - return PyInt_FromLong((long) value); - } else if (sizeof(long) <= sizeof(unsigned long)) { - return PyLong_FromUnsignedLong((unsigned long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { - return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); -#endif - } - } else { - if (sizeof(long) <= sizeof(long)) { - return PyInt_FromLong((long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { - return PyLong_FromLongLong((PY_LONG_LONG) value); -#endif - } - } - { - int one = 1; int little = (int)*(unsigned char *)&one; - unsigned char *bytes = (unsigned char *)&value; - return _PyLong_FromByteArray(bytes, sizeof(long), - little, !is_unsigned); - } -} - -/* CIntFromPyVerify */ -#define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\ - __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0) -#define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)\ - __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1) -#define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc)\ - {\ - func_type value = func_value;\ - if (sizeof(target_type) < sizeof(func_type)) {\ - if (unlikely(value != (func_type) (target_type) value)) {\ - func_type zero = 0;\ - if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred()))\ - return (target_type) -1;\ - if (is_unsigned && unlikely(value < zero))\ - goto raise_neg_overflow;\ - else\ - goto raise_overflow;\ - }\ - }\ - return (target_type) value;\ - } - -/* CIntToPy */ -static CYTHON_INLINE PyObject* __Pyx_PyInt_From_int(int value) { - const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; - const int is_unsigned = neg_one > const_zero; - if (is_unsigned) { - if (sizeof(int) < sizeof(long)) { - return PyInt_FromLong((long) value); - } else if (sizeof(int) <= sizeof(unsigned long)) { - return PyLong_FromUnsignedLong((unsigned long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { - return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); -#endif - } - } else { - if (sizeof(int) <= sizeof(long)) { - return PyInt_FromLong((long) value); -#ifdef HAVE_LONG_LONG - } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { - return PyLong_FromLongLong((PY_LONG_LONG) value); -#endif - } - } - { - int one = 1; int little = (int)*(unsigned char *)&one; - unsigned char *bytes = (unsigned char *)&value; - return _PyLong_FromByteArray(bytes, sizeof(int), - little, !is_unsigned); - } -} - -/* CIntFromPy */ -static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { - const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; - const int is_unsigned = neg_one > const_zero; -#if PY_MAJOR_VERSION < 3 - if (likely(PyInt_Check(x))) { - if (sizeof(int) < sizeof(long)) { - __PYX_VERIFY_RETURN_INT(int, long, PyInt_AS_LONG(x)) - } else { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - goto raise_neg_overflow; - } - return (int) val; - } - } else -#endif - if (likely(PyLong_Check(x))) { - if (is_unsigned) { -#if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)x)->ob_digit; - switch (Py_SIZE(x)) { - case 0: return (int) 0; - case 1: __PYX_VERIFY_RETURN_INT(int, digit, digits[0]) - case 2: - if (8 * sizeof(int) > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) >= 2 * PyLong_SHIFT) { - return (int) (((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); - } - } - break; - case 3: - if (8 * sizeof(int) > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) >= 3 * PyLong_SHIFT) { - return (int) (((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); - } - } - break; - case 4: - if (8 * sizeof(int) > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) >= 4 * PyLong_SHIFT) { - return (int) (((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); - } - } - break; - } -#endif -#if CYTHON_COMPILING_IN_CPYTHON - if (unlikely(Py_SIZE(x) < 0)) { - goto raise_neg_overflow; - } -#else - { - int result = PyObject_RichCompareBool(x, Py_False, Py_LT); - if (unlikely(result < 0)) - return (int) -1; - if (unlikely(result == 1)) - goto raise_neg_overflow; - } -#endif - if (sizeof(int) <= sizeof(unsigned long)) { - __PYX_VERIFY_RETURN_INT_EXC(int, unsigned long, PyLong_AsUnsignedLong(x)) -#ifdef HAVE_LONG_LONG - } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { - __PYX_VERIFY_RETURN_INT_EXC(int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) -#endif - } - } else { -#if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)x)->ob_digit; - switch (Py_SIZE(x)) { - case 0: return (int) 0; - case -1: __PYX_VERIFY_RETURN_INT(int, sdigit, (sdigit) (-(sdigit)digits[0])) - case 1: __PYX_VERIFY_RETURN_INT(int, digit, +digits[0]) - case -2: - if (8 * sizeof(int) - 1 > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { - return (int) (((int)-1)*(((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); - } - } - break; - case 2: - if (8 * sizeof(int) > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { - return (int) ((((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); - } - } - break; - case -3: - if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { - return (int) (((int)-1)*(((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); - } - } - break; - case 3: - if (8 * sizeof(int) > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { - return (int) ((((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); - } - } - break; - case -4: - if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { - return (int) (((int)-1)*(((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); - } - } - break; - case 4: - if (8 * sizeof(int) > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { - return (int) ((((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); - } - } - break; - } -#endif - if (sizeof(int) <= sizeof(long)) { - __PYX_VERIFY_RETURN_INT_EXC(int, long, PyLong_AsLong(x)) -#ifdef HAVE_LONG_LONG - } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { - __PYX_VERIFY_RETURN_INT_EXC(int, PY_LONG_LONG, PyLong_AsLongLong(x)) -#endif - } - } - { -#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) - PyErr_SetString(PyExc_RuntimeError, - "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); -#else - int val; - PyObject *v = __Pyx_PyNumber_IntOrLong(x); - #if PY_MAJOR_VERSION < 3 - if (likely(v) && !PyLong_Check(v)) { - PyObject *tmp = v; - v = PyNumber_Long(tmp); - Py_DECREF(tmp); - } - #endif - if (likely(v)) { - int one = 1; int is_little = (int)*(unsigned char *)&one; - unsigned char *bytes = (unsigned char *)&val; - int ret = _PyLong_AsByteArray((PyLongObject *)v, - bytes, sizeof(val), - is_little, !is_unsigned); - Py_DECREF(v); - if (likely(!ret)) - return val; - } -#endif - return (int) -1; - } - } else { - int val; - PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); - if (!tmp) return (int) -1; - val = __Pyx_PyInt_As_int(tmp); - Py_DECREF(tmp); - return val; - } -raise_overflow: - PyErr_SetString(PyExc_OverflowError, - "value too large to convert to int"); - return (int) -1; -raise_neg_overflow: - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to int"); - return (int) -1; -} - -/* CIntFromPy */ -static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { - const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; - const int is_unsigned = neg_one > const_zero; -#if PY_MAJOR_VERSION < 3 - if (likely(PyInt_Check(x))) { - if (sizeof(long) < sizeof(long)) { - __PYX_VERIFY_RETURN_INT(long, long, PyInt_AS_LONG(x)) - } else { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - goto raise_neg_overflow; - } - return (long) val; - } - } else -#endif - if (likely(PyLong_Check(x))) { - if (is_unsigned) { -#if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)x)->ob_digit; - switch (Py_SIZE(x)) { - case 0: return (long) 0; - case 1: __PYX_VERIFY_RETURN_INT(long, digit, digits[0]) - case 2: - if (8 * sizeof(long) > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) >= 2 * PyLong_SHIFT) { - return (long) (((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); - } - } - break; - case 3: - if (8 * sizeof(long) > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) >= 3 * PyLong_SHIFT) { - return (long) (((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); - } - } - break; - case 4: - if (8 * sizeof(long) > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) >= 4 * PyLong_SHIFT) { - return (long) (((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); - } - } - break; - } -#endif -#if CYTHON_COMPILING_IN_CPYTHON - if (unlikely(Py_SIZE(x) < 0)) { - goto raise_neg_overflow; - } -#else - { - int result = PyObject_RichCompareBool(x, Py_False, Py_LT); - if (unlikely(result < 0)) - return (long) -1; - if (unlikely(result == 1)) - goto raise_neg_overflow; - } -#endif - if (sizeof(long) <= sizeof(unsigned long)) { - __PYX_VERIFY_RETURN_INT_EXC(long, unsigned long, PyLong_AsUnsignedLong(x)) -#ifdef HAVE_LONG_LONG - } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { - __PYX_VERIFY_RETURN_INT_EXC(long, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) -#endif - } - } else { -#if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)x)->ob_digit; - switch (Py_SIZE(x)) { - case 0: return (long) 0; - case -1: __PYX_VERIFY_RETURN_INT(long, sdigit, (sdigit) (-(sdigit)digits[0])) - case 1: __PYX_VERIFY_RETURN_INT(long, digit, +digits[0]) - case -2: - if (8 * sizeof(long) - 1 > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { - return (long) (((long)-1)*(((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); - } - } - break; - case 2: - if (8 * sizeof(long) > 1 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { - return (long) ((((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); - } - } - break; - case -3: - if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { - return (long) (((long)-1)*(((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); - } - } - break; - case 3: - if (8 * sizeof(long) > 2 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { - return (long) ((((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); - } - } - break; - case -4: - if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { - return (long) (((long)-1)*(((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); - } - } - break; - case 4: - if (8 * sizeof(long) > 3 * PyLong_SHIFT) { - if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { - __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) - } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { - return (long) ((((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); - } - } - break; - } -#endif - if (sizeof(long) <= sizeof(long)) { - __PYX_VERIFY_RETURN_INT_EXC(long, long, PyLong_AsLong(x)) -#ifdef HAVE_LONG_LONG - } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { - __PYX_VERIFY_RETURN_INT_EXC(long, PY_LONG_LONG, PyLong_AsLongLong(x)) -#endif - } - } - { -#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) - PyErr_SetString(PyExc_RuntimeError, - "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); -#else - long val; - PyObject *v = __Pyx_PyNumber_IntOrLong(x); - #if PY_MAJOR_VERSION < 3 - if (likely(v) && !PyLong_Check(v)) { - PyObject *tmp = v; - v = PyNumber_Long(tmp); - Py_DECREF(tmp); - } - #endif - if (likely(v)) { - int one = 1; int is_little = (int)*(unsigned char *)&one; - unsigned char *bytes = (unsigned char *)&val; - int ret = _PyLong_AsByteArray((PyLongObject *)v, - bytes, sizeof(val), - is_little, !is_unsigned); - Py_DECREF(v); - if (likely(!ret)) - return val; - } -#endif - return (long) -1; - } - } else { - long val; - PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); - if (!tmp) return (long) -1; - val = __Pyx_PyInt_As_long(tmp); - Py_DECREF(tmp); - return val; - } -raise_overflow: - PyErr_SetString(PyExc_OverflowError, - "value too large to convert to long"); - return (long) -1; -raise_neg_overflow: - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to long"); - return (long) -1; -} - -/* FastTypeChecks */ -#if CYTHON_COMPILING_IN_CPYTHON -static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) { - while (a) { - a = a->tp_base; - if (a == b) - return 1; - } - return b == &PyBaseObject_Type; -} -static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) { - PyObject *mro; - if (a == b) return 1; - mro = a->tp_mro; - if (likely(mro)) { - Py_ssize_t i, n; - n = PyTuple_GET_SIZE(mro); - for (i = 0; i < n; i++) { - if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b) - return 1; - } - return 0; - } - return __Pyx_InBases(a, b); -} -#if PY_MAJOR_VERSION == 2 -static int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject* exc_type2) { - PyObject *exception, *value, *tb; - int res; - __Pyx_PyThreadState_declare - __Pyx_PyThreadState_assign - __Pyx_ErrFetch(&exception, &value, &tb); - res = exc_type1 ? PyObject_IsSubclass(err, exc_type1) : 0; - if (unlikely(res == -1)) { - PyErr_WriteUnraisable(err); - res = 0; - } - if (!res) { - res = PyObject_IsSubclass(err, exc_type2); - if (unlikely(res == -1)) { - PyErr_WriteUnraisable(err); - res = 0; - } - } - __Pyx_ErrRestore(exception, value, tb); - return res; -} -#else -static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject *exc_type2) { - int res = exc_type1 ? __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type1) : 0; - if (!res) { - res = __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2); - } - return res; -} -#endif -static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { - Py_ssize_t i, n; - assert(PyExceptionClass_Check(exc_type)); - n = PyTuple_GET_SIZE(tuple); -#if PY_MAJOR_VERSION >= 3 - for (i=0; ip) { - #if PY_MAJOR_VERSION < 3 - if (t->is_unicode) { - *t->p = PyUnicode_DecodeUTF8(t->s, t->n - 1, NULL); - } else if (t->intern) { - *t->p = PyString_InternFromString(t->s); - } else { - *t->p = PyString_FromStringAndSize(t->s, t->n - 1); - } - #else - if (t->is_unicode | t->is_str) { - if (t->intern) { - *t->p = PyUnicode_InternFromString(t->s); - } else if (t->encoding) { - *t->p = PyUnicode_Decode(t->s, t->n - 1, t->encoding, NULL); - } else { - *t->p = PyUnicode_FromStringAndSize(t->s, t->n - 1); - } - } else { - *t->p = PyBytes_FromStringAndSize(t->s, t->n - 1); - } - #endif - if (!*t->p) - return -1; - if (PyObject_Hash(*t->p) == -1) - return -1; - ++t; - } - return 0; -} - -static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) { - return __Pyx_PyUnicode_FromStringAndSize(c_str, (Py_ssize_t)strlen(c_str)); -} -static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject* o) { - Py_ssize_t ignore; - return __Pyx_PyObject_AsStringAndSize(o, &ignore); -} -#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT -#if !CYTHON_PEP393_ENABLED -static const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { - char* defenc_c; - PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL); - if (!defenc) return NULL; - defenc_c = PyBytes_AS_STRING(defenc); -#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII - { - char* end = defenc_c + PyBytes_GET_SIZE(defenc); - char* c; - for (c = defenc_c; c < end; c++) { - if ((unsigned char) (*c) >= 128) { - PyUnicode_AsASCIIString(o); - return NULL; - } - } - } -#endif - *length = PyBytes_GET_SIZE(defenc); - return defenc_c; -} -#else -static CYTHON_INLINE const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { - if (unlikely(__Pyx_PyUnicode_READY(o) == -1)) return NULL; -#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII - if (likely(PyUnicode_IS_ASCII(o))) { - *length = PyUnicode_GET_LENGTH(o); - return PyUnicode_AsUTF8(o); - } else { - PyUnicode_AsASCIIString(o); - return NULL; - } -#else - return PyUnicode_AsUTF8AndSize(o, length); -#endif -} -#endif -#endif -static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) { -#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT - if ( -#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII - __Pyx_sys_getdefaultencoding_not_ascii && -#endif - PyUnicode_Check(o)) { - return __Pyx_PyUnicode_AsStringAndSize(o, length); - } else -#endif -#if (!CYTHON_COMPILING_IN_PYPY) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE)) - if (PyByteArray_Check(o)) { - *length = PyByteArray_GET_SIZE(o); - return PyByteArray_AS_STRING(o); - } else -#endif - { - char* result; - int r = PyBytes_AsStringAndSize(o, &result, length); - if (unlikely(r < 0)) { - return NULL; - } else { - return result; - } - } -} -static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { - int is_true = x == Py_True; - if (is_true | (x == Py_False) | (x == Py_None)) return is_true; - else return PyObject_IsTrue(x); -} -static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject* x) { - int retval; - if (unlikely(!x)) return -1; - retval = __Pyx_PyObject_IsTrue(x); - Py_DECREF(x); - return retval; -} -static PyObject* __Pyx_PyNumber_IntOrLongWrongResultType(PyObject* result, const char* type_name) { -#if PY_MAJOR_VERSION >= 3 - if (PyLong_Check(result)) { - if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, - "__int__ returned non-int (type %.200s). " - "The ability to return an instance of a strict subclass of int " - "is deprecated, and may be removed in a future version of Python.", - Py_TYPE(result)->tp_name)) { - Py_DECREF(result); - return NULL; - } - return result; - } -#endif - PyErr_Format(PyExc_TypeError, - "__%.4s__ returned non-%.4s (type %.200s)", - type_name, type_name, Py_TYPE(result)->tp_name); - Py_DECREF(result); - return NULL; -} -static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x) { -#if CYTHON_USE_TYPE_SLOTS - PyNumberMethods *m; -#endif - const char *name = NULL; - PyObject *res = NULL; -#if PY_MAJOR_VERSION < 3 - if (likely(PyInt_Check(x) || PyLong_Check(x))) -#else - if (likely(PyLong_Check(x))) -#endif - return __Pyx_NewRef(x); -#if CYTHON_USE_TYPE_SLOTS - m = Py_TYPE(x)->tp_as_number; - #if PY_MAJOR_VERSION < 3 - if (m && m->nb_int) { - name = "int"; - res = m->nb_int(x); - } - else if (m && m->nb_long) { - name = "long"; - res = m->nb_long(x); - } - #else - if (likely(m && m->nb_int)) { - name = "int"; - res = m->nb_int(x); - } - #endif -#else - if (!PyBytes_CheckExact(x) && !PyUnicode_CheckExact(x)) { - res = PyNumber_Int(x); - } -#endif - if (likely(res)) { -#if PY_MAJOR_VERSION < 3 - if (unlikely(!PyInt_Check(res) && !PyLong_Check(res))) { -#else - if (unlikely(!PyLong_CheckExact(res))) { -#endif - return __Pyx_PyNumber_IntOrLongWrongResultType(res, name); - } - } - else if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, - "an integer is required"); - } - return res; -} -static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { - Py_ssize_t ival; - PyObject *x; -#if PY_MAJOR_VERSION < 3 - if (likely(PyInt_CheckExact(b))) { - if (sizeof(Py_ssize_t) >= sizeof(long)) - return PyInt_AS_LONG(b); - else - return PyInt_AsSsize_t(b); - } -#endif - if (likely(PyLong_CheckExact(b))) { - #if CYTHON_USE_PYLONG_INTERNALS - const digit* digits = ((PyLongObject*)b)->ob_digit; - const Py_ssize_t size = Py_SIZE(b); - if (likely(__Pyx_sst_abs(size) <= 1)) { - ival = likely(size) ? digits[0] : 0; - if (size == -1) ival = -ival; - return ival; - } else { - switch (size) { - case 2: - if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { - return (Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); - } - break; - case -2: - if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { - return -(Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); - } - break; - case 3: - if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { - return (Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); - } - break; - case -3: - if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { - return -(Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); - } - break; - case 4: - if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { - return (Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); - } - break; - case -4: - if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { - return -(Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); - } - break; - } - } - #endif - return PyLong_AsSsize_t(b); - } - x = PyNumber_Index(b); - if (!x) return -1; - ival = PyInt_AsSsize_t(x); - Py_DECREF(x); - return ival; -} -static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { - return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False); -} -static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { - return PyInt_FromSize_t(ival); -} - - -#endif /* Py_PYTHON_H */ diff --git a/netharn/initializers/_nx_ext/balanced_sequence_cython.html b/netharn/initializers/_nx_ext/balanced_sequence_cython.html deleted file mode 100644 index 3bf259f..0000000 --- a/netharn/initializers/_nx_ext/balanced_sequence_cython.html +++ /dev/null @@ -1,4497 +0,0 @@ - - - - - - Cython: balanced_sequence_cython.pyx - - - -

Generated by Cython 0.29.20

-

- Yellow lines hint at Python interaction.
- Click on a line that starts with a "+" to see the C code that Cython generated for it. -

-

Raw output: balanced_sequence_cython.cpp

-
 001: # distutils: language = c++
-
 002: """
-
 003: This module re-implements functions in :module:`balanced_sequence` in cython
-
 004: and obtains 40-50x speedups in common circumstances. There are likely more
-
 005: speed improvements that could be made.
-
 006: 
-
 007: CommandLine
-
 008: -----------
-
 009: # Explicitly build this cython module
-
 010: cythonize -a -i $HOME/code/networkx/networkx/algorithms/isomorphism/_embedding/balanced_sequence_cython.pyx
-
 011: 
-
 012: 
-
 013: Examples
-
 014: --------
-
 015: >>> from networkx.algorithms.isomorphism._embedding.balanced_sequence_cython import *
-
 016: >>> from networkx.algorithms.isomorphism._embedding.demodata import random_balanced_sequence
-
 017: >>> seq1, open_to_close1 = random_balanced_sequence(300, mode='paren')
-
 018: >>> seq2, open_to_close2 = random_balanced_sequence(300, mode='paren')
-
 019: >>> open_to_close = {**open_to_close1, **open_to_close2}
-
 020: >>> full_seq1 = seq1
-
 021: >>> full_seq2 = seq2
-
 022: >>> import operator
-
 023: >>> node_affinity = operator.eq
-
 024: >>> open_to_node = IdentityDict()
-
 025: 
-
 026: with ub.Timer('cython'):
-
 027:     best, value = _lcs_iter_simple_alt2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node)
-
 028: 
-
 029: with ub.Timer('python'):
-
 030:     best, value = _lcs_iter_simple_alt2(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node)
-
 031: 
-
 032: """
-
 033: 
-
 034: 
-
+035: def _lcs_iter_simple_alt2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node):
-
/* Python wrapper */
-static PyObject *__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_1_lcs_iter_simple_alt2_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython__lcs_iter_simple_alt2_cython[] = "\n    Depth first stack trajectory and replace try except statements with ifs\n    ";
-static PyMethodDef __pyx_mdef_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_1_lcs_iter_simple_alt2_cython = {"_lcs_iter_simple_alt2_cython", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_1_lcs_iter_simple_alt2_cython, METH_VARARGS|METH_KEYWORDS, __pyx_doc_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython__lcs_iter_simple_alt2_cython};
-static PyObject *__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_1_lcs_iter_simple_alt2_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyObject *__pyx_v_full_seq1 = 0;
-  PyObject *__pyx_v_full_seq2 = 0;
-  PyObject *__pyx_v_open_to_close = 0;
-  PyObject *__pyx_v_node_affinity = 0;
-  PyObject *__pyx_v_open_to_node = 0;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("_lcs_iter_simple_alt2_cython (wrapper)", 0);
-  {
-    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_full_seq1,&__pyx_n_s_full_seq2,&__pyx_n_s_open_to_close,&__pyx_n_s_node_affinity,&__pyx_n_s_open_to_node,0};
-    PyObject* values[5] = {0,0,0,0,0};
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
-        CYTHON_FALLTHROUGH;
-        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
-        CYTHON_FALLTHROUGH;
-        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
-        CYTHON_FALLTHROUGH;
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        CYTHON_FALLTHROUGH;
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        CYTHON_FALLTHROUGH;
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_full_seq1)) != 0)) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        CYTHON_FALLTHROUGH;
-        case  1:
-        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_full_seq2)) != 0)) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("_lcs_iter_simple_alt2_cython", 1, 5, 5, 1); __PYX_ERR(0, 35, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case  2:
-        if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_open_to_close)) != 0)) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("_lcs_iter_simple_alt2_cython", 1, 5, 5, 2); __PYX_ERR(0, 35, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case  3:
-        if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_node_affinity)) != 0)) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("_lcs_iter_simple_alt2_cython", 1, 5, 5, 3); __PYX_ERR(0, 35, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case  4:
-        if (likely((values[4] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_open_to_node)) != 0)) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("_lcs_iter_simple_alt2_cython", 1, 5, 5, 4); __PYX_ERR(0, 35, __pyx_L3_error)
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "_lcs_iter_simple_alt2_cython") < 0)) __PYX_ERR(0, 35, __pyx_L3_error)
-      }
-    } else if (PyTuple_GET_SIZE(__pyx_args) != 5) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
-      values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
-      values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
-    }
-    __pyx_v_full_seq1 = values[0];
-    __pyx_v_full_seq2 = values[1];
-    __pyx_v_open_to_close = values[2];
-    __pyx_v_node_affinity = values[3];
-    __pyx_v_open_to_node = values[4];
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("_lcs_iter_simple_alt2_cython", 1, 5, 5, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 35, __pyx_L3_error)
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython._lcs_iter_simple_alt2_cython", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython__lcs_iter_simple_alt2_cython(__pyx_self, __pyx_v_full_seq1, __pyx_v_full_seq2, __pyx_v_open_to_close, __pyx_v_node_affinity, __pyx_v_open_to_node);
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython__lcs_iter_simple_alt2_cython(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_full_seq1, PyObject *__pyx_v_full_seq2, PyObject *__pyx_v_open_to_close, PyObject *__pyx_v_node_affinity, PyObject *__pyx_v_open_to_node) {
-  PyObject *__pyx_v_all_decomp1 = NULL;
-  PyObject *__pyx_v_all_decomp2 = NULL;
-  PyObject *__pyx_v_key0 = NULL;
-  PyObject *__pyx_v_frame0 = NULL;
-  PyObject *__pyx_v_stack = NULL;
-  PyObject *__pyx_v__results = NULL;
-  PyObject *__pyx_v_empty1 = NULL;
-  PyObject *__pyx_v_empty2 = NULL;
-  PyObject *__pyx_v_best = NULL;
-  PyObject *__pyx_v_base_result = NULL;
-  PyObject *__pyx_v_seq1 = NULL;
-  PyObject *__pyx_v_key1 = NULL;
-  PyObject *__pyx_v_t1 = NULL;
-  PyObject *__pyx_v_a1 = NULL;
-  PyObject *__pyx_v_b1 = NULL;
-  PyObject *__pyx_v_head1 = NULL;
-  PyObject *__pyx_v_tail1 = NULL;
-  PyObject *__pyx_v_head_tail1 = NULL;
-  PyObject *__pyx_v_seq2 = NULL;
-  PyObject *__pyx_v_key2 = NULL;
-  PyObject *__pyx_v_t2 = NULL;
-  PyObject *__pyx_v_a2 = NULL;
-  PyObject *__pyx_v_b2 = NULL;
-  PyObject *__pyx_v_head2 = NULL;
-  PyObject *__pyx_v_tail2 = NULL;
-  PyObject *__pyx_v_head_tail2 = NULL;
-  PyObject *__pyx_v_key = NULL;
-  PyObject *__pyx_v_try_key = NULL;
-  PyObject *__pyx_v_cand1 = NULL;
-  PyObject *__pyx_v_cand2 = NULL;
-  PyObject *__pyx_v_affinity = NULL;
-  PyObject *__pyx_v_pval_h = NULL;
-  PyObject *__pyx_v_new_heads = NULL;
-  PyObject *__pyx_v_pval_t = NULL;
-  PyObject *__pyx_v_new_tails = NULL;
-  PyObject *__pyx_v_new_head1 = NULL;
-  PyObject *__pyx_v_new_head2 = NULL;
-  PyObject *__pyx_v_new_tail1 = NULL;
-  PyObject *__pyx_v_new_tail2 = NULL;
-  PyObject *__pyx_v_subseq1 = NULL;
-  PyObject *__pyx_v_subseq2 = NULL;
-  PyObject *__pyx_v_res3 = NULL;
-  PyObject *__pyx_v_val3 = NULL;
-  PyObject *__pyx_v_cand3 = NULL;
-  PyObject *__pyx_v_val = NULL;
-  PyObject *__pyx_v_found = NULL;
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("_lcs_iter_simple_alt2_cython", 0);
-  __Pyx_INCREF(__pyx_v_open_to_node);
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_10);
-  __Pyx_XDECREF(__pyx_t_11);
-  __Pyx_XDECREF(__pyx_t_12);
-  __Pyx_XDECREF(__pyx_t_13);
-  __Pyx_XDECREF(__pyx_t_14);
-  __Pyx_XDECREF(__pyx_t_18);
-  __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython._lcs_iter_simple_alt2_cython", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_all_decomp1);
-  __Pyx_XDECREF(__pyx_v_all_decomp2);
-  __Pyx_XDECREF(__pyx_v_key0);
-  __Pyx_XDECREF(__pyx_v_frame0);
-  __Pyx_XDECREF(__pyx_v_stack);
-  __Pyx_XDECREF(__pyx_v__results);
-  __Pyx_XDECREF(__pyx_v_empty1);
-  __Pyx_XDECREF(__pyx_v_empty2);
-  __Pyx_XDECREF(__pyx_v_best);
-  __Pyx_XDECREF(__pyx_v_base_result);
-  __Pyx_XDECREF(__pyx_v_seq1);
-  __Pyx_XDECREF(__pyx_v_key1);
-  __Pyx_XDECREF(__pyx_v_t1);
-  __Pyx_XDECREF(__pyx_v_a1);
-  __Pyx_XDECREF(__pyx_v_b1);
-  __Pyx_XDECREF(__pyx_v_head1);
-  __Pyx_XDECREF(__pyx_v_tail1);
-  __Pyx_XDECREF(__pyx_v_head_tail1);
-  __Pyx_XDECREF(__pyx_v_seq2);
-  __Pyx_XDECREF(__pyx_v_key2);
-  __Pyx_XDECREF(__pyx_v_t2);
-  __Pyx_XDECREF(__pyx_v_a2);
-  __Pyx_XDECREF(__pyx_v_b2);
-  __Pyx_XDECREF(__pyx_v_head2);
-  __Pyx_XDECREF(__pyx_v_tail2);
-  __Pyx_XDECREF(__pyx_v_head_tail2);
-  __Pyx_XDECREF(__pyx_v_key);
-  __Pyx_XDECREF(__pyx_v_try_key);
-  __Pyx_XDECREF(__pyx_v_cand1);
-  __Pyx_XDECREF(__pyx_v_cand2);
-  __Pyx_XDECREF(__pyx_v_affinity);
-  __Pyx_XDECREF(__pyx_v_pval_h);
-  __Pyx_XDECREF(__pyx_v_new_heads);
-  __Pyx_XDECREF(__pyx_v_pval_t);
-  __Pyx_XDECREF(__pyx_v_new_tails);
-  __Pyx_XDECREF(__pyx_v_new_head1);
-  __Pyx_XDECREF(__pyx_v_new_head2);
-  __Pyx_XDECREF(__pyx_v_new_tail1);
-  __Pyx_XDECREF(__pyx_v_new_tail2);
-  __Pyx_XDECREF(__pyx_v_subseq1);
-  __Pyx_XDECREF(__pyx_v_subseq2);
-  __Pyx_XDECREF(__pyx_v_res3);
-  __Pyx_XDECREF(__pyx_v_val3);
-  __Pyx_XDECREF(__pyx_v_cand3);
-  __Pyx_XDECREF(__pyx_v_val);
-  __Pyx_XDECREF(__pyx_v_found);
-  __Pyx_XDECREF(__pyx_v_open_to_node);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-/* … */
-  __pyx_tuple__4 = PyTuple_Pack(51, __pyx_n_s_full_seq1, __pyx_n_s_full_seq2, __pyx_n_s_open_to_close, __pyx_n_s_node_affinity, __pyx_n_s_open_to_node, __pyx_n_s_all_decomp1, __pyx_n_s_all_decomp2, __pyx_n_s_key0, __pyx_n_s_frame0, __pyx_n_s_stack, __pyx_n_s_results, __pyx_n_s_empty1, __pyx_n_s_empty2, __pyx_n_s_best, __pyx_n_s_base_result, __pyx_n_s_seq1, __pyx_n_s_key1, __pyx_n_s_t1, __pyx_n_s_a1, __pyx_n_s_b1, __pyx_n_s_head1, __pyx_n_s_tail1, __pyx_n_s_head_tail1, __pyx_n_s_seq2, __pyx_n_s_key2, __pyx_n_s_t2, __pyx_n_s_a2, __pyx_n_s_b2, __pyx_n_s_head2, __pyx_n_s_tail2, __pyx_n_s_head_tail2, __pyx_n_s_key, __pyx_n_s_try_key, __pyx_n_s_cand1, __pyx_n_s_cand2, __pyx_n_s_affinity, __pyx_n_s_pval_h, __pyx_n_s_new_heads, __pyx_n_s_pval_t, __pyx_n_s_new_tails, __pyx_n_s_new_head1, __pyx_n_s_new_head2, __pyx_n_s_new_tail1, __pyx_n_s_new_tail2, __pyx_n_s_subseq1, __pyx_n_s_subseq2, __pyx_n_s_res3, __pyx_n_s_val3, __pyx_n_s_cand3, __pyx_n_s_val, __pyx_n_s_found); if (unlikely(!__pyx_tuple__4)) __PYX_ERR(0, 35, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__4);
-  __Pyx_GIVEREF(__pyx_tuple__4);
-/* … */
-  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_1_lcs_iter_simple_alt2_cython, NULL, __pyx_n_s_networkx_algorithms_isomorphism); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 35, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_lcs_iter_simple_alt2_cython, __pyx_t_1) < 0) __PYX_ERR(0, 35, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_codeobj__5 = (PyObject*)__Pyx_PyCode_New(5, 0, 51, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__4, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_embedding_balanced_sequence_cyt, __pyx_n_s_lcs_iter_simple_alt2_cython, 35, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__5)) __PYX_ERR(0, 35, __pyx_L1_error)
-
 036:     """
-
 037:     Depth first stack trajectory and replace try except statements with ifs
-
 038:     """
-
+039:     if open_to_node is None:
-
  __pyx_t_1 = (__pyx_v_open_to_node == Py_None);
-  __pyx_t_2 = (__pyx_t_1 != 0);
-  if (__pyx_t_2) {
-/* … */
-  }
-
+040:         open_to_node = IdentityDict()
-
    __Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_IdentityDict); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 40, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_5 = NULL;
-    if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
-      __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
-      if (likely(__pyx_t_5)) {
-        PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
-        __Pyx_INCREF(__pyx_t_5);
-        __Pyx_INCREF(function);
-        __Pyx_DECREF_SET(__pyx_t_4, function);
-      }
-    }
-    __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5) : __Pyx_PyObject_CallNoArg(__pyx_t_4);
-    __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-    if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 40, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    __Pyx_DECREF_SET(__pyx_v_open_to_node, __pyx_t_3);
-    __pyx_t_3 = 0;
-
+041:     all_decomp1 = generate_all_decomp_cython(full_seq1, open_to_close, open_to_node)
-
  __pyx_t_6.__pyx_n = 1;
-  __pyx_t_6.open_to_node = __pyx_v_open_to_node;
-  __pyx_t_3 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython(__pyx_v_full_seq1, __pyx_v_open_to_close, &__pyx_t_6); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 41, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_v_all_decomp1 = __pyx_t_3;
-  __pyx_t_3 = 0;
-
+042:     all_decomp2 = generate_all_decomp_cython(full_seq2, open_to_close, open_to_node)
-
  __pyx_t_6.__pyx_n = 1;
-  __pyx_t_6.open_to_node = __pyx_v_open_to_node;
-  __pyx_t_3 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython(__pyx_v_full_seq2, __pyx_v_open_to_close, &__pyx_t_6); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 42, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_v_all_decomp2 = __pyx_t_3;
-  __pyx_t_3 = 0;
-
 043: 
-
+044:     key0 = (full_seq1, full_seq2)
-
  __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 44, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_INCREF(__pyx_v_full_seq1);
-  __Pyx_GIVEREF(__pyx_v_full_seq1);
-  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_full_seq1);
-  __Pyx_INCREF(__pyx_v_full_seq2);
-  __Pyx_GIVEREF(__pyx_v_full_seq2);
-  PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_full_seq2);
-  __pyx_v_key0 = ((PyObject*)__pyx_t_3);
-  __pyx_t_3 = 0;
-
+045:     frame0 = key0
-
  __Pyx_INCREF(__pyx_v_key0);
-  __pyx_v_frame0 = __pyx_v_key0;
-
+046:     stack = [frame0]
-
  __pyx_t_3 = PyList_New(1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 46, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_INCREF(__pyx_v_frame0);
-  __Pyx_GIVEREF(__pyx_v_frame0);
-  PyList_SET_ITEM(__pyx_t_3, 0, __pyx_v_frame0);
-  __pyx_v_stack = ((PyObject*)__pyx_t_3);
-  __pyx_t_3 = 0;
-
 047: 
-
+048:     _results = {}
-
  __pyx_t_3 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 48, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_v__results = ((PyObject*)__pyx_t_3);
-  __pyx_t_3 = 0;
-
 049:     # Populate base cases
-
+050:     empty1 = type(next(iter(all_decomp1.keys())))()
-
  __pyx_t_5 = __Pyx_PyObject_GetAttrStr(__pyx_v_all_decomp1, __pyx_n_s_keys); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 50, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __pyx_t_7 = NULL;
-  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_5))) {
-    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_5);
-    if (likely(__pyx_t_7)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
-      __Pyx_INCREF(__pyx_t_7);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_5, function);
-    }
-  }
-  __pyx_t_4 = (__pyx_t_7) ? __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_7) : __Pyx_PyObject_CallNoArg(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-  if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 50, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  __pyx_t_5 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 50, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_t_4 = __Pyx_PyIter_Next(__pyx_t_5); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 50, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  __Pyx_INCREF(((PyObject *)Py_TYPE(__pyx_t_4)));
-  __pyx_t_5 = ((PyObject *)Py_TYPE(__pyx_t_4)); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_t_4 = NULL;
-  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_5))) {
-    __pyx_t_4 = PyMethod_GET_SELF(__pyx_t_5);
-    if (likely(__pyx_t_4)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_5);
-      __Pyx_INCREF(__pyx_t_4);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_5, function);
-    }
-  }
-  __pyx_t_3 = (__pyx_t_4) ? __Pyx_PyObject_CallOneArg(__pyx_t_5, __pyx_t_4) : __Pyx_PyObject_CallNoArg(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_4); __pyx_t_4 = 0;
-  if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 50, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  __pyx_v_empty1 = __pyx_t_3;
-  __pyx_t_3 = 0;
-
+051:     empty2 = type(next(iter(all_decomp2.keys())))()
-
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_all_decomp2, __pyx_n_s_keys); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 51, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_7 = NULL;
-  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) {
-    __pyx_t_7 = PyMethod_GET_SELF(__pyx_t_4);
-    if (likely(__pyx_t_7)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
-      __Pyx_INCREF(__pyx_t_7);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_4, function);
-    }
-  }
-  __pyx_t_5 = (__pyx_t_7) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_7) : __Pyx_PyObject_CallNoArg(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_7); __pyx_t_7 = 0;
-  if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 51, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_t_4 = PyObject_GetIter(__pyx_t_5); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 51, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  __pyx_t_5 = __Pyx_PyIter_Next(__pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 51, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __Pyx_INCREF(((PyObject *)Py_TYPE(__pyx_t_5)));
-  __pyx_t_4 = ((PyObject *)Py_TYPE(__pyx_t_5)); __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-  __pyx_t_5 = NULL;
-  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_4))) {
-    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
-    if (likely(__pyx_t_5)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
-      __Pyx_INCREF(__pyx_t_5);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_4, function);
-    }
-  }
-  __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5) : __Pyx_PyObject_CallNoArg(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-  if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 51, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  __pyx_v_empty2 = __pyx_t_3;
-  __pyx_t_3 = 0;
-
+052:     best = (empty1, empty2)
-
  __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 52, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_INCREF(__pyx_v_empty1);
-  __Pyx_GIVEREF(__pyx_v_empty1);
-  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_empty1);
-  __Pyx_INCREF(__pyx_v_empty2);
-  __Pyx_GIVEREF(__pyx_v_empty2);
-  PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_empty2);
-  __pyx_v_best = __pyx_t_3;
-  __pyx_t_3 = 0;
-
+053:     base_result = (0, best)
-
  __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 53, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_INCREF(__pyx_int_0);
-  __Pyx_GIVEREF(__pyx_int_0);
-  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_int_0);
-  __Pyx_INCREF(__pyx_v_best);
-  __Pyx_GIVEREF(__pyx_v_best);
-  PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_best);
-  __pyx_v_base_result = ((PyObject*)__pyx_t_3);
-  __pyx_t_3 = 0;
-
+054:     for seq1 in all_decomp1.keys():
-
  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_v_all_decomp1, __pyx_n_s_keys); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 54, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_5 = NULL;
-  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_4))) {
-    __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_4);
-    if (likely(__pyx_t_5)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_4);
-      __Pyx_INCREF(__pyx_t_5);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_4, function);
-    }
-  }
-  __pyx_t_3 = (__pyx_t_5) ? __Pyx_PyObject_CallOneArg(__pyx_t_4, __pyx_t_5) : __Pyx_PyObject_CallNoArg(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-  if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 54, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  if (likely(PyList_CheckExact(__pyx_t_3)) || PyTuple_CheckExact(__pyx_t_3)) {
-    __pyx_t_4 = __pyx_t_3; __Pyx_INCREF(__pyx_t_4); __pyx_t_8 = 0;
-    __pyx_t_9 = NULL;
-  } else {
-    __pyx_t_8 = -1; __pyx_t_4 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 54, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __pyx_t_9 = Py_TYPE(__pyx_t_4)->tp_iternext; if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 54, __pyx_L1_error)
-  }
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  for (;;) {
-    if (likely(!__pyx_t_9)) {
-      if (likely(PyList_CheckExact(__pyx_t_4))) {
-        if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_4)) break;
-        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        __pyx_t_3 = PyList_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_3); __pyx_t_8++; if (unlikely(0 < 0)) __PYX_ERR(0, 54, __pyx_L1_error)
-        #else
-        __pyx_t_3 = PySequence_ITEM(__pyx_t_4, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 54, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        #endif
-      } else {
-        if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_4)) break;
-        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        __pyx_t_3 = PyTuple_GET_ITEM(__pyx_t_4, __pyx_t_8); __Pyx_INCREF(__pyx_t_3); __pyx_t_8++; if (unlikely(0 < 0)) __PYX_ERR(0, 54, __pyx_L1_error)
-        #else
-        __pyx_t_3 = PySequence_ITEM(__pyx_t_4, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 54, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        #endif
-      }
-    } else {
-      __pyx_t_3 = __pyx_t_9(__pyx_t_4);
-      if (unlikely(!__pyx_t_3)) {
-        PyObject* exc_type = PyErr_Occurred();
-        if (exc_type) {
-          if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
-          else __PYX_ERR(0, 54, __pyx_L1_error)
-        }
-        break;
-      }
-      __Pyx_GOTREF(__pyx_t_3);
-    }
-    __Pyx_XDECREF_SET(__pyx_v_seq1, __pyx_t_3);
-    __pyx_t_3 = 0;
-/* … */
-  }
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-
+055:         key1 = seq1
-
    __Pyx_INCREF(__pyx_v_seq1);
-    __Pyx_XDECREF_SET(__pyx_v_key1, __pyx_v_seq1);
-
+056:         t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[key1]
-
    __pyx_t_3 = __Pyx_PyObject_GetItem(__pyx_v_all_decomp1, __pyx_v_key1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 56, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) {
-      PyObject* sequence = __pyx_t_3;
-      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-      if (unlikely(size != 6)) {
-        if (size > 6) __Pyx_RaiseTooManyValuesError(6);
-        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-        __PYX_ERR(0, 56, __pyx_L1_error)
-      }
-      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-      if (likely(PyTuple_CheckExact(sequence))) {
-        __pyx_t_5 = PyTuple_GET_ITEM(sequence, 0); 
-        __pyx_t_7 = PyTuple_GET_ITEM(sequence, 1); 
-        __pyx_t_10 = PyTuple_GET_ITEM(sequence, 2); 
-        __pyx_t_11 = PyTuple_GET_ITEM(sequence, 3); 
-        __pyx_t_12 = PyTuple_GET_ITEM(sequence, 4); 
-        __pyx_t_13 = PyTuple_GET_ITEM(sequence, 5); 
-      } else {
-        __pyx_t_5 = PyList_GET_ITEM(sequence, 0); 
-        __pyx_t_7 = PyList_GET_ITEM(sequence, 1); 
-        __pyx_t_10 = PyList_GET_ITEM(sequence, 2); 
-        __pyx_t_11 = PyList_GET_ITEM(sequence, 3); 
-        __pyx_t_12 = PyList_GET_ITEM(sequence, 4); 
-        __pyx_t_13 = PyList_GET_ITEM(sequence, 5); 
-      }
-      __Pyx_INCREF(__pyx_t_5);
-      __Pyx_INCREF(__pyx_t_7);
-      __Pyx_INCREF(__pyx_t_10);
-      __Pyx_INCREF(__pyx_t_11);
-      __Pyx_INCREF(__pyx_t_12);
-      __Pyx_INCREF(__pyx_t_13);
-      #else
-      {
-        Py_ssize_t i;
-        PyObject** temps[6] = {&__pyx_t_5,&__pyx_t_7,&__pyx_t_10,&__pyx_t_11,&__pyx_t_12,&__pyx_t_13};
-        for (i=0; i < 6; i++) {
-          PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 56, __pyx_L1_error)
-          __Pyx_GOTREF(item);
-          *(temps[i]) = item;
-        }
-      }
-      #endif
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else {
-      Py_ssize_t index = -1;
-      PyObject** temps[6] = {&__pyx_t_5,&__pyx_t_7,&__pyx_t_10,&__pyx_t_11,&__pyx_t_12,&__pyx_t_13};
-      __pyx_t_14 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 56, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_14);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_15 = Py_TYPE(__pyx_t_14)->tp_iternext;
-      for (index=0; index < 6; index++) {
-        PyObject* item = __pyx_t_15(__pyx_t_14); if (unlikely(!item)) goto __pyx_L6_unpacking_failed;
-        __Pyx_GOTREF(item);
-        *(temps[index]) = item;
-      }
-      if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_14), 6) < 0) __PYX_ERR(0, 56, __pyx_L1_error)
-      __pyx_t_15 = NULL;
-      __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
-      goto __pyx_L7_unpacking_done;
-      __pyx_L6_unpacking_failed:;
-      __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
-      __pyx_t_15 = NULL;
-      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-      __PYX_ERR(0, 56, __pyx_L1_error)
-      __pyx_L7_unpacking_done:;
-    }
-    __Pyx_XDECREF_SET(__pyx_v_t1, __pyx_t_5);
-    __pyx_t_5 = 0;
-    __Pyx_XDECREF_SET(__pyx_v_a1, __pyx_t_7);
-    __pyx_t_7 = 0;
-    __Pyx_XDECREF_SET(__pyx_v_b1, __pyx_t_10);
-    __pyx_t_10 = 0;
-    __Pyx_XDECREF_SET(__pyx_v_head1, __pyx_t_11);
-    __pyx_t_11 = 0;
-    __Pyx_XDECREF_SET(__pyx_v_tail1, __pyx_t_12);
-    __pyx_t_12 = 0;
-    __Pyx_XDECREF_SET(__pyx_v_head_tail1, __pyx_t_13);
-    __pyx_t_13 = 0;
-
+057:         _results[(seq1, empty2)] = base_result
-
    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 57, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_INCREF(__pyx_v_seq1);
-    __Pyx_GIVEREF(__pyx_v_seq1);
-    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_seq1);
-    __Pyx_INCREF(__pyx_v_empty2);
-    __Pyx_GIVEREF(__pyx_v_empty2);
-    PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_empty2);
-    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 57, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+058:         _results[(head1, empty2)] = base_result
-
    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 58, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_INCREF(__pyx_v_head1);
-    __Pyx_GIVEREF(__pyx_v_head1);
-    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_head1);
-    __Pyx_INCREF(__pyx_v_empty2);
-    __Pyx_GIVEREF(__pyx_v_empty2);
-    PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_empty2);
-    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 58, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+059:         _results[(tail1, empty2)] = base_result
-
    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 59, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_INCREF(__pyx_v_tail1);
-    __Pyx_GIVEREF(__pyx_v_tail1);
-    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_tail1);
-    __Pyx_INCREF(__pyx_v_empty2);
-    __Pyx_GIVEREF(__pyx_v_empty2);
-    PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_empty2);
-    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 59, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+060:         _results[(head_tail1, empty2)] = base_result
-
    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 60, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_INCREF(__pyx_v_head_tail1);
-    __Pyx_GIVEREF(__pyx_v_head_tail1);
-    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_head_tail1);
-    __Pyx_INCREF(__pyx_v_empty2);
-    __Pyx_GIVEREF(__pyx_v_empty2);
-    PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_empty2);
-    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 60, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
 061: 
-
+062:     for seq2 in all_decomp2.keys():
-
  __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_v_all_decomp2, __pyx_n_s_keys); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 62, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_13 = NULL;
-  if (CYTHON_UNPACK_METHODS && likely(PyMethod_Check(__pyx_t_3))) {
-    __pyx_t_13 = PyMethod_GET_SELF(__pyx_t_3);
-    if (likely(__pyx_t_13)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-      __Pyx_INCREF(__pyx_t_13);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_3, function);
-    }
-  }
-  __pyx_t_4 = (__pyx_t_13) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_13) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_13); __pyx_t_13 = 0;
-  if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 62, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (likely(PyList_CheckExact(__pyx_t_4)) || PyTuple_CheckExact(__pyx_t_4)) {
-    __pyx_t_3 = __pyx_t_4; __Pyx_INCREF(__pyx_t_3); __pyx_t_8 = 0;
-    __pyx_t_9 = NULL;
-  } else {
-    __pyx_t_8 = -1; __pyx_t_3 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 62, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_9 = Py_TYPE(__pyx_t_3)->tp_iternext; if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 62, __pyx_L1_error)
-  }
-  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-  for (;;) {
-    if (likely(!__pyx_t_9)) {
-      if (likely(PyList_CheckExact(__pyx_t_3))) {
-        if (__pyx_t_8 >= PyList_GET_SIZE(__pyx_t_3)) break;
-        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        __pyx_t_4 = PyList_GET_ITEM(__pyx_t_3, __pyx_t_8); __Pyx_INCREF(__pyx_t_4); __pyx_t_8++; if (unlikely(0 < 0)) __PYX_ERR(0, 62, __pyx_L1_error)
-        #else
-        __pyx_t_4 = PySequence_ITEM(__pyx_t_3, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 62, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        #endif
-      } else {
-        if (__pyx_t_8 >= PyTuple_GET_SIZE(__pyx_t_3)) break;
-        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_3, __pyx_t_8); __Pyx_INCREF(__pyx_t_4); __pyx_t_8++; if (unlikely(0 < 0)) __PYX_ERR(0, 62, __pyx_L1_error)
-        #else
-        __pyx_t_4 = PySequence_ITEM(__pyx_t_3, __pyx_t_8); __pyx_t_8++; if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 62, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        #endif
-      }
-    } else {
-      __pyx_t_4 = __pyx_t_9(__pyx_t_3);
-      if (unlikely(!__pyx_t_4)) {
-        PyObject* exc_type = PyErr_Occurred();
-        if (exc_type) {
-          if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
-          else __PYX_ERR(0, 62, __pyx_L1_error)
-        }
-        break;
-      }
-      __Pyx_GOTREF(__pyx_t_4);
-    }
-    __Pyx_XDECREF_SET(__pyx_v_seq2, __pyx_t_4);
-    __pyx_t_4 = 0;
-/* … */
-  }
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+063:         key2 = seq2
-
    __Pyx_INCREF(__pyx_v_seq2);
-    __Pyx_XDECREF_SET(__pyx_v_key2, __pyx_v_seq2);
-
+064:         t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[key2]
-
    __pyx_t_4 = __Pyx_PyObject_GetItem(__pyx_v_all_decomp2, __pyx_v_key2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 64, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) {
-      PyObject* sequence = __pyx_t_4;
-      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-      if (unlikely(size != 6)) {
-        if (size > 6) __Pyx_RaiseTooManyValuesError(6);
-        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-        __PYX_ERR(0, 64, __pyx_L1_error)
-      }
-      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-      if (likely(PyTuple_CheckExact(sequence))) {
-        __pyx_t_13 = PyTuple_GET_ITEM(sequence, 0); 
-        __pyx_t_12 = PyTuple_GET_ITEM(sequence, 1); 
-        __pyx_t_11 = PyTuple_GET_ITEM(sequence, 2); 
-        __pyx_t_10 = PyTuple_GET_ITEM(sequence, 3); 
-        __pyx_t_7 = PyTuple_GET_ITEM(sequence, 4); 
-        __pyx_t_5 = PyTuple_GET_ITEM(sequence, 5); 
-      } else {
-        __pyx_t_13 = PyList_GET_ITEM(sequence, 0); 
-        __pyx_t_12 = PyList_GET_ITEM(sequence, 1); 
-        __pyx_t_11 = PyList_GET_ITEM(sequence, 2); 
-        __pyx_t_10 = PyList_GET_ITEM(sequence, 3); 
-        __pyx_t_7 = PyList_GET_ITEM(sequence, 4); 
-        __pyx_t_5 = PyList_GET_ITEM(sequence, 5); 
-      }
-      __Pyx_INCREF(__pyx_t_13);
-      __Pyx_INCREF(__pyx_t_12);
-      __Pyx_INCREF(__pyx_t_11);
-      __Pyx_INCREF(__pyx_t_10);
-      __Pyx_INCREF(__pyx_t_7);
-      __Pyx_INCREF(__pyx_t_5);
-      #else
-      {
-        Py_ssize_t i;
-        PyObject** temps[6] = {&__pyx_t_13,&__pyx_t_12,&__pyx_t_11,&__pyx_t_10,&__pyx_t_7,&__pyx_t_5};
-        for (i=0; i < 6; i++) {
-          PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 64, __pyx_L1_error)
-          __Pyx_GOTREF(item);
-          *(temps[i]) = item;
-        }
-      }
-      #endif
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-    } else {
-      Py_ssize_t index = -1;
-      PyObject** temps[6] = {&__pyx_t_13,&__pyx_t_12,&__pyx_t_11,&__pyx_t_10,&__pyx_t_7,&__pyx_t_5};
-      __pyx_t_14 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_14)) __PYX_ERR(0, 64, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_14);
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __pyx_t_15 = Py_TYPE(__pyx_t_14)->tp_iternext;
-      for (index=0; index < 6; index++) {
-        PyObject* item = __pyx_t_15(__pyx_t_14); if (unlikely(!item)) goto __pyx_L10_unpacking_failed;
-        __Pyx_GOTREF(item);
-        *(temps[index]) = item;
-      }
-      if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_14), 6) < 0) __PYX_ERR(0, 64, __pyx_L1_error)
-      __pyx_t_15 = NULL;
-      __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
-      goto __pyx_L11_unpacking_done;
-      __pyx_L10_unpacking_failed:;
-      __Pyx_DECREF(__pyx_t_14); __pyx_t_14 = 0;
-      __pyx_t_15 = NULL;
-      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-      __PYX_ERR(0, 64, __pyx_L1_error)
-      __pyx_L11_unpacking_done:;
-    }
-    __Pyx_XDECREF_SET(__pyx_v_t2, __pyx_t_13);
-    __pyx_t_13 = 0;
-    __Pyx_XDECREF_SET(__pyx_v_a2, __pyx_t_12);
-    __pyx_t_12 = 0;
-    __Pyx_XDECREF_SET(__pyx_v_b2, __pyx_t_11);
-    __pyx_t_11 = 0;
-    __Pyx_XDECREF_SET(__pyx_v_head2, __pyx_t_10);
-    __pyx_t_10 = 0;
-    __Pyx_XDECREF_SET(__pyx_v_tail2, __pyx_t_7);
-    __pyx_t_7 = 0;
-    __Pyx_XDECREF_SET(__pyx_v_head_tail2, __pyx_t_5);
-    __pyx_t_5 = 0;
-
+065:         _results[(empty1, seq2)] = base_result
-
    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 65, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_INCREF(__pyx_v_empty1);
-    __Pyx_GIVEREF(__pyx_v_empty1);
-    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_empty1);
-    __Pyx_INCREF(__pyx_v_seq2);
-    __Pyx_GIVEREF(__pyx_v_seq2);
-    PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_seq2);
-    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_4, __pyx_v_base_result) < 0)) __PYX_ERR(0, 65, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-
+066:         _results[(empty1, head2)] = base_result
-
    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 66, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_INCREF(__pyx_v_empty1);
-    __Pyx_GIVEREF(__pyx_v_empty1);
-    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_empty1);
-    __Pyx_INCREF(__pyx_v_head2);
-    __Pyx_GIVEREF(__pyx_v_head2);
-    PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_head2);
-    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_4, __pyx_v_base_result) < 0)) __PYX_ERR(0, 66, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-
+067:         _results[(empty1, tail2)] = base_result
-
    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 67, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_INCREF(__pyx_v_empty1);
-    __Pyx_GIVEREF(__pyx_v_empty1);
-    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_empty1);
-    __Pyx_INCREF(__pyx_v_tail2);
-    __Pyx_GIVEREF(__pyx_v_tail2);
-    PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_tail2);
-    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_4, __pyx_v_base_result) < 0)) __PYX_ERR(0, 67, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-
+068:         _results[(empty1, head_tail2)] = base_result
-
    __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 68, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    __Pyx_INCREF(__pyx_v_empty1);
-    __Pyx_GIVEREF(__pyx_v_empty1);
-    PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_empty1);
-    __Pyx_INCREF(__pyx_v_head_tail2);
-    __Pyx_GIVEREF(__pyx_v_head_tail2);
-    PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_head_tail2);
-    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_4, __pyx_v_base_result) < 0)) __PYX_ERR(0, 68, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-
 069: 
-
+070:     while stack:
-
  while (1) {
-    __pyx_t_2 = (PyList_GET_SIZE(__pyx_v_stack) != 0);
-    if (!__pyx_t_2) break;
-
+071:         key = stack[-1]
-
    __pyx_t_3 = __Pyx_GetItemInt_List(__pyx_v_stack, -1L, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 71, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_XDECREF_SET(__pyx_v_key, __pyx_t_3);
-    __pyx_t_3 = 0;
-
+072:         if key not in _results:
-
    __pyx_t_2 = (__Pyx_PyDict_ContainsTF(__pyx_v_key, __pyx_v__results, Py_NE)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 72, __pyx_L1_error)
-    __pyx_t_1 = (__pyx_t_2 != 0);
-    if (__pyx_t_1) {
-/* … */
-    }
-
+073:             seq1, seq2 = key
-
      if ((likely(PyTuple_CheckExact(__pyx_v_key))) || (PyList_CheckExact(__pyx_v_key))) {
-        PyObject* sequence = __pyx_v_key;
-        Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-        if (unlikely(size != 2)) {
-          if (size > 2) __Pyx_RaiseTooManyValuesError(2);
-          else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-          __PYX_ERR(0, 73, __pyx_L1_error)
-        }
-        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        if (likely(PyTuple_CheckExact(sequence))) {
-          __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); 
-          __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); 
-        } else {
-          __pyx_t_3 = PyList_GET_ITEM(sequence, 0); 
-          __pyx_t_4 = PyList_GET_ITEM(sequence, 1); 
-        }
-        __Pyx_INCREF(__pyx_t_3);
-        __Pyx_INCREF(__pyx_t_4);
-        #else
-        __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 73, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 73, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        #endif
-      } else {
-        Py_ssize_t index = -1;
-        __pyx_t_5 = PyObject_GetIter(__pyx_v_key); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 73, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_5);
-        __pyx_t_15 = Py_TYPE(__pyx_t_5)->tp_iternext;
-        index = 0; __pyx_t_3 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_3)) goto __pyx_L15_unpacking_failed;
-        __Pyx_GOTREF(__pyx_t_3);
-        index = 1; __pyx_t_4 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_4)) goto __pyx_L15_unpacking_failed;
-        __Pyx_GOTREF(__pyx_t_4);
-        if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_5), 2) < 0) __PYX_ERR(0, 73, __pyx_L1_error)
-        __pyx_t_15 = NULL;
-        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-        goto __pyx_L16_unpacking_done;
-        __pyx_L15_unpacking_failed:;
-        __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-        __pyx_t_15 = NULL;
-        if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-        __PYX_ERR(0, 73, __pyx_L1_error)
-        __pyx_L16_unpacking_done:;
-      }
-      __Pyx_XDECREF_SET(__pyx_v_seq1, __pyx_t_3);
-      __pyx_t_3 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_seq2, __pyx_t_4);
-      __pyx_t_4 = 0;
-
 074: 
-
+075:             t1, a1, b1, head1, tail1, head_tail1 = all_decomp1[seq1]
-
      __pyx_t_4 = __Pyx_PyObject_GetItem(__pyx_v_all_decomp1, __pyx_v_seq1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 75, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_4);
-      if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) {
-        PyObject* sequence = __pyx_t_4;
-        Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-        if (unlikely(size != 6)) {
-          if (size > 6) __Pyx_RaiseTooManyValuesError(6);
-          else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-          __PYX_ERR(0, 75, __pyx_L1_error)
-        }
-        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        if (likely(PyTuple_CheckExact(sequence))) {
-          __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); 
-          __pyx_t_5 = PyTuple_GET_ITEM(sequence, 1); 
-          __pyx_t_7 = PyTuple_GET_ITEM(sequence, 2); 
-          __pyx_t_10 = PyTuple_GET_ITEM(sequence, 3); 
-          __pyx_t_11 = PyTuple_GET_ITEM(sequence, 4); 
-          __pyx_t_12 = PyTuple_GET_ITEM(sequence, 5); 
-        } else {
-          __pyx_t_3 = PyList_GET_ITEM(sequence, 0); 
-          __pyx_t_5 = PyList_GET_ITEM(sequence, 1); 
-          __pyx_t_7 = PyList_GET_ITEM(sequence, 2); 
-          __pyx_t_10 = PyList_GET_ITEM(sequence, 3); 
-          __pyx_t_11 = PyList_GET_ITEM(sequence, 4); 
-          __pyx_t_12 = PyList_GET_ITEM(sequence, 5); 
-        }
-        __Pyx_INCREF(__pyx_t_3);
-        __Pyx_INCREF(__pyx_t_5);
-        __Pyx_INCREF(__pyx_t_7);
-        __Pyx_INCREF(__pyx_t_10);
-        __Pyx_INCREF(__pyx_t_11);
-        __Pyx_INCREF(__pyx_t_12);
-        #else
-        {
-          Py_ssize_t i;
-          PyObject** temps[6] = {&__pyx_t_3,&__pyx_t_5,&__pyx_t_7,&__pyx_t_10,&__pyx_t_11,&__pyx_t_12};
-          for (i=0; i < 6; i++) {
-            PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 75, __pyx_L1_error)
-            __Pyx_GOTREF(item);
-            *(temps[i]) = item;
-          }
-        }
-        #endif
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        Py_ssize_t index = -1;
-        PyObject** temps[6] = {&__pyx_t_3,&__pyx_t_5,&__pyx_t_7,&__pyx_t_10,&__pyx_t_11,&__pyx_t_12};
-        __pyx_t_13 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 75, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_13);
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-        __pyx_t_15 = Py_TYPE(__pyx_t_13)->tp_iternext;
-        for (index=0; index < 6; index++) {
-          PyObject* item = __pyx_t_15(__pyx_t_13); if (unlikely(!item)) goto __pyx_L17_unpacking_failed;
-          __Pyx_GOTREF(item);
-          *(temps[index]) = item;
-        }
-        if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_13), 6) < 0) __PYX_ERR(0, 75, __pyx_L1_error)
-        __pyx_t_15 = NULL;
-        __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
-        goto __pyx_L18_unpacking_done;
-        __pyx_L17_unpacking_failed:;
-        __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
-        __pyx_t_15 = NULL;
-        if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-        __PYX_ERR(0, 75, __pyx_L1_error)
-        __pyx_L18_unpacking_done:;
-      }
-      __Pyx_XDECREF_SET(__pyx_v_t1, __pyx_t_3);
-      __pyx_t_3 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_a1, __pyx_t_5);
-      __pyx_t_5 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_b1, __pyx_t_7);
-      __pyx_t_7 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_head1, __pyx_t_10);
-      __pyx_t_10 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_tail1, __pyx_t_11);
-      __pyx_t_11 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_head_tail1, __pyx_t_12);
-      __pyx_t_12 = 0;
-
+076:             t2, a2, b2, head2, tail2, head_tail2 = all_decomp2[seq2]
-
      __pyx_t_4 = __Pyx_PyObject_GetItem(__pyx_v_all_decomp2, __pyx_v_seq2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 76, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_4);
-      if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) {
-        PyObject* sequence = __pyx_t_4;
-        Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-        if (unlikely(size != 6)) {
-          if (size > 6) __Pyx_RaiseTooManyValuesError(6);
-          else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-          __PYX_ERR(0, 76, __pyx_L1_error)
-        }
-        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        if (likely(PyTuple_CheckExact(sequence))) {
-          __pyx_t_12 = PyTuple_GET_ITEM(sequence, 0); 
-          __pyx_t_11 = PyTuple_GET_ITEM(sequence, 1); 
-          __pyx_t_10 = PyTuple_GET_ITEM(sequence, 2); 
-          __pyx_t_7 = PyTuple_GET_ITEM(sequence, 3); 
-          __pyx_t_5 = PyTuple_GET_ITEM(sequence, 4); 
-          __pyx_t_3 = PyTuple_GET_ITEM(sequence, 5); 
-        } else {
-          __pyx_t_12 = PyList_GET_ITEM(sequence, 0); 
-          __pyx_t_11 = PyList_GET_ITEM(sequence, 1); 
-          __pyx_t_10 = PyList_GET_ITEM(sequence, 2); 
-          __pyx_t_7 = PyList_GET_ITEM(sequence, 3); 
-          __pyx_t_5 = PyList_GET_ITEM(sequence, 4); 
-          __pyx_t_3 = PyList_GET_ITEM(sequence, 5); 
-        }
-        __Pyx_INCREF(__pyx_t_12);
-        __Pyx_INCREF(__pyx_t_11);
-        __Pyx_INCREF(__pyx_t_10);
-        __Pyx_INCREF(__pyx_t_7);
-        __Pyx_INCREF(__pyx_t_5);
-        __Pyx_INCREF(__pyx_t_3);
-        #else
-        {
-          Py_ssize_t i;
-          PyObject** temps[6] = {&__pyx_t_12,&__pyx_t_11,&__pyx_t_10,&__pyx_t_7,&__pyx_t_5,&__pyx_t_3};
-          for (i=0; i < 6; i++) {
-            PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 76, __pyx_L1_error)
-            __Pyx_GOTREF(item);
-            *(temps[i]) = item;
-          }
-        }
-        #endif
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      } else {
-        Py_ssize_t index = -1;
-        PyObject** temps[6] = {&__pyx_t_12,&__pyx_t_11,&__pyx_t_10,&__pyx_t_7,&__pyx_t_5,&__pyx_t_3};
-        __pyx_t_13 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 76, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_13);
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-        __pyx_t_15 = Py_TYPE(__pyx_t_13)->tp_iternext;
-        for (index=0; index < 6; index++) {
-          PyObject* item = __pyx_t_15(__pyx_t_13); if (unlikely(!item)) goto __pyx_L19_unpacking_failed;
-          __Pyx_GOTREF(item);
-          *(temps[index]) = item;
-        }
-        if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_13), 6) < 0) __PYX_ERR(0, 76, __pyx_L1_error)
-        __pyx_t_15 = NULL;
-        __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
-        goto __pyx_L20_unpacking_done;
-        __pyx_L19_unpacking_failed:;
-        __Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
-        __pyx_t_15 = NULL;
-        if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-        __PYX_ERR(0, 76, __pyx_L1_error)
-        __pyx_L20_unpacking_done:;
-      }
-      __Pyx_XDECREF_SET(__pyx_v_t2, __pyx_t_12);
-      __pyx_t_12 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_a2, __pyx_t_11);
-      __pyx_t_11 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_b2, __pyx_t_10);
-      __pyx_t_10 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_head2, __pyx_t_7);
-      __pyx_t_7 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_tail2, __pyx_t_5);
-      __pyx_t_5 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_head_tail2, __pyx_t_3);
-      __pyx_t_3 = 0;
-
 077: 
-
 078:             # Case 2: The current edge in sequence1 is deleted
-
+079:             try_key = (head_tail1, seq2)
-
      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 79, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_4);
-      __Pyx_INCREF(__pyx_v_head_tail1);
-      __Pyx_GIVEREF(__pyx_v_head_tail1);
-      PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_head_tail1);
-      __Pyx_INCREF(__pyx_v_seq2);
-      __Pyx_GIVEREF(__pyx_v_seq2);
-      PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_seq2);
-      __Pyx_XDECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_4));
-      __pyx_t_4 = 0;
-
+080:             if try_key in _results:
-
      __pyx_t_1 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 80, __pyx_L1_error)
-      __pyx_t_2 = (__pyx_t_1 != 0);
-      if (__pyx_t_2) {
-/* … */
-        goto __pyx_L21;
-      }
-
+081:                 cand1 = _results[try_key]
-
        __pyx_t_4 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 81, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_XDECREF_SET(__pyx_v_cand1, __pyx_t_4);
-        __pyx_t_4 = 0;
-
 082:             else:
-
 083:                 # stack.append(key)
-
+084:                 stack.append(try_key)
-
      /*else*/ {
-        __pyx_t_16 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_try_key); if (unlikely(__pyx_t_16 == ((int)-1))) __PYX_ERR(0, 84, __pyx_L1_error)
-
+085:                 continue
-
        goto __pyx_L12_continue;
-      }
-      __pyx_L21:;
-
 086: 
-
 087:             # Case 3: The current edge in sequence2 is deleted
-
+088:             try_key = (seq1, head_tail2)
-
      __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 88, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_4);
-      __Pyx_INCREF(__pyx_v_seq1);
-      __Pyx_GIVEREF(__pyx_v_seq1);
-      PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_seq1);
-      __Pyx_INCREF(__pyx_v_head_tail2);
-      __Pyx_GIVEREF(__pyx_v_head_tail2);
-      PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_head_tail2);
-      __Pyx_DECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_4));
-      __pyx_t_4 = 0;
-
+089:             if try_key in _results:
-
      __pyx_t_2 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 89, __pyx_L1_error)
-      __pyx_t_1 = (__pyx_t_2 != 0);
-      if (__pyx_t_1) {
-/* … */
-        goto __pyx_L22;
-      }
-
+090:                 cand2 = _results[try_key]
-
        __pyx_t_4 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 90, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_XDECREF_SET(__pyx_v_cand2, __pyx_t_4);
-        __pyx_t_4 = 0;
-
 091:             else:
-
 092:                 # stack.append(key)
-
+093:                 stack.append(try_key)
-
      /*else*/ {
-        __pyx_t_16 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_try_key); if (unlikely(__pyx_t_16 == ((int)-1))) __PYX_ERR(0, 93, __pyx_L1_error)
-
+094:                 continue
-
        goto __pyx_L12_continue;
-      }
-      __pyx_L22:;
-
 095: 
-
 096:             # Case 1: The LCS involves this edge
-
+097:             affinity = node_affinity(t1, t2)
-
      __Pyx_INCREF(__pyx_v_node_affinity);
-      __pyx_t_3 = __pyx_v_node_affinity; __pyx_t_5 = NULL;
-      __pyx_t_17 = 0;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_5 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_5)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_5);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
-          __pyx_t_17 = 1;
-        }
-      }
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_3)) {
-        PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_v_t1, __pyx_v_t2};
-        __pyx_t_4 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_17, 2+__pyx_t_17); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 97, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
-        PyObject *__pyx_temp[3] = {__pyx_t_5, __pyx_v_t1, __pyx_v_t2};
-        __pyx_t_4 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_17, 2+__pyx_t_17); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 97, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_5); __pyx_t_5 = 0;
-        __Pyx_GOTREF(__pyx_t_4);
-      } else
-      #endif
-      {
-        __pyx_t_7 = PyTuple_New(2+__pyx_t_17); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 97, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_7);
-        if (__pyx_t_5) {
-          __Pyx_GIVEREF(__pyx_t_5); PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_5); __pyx_t_5 = NULL;
-        }
-        __Pyx_INCREF(__pyx_v_t1);
-        __Pyx_GIVEREF(__pyx_v_t1);
-        PyTuple_SET_ITEM(__pyx_t_7, 0+__pyx_t_17, __pyx_v_t1);
-        __Pyx_INCREF(__pyx_v_t2);
-        __Pyx_GIVEREF(__pyx_v_t2);
-        PyTuple_SET_ITEM(__pyx_t_7, 1+__pyx_t_17, __pyx_v_t2);
-        __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_7, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 97, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-      }
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_affinity, __pyx_t_4);
-      __pyx_t_4 = 0;
-
+098:             if affinity:
-
      __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_affinity); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 98, __pyx_L1_error)
-      if (__pyx_t_1) {
-/* … */
-        goto __pyx_L23;
-      }
-
+099:                 try_key = (head1, head2)
-
        __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 99, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_INCREF(__pyx_v_head1);
-        __Pyx_GIVEREF(__pyx_v_head1);
-        PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_head1);
-        __Pyx_INCREF(__pyx_v_head2);
-        __Pyx_GIVEREF(__pyx_v_head2);
-        PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_head2);
-        __Pyx_DECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_4));
-        __pyx_t_4 = 0;
-
+100:                 if try_key in _results:
-
        __pyx_t_1 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 100, __pyx_L1_error)
-        __pyx_t_2 = (__pyx_t_1 != 0);
-        if (__pyx_t_2) {
-/* … */
-          goto __pyx_L24;
-        }
-
+101:                     pval_h, new_heads = _results[try_key]
-
          __pyx_t_4 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 101, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_4);
-          if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) {
-            PyObject* sequence = __pyx_t_4;
-            Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-            if (unlikely(size != 2)) {
-              if (size > 2) __Pyx_RaiseTooManyValuesError(2);
-              else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-              __PYX_ERR(0, 101, __pyx_L1_error)
-            }
-            #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-            if (likely(PyTuple_CheckExact(sequence))) {
-              __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); 
-              __pyx_t_7 = PyTuple_GET_ITEM(sequence, 1); 
-            } else {
-              __pyx_t_3 = PyList_GET_ITEM(sequence, 0); 
-              __pyx_t_7 = PyList_GET_ITEM(sequence, 1); 
-            }
-            __Pyx_INCREF(__pyx_t_3);
-            __Pyx_INCREF(__pyx_t_7);
-            #else
-            __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 101, __pyx_L1_error)
-            __Pyx_GOTREF(__pyx_t_3);
-            __pyx_t_7 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 101, __pyx_L1_error)
-            __Pyx_GOTREF(__pyx_t_7);
-            #endif
-            __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-          } else {
-            Py_ssize_t index = -1;
-            __pyx_t_5 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 101, __pyx_L1_error)
-            __Pyx_GOTREF(__pyx_t_5);
-            __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-            __pyx_t_15 = Py_TYPE(__pyx_t_5)->tp_iternext;
-            index = 0; __pyx_t_3 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_3)) goto __pyx_L25_unpacking_failed;
-            __Pyx_GOTREF(__pyx_t_3);
-            index = 1; __pyx_t_7 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_7)) goto __pyx_L25_unpacking_failed;
-            __Pyx_GOTREF(__pyx_t_7);
-            if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_5), 2) < 0) __PYX_ERR(0, 101, __pyx_L1_error)
-            __pyx_t_15 = NULL;
-            __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-            goto __pyx_L26_unpacking_done;
-            __pyx_L25_unpacking_failed:;
-            __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-            __pyx_t_15 = NULL;
-            if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-            __PYX_ERR(0, 101, __pyx_L1_error)
-            __pyx_L26_unpacking_done:;
-          }
-          __Pyx_XDECREF_SET(__pyx_v_pval_h, __pyx_t_3);
-          __pyx_t_3 = 0;
-          __Pyx_XDECREF_SET(__pyx_v_new_heads, __pyx_t_7);
-          __pyx_t_7 = 0;
-
 102:                 else:
-
 103:                     # stack.append(key)
-
+104:                     stack.append(try_key)
-
        /*else*/ {
-          __pyx_t_16 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_try_key); if (unlikely(__pyx_t_16 == ((int)-1))) __PYX_ERR(0, 104, __pyx_L1_error)
-
+105:                     continue
-
          goto __pyx_L12_continue;
-        }
-        __pyx_L24:;
-
 106: 
-
+107:                 try_key = (tail1, tail2)
-
        __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 107, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_INCREF(__pyx_v_tail1);
-        __Pyx_GIVEREF(__pyx_v_tail1);
-        PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_tail1);
-        __Pyx_INCREF(__pyx_v_tail2);
-        __Pyx_GIVEREF(__pyx_v_tail2);
-        PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_tail2);
-        __Pyx_DECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_4));
-        __pyx_t_4 = 0;
-
+108:                 if try_key in _results:
-
        __pyx_t_2 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 108, __pyx_L1_error)
-        __pyx_t_1 = (__pyx_t_2 != 0);
-        if (__pyx_t_1) {
-/* … */
-          goto __pyx_L27;
-        }
-
+109:                     pval_t, new_tails = _results[try_key]
-
          __pyx_t_4 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 109, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_4);
-          if ((likely(PyTuple_CheckExact(__pyx_t_4))) || (PyList_CheckExact(__pyx_t_4))) {
-            PyObject* sequence = __pyx_t_4;
-            Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-            if (unlikely(size != 2)) {
-              if (size > 2) __Pyx_RaiseTooManyValuesError(2);
-              else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-              __PYX_ERR(0, 109, __pyx_L1_error)
-            }
-            #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-            if (likely(PyTuple_CheckExact(sequence))) {
-              __pyx_t_7 = PyTuple_GET_ITEM(sequence, 0); 
-              __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); 
-            } else {
-              __pyx_t_7 = PyList_GET_ITEM(sequence, 0); 
-              __pyx_t_3 = PyList_GET_ITEM(sequence, 1); 
-            }
-            __Pyx_INCREF(__pyx_t_7);
-            __Pyx_INCREF(__pyx_t_3);
-            #else
-            __pyx_t_7 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 109, __pyx_L1_error)
-            __Pyx_GOTREF(__pyx_t_7);
-            __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 109, __pyx_L1_error)
-            __Pyx_GOTREF(__pyx_t_3);
-            #endif
-            __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-          } else {
-            Py_ssize_t index = -1;
-            __pyx_t_5 = PyObject_GetIter(__pyx_t_4); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 109, __pyx_L1_error)
-            __Pyx_GOTREF(__pyx_t_5);
-            __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-            __pyx_t_15 = Py_TYPE(__pyx_t_5)->tp_iternext;
-            index = 0; __pyx_t_7 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_7)) goto __pyx_L28_unpacking_failed;
-            __Pyx_GOTREF(__pyx_t_7);
-            index = 1; __pyx_t_3 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_3)) goto __pyx_L28_unpacking_failed;
-            __Pyx_GOTREF(__pyx_t_3);
-            if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_5), 2) < 0) __PYX_ERR(0, 109, __pyx_L1_error)
-            __pyx_t_15 = NULL;
-            __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-            goto __pyx_L29_unpacking_done;
-            __pyx_L28_unpacking_failed:;
-            __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-            __pyx_t_15 = NULL;
-            if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-            __PYX_ERR(0, 109, __pyx_L1_error)
-            __pyx_L29_unpacking_done:;
-          }
-          __Pyx_XDECREF_SET(__pyx_v_pval_t, __pyx_t_7);
-          __pyx_t_7 = 0;
-          __Pyx_XDECREF_SET(__pyx_v_new_tails, __pyx_t_3);
-          __pyx_t_3 = 0;
-
 110:                 else:
-
 111:                     # stack.append(key)
-
+112:                     stack.append(try_key)
-
        /*else*/ {
-          __pyx_t_16 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_try_key); if (unlikely(__pyx_t_16 == ((int)-1))) __PYX_ERR(0, 112, __pyx_L1_error)
-
+113:                     continue
-
          goto __pyx_L12_continue;
-        }
-        __pyx_L27:;
-
 114: 
-
+115:                 new_head1, new_head2 = new_heads
-
        if ((likely(PyTuple_CheckExact(__pyx_v_new_heads))) || (PyList_CheckExact(__pyx_v_new_heads))) {
-          PyObject* sequence = __pyx_v_new_heads;
-          Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-          if (unlikely(size != 2)) {
-            if (size > 2) __Pyx_RaiseTooManyValuesError(2);
-            else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-            __PYX_ERR(0, 115, __pyx_L1_error)
-          }
-          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-          if (likely(PyTuple_CheckExact(sequence))) {
-            __pyx_t_4 = PyTuple_GET_ITEM(sequence, 0); 
-            __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); 
-          } else {
-            __pyx_t_4 = PyList_GET_ITEM(sequence, 0); 
-            __pyx_t_3 = PyList_GET_ITEM(sequence, 1); 
-          }
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(__pyx_t_3);
-          #else
-          __pyx_t_4 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 115, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_4);
-          __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 115, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_3);
-          #endif
-        } else {
-          Py_ssize_t index = -1;
-          __pyx_t_7 = PyObject_GetIter(__pyx_v_new_heads); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 115, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_7);
-          __pyx_t_15 = Py_TYPE(__pyx_t_7)->tp_iternext;
-          index = 0; __pyx_t_4 = __pyx_t_15(__pyx_t_7); if (unlikely(!__pyx_t_4)) goto __pyx_L30_unpacking_failed;
-          __Pyx_GOTREF(__pyx_t_4);
-          index = 1; __pyx_t_3 = __pyx_t_15(__pyx_t_7); if (unlikely(!__pyx_t_3)) goto __pyx_L30_unpacking_failed;
-          __Pyx_GOTREF(__pyx_t_3);
-          if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_7), 2) < 0) __PYX_ERR(0, 115, __pyx_L1_error)
-          __pyx_t_15 = NULL;
-          __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-          goto __pyx_L31_unpacking_done;
-          __pyx_L30_unpacking_failed:;
-          __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-          __pyx_t_15 = NULL;
-          if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-          __PYX_ERR(0, 115, __pyx_L1_error)
-          __pyx_L31_unpacking_done:;
-        }
-        __Pyx_XDECREF_SET(__pyx_v_new_head1, __pyx_t_4);
-        __pyx_t_4 = 0;
-        __Pyx_XDECREF_SET(__pyx_v_new_head2, __pyx_t_3);
-        __pyx_t_3 = 0;
-
+116:                 new_tail1, new_tail2 = new_tails
-
        if ((likely(PyTuple_CheckExact(__pyx_v_new_tails))) || (PyList_CheckExact(__pyx_v_new_tails))) {
-          PyObject* sequence = __pyx_v_new_tails;
-          Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-          if (unlikely(size != 2)) {
-            if (size > 2) __Pyx_RaiseTooManyValuesError(2);
-            else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-            __PYX_ERR(0, 116, __pyx_L1_error)
-          }
-          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-          if (likely(PyTuple_CheckExact(sequence))) {
-            __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); 
-            __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); 
-          } else {
-            __pyx_t_3 = PyList_GET_ITEM(sequence, 0); 
-            __pyx_t_4 = PyList_GET_ITEM(sequence, 1); 
-          }
-          __Pyx_INCREF(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_4);
-          #else
-          __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 116, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_3);
-          __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 116, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_4);
-          #endif
-        } else {
-          Py_ssize_t index = -1;
-          __pyx_t_7 = PyObject_GetIter(__pyx_v_new_tails); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 116, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_7);
-          __pyx_t_15 = Py_TYPE(__pyx_t_7)->tp_iternext;
-          index = 0; __pyx_t_3 = __pyx_t_15(__pyx_t_7); if (unlikely(!__pyx_t_3)) goto __pyx_L32_unpacking_failed;
-          __Pyx_GOTREF(__pyx_t_3);
-          index = 1; __pyx_t_4 = __pyx_t_15(__pyx_t_7); if (unlikely(!__pyx_t_4)) goto __pyx_L32_unpacking_failed;
-          __Pyx_GOTREF(__pyx_t_4);
-          if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_7), 2) < 0) __PYX_ERR(0, 116, __pyx_L1_error)
-          __pyx_t_15 = NULL;
-          __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-          goto __pyx_L33_unpacking_done;
-          __pyx_L32_unpacking_failed:;
-          __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-          __pyx_t_15 = NULL;
-          if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-          __PYX_ERR(0, 116, __pyx_L1_error)
-          __pyx_L33_unpacking_done:;
-        }
-        __Pyx_XDECREF_SET(__pyx_v_new_tail1, __pyx_t_3);
-        __pyx_t_3 = 0;
-        __Pyx_XDECREF_SET(__pyx_v_new_tail2, __pyx_t_4);
-        __pyx_t_4 = 0;
-
 117: 
-
+118:                 subseq1 = a1 + new_head1 + b1 + new_tail1
-
        __pyx_t_4 = PyNumber_Add(__pyx_v_a1, __pyx_v_new_head1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 118, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        __pyx_t_3 = PyNumber_Add(__pyx_t_4, __pyx_v_b1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 118, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-        __pyx_t_4 = PyNumber_Add(__pyx_t_3, __pyx_v_new_tail1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 118, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        __Pyx_XDECREF_SET(__pyx_v_subseq1, __pyx_t_4);
-        __pyx_t_4 = 0;
-
+119:                 subseq2 = a2 + new_head2 + b2 + new_tail2
-
        __pyx_t_4 = PyNumber_Add(__pyx_v_a2, __pyx_v_new_head2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 119, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        __pyx_t_3 = PyNumber_Add(__pyx_t_4, __pyx_v_b2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 119, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-        __pyx_t_4 = PyNumber_Add(__pyx_t_3, __pyx_v_new_tail2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 119, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        __Pyx_XDECREF_SET(__pyx_v_subseq2, __pyx_t_4);
-        __pyx_t_4 = 0;
-
 120: 
-
+121:                 res3 = (subseq1, subseq2)
-
        __pyx_t_4 = PyTuple_New(2); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 121, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        __Pyx_INCREF(__pyx_v_subseq1);
-        __Pyx_GIVEREF(__pyx_v_subseq1);
-        PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_subseq1);
-        __Pyx_INCREF(__pyx_v_subseq2);
-        __Pyx_GIVEREF(__pyx_v_subseq2);
-        PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_subseq2);
-        __Pyx_XDECREF_SET(__pyx_v_res3, ((PyObject*)__pyx_t_4));
-        __pyx_t_4 = 0;
-
+122:                 val3 = pval_h + pval_t + affinity
-
        __pyx_t_4 = PyNumber_Add(__pyx_v_pval_h, __pyx_v_pval_t); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 122, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_4);
-        __pyx_t_3 = PyNumber_Add(__pyx_t_4, __pyx_v_affinity); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 122, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-        __Pyx_XDECREF_SET(__pyx_v_val3, __pyx_t_3);
-        __pyx_t_3 = 0;
-
+123:                 cand3 = (val3, res3)
-
        __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 123, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_INCREF(__pyx_v_val3);
-        __Pyx_GIVEREF(__pyx_v_val3);
-        PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_val3);
-        __Pyx_INCREF(__pyx_v_res3);
-        __Pyx_GIVEREF(__pyx_v_res3);
-        PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_res3);
-        __Pyx_XDECREF_SET(__pyx_v_cand3, ((PyObject*)__pyx_t_3));
-        __pyx_t_3 = 0;
-
 124:             else:
-
+125:                 cand3 = (-1, None)
-
      /*else*/ {
-        __Pyx_INCREF(__pyx_tuple_);
-        __Pyx_XDECREF_SET(__pyx_v_cand3, __pyx_tuple_);
-      }
-      __pyx_L23:;
-/* … */
-  __pyx_tuple_ = PyTuple_Pack(2, __pyx_int_neg_1, Py_None); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 125, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple_);
-  __Pyx_GIVEREF(__pyx_tuple_);
-
 126: 
-
 127:             # We solved the frame
-
+128:             _results[key] = max(cand1, cand2, cand3)
-
      __Pyx_INCREF(__pyx_v_cand2);
-      __pyx_t_3 = __pyx_v_cand2;
-      __Pyx_INCREF(__pyx_v_cand3);
-      __pyx_t_18 = __pyx_v_cand3;
-      __Pyx_INCREF(__pyx_v_cand1);
-      __pyx_t_4 = __pyx_v_cand1;
-      __pyx_t_5 = PyObject_RichCompare(__pyx_t_3, __pyx_t_4, Py_GT); __Pyx_XGOTREF(__pyx_t_5); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 128, __pyx_L1_error)
-      __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 128, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      if (__pyx_t_1) {
-        __Pyx_INCREF(__pyx_t_3);
-        __pyx_t_7 = __pyx_t_3;
-      } else {
-        __Pyx_INCREF(__pyx_t_4);
-        __pyx_t_7 = __pyx_t_4;
-      }
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_INCREF(__pyx_t_7);
-      __pyx_t_4 = __pyx_t_7;
-      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-      __pyx_t_5 = PyObject_RichCompare(__pyx_t_18, __pyx_t_4, Py_GT); __Pyx_XGOTREF(__pyx_t_5); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 128, __pyx_L1_error)
-      __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_t_5); if (unlikely(__pyx_t_1 < 0)) __PYX_ERR(0, 128, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-      if (__pyx_t_1) {
-        __Pyx_INCREF(__pyx_t_18);
-        __pyx_t_7 = __pyx_t_18;
-      } else {
-        __Pyx_INCREF(__pyx_t_4);
-        __pyx_t_7 = __pyx_t_4;
-      }
-      __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_3 = __pyx_t_7;
-      __Pyx_INCREF(__pyx_t_3);
-      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-      if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_v_key, __pyx_t_3) < 0)) __PYX_ERR(0, 128, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+129:         stack.pop()
-
    __pyx_t_3 = __Pyx_PyList_Pop(__pyx_v_stack); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 129, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __pyx_L12_continue:;
-  }
-
 130: 
-
+131:     val, best = _results[key0]
-
  __pyx_t_3 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_key0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 131, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) {
-    PyObject* sequence = __pyx_t_3;
-    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-    if (unlikely(size != 2)) {
-      if (size > 2) __Pyx_RaiseTooManyValuesError(2);
-      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-      __PYX_ERR(0, 131, __pyx_L1_error)
-    }
-    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-    if (likely(PyTuple_CheckExact(sequence))) {
-      __pyx_t_7 = PyTuple_GET_ITEM(sequence, 0); 
-      __pyx_t_4 = PyTuple_GET_ITEM(sequence, 1); 
-    } else {
-      __pyx_t_7 = PyList_GET_ITEM(sequence, 0); 
-      __pyx_t_4 = PyList_GET_ITEM(sequence, 1); 
-    }
-    __Pyx_INCREF(__pyx_t_7);
-    __Pyx_INCREF(__pyx_t_4);
-    #else
-    __pyx_t_7 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 131, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
-    __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 131, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_4);
-    #endif
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  } else {
-    Py_ssize_t index = -1;
-    __pyx_t_5 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 131, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_5);
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __pyx_t_15 = Py_TYPE(__pyx_t_5)->tp_iternext;
-    index = 0; __pyx_t_7 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_7)) goto __pyx_L34_unpacking_failed;
-    __Pyx_GOTREF(__pyx_t_7);
-    index = 1; __pyx_t_4 = __pyx_t_15(__pyx_t_5); if (unlikely(!__pyx_t_4)) goto __pyx_L34_unpacking_failed;
-    __Pyx_GOTREF(__pyx_t_4);
-    if (__Pyx_IternextUnpackEndCheck(__pyx_t_15(__pyx_t_5), 2) < 0) __PYX_ERR(0, 131, __pyx_L1_error)
-    __pyx_t_15 = NULL;
-    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    goto __pyx_L35_unpacking_done;
-    __pyx_L34_unpacking_failed:;
-    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
-    __pyx_t_15 = NULL;
-    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-    __PYX_ERR(0, 131, __pyx_L1_error)
-    __pyx_L35_unpacking_done:;
-  }
-  __pyx_v_val = __pyx_t_7;
-  __pyx_t_7 = 0;
-  __Pyx_DECREF_SET(__pyx_v_best, __pyx_t_4);
-  __pyx_t_4 = 0;
-
+132:     found = (best, val)
-
  __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 132, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_INCREF(__pyx_v_best);
-  __Pyx_GIVEREF(__pyx_v_best);
-  PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_best);
-  __Pyx_INCREF(__pyx_v_val);
-  __Pyx_GIVEREF(__pyx_v_val);
-  PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_val);
-  __pyx_v_found = ((PyObject*)__pyx_t_3);
-  __pyx_t_3 = 0;
-
+133:     return found
-
  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_found);
-  __pyx_r = __pyx_v_found;
-  goto __pyx_L0;
-
 134: 
-
 135: 
-
+136: def _lcs_iter_prehash2_cython(full_seq1, full_seq2, open_to_close, node_affinity, open_to_node):
-
/* Python wrapper */
-static PyObject *__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_3_lcs_iter_prehash2_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_2_lcs_iter_prehash2_cython[] = "\n    Version of the lcs iterative algorithm where we precompute hash values\n    ";
-static PyMethodDef __pyx_mdef_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_3_lcs_iter_prehash2_cython = {"_lcs_iter_prehash2_cython", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_3_lcs_iter_prehash2_cython, METH_VARARGS|METH_KEYWORDS, __pyx_doc_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_2_lcs_iter_prehash2_cython};
-static PyObject *__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_3_lcs_iter_prehash2_cython(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  PyObject *__pyx_v_full_seq1 = 0;
-  PyObject *__pyx_v_full_seq2 = 0;
-  PyObject *__pyx_v_open_to_close = 0;
-  PyObject *__pyx_v_node_affinity = 0;
-  PyObject *__pyx_v_open_to_node = 0;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("_lcs_iter_prehash2_cython (wrapper)", 0);
-  {
-    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_full_seq1,&__pyx_n_s_full_seq2,&__pyx_n_s_open_to_close,&__pyx_n_s_node_affinity,&__pyx_n_s_open_to_node,0};
-    PyObject* values[5] = {0,0,0,0,0};
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
-        CYTHON_FALLTHROUGH;
-        case  4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
-        CYTHON_FALLTHROUGH;
-        case  3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
-        CYTHON_FALLTHROUGH;
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        CYTHON_FALLTHROUGH;
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        CYTHON_FALLTHROUGH;
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_full_seq1)) != 0)) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        CYTHON_FALLTHROUGH;
-        case  1:
-        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_full_seq2)) != 0)) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("_lcs_iter_prehash2_cython", 1, 5, 5, 1); __PYX_ERR(0, 136, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case  2:
-        if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_open_to_close)) != 0)) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("_lcs_iter_prehash2_cython", 1, 5, 5, 2); __PYX_ERR(0, 136, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case  3:
-        if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_node_affinity)) != 0)) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("_lcs_iter_prehash2_cython", 1, 5, 5, 3); __PYX_ERR(0, 136, __pyx_L3_error)
-        }
-        CYTHON_FALLTHROUGH;
-        case  4:
-        if (likely((values[4] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_open_to_node)) != 0)) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("_lcs_iter_prehash2_cython", 1, 5, 5, 4); __PYX_ERR(0, 136, __pyx_L3_error)
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "_lcs_iter_prehash2_cython") < 0)) __PYX_ERR(0, 136, __pyx_L3_error)
-      }
-    } else if (PyTuple_GET_SIZE(__pyx_args) != 5) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-      values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
-      values[3] = PyTuple_GET_ITEM(__pyx_args, 3);
-      values[4] = PyTuple_GET_ITEM(__pyx_args, 4);
-    }
-    __pyx_v_full_seq1 = values[0];
-    __pyx_v_full_seq2 = values[1];
-    __pyx_v_open_to_close = values[2];
-    __pyx_v_node_affinity = values[3];
-    __pyx_v_open_to_node = values[4];
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("_lcs_iter_prehash2_cython", 1, 5, 5, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 136, __pyx_L3_error)
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython._lcs_iter_prehash2_cython", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_2_lcs_iter_prehash2_cython(__pyx_self, __pyx_v_full_seq1, __pyx_v_full_seq2, __pyx_v_open_to_close, __pyx_v_node_affinity, __pyx_v_open_to_node);
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_2_lcs_iter_prehash2_cython(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_full_seq1, PyObject *__pyx_v_full_seq2, PyObject *__pyx_v_open_to_close, PyObject *__pyx_v_node_affinity, PyObject *__pyx_v_open_to_node) {
-  PyObject *__pyx_v_all_decomp1 = 0;
-  PyObject *__pyx_v_all_decomp2 = 0;
-  PyObject *__pyx_v_key_decomp1 = 0;
-  PyObject *__pyx_v_key_decomp2 = 0;
-  PyObject *__pyx_v__results = 0;
-  PyObject *__pyx_v_empty1 = NULL;
-  PyObject *__pyx_v_empty2 = NULL;
-  Py_hash_t __pyx_v_empty1_key;
-  Py_hash_t __pyx_v_empty2_key;
-  PyObject *__pyx_v_best = 0;
-  PyObject *__pyx_v_info1 = 0;
-  PyObject *__pyx_v_info2 = 0;
-  PyObject *__pyx_v_try_key = 0;
-  PyObject *__pyx_v_key = 0;
-  Py_hash_t __pyx_v_seq1_key;
-  Py_hash_t __pyx_v_seq2_key;
-  Py_hash_t __pyx_v_head1_key;
-  Py_hash_t __pyx_v_tail1_key;
-  Py_hash_t __pyx_v_head_tail1_key;
-  Py_hash_t __pyx_v_head2_key;
-  Py_hash_t __pyx_v_tail2_key;
-  Py_hash_t __pyx_v_head_tail2_key;
-  PyObject *__pyx_v_frame = 0;
-  PyObject *__pyx_v_miss_frame = 0;
-  PyObject *__pyx_v_base_result = NULL;
-  PyObject *__pyx_v_seq1 = NULL;
-  PyObject *__pyx_v_seq2 = NULL;
-  Py_hash_t __pyx_v_full_seq1_key;
-  Py_hash_t __pyx_v_full_seq2_key;
-  PyObject *__pyx_v_key0 = 0;
-  PyObject *__pyx_v_frame0 = 0;
-  PyObject *__pyx_v_stack = 0;
-  PyObject *__pyx_v_tok1 = NULL;
-  PyObject *__pyx_v_head1 = NULL;
-  PyObject *__pyx_v_tail1 = NULL;
-  PyObject *__pyx_v_head_tail1 = NULL;
-  PyObject *__pyx_v_a1 = NULL;
-  PyObject *__pyx_v_b1 = NULL;
-  PyObject *__pyx_v_tok2 = NULL;
-  PyObject *__pyx_v_head2 = NULL;
-  PyObject *__pyx_v_tail2 = NULL;
-  PyObject *__pyx_v_head_tail2 = NULL;
-  PyObject *__pyx_v_a2 = NULL;
-  PyObject *__pyx_v_b2 = NULL;
-  PyObject *__pyx_v_affinity = NULL;
-  PyObject *__pyx_v_cand1 = NULL;
-  PyObject *__pyx_v_cand2 = NULL;
-  PyObject *__pyx_v_pval_h = NULL;
-  PyObject *__pyx_v_new_heads = NULL;
-  PyObject *__pyx_v_pval_t = NULL;
-  PyObject *__pyx_v_new_tails = NULL;
-  PyObject *__pyx_v_new_head1 = NULL;
-  PyObject *__pyx_v_new_head2 = NULL;
-  PyObject *__pyx_v_new_tail1 = NULL;
-  PyObject *__pyx_v_new_tail2 = NULL;
-  PyObject *__pyx_v_subseq1 = NULL;
-  PyObject *__pyx_v_subseq2 = NULL;
-  PyObject *__pyx_v_res3 = NULL;
-  PyObject *__pyx_v_val3 = NULL;
-  PyObject *__pyx_v_cand3 = NULL;
-  PyObject *__pyx_v_val = NULL;
-  PyObject *__pyx_v_found = NULL;
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("_lcs_iter_prehash2_cython", 0);
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_8);
-  __Pyx_XDECREF(__pyx_t_10);
-  __Pyx_XDECREF(__pyx_t_15);
-  __Pyx_XDECREF(__pyx_t_16);
-  __Pyx_XDECREF(__pyx_t_17);
-  __Pyx_XDECREF(__pyx_t_18);
-  __Pyx_XDECREF(__pyx_t_21);
-  __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython._lcs_iter_prehash2_cython", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = NULL;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_all_decomp1);
-  __Pyx_XDECREF(__pyx_v_all_decomp2);
-  __Pyx_XDECREF(__pyx_v_key_decomp1);
-  __Pyx_XDECREF(__pyx_v_key_decomp2);
-  __Pyx_XDECREF(__pyx_v__results);
-  __Pyx_XDECREF(__pyx_v_empty1);
-  __Pyx_XDECREF(__pyx_v_empty2);
-  __Pyx_XDECREF(__pyx_v_best);
-  __Pyx_XDECREF(__pyx_v_info1);
-  __Pyx_XDECREF(__pyx_v_info2);
-  __Pyx_XDECREF(__pyx_v_try_key);
-  __Pyx_XDECREF(__pyx_v_key);
-  __Pyx_XDECREF(__pyx_v_frame);
-  __Pyx_XDECREF(__pyx_v_miss_frame);
-  __Pyx_XDECREF(__pyx_v_base_result);
-  __Pyx_XDECREF(__pyx_v_seq1);
-  __Pyx_XDECREF(__pyx_v_seq2);
-  __Pyx_XDECREF(__pyx_v_key0);
-  __Pyx_XDECREF(__pyx_v_frame0);
-  __Pyx_XDECREF(__pyx_v_stack);
-  __Pyx_XDECREF(__pyx_v_tok1);
-  __Pyx_XDECREF(__pyx_v_head1);
-  __Pyx_XDECREF(__pyx_v_tail1);
-  __Pyx_XDECREF(__pyx_v_head_tail1);
-  __Pyx_XDECREF(__pyx_v_a1);
-  __Pyx_XDECREF(__pyx_v_b1);
-  __Pyx_XDECREF(__pyx_v_tok2);
-  __Pyx_XDECREF(__pyx_v_head2);
-  __Pyx_XDECREF(__pyx_v_tail2);
-  __Pyx_XDECREF(__pyx_v_head_tail2);
-  __Pyx_XDECREF(__pyx_v_a2);
-  __Pyx_XDECREF(__pyx_v_b2);
-  __Pyx_XDECREF(__pyx_v_affinity);
-  __Pyx_XDECREF(__pyx_v_cand1);
-  __Pyx_XDECREF(__pyx_v_cand2);
-  __Pyx_XDECREF(__pyx_v_pval_h);
-  __Pyx_XDECREF(__pyx_v_new_heads);
-  __Pyx_XDECREF(__pyx_v_pval_t);
-  __Pyx_XDECREF(__pyx_v_new_tails);
-  __Pyx_XDECREF(__pyx_v_new_head1);
-  __Pyx_XDECREF(__pyx_v_new_head2);
-  __Pyx_XDECREF(__pyx_v_new_tail1);
-  __Pyx_XDECREF(__pyx_v_new_tail2);
-  __Pyx_XDECREF(__pyx_v_subseq1);
-  __Pyx_XDECREF(__pyx_v_subseq2);
-  __Pyx_XDECREF(__pyx_v_res3);
-  __Pyx_XDECREF(__pyx_v_val3);
-  __Pyx_XDECREF(__pyx_v_cand3);
-  __Pyx_XDECREF(__pyx_v_val);
-  __Pyx_XDECREF(__pyx_v_found);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-/* … */
-  __pyx_tuple__6 = PyTuple_Pack(67, __pyx_n_s_full_seq1, __pyx_n_s_full_seq2, __pyx_n_s_open_to_close, __pyx_n_s_node_affinity, __pyx_n_s_open_to_node, __pyx_n_s_all_decomp1, __pyx_n_s_all_decomp2, __pyx_n_s_key_decomp1, __pyx_n_s_key_decomp2, __pyx_n_s_results, __pyx_n_s_empty1, __pyx_n_s_empty2, __pyx_n_s_empty1_key, __pyx_n_s_empty2_key, __pyx_n_s_best, __pyx_n_s_info1, __pyx_n_s_info2, __pyx_n_s_try_key, __pyx_n_s_key, __pyx_n_s_seq1_key, __pyx_n_s_seq2_key, __pyx_n_s_head1_key, __pyx_n_s_tail1_key, __pyx_n_s_head_tail1_key, __pyx_n_s_head2_key, __pyx_n_s_tail2_key, __pyx_n_s_head_tail2_key, __pyx_n_s_frame, __pyx_n_s_miss_frame, __pyx_n_s_base_result, __pyx_n_s_seq1, __pyx_n_s_seq2, __pyx_n_s_full_seq1_key, __pyx_n_s_full_seq2_key, __pyx_n_s_key0, __pyx_n_s_frame0, __pyx_n_s_stack, __pyx_n_s_tok1, __pyx_n_s_head1, __pyx_n_s_tail1, __pyx_n_s_head_tail1, __pyx_n_s_a1, __pyx_n_s_b1, __pyx_n_s_tok2, __pyx_n_s_head2, __pyx_n_s_tail2, __pyx_n_s_head_tail2, __pyx_n_s_a2, __pyx_n_s_b2, __pyx_n_s_affinity, __pyx_n_s_cand1, __pyx_n_s_cand2, __pyx_n_s_pval_h, __pyx_n_s_new_heads, __pyx_n_s_pval_t, __pyx_n_s_new_tails, __pyx_n_s_new_head1, __pyx_n_s_new_head2, __pyx_n_s_new_tail1, __pyx_n_s_new_tail2, __pyx_n_s_subseq1, __pyx_n_s_subseq2, __pyx_n_s_res3, __pyx_n_s_val3, __pyx_n_s_cand3, __pyx_n_s_val, __pyx_n_s_found); if (unlikely(!__pyx_tuple__6)) __PYX_ERR(0, 136, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__6);
-  __Pyx_GIVEREF(__pyx_tuple__6);
-/* … */
-  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_3_lcs_iter_prehash2_cython, NULL, __pyx_n_s_networkx_algorithms_isomorphism); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 136, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_lcs_iter_prehash2_cython, __pyx_t_1) < 0) __PYX_ERR(0, 136, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_codeobj__7 = (PyObject*)__Pyx_PyCode_New(5, 0, 67, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__6, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_embedding_balanced_sequence_cyt, __pyx_n_s_lcs_iter_prehash2_cython, 136, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__7)) __PYX_ERR(0, 136, __pyx_L1_error)
-
 137:     """
-
 138:     Version of the lcs iterative algorithm where we precompute hash values
-
 139:     """
-
+140:     cdef dict all_decomp1 = generate_all_decomp_prehash_cython(full_seq1, open_to_close, open_to_node)
-
  if (!(likely(PyDict_CheckExact(__pyx_v_open_to_close))||((__pyx_v_open_to_close) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "dict", Py_TYPE(__pyx_v_open_to_close)->tp_name), 0))) __PYX_ERR(0, 140, __pyx_L1_error)
-  __pyx_t_1 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_prehash_cython(__pyx_v_full_seq1, ((PyObject*)__pyx_v_open_to_close), __pyx_v_open_to_node); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 140, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_v_all_decomp1 = ((PyObject*)__pyx_t_1);
-  __pyx_t_1 = 0;
-
+141:     cdef dict all_decomp2 = generate_all_decomp_prehash_cython(full_seq2, open_to_close, open_to_node)
-
  if (!(likely(PyDict_CheckExact(__pyx_v_open_to_close))||((__pyx_v_open_to_close) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "dict", Py_TYPE(__pyx_v_open_to_close)->tp_name), 0))) __PYX_ERR(0, 141, __pyx_L1_error)
-  __pyx_t_1 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_prehash_cython(__pyx_v_full_seq2, ((PyObject*)__pyx_v_open_to_close), __pyx_v_open_to_node); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 141, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_v_all_decomp2 = ((PyObject*)__pyx_t_1);
-  __pyx_t_1 = 0;
-
+142:     cdef dict key_decomp1 = {}
-
  __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 142, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_v_key_decomp1 = ((PyObject*)__pyx_t_1);
-  __pyx_t_1 = 0;
-
+143:     cdef dict key_decomp2 = {}
-
  __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 143, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_v_key_decomp2 = ((PyObject*)__pyx_t_1);
-  __pyx_t_1 = 0;
-
 144: 
-
+145:     cdef dict _results = {}
-
  __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 145, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_v__results = ((PyObject*)__pyx_t_1);
-  __pyx_t_1 = 0;
-
 146:     # Populate base cases
-
+147:     empty1 = type(next(iter(all_decomp1.keys())))()
-
  if (unlikely(__pyx_v_all_decomp1 == Py_None)) {
-    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "keys");
-    __PYX_ERR(0, 147, __pyx_L1_error)
-  }
-  __pyx_t_2 = __Pyx_PyDict_Keys(__pyx_v_all_decomp1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 147, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __pyx_t_3 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 147, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_2 = __Pyx_PyIter_Next(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 147, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __Pyx_INCREF(((PyObject *)Py_TYPE(__pyx_t_2)));
-  __pyx_t_3 = ((PyObject *)Py_TYPE(__pyx_t_2)); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_t_2 = NULL;
-  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-    __pyx_t_2 = PyMethod_GET_SELF(__pyx_t_3);
-    if (likely(__pyx_t_2)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-      __Pyx_INCREF(__pyx_t_2);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_3, function);
-    }
-  }
-  __pyx_t_1 = (__pyx_t_2) ? __Pyx_PyObject_CallOneArg(__pyx_t_3, __pyx_t_2) : __Pyx_PyObject_CallNoArg(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_2); __pyx_t_2 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 147, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_v_empty1 = __pyx_t_1;
-  __pyx_t_1 = 0;
-
+148:     empty2 = type(next(iter(all_decomp2.keys())))()
-
  if (unlikely(__pyx_v_all_decomp2 == Py_None)) {
-    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "keys");
-    __PYX_ERR(0, 148, __pyx_L1_error)
-  }
-  __pyx_t_3 = __Pyx_PyDict_Keys(__pyx_v_all_decomp2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 148, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_2 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 148, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_3 = __Pyx_PyIter_Next(__pyx_t_2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 148, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __Pyx_INCREF(((PyObject *)Py_TYPE(__pyx_t_3)));
-  __pyx_t_2 = ((PyObject *)Py_TYPE(__pyx_t_3)); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-  __pyx_t_3 = NULL;
-  if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_2))) {
-    __pyx_t_3 = PyMethod_GET_SELF(__pyx_t_2);
-    if (likely(__pyx_t_3)) {
-      PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_2);
-      __Pyx_INCREF(__pyx_t_3);
-      __Pyx_INCREF(function);
-      __Pyx_DECREF_SET(__pyx_t_2, function);
-    }
-  }
-  __pyx_t_1 = (__pyx_t_3) ? __Pyx_PyObject_CallOneArg(__pyx_t_2, __pyx_t_3) : __Pyx_PyObject_CallNoArg(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3); __pyx_t_3 = 0;
-  if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 148, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __pyx_v_empty2 = __pyx_t_1;
-  __pyx_t_1 = 0;
-
+149:     cdef Py_hash_t empty1_key = hash(empty1)
-
  __pyx_t_4 = PyObject_Hash(__pyx_v_empty1); if (unlikely(__pyx_t_4 == ((Py_hash_t)-1))) __PYX_ERR(0, 149, __pyx_L1_error)
-  __pyx_v_empty1_key = __pyx_t_4;
-
+150:     cdef Py_hash_t empty2_key = hash(empty2)
-
  __pyx_t_4 = PyObject_Hash(__pyx_v_empty2); if (unlikely(__pyx_t_4 == ((Py_hash_t)-1))) __PYX_ERR(0, 150, __pyx_L1_error)
-  __pyx_v_empty2_key = __pyx_t_4;
-
+151:     cdef tuple best = (empty1, empty2)
-
  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 151, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_INCREF(__pyx_v_empty1);
-  __Pyx_GIVEREF(__pyx_v_empty1);
-  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_empty1);
-  __Pyx_INCREF(__pyx_v_empty2);
-  __Pyx_GIVEREF(__pyx_v_empty2);
-  PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_empty2);
-  __pyx_v_best = ((PyObject*)__pyx_t_1);
-  __pyx_t_1 = 0;
-
 152: 
-
 153:     cdef tuple info1, info2
-
 154:     cdef tuple try_key, key
-
 155:     cdef Py_hash_t seq1_key, seq2_key
-
 156:     cdef Py_hash_t head1_key, tail1_key, head_tail1_key
-
 157:     cdef Py_hash_t head2_key, tail2_key, head_tail2_key
-
 158:     cdef tuple frame
-
 159:     cdef tuple miss_frame
-
 160: 
-
+161:     base_result = (0, best)
-
  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 161, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_INCREF(__pyx_int_0);
-  __Pyx_GIVEREF(__pyx_int_0);
-  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_int_0);
-  __Pyx_INCREF(__pyx_v_best);
-  __Pyx_GIVEREF(__pyx_v_best);
-  PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_best);
-  __pyx_v_base_result = ((PyObject*)__pyx_t_1);
-  __pyx_t_1 = 0;
-
+162:     for seq1, info1 in all_decomp1.items():
-
  if (unlikely(__pyx_v_all_decomp1 == Py_None)) {
-    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "items");
-    __PYX_ERR(0, 162, __pyx_L1_error)
-  }
-  __pyx_t_1 = __Pyx_PyDict_Items(__pyx_v_all_decomp1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 162, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  if (likely(PyList_CheckExact(__pyx_t_1)) || PyTuple_CheckExact(__pyx_t_1)) {
-    __pyx_t_2 = __pyx_t_1; __Pyx_INCREF(__pyx_t_2); __pyx_t_5 = 0;
-    __pyx_t_6 = NULL;
-  } else {
-    __pyx_t_5 = -1; __pyx_t_2 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 162, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_6 = Py_TYPE(__pyx_t_2)->tp_iternext; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 162, __pyx_L1_error)
-  }
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  for (;;) {
-    if (likely(!__pyx_t_6)) {
-      if (likely(PyList_CheckExact(__pyx_t_2))) {
-        if (__pyx_t_5 >= PyList_GET_SIZE(__pyx_t_2)) break;
-        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        __pyx_t_1 = PyList_GET_ITEM(__pyx_t_2, __pyx_t_5); __Pyx_INCREF(__pyx_t_1); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 162, __pyx_L1_error)
-        #else
-        __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 162, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_1);
-        #endif
-      } else {
-        if (__pyx_t_5 >= PyTuple_GET_SIZE(__pyx_t_2)) break;
-        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        __pyx_t_1 = PyTuple_GET_ITEM(__pyx_t_2, __pyx_t_5); __Pyx_INCREF(__pyx_t_1); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 162, __pyx_L1_error)
-        #else
-        __pyx_t_1 = PySequence_ITEM(__pyx_t_2, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 162, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_1);
-        #endif
-      }
-    } else {
-      __pyx_t_1 = __pyx_t_6(__pyx_t_2);
-      if (unlikely(!__pyx_t_1)) {
-        PyObject* exc_type = PyErr_Occurred();
-        if (exc_type) {
-          if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
-          else __PYX_ERR(0, 162, __pyx_L1_error)
-        }
-        break;
-      }
-      __Pyx_GOTREF(__pyx_t_1);
-    }
-    if ((likely(PyTuple_CheckExact(__pyx_t_1))) || (PyList_CheckExact(__pyx_t_1))) {
-      PyObject* sequence = __pyx_t_1;
-      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-      if (unlikely(size != 2)) {
-        if (size > 2) __Pyx_RaiseTooManyValuesError(2);
-        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-        __PYX_ERR(0, 162, __pyx_L1_error)
-      }
-      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-      if (likely(PyTuple_CheckExact(sequence))) {
-        __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); 
-        __pyx_t_7 = PyTuple_GET_ITEM(sequence, 1); 
-      } else {
-        __pyx_t_3 = PyList_GET_ITEM(sequence, 0); 
-        __pyx_t_7 = PyList_GET_ITEM(sequence, 1); 
-      }
-      __Pyx_INCREF(__pyx_t_3);
-      __Pyx_INCREF(__pyx_t_7);
-      #else
-      __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 162, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_7 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 162, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_7);
-      #endif
-      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    } else {
-      Py_ssize_t index = -1;
-      __pyx_t_8 = PyObject_GetIter(__pyx_t_1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 162, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_8);
-      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      __pyx_t_9 = Py_TYPE(__pyx_t_8)->tp_iternext;
-      index = 0; __pyx_t_3 = __pyx_t_9(__pyx_t_8); if (unlikely(!__pyx_t_3)) goto __pyx_L5_unpacking_failed;
-      __Pyx_GOTREF(__pyx_t_3);
-      index = 1; __pyx_t_7 = __pyx_t_9(__pyx_t_8); if (unlikely(!__pyx_t_7)) goto __pyx_L5_unpacking_failed;
-      __Pyx_GOTREF(__pyx_t_7);
-      if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_8), 2) < 0) __PYX_ERR(0, 162, __pyx_L1_error)
-      __pyx_t_9 = NULL;
-      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      goto __pyx_L6_unpacking_done;
-      __pyx_L5_unpacking_failed:;
-      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      __pyx_t_9 = NULL;
-      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-      __PYX_ERR(0, 162, __pyx_L1_error)
-      __pyx_L6_unpacking_done:;
-    }
-    if (!(likely(PyTuple_CheckExact(__pyx_t_7))||((__pyx_t_7) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_7)->tp_name), 0))) __PYX_ERR(0, 162, __pyx_L1_error)
-    __Pyx_XDECREF_SET(__pyx_v_seq1, __pyx_t_3);
-    __pyx_t_3 = 0;
-    __Pyx_XDECREF_SET(__pyx_v_info1, ((PyObject*)__pyx_t_7));
-    __pyx_t_7 = 0;
-/* … */
-  }
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-
+163:         seq1_key = hash(seq1)
-
    __pyx_t_4 = PyObject_Hash(__pyx_v_seq1); if (unlikely(__pyx_t_4 == ((Py_hash_t)-1))) __PYX_ERR(0, 163, __pyx_L1_error)
-    __pyx_v_seq1_key = __pyx_t_4;
-
+164:         head1_key, tail1_key, head_tail1_key = all_decomp1[seq1][5:8]
-
    if (unlikely(__pyx_v_all_decomp1 == Py_None)) {
-      PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-      __PYX_ERR(0, 164, __pyx_L1_error)
-    }
-    __pyx_t_1 = __Pyx_PyDict_GetItem(__pyx_v_all_decomp1, __pyx_v_seq1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 164, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_7 = __Pyx_PyObject_GetSlice(__pyx_t_1, 5, 8, NULL, NULL, &__pyx_slice__2, 1, 1, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 164, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    if ((likely(PyTuple_CheckExact(__pyx_t_7))) || (PyList_CheckExact(__pyx_t_7))) {
-      PyObject* sequence = __pyx_t_7;
-      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-      if (unlikely(size != 3)) {
-        if (size > 3) __Pyx_RaiseTooManyValuesError(3);
-        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-        __PYX_ERR(0, 164, __pyx_L1_error)
-      }
-      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-      if (likely(PyTuple_CheckExact(sequence))) {
-        __pyx_t_1 = PyTuple_GET_ITEM(sequence, 0); 
-        __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); 
-        __pyx_t_8 = PyTuple_GET_ITEM(sequence, 2); 
-      } else {
-        __pyx_t_1 = PyList_GET_ITEM(sequence, 0); 
-        __pyx_t_3 = PyList_GET_ITEM(sequence, 1); 
-        __pyx_t_8 = PyList_GET_ITEM(sequence, 2); 
-      }
-      __Pyx_INCREF(__pyx_t_1);
-      __Pyx_INCREF(__pyx_t_3);
-      __Pyx_INCREF(__pyx_t_8);
-      #else
-      __pyx_t_1 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 164, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 164, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_8 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 164, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_8);
-      #endif
-      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-    } else {
-      Py_ssize_t index = -1;
-      __pyx_t_10 = PyObject_GetIter(__pyx_t_7); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 164, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_10);
-      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-      __pyx_t_9 = Py_TYPE(__pyx_t_10)->tp_iternext;
-      index = 0; __pyx_t_1 = __pyx_t_9(__pyx_t_10); if (unlikely(!__pyx_t_1)) goto __pyx_L7_unpacking_failed;
-      __Pyx_GOTREF(__pyx_t_1);
-      index = 1; __pyx_t_3 = __pyx_t_9(__pyx_t_10); if (unlikely(!__pyx_t_3)) goto __pyx_L7_unpacking_failed;
-      __Pyx_GOTREF(__pyx_t_3);
-      index = 2; __pyx_t_8 = __pyx_t_9(__pyx_t_10); if (unlikely(!__pyx_t_8)) goto __pyx_L7_unpacking_failed;
-      __Pyx_GOTREF(__pyx_t_8);
-      if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_10), 3) < 0) __PYX_ERR(0, 164, __pyx_L1_error)
-      __pyx_t_9 = NULL;
-      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
-      goto __pyx_L8_unpacking_done;
-      __pyx_L7_unpacking_failed:;
-      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
-      __pyx_t_9 = NULL;
-      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-      __PYX_ERR(0, 164, __pyx_L1_error)
-      __pyx_L8_unpacking_done:;
-    }
-    __pyx_t_4 = __Pyx_PyInt_AsHash_t(__pyx_t_1); if (unlikely((__pyx_t_4 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 164, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __pyx_t_11 = __Pyx_PyInt_AsHash_t(__pyx_t_3); if (unlikely((__pyx_t_11 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 164, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __pyx_t_12 = __Pyx_PyInt_AsHash_t(__pyx_t_8); if (unlikely((__pyx_t_12 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 164, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-    __pyx_v_head1_key = __pyx_t_4;
-    __pyx_v_tail1_key = __pyx_t_11;
-    __pyx_v_head_tail1_key = __pyx_t_12;
-/* … */
-  __pyx_slice__2 = PySlice_New(__pyx_int_5, __pyx_int_8, Py_None); if (unlikely(!__pyx_slice__2)) __PYX_ERR(0, 164, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_slice__2);
-  __Pyx_GIVEREF(__pyx_slice__2);
-
+165:         _results[(seq1_key, empty2_key)] = base_result
-
    __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_seq1_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 165, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
-    __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_empty2_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 165, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_8);
-    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 165, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_GIVEREF(__pyx_t_7);
-    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_7);
-    __Pyx_GIVEREF(__pyx_t_8);
-    PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_8);
-    __pyx_t_7 = 0;
-    __pyx_t_8 = 0;
-    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 165, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+166:         _results[(head1_key, empty2_key)] = base_result
-
    __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_head1_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 166, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_empty2_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 166, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_8);
-    __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 166, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
-    __Pyx_GIVEREF(__pyx_t_3);
-    PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_3);
-    __Pyx_GIVEREF(__pyx_t_8);
-    PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_t_8);
-    __pyx_t_3 = 0;
-    __pyx_t_8 = 0;
-    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_7, __pyx_v_base_result) < 0)) __PYX_ERR(0, 166, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-
+167:         _results[(tail1_key, empty2_key)] = base_result
-
    __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_tail1_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 167, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
-    __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_empty2_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 167, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_8);
-    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 167, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_GIVEREF(__pyx_t_7);
-    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_7);
-    __Pyx_GIVEREF(__pyx_t_8);
-    PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_8);
-    __pyx_t_7 = 0;
-    __pyx_t_8 = 0;
-    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 167, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+168:         _results[(head_tail1_key, empty2_key)] = base_result
-
    __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_head_tail1_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 168, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_empty2_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 168, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_8);
-    __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 168, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
-    __Pyx_GIVEREF(__pyx_t_3);
-    PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_3);
-    __Pyx_GIVEREF(__pyx_t_8);
-    PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_t_8);
-    __pyx_t_3 = 0;
-    __pyx_t_8 = 0;
-    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_7, __pyx_v_base_result) < 0)) __PYX_ERR(0, 168, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-
+169:         key_decomp1[seq1_key] = info1
-
    __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_seq1_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 169, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
-    if (unlikely(PyDict_SetItem(__pyx_v_key_decomp1, __pyx_t_7, __pyx_v_info1) < 0)) __PYX_ERR(0, 169, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-
 170: 
-
+171:     for seq2, info2 in all_decomp2.items():
-
  if (unlikely(__pyx_v_all_decomp2 == Py_None)) {
-    PyErr_Format(PyExc_AttributeError, "'NoneType' object has no attribute '%.30s'", "items");
-    __PYX_ERR(0, 171, __pyx_L1_error)
-  }
-  __pyx_t_2 = __Pyx_PyDict_Items(__pyx_v_all_decomp2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 171, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  if (likely(PyList_CheckExact(__pyx_t_2)) || PyTuple_CheckExact(__pyx_t_2)) {
-    __pyx_t_7 = __pyx_t_2; __Pyx_INCREF(__pyx_t_7); __pyx_t_5 = 0;
-    __pyx_t_6 = NULL;
-  } else {
-    __pyx_t_5 = -1; __pyx_t_7 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 171, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
-    __pyx_t_6 = Py_TYPE(__pyx_t_7)->tp_iternext; if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 171, __pyx_L1_error)
-  }
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  for (;;) {
-    if (likely(!__pyx_t_6)) {
-      if (likely(PyList_CheckExact(__pyx_t_7))) {
-        if (__pyx_t_5 >= PyList_GET_SIZE(__pyx_t_7)) break;
-        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        __pyx_t_2 = PyList_GET_ITEM(__pyx_t_7, __pyx_t_5); __Pyx_INCREF(__pyx_t_2); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 171, __pyx_L1_error)
-        #else
-        __pyx_t_2 = PySequence_ITEM(__pyx_t_7, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 171, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_2);
-        #endif
-      } else {
-        if (__pyx_t_5 >= PyTuple_GET_SIZE(__pyx_t_7)) break;
-        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_7, __pyx_t_5); __Pyx_INCREF(__pyx_t_2); __pyx_t_5++; if (unlikely(0 < 0)) __PYX_ERR(0, 171, __pyx_L1_error)
-        #else
-        __pyx_t_2 = PySequence_ITEM(__pyx_t_7, __pyx_t_5); __pyx_t_5++; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 171, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_2);
-        #endif
-      }
-    } else {
-      __pyx_t_2 = __pyx_t_6(__pyx_t_7);
-      if (unlikely(!__pyx_t_2)) {
-        PyObject* exc_type = PyErr_Occurred();
-        if (exc_type) {
-          if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
-          else __PYX_ERR(0, 171, __pyx_L1_error)
-        }
-        break;
-      }
-      __Pyx_GOTREF(__pyx_t_2);
-    }
-    if ((likely(PyTuple_CheckExact(__pyx_t_2))) || (PyList_CheckExact(__pyx_t_2))) {
-      PyObject* sequence = __pyx_t_2;
-      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-      if (unlikely(size != 2)) {
-        if (size > 2) __Pyx_RaiseTooManyValuesError(2);
-        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-        __PYX_ERR(0, 171, __pyx_L1_error)
-      }
-      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-      if (likely(PyTuple_CheckExact(sequence))) {
-        __pyx_t_8 = PyTuple_GET_ITEM(sequence, 0); 
-        __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); 
-      } else {
-        __pyx_t_8 = PyList_GET_ITEM(sequence, 0); 
-        __pyx_t_3 = PyList_GET_ITEM(sequence, 1); 
-      }
-      __Pyx_INCREF(__pyx_t_8);
-      __Pyx_INCREF(__pyx_t_3);
-      #else
-      __pyx_t_8 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 171, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_8);
-      __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 171, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      #endif
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    } else {
-      Py_ssize_t index = -1;
-      __pyx_t_1 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 171, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext;
-      index = 0; __pyx_t_8 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_8)) goto __pyx_L11_unpacking_failed;
-      __Pyx_GOTREF(__pyx_t_8);
-      index = 1; __pyx_t_3 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_3)) goto __pyx_L11_unpacking_failed;
-      __Pyx_GOTREF(__pyx_t_3);
-      if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_1), 2) < 0) __PYX_ERR(0, 171, __pyx_L1_error)
-      __pyx_t_9 = NULL;
-      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      goto __pyx_L12_unpacking_done;
-      __pyx_L11_unpacking_failed:;
-      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      __pyx_t_9 = NULL;
-      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-      __PYX_ERR(0, 171, __pyx_L1_error)
-      __pyx_L12_unpacking_done:;
-    }
-    if (!(likely(PyTuple_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_3)->tp_name), 0))) __PYX_ERR(0, 171, __pyx_L1_error)
-    __Pyx_XDECREF_SET(__pyx_v_seq2, __pyx_t_8);
-    __pyx_t_8 = 0;
-    __Pyx_XDECREF_SET(__pyx_v_info2, ((PyObject*)__pyx_t_3));
-    __pyx_t_3 = 0;
-/* … */
-  }
-  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-
+172:         seq2_key = hash(seq2)
-
    __pyx_t_12 = PyObject_Hash(__pyx_v_seq2); if (unlikely(__pyx_t_12 == ((Py_hash_t)-1))) __PYX_ERR(0, 172, __pyx_L1_error)
-    __pyx_v_seq2_key = __pyx_t_12;
-
+173:         head2_key, tail2_key, head_tail2_key = all_decomp2[seq2][5:8]
-
    if (unlikely(__pyx_v_all_decomp2 == Py_None)) {
-      PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-      __PYX_ERR(0, 173, __pyx_L1_error)
-    }
-    __pyx_t_2 = __Pyx_PyDict_GetItem(__pyx_v_all_decomp2, __pyx_v_seq2); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 173, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = __Pyx_PyObject_GetSlice(__pyx_t_2, 5, 8, NULL, NULL, &__pyx_slice__2, 1, 1, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 173, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) {
-      PyObject* sequence = __pyx_t_3;
-      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-      if (unlikely(size != 3)) {
-        if (size > 3) __Pyx_RaiseTooManyValuesError(3);
-        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-        __PYX_ERR(0, 173, __pyx_L1_error)
-      }
-      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-      if (likely(PyTuple_CheckExact(sequence))) {
-        __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0); 
-        __pyx_t_8 = PyTuple_GET_ITEM(sequence, 1); 
-        __pyx_t_1 = PyTuple_GET_ITEM(sequence, 2); 
-      } else {
-        __pyx_t_2 = PyList_GET_ITEM(sequence, 0); 
-        __pyx_t_8 = PyList_GET_ITEM(sequence, 1); 
-        __pyx_t_1 = PyList_GET_ITEM(sequence, 2); 
-      }
-      __Pyx_INCREF(__pyx_t_2);
-      __Pyx_INCREF(__pyx_t_8);
-      __Pyx_INCREF(__pyx_t_1);
-      #else
-      __pyx_t_2 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 173, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_8 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 173, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_8);
-      __pyx_t_1 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 173, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      #endif
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    } else {
-      Py_ssize_t index = -1;
-      __pyx_t_10 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 173, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_10);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __pyx_t_9 = Py_TYPE(__pyx_t_10)->tp_iternext;
-      index = 0; __pyx_t_2 = __pyx_t_9(__pyx_t_10); if (unlikely(!__pyx_t_2)) goto __pyx_L13_unpacking_failed;
-      __Pyx_GOTREF(__pyx_t_2);
-      index = 1; __pyx_t_8 = __pyx_t_9(__pyx_t_10); if (unlikely(!__pyx_t_8)) goto __pyx_L13_unpacking_failed;
-      __Pyx_GOTREF(__pyx_t_8);
-      index = 2; __pyx_t_1 = __pyx_t_9(__pyx_t_10); if (unlikely(!__pyx_t_1)) goto __pyx_L13_unpacking_failed;
-      __Pyx_GOTREF(__pyx_t_1);
-      if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_10), 3) < 0) __PYX_ERR(0, 173, __pyx_L1_error)
-      __pyx_t_9 = NULL;
-      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
-      goto __pyx_L14_unpacking_done;
-      __pyx_L13_unpacking_failed:;
-      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
-      __pyx_t_9 = NULL;
-      if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-      __PYX_ERR(0, 173, __pyx_L1_error)
-      __pyx_L14_unpacking_done:;
-    }
-    __pyx_t_12 = __Pyx_PyInt_AsHash_t(__pyx_t_2); if (unlikely((__pyx_t_12 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 173, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __pyx_t_11 = __Pyx_PyInt_AsHash_t(__pyx_t_8); if (unlikely((__pyx_t_11 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 173, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-    __pyx_t_4 = __Pyx_PyInt_AsHash_t(__pyx_t_1); if (unlikely((__pyx_t_4 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 173, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __pyx_v_head2_key = __pyx_t_12;
-    __pyx_v_tail2_key = __pyx_t_11;
-    __pyx_v_head_tail2_key = __pyx_t_4;
-
+174:         _results[(empty1_key, seq2_key)] = base_result
-
    __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_empty1_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 174, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_1 = __Pyx_PyInt_FromHash_t(__pyx_v_seq2_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 174, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 174, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_8);
-    __Pyx_GIVEREF(__pyx_t_3);
-    PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_3);
-    __Pyx_GIVEREF(__pyx_t_1);
-    PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_1);
-    __pyx_t_3 = 0;
-    __pyx_t_1 = 0;
-    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_8, __pyx_v_base_result) < 0)) __PYX_ERR(0, 174, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-
+175:         _results[(empty1_key, head2_key)] = base_result
-
    __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_empty1_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 175, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_8);
-    __pyx_t_1 = __Pyx_PyInt_FromHash_t(__pyx_v_head2_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 175, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 175, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_GIVEREF(__pyx_t_8);
-    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_8);
-    __Pyx_GIVEREF(__pyx_t_1);
-    PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_1);
-    __pyx_t_8 = 0;
-    __pyx_t_1 = 0;
-    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 175, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+176:         _results[(empty1_key, tail2_key)] = base_result
-
    __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_empty1_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 176, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __pyx_t_1 = __Pyx_PyInt_FromHash_t(__pyx_v_tail2_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 176, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 176, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_8);
-    __Pyx_GIVEREF(__pyx_t_3);
-    PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_3);
-    __Pyx_GIVEREF(__pyx_t_1);
-    PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_1);
-    __pyx_t_3 = 0;
-    __pyx_t_1 = 0;
-    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_8, __pyx_v_base_result) < 0)) __PYX_ERR(0, 176, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-
+177:         _results[(empty1_key, head_tail2_key)] = base_result
-
    __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_empty1_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 177, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_8);
-    __pyx_t_1 = __Pyx_PyInt_FromHash_t(__pyx_v_head_tail2_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 177, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 177, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    __Pyx_GIVEREF(__pyx_t_8);
-    PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_8);
-    __Pyx_GIVEREF(__pyx_t_1);
-    PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_1);
-    __pyx_t_8 = 0;
-    __pyx_t_1 = 0;
-    if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_t_3, __pyx_v_base_result) < 0)) __PYX_ERR(0, 177, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
+178:         key_decomp2[seq2_key] = info2
-
    __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_seq2_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 178, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    if (unlikely(PyDict_SetItem(__pyx_v_key_decomp2, __pyx_t_3, __pyx_v_info2) < 0)) __PYX_ERR(0, 178, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-
 179: 
-
+180:     cdef Py_hash_t full_seq1_key = hash(full_seq1)
-
  __pyx_t_4 = PyObject_Hash(__pyx_v_full_seq1); if (unlikely(__pyx_t_4 == ((Py_hash_t)-1))) __PYX_ERR(0, 180, __pyx_L1_error)
-  __pyx_v_full_seq1_key = __pyx_t_4;
-
+181:     cdef Py_hash_t full_seq2_key = hash(full_seq2)
-
  __pyx_t_4 = PyObject_Hash(__pyx_v_full_seq2); if (unlikely(__pyx_t_4 == ((Py_hash_t)-1))) __PYX_ERR(0, 181, __pyx_L1_error)
-  __pyx_v_full_seq2_key = __pyx_t_4;
-
 182: 
-
+183:     cdef tuple key0 = (full_seq1_key, full_seq2_key)
-
  __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_full_seq1_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 183, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_7);
-  __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_full_seq2_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 183, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_3);
-  __pyx_t_1 = PyTuple_New(2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 183, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_GIVEREF(__pyx_t_7);
-  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_t_7);
-  __Pyx_GIVEREF(__pyx_t_3);
-  PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_t_3);
-  __pyx_t_7 = 0;
-  __pyx_t_3 = 0;
-  __pyx_v_key0 = ((PyObject*)__pyx_t_1);
-  __pyx_t_1 = 0;
-
+184:     cdef tuple frame0 = (key0, full_seq1, full_seq2)
-
  __pyx_t_1 = PyTuple_New(3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 184, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_INCREF(__pyx_v_key0);
-  __Pyx_GIVEREF(__pyx_v_key0);
-  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_key0);
-  __Pyx_INCREF(__pyx_v_full_seq1);
-  __Pyx_GIVEREF(__pyx_v_full_seq1);
-  PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_full_seq1);
-  __Pyx_INCREF(__pyx_v_full_seq2);
-  __Pyx_GIVEREF(__pyx_v_full_seq2);
-  PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_full_seq2);
-  __pyx_v_frame0 = ((PyObject*)__pyx_t_1);
-  __pyx_t_1 = 0;
-
+185:     cdef list stack = [frame0]
-
  __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 185, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_INCREF(__pyx_v_frame0);
-  __Pyx_GIVEREF(__pyx_v_frame0);
-  PyList_SET_ITEM(__pyx_t_1, 0, __pyx_v_frame0);
-  __pyx_v_stack = ((PyObject*)__pyx_t_1);
-  __pyx_t_1 = 0;
-
 186: 
-
+187:     while stack:
-
  while (1) {
-    __pyx_t_13 = (PyList_GET_SIZE(__pyx_v_stack) != 0);
-    if (!__pyx_t_13) break;
-
+188:         frame = stack[-1]
-
    __pyx_t_1 = __Pyx_GetItemInt_List(__pyx_v_stack, -1L, long, 1, __Pyx_PyInt_From_long, 1, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 188, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    if (!(likely(PyTuple_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(0, 188, __pyx_L1_error)
-    __Pyx_XDECREF_SET(__pyx_v_frame, ((PyObject*)__pyx_t_1));
-    __pyx_t_1 = 0;
-
+189:         key, seq1, seq2 = frame
-
    if (likely(__pyx_v_frame != Py_None)) {
-      PyObject* sequence = __pyx_v_frame;
-      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-      if (unlikely(size != 3)) {
-        if (size > 3) __Pyx_RaiseTooManyValuesError(3);
-        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-        __PYX_ERR(0, 189, __pyx_L1_error)
-      }
-      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-      __pyx_t_1 = PyTuple_GET_ITEM(sequence, 0); 
-      __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); 
-      __pyx_t_7 = PyTuple_GET_ITEM(sequence, 2); 
-      __Pyx_INCREF(__pyx_t_1);
-      __Pyx_INCREF(__pyx_t_3);
-      __Pyx_INCREF(__pyx_t_7);
-      #else
-      __pyx_t_1 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 189, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 189, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_7 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 189, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_7);
-      #endif
-    } else {
-      __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 189, __pyx_L1_error)
-    }
-    if (!(likely(PyTuple_CheckExact(__pyx_t_1))||((__pyx_t_1) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_1)->tp_name), 0))) __PYX_ERR(0, 189, __pyx_L1_error)
-    __Pyx_XDECREF_SET(__pyx_v_key, ((PyObject*)__pyx_t_1));
-    __pyx_t_1 = 0;
-    __Pyx_XDECREF_SET(__pyx_v_seq1, __pyx_t_3);
-    __pyx_t_3 = 0;
-    __Pyx_XDECREF_SET(__pyx_v_seq2, __pyx_t_7);
-    __pyx_t_7 = 0;
-
+190:         seq1_key, seq2_key = key
-
    if (likely(__pyx_v_key != Py_None)) {
-      PyObject* sequence = __pyx_v_key;
-      Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-      if (unlikely(size != 2)) {
-        if (size > 2) __Pyx_RaiseTooManyValuesError(2);
-        else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-        __PYX_ERR(0, 190, __pyx_L1_error)
-      }
-      #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-      __pyx_t_7 = PyTuple_GET_ITEM(sequence, 0); 
-      __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); 
-      __Pyx_INCREF(__pyx_t_7);
-      __Pyx_INCREF(__pyx_t_3);
-      #else
-      __pyx_t_7 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 190, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_7);
-      __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 190, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      #endif
-    } else {
-      __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 190, __pyx_L1_error)
-    }
-    __pyx_t_4 = __Pyx_PyInt_AsHash_t(__pyx_t_7); if (unlikely((__pyx_t_4 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 190, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-    __pyx_t_11 = __Pyx_PyInt_AsHash_t(__pyx_t_3); if (unlikely((__pyx_t_11 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 190, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-    __pyx_v_seq1_key = __pyx_t_4;
-    __pyx_v_seq2_key = __pyx_t_11;
-
+191:         if key not in _results:
-
    __pyx_t_13 = (__Pyx_PyDict_ContainsTF(__pyx_v_key, __pyx_v__results, Py_NE)); if (unlikely(__pyx_t_13 < 0)) __PYX_ERR(0, 191, __pyx_L1_error)
-    __pyx_t_14 = (__pyx_t_13 != 0);
-    if (__pyx_t_14) {
-/* … */
-    }
-
+192:             info1 = key_decomp1[seq1_key]
-
      __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_seq1_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 192, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_7 = __Pyx_PyDict_GetItem(__pyx_v_key_decomp1, __pyx_t_3); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 192, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_7);
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      if (!(likely(PyTuple_CheckExact(__pyx_t_7))||((__pyx_t_7) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_7)->tp_name), 0))) __PYX_ERR(0, 192, __pyx_L1_error)
-      __Pyx_XDECREF_SET(__pyx_v_info1, ((PyObject*)__pyx_t_7));
-      __pyx_t_7 = 0;
-
+193:             tok1, seq1, head1, tail1, head_tail1, head1_key, tail1_key, head_tail1_key, a1, b1 = info1
-
      if (likely(__pyx_v_info1 != Py_None)) {
-        PyObject* sequence = __pyx_v_info1;
-        Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-        if (unlikely(size != 10)) {
-          if (size > 10) __Pyx_RaiseTooManyValuesError(10);
-          else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-          __PYX_ERR(0, 193, __pyx_L1_error)
-        }
-        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        __pyx_t_7 = PyTuple_GET_ITEM(sequence, 0); 
-        __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); 
-        __pyx_t_1 = PyTuple_GET_ITEM(sequence, 2); 
-        __pyx_t_8 = PyTuple_GET_ITEM(sequence, 3); 
-        __pyx_t_2 = PyTuple_GET_ITEM(sequence, 4); 
-        __pyx_t_10 = PyTuple_GET_ITEM(sequence, 5); 
-        __pyx_t_15 = PyTuple_GET_ITEM(sequence, 6); 
-        __pyx_t_16 = PyTuple_GET_ITEM(sequence, 7); 
-        __pyx_t_17 = PyTuple_GET_ITEM(sequence, 8); 
-        __pyx_t_18 = PyTuple_GET_ITEM(sequence, 9); 
-        __Pyx_INCREF(__pyx_t_7);
-        __Pyx_INCREF(__pyx_t_3);
-        __Pyx_INCREF(__pyx_t_1);
-        __Pyx_INCREF(__pyx_t_8);
-        __Pyx_INCREF(__pyx_t_2);
-        __Pyx_INCREF(__pyx_t_10);
-        __Pyx_INCREF(__pyx_t_15);
-        __Pyx_INCREF(__pyx_t_16);
-        __Pyx_INCREF(__pyx_t_17);
-        __Pyx_INCREF(__pyx_t_18);
-        #else
-        {
-          Py_ssize_t i;
-          PyObject** temps[10] = {&__pyx_t_7,&__pyx_t_3,&__pyx_t_1,&__pyx_t_8,&__pyx_t_2,&__pyx_t_10,&__pyx_t_15,&__pyx_t_16,&__pyx_t_17,&__pyx_t_18};
-          for (i=0; i < 10; i++) {
-            PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 193, __pyx_L1_error)
-            __Pyx_GOTREF(item);
-            *(temps[i]) = item;
-          }
-        }
-        #endif
-      } else {
-        __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 193, __pyx_L1_error)
-      }
-      __pyx_t_11 = __Pyx_PyInt_AsHash_t(__pyx_t_10); if (unlikely((__pyx_t_11 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 193, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
-      __pyx_t_4 = __Pyx_PyInt_AsHash_t(__pyx_t_15); if (unlikely((__pyx_t_4 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 193, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_15); __pyx_t_15 = 0;
-      __pyx_t_12 = __Pyx_PyInt_AsHash_t(__pyx_t_16); if (unlikely((__pyx_t_12 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 193, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_16); __pyx_t_16 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_tok1, __pyx_t_7);
-      __pyx_t_7 = 0;
-      __Pyx_DECREF_SET(__pyx_v_seq1, __pyx_t_3);
-      __pyx_t_3 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_head1, __pyx_t_1);
-      __pyx_t_1 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_tail1, __pyx_t_8);
-      __pyx_t_8 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_head_tail1, __pyx_t_2);
-      __pyx_t_2 = 0;
-      __pyx_v_head1_key = __pyx_t_11;
-      __pyx_v_tail1_key = __pyx_t_4;
-      __pyx_v_head_tail1_key = __pyx_t_12;
-      __Pyx_XDECREF_SET(__pyx_v_a1, __pyx_t_17);
-      __pyx_t_17 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_b1, __pyx_t_18);
-      __pyx_t_18 = 0;
-
 194: 
-
+195:             info2 = key_decomp2[seq2_key]
-
      __pyx_t_18 = __Pyx_PyInt_FromHash_t(__pyx_v_seq2_key); if (unlikely(!__pyx_t_18)) __PYX_ERR(0, 195, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_18);
-      __pyx_t_17 = __Pyx_PyDict_GetItem(__pyx_v_key_decomp2, __pyx_t_18); if (unlikely(!__pyx_t_17)) __PYX_ERR(0, 195, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_17);
-      __Pyx_DECREF(__pyx_t_18); __pyx_t_18 = 0;
-      if (!(likely(PyTuple_CheckExact(__pyx_t_17))||((__pyx_t_17) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_17)->tp_name), 0))) __PYX_ERR(0, 195, __pyx_L1_error)
-      __Pyx_XDECREF_SET(__pyx_v_info2, ((PyObject*)__pyx_t_17));
-      __pyx_t_17 = 0;
-
+196:             tok2, seq2, head2, tail2, head_tail2, head2_key, tail2_key, head_tail2_key, a2, b2 = info2
-
      if (likely(__pyx_v_info2 != Py_None)) {
-        PyObject* sequence = __pyx_v_info2;
-        Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-        if (unlikely(size != 10)) {
-          if (size > 10) __Pyx_RaiseTooManyValuesError(10);
-          else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-          __PYX_ERR(0, 196, __pyx_L1_error)
-        }
-        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        __pyx_t_17 = PyTuple_GET_ITEM(sequence, 0); 
-        __pyx_t_18 = PyTuple_GET_ITEM(sequence, 1); 
-        __pyx_t_16 = PyTuple_GET_ITEM(sequence, 2); 
-        __pyx_t_15 = PyTuple_GET_ITEM(sequence, 3); 
-        __pyx_t_10 = PyTuple_GET_ITEM(sequence, 4); 
-        __pyx_t_2 = PyTuple_GET_ITEM(sequence, 5); 
-        __pyx_t_8 = PyTuple_GET_ITEM(sequence, 6); 
-        __pyx_t_1 = PyTuple_GET_ITEM(sequence, 7); 
-        __pyx_t_3 = PyTuple_GET_ITEM(sequence, 8); 
-        __pyx_t_7 = PyTuple_GET_ITEM(sequence, 9); 
-        __Pyx_INCREF(__pyx_t_17);
-        __Pyx_INCREF(__pyx_t_18);
-        __Pyx_INCREF(__pyx_t_16);
-        __Pyx_INCREF(__pyx_t_15);
-        __Pyx_INCREF(__pyx_t_10);
-        __Pyx_INCREF(__pyx_t_2);
-        __Pyx_INCREF(__pyx_t_8);
-        __Pyx_INCREF(__pyx_t_1);
-        __Pyx_INCREF(__pyx_t_3);
-        __Pyx_INCREF(__pyx_t_7);
-        #else
-        {
-          Py_ssize_t i;
-          PyObject** temps[10] = {&__pyx_t_17,&__pyx_t_18,&__pyx_t_16,&__pyx_t_15,&__pyx_t_10,&__pyx_t_2,&__pyx_t_8,&__pyx_t_1,&__pyx_t_3,&__pyx_t_7};
-          for (i=0; i < 10; i++) {
-            PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 196, __pyx_L1_error)
-            __Pyx_GOTREF(item);
-            *(temps[i]) = item;
-          }
-        }
-        #endif
-      } else {
-        __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 196, __pyx_L1_error)
-      }
-      __pyx_t_12 = __Pyx_PyInt_AsHash_t(__pyx_t_2); if (unlikely((__pyx_t_12 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 196, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __pyx_t_4 = __Pyx_PyInt_AsHash_t(__pyx_t_8); if (unlikely((__pyx_t_4 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 196, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      __pyx_t_11 = __Pyx_PyInt_AsHash_t(__pyx_t_1); if (unlikely((__pyx_t_11 == (Py_hash_t)-1) && PyErr_Occurred())) __PYX_ERR(0, 196, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_tok2, __pyx_t_17);
-      __pyx_t_17 = 0;
-      __Pyx_DECREF_SET(__pyx_v_seq2, __pyx_t_18);
-      __pyx_t_18 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_head2, __pyx_t_16);
-      __pyx_t_16 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_tail2, __pyx_t_15);
-      __pyx_t_15 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_head_tail2, __pyx_t_10);
-      __pyx_t_10 = 0;
-      __pyx_v_head2_key = __pyx_t_12;
-      __pyx_v_tail2_key = __pyx_t_4;
-      __pyx_v_head_tail2_key = __pyx_t_11;
-      __Pyx_XDECREF_SET(__pyx_v_a2, __pyx_t_3);
-      __pyx_t_3 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_b2, __pyx_t_7);
-      __pyx_t_7 = 0;
-
 197: 
-
+198:             affinity = node_affinity(tok1, tok2)
-
      __Pyx_INCREF(__pyx_v_node_affinity);
-      __pyx_t_3 = __pyx_v_node_affinity; __pyx_t_1 = NULL;
-      __pyx_t_19 = 0;
-      if (CYTHON_UNPACK_METHODS && unlikely(PyMethod_Check(__pyx_t_3))) {
-        __pyx_t_1 = PyMethod_GET_SELF(__pyx_t_3);
-        if (likely(__pyx_t_1)) {
-          PyObject* function = PyMethod_GET_FUNCTION(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_1);
-          __Pyx_INCREF(function);
-          __Pyx_DECREF_SET(__pyx_t_3, function);
-          __pyx_t_19 = 1;
-        }
-      }
-      #if CYTHON_FAST_PYCALL
-      if (PyFunction_Check(__pyx_t_3)) {
-        PyObject *__pyx_temp[3] = {__pyx_t_1, __pyx_v_tok1, __pyx_v_tok2};
-        __pyx_t_7 = __Pyx_PyFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_19, 2+__pyx_t_19); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 198, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
-        __Pyx_GOTREF(__pyx_t_7);
-      } else
-      #endif
-      #if CYTHON_FAST_PYCCALL
-      if (__Pyx_PyFastCFunction_Check(__pyx_t_3)) {
-        PyObject *__pyx_temp[3] = {__pyx_t_1, __pyx_v_tok1, __pyx_v_tok2};
-        __pyx_t_7 = __Pyx_PyCFunction_FastCall(__pyx_t_3, __pyx_temp+1-__pyx_t_19, 2+__pyx_t_19); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 198, __pyx_L1_error)
-        __Pyx_XDECREF(__pyx_t_1); __pyx_t_1 = 0;
-        __Pyx_GOTREF(__pyx_t_7);
-      } else
-      #endif
-      {
-        __pyx_t_8 = PyTuple_New(2+__pyx_t_19); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 198, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        if (__pyx_t_1) {
-          __Pyx_GIVEREF(__pyx_t_1); PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_1); __pyx_t_1 = NULL;
-        }
-        __Pyx_INCREF(__pyx_v_tok1);
-        __Pyx_GIVEREF(__pyx_v_tok1);
-        PyTuple_SET_ITEM(__pyx_t_8, 0+__pyx_t_19, __pyx_v_tok1);
-        __Pyx_INCREF(__pyx_v_tok2);
-        __Pyx_GIVEREF(__pyx_v_tok2);
-        PyTuple_SET_ITEM(__pyx_t_8, 1+__pyx_t_19, __pyx_v_tok2);
-        __pyx_t_7 = __Pyx_PyObject_Call(__pyx_t_3, __pyx_t_8, NULL); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 198, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_7);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      }
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_affinity, __pyx_t_7);
-      __pyx_t_7 = 0;
-
 199: 
-
 200:             # Case 2: The current edge in sequence1 is deleted
-
+201:             try_key = (head_tail1_key, seq2_key)
-
      __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_head_tail1_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 201, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_7);
-      __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_seq2_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 201, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 201, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_8);
-      __Pyx_GIVEREF(__pyx_t_7);
-      PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_7);
-      __Pyx_GIVEREF(__pyx_t_3);
-      PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_3);
-      __pyx_t_7 = 0;
-      __pyx_t_3 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_8));
-      __pyx_t_8 = 0;
-
+202:             if try_key in _results:
-
      __pyx_t_14 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 202, __pyx_L1_error)
-      __pyx_t_13 = (__pyx_t_14 != 0);
-      if (__pyx_t_13) {
-/* … */
-        goto __pyx_L18;
-      }
-
+203:                 cand1 = _results[try_key]
-
        __pyx_t_8 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 203, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_XDECREF_SET(__pyx_v_cand1, __pyx_t_8);
-        __pyx_t_8 = 0;
-
 204:             else:
-
+205:                 miss_frame = try_key, head_tail1, seq2
-
      /*else*/ {
-        __pyx_t_8 = PyTuple_New(3); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 205, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_INCREF(__pyx_v_try_key);
-        __Pyx_GIVEREF(__pyx_v_try_key);
-        PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_v_try_key);
-        __Pyx_INCREF(__pyx_v_head_tail1);
-        __Pyx_GIVEREF(__pyx_v_head_tail1);
-        PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_v_head_tail1);
-        __Pyx_INCREF(__pyx_v_seq2);
-        __Pyx_GIVEREF(__pyx_v_seq2);
-        PyTuple_SET_ITEM(__pyx_t_8, 2, __pyx_v_seq2);
-        __Pyx_XDECREF_SET(__pyx_v_miss_frame, ((PyObject*)__pyx_t_8));
-        __pyx_t_8 = 0;
-
+206:                 stack.append(miss_frame)
-
        __pyx_t_20 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_miss_frame); if (unlikely(__pyx_t_20 == ((int)-1))) __PYX_ERR(0, 206, __pyx_L1_error)
-
+207:                 continue
-
        goto __pyx_L15_continue;
-      }
-      __pyx_L18:;
-
 208: 
-
 209:             # Case 3: The current edge in sequence2 is deleted
-
+210:             try_key = (seq1_key, head_tail2_key)
-
      __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_seq1_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 210, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_8);
-      __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_head_tail2_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 210, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_3);
-      __pyx_t_7 = PyTuple_New(2); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 210, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_7);
-      __Pyx_GIVEREF(__pyx_t_8);
-      PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_8);
-      __Pyx_GIVEREF(__pyx_t_3);
-      PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_t_3);
-      __pyx_t_8 = 0;
-      __pyx_t_3 = 0;
-      __Pyx_DECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_7));
-      __pyx_t_7 = 0;
-
+211:             if try_key in _results:
-
      __pyx_t_13 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_13 < 0)) __PYX_ERR(0, 211, __pyx_L1_error)
-      __pyx_t_14 = (__pyx_t_13 != 0);
-      if (__pyx_t_14) {
-/* … */
-        goto __pyx_L19;
-      }
-
+212:                 cand2 = _results[try_key]
-
        __pyx_t_7 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 212, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_7);
-        __Pyx_XDECREF_SET(__pyx_v_cand2, __pyx_t_7);
-        __pyx_t_7 = 0;
-
 213:             else:
-
+214:                 miss_frame = try_key, seq1, head_tail2
-
      /*else*/ {
-        __pyx_t_7 = PyTuple_New(3); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 214, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_7);
-        __Pyx_INCREF(__pyx_v_try_key);
-        __Pyx_GIVEREF(__pyx_v_try_key);
-        PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_v_try_key);
-        __Pyx_INCREF(__pyx_v_seq1);
-        __Pyx_GIVEREF(__pyx_v_seq1);
-        PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_v_seq1);
-        __Pyx_INCREF(__pyx_v_head_tail2);
-        __Pyx_GIVEREF(__pyx_v_head_tail2);
-        PyTuple_SET_ITEM(__pyx_t_7, 2, __pyx_v_head_tail2);
-        __Pyx_XDECREF_SET(__pyx_v_miss_frame, ((PyObject*)__pyx_t_7));
-        __pyx_t_7 = 0;
-
+215:                 stack.append(miss_frame)
-
        __pyx_t_20 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_miss_frame); if (unlikely(__pyx_t_20 == ((int)-1))) __PYX_ERR(0, 215, __pyx_L1_error)
-
+216:                 continue
-
        goto __pyx_L15_continue;
-      }
-      __pyx_L19:;
-
 217: 
-
 218:             # Case 1: The LCS involves this edge
-
+219:             if affinity:
-
      __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_v_affinity); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 219, __pyx_L1_error)
-      if (__pyx_t_14) {
-/* … */
-        goto __pyx_L20;
-      }
-
+220:                 try_key = (head1_key, head2_key)
-
        __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_head1_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 220, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_7);
-        __pyx_t_3 = __Pyx_PyInt_FromHash_t(__pyx_v_head2_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 220, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 220, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_7);
-        PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_7);
-        __Pyx_GIVEREF(__pyx_t_3);
-        PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_t_3);
-        __pyx_t_7 = 0;
-        __pyx_t_3 = 0;
-        __Pyx_DECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_8));
-        __pyx_t_8 = 0;
-
+221:                 if try_key in _results:
-
        __pyx_t_14 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 221, __pyx_L1_error)
-        __pyx_t_13 = (__pyx_t_14 != 0);
-        if (__pyx_t_13) {
-/* … */
-          goto __pyx_L21;
-        }
-
+222:                     pval_h, new_heads = _results[try_key]
-
          __pyx_t_8 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 222, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_8);
-          if ((likely(PyTuple_CheckExact(__pyx_t_8))) || (PyList_CheckExact(__pyx_t_8))) {
-            PyObject* sequence = __pyx_t_8;
-            Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-            if (unlikely(size != 2)) {
-              if (size > 2) __Pyx_RaiseTooManyValuesError(2);
-              else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-              __PYX_ERR(0, 222, __pyx_L1_error)
-            }
-            #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-            if (likely(PyTuple_CheckExact(sequence))) {
-              __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); 
-              __pyx_t_7 = PyTuple_GET_ITEM(sequence, 1); 
-            } else {
-              __pyx_t_3 = PyList_GET_ITEM(sequence, 0); 
-              __pyx_t_7 = PyList_GET_ITEM(sequence, 1); 
-            }
-            __Pyx_INCREF(__pyx_t_3);
-            __Pyx_INCREF(__pyx_t_7);
-            #else
-            __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 222, __pyx_L1_error)
-            __Pyx_GOTREF(__pyx_t_3);
-            __pyx_t_7 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 222, __pyx_L1_error)
-            __Pyx_GOTREF(__pyx_t_7);
-            #endif
-            __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-          } else {
-            Py_ssize_t index = -1;
-            __pyx_t_1 = PyObject_GetIter(__pyx_t_8); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 222, __pyx_L1_error)
-            __Pyx_GOTREF(__pyx_t_1);
-            __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-            __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext;
-            index = 0; __pyx_t_3 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_3)) goto __pyx_L22_unpacking_failed;
-            __Pyx_GOTREF(__pyx_t_3);
-            index = 1; __pyx_t_7 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_7)) goto __pyx_L22_unpacking_failed;
-            __Pyx_GOTREF(__pyx_t_7);
-            if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_1), 2) < 0) __PYX_ERR(0, 222, __pyx_L1_error)
-            __pyx_t_9 = NULL;
-            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-            goto __pyx_L23_unpacking_done;
-            __pyx_L22_unpacking_failed:;
-            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-            __pyx_t_9 = NULL;
-            if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-            __PYX_ERR(0, 222, __pyx_L1_error)
-            __pyx_L23_unpacking_done:;
-          }
-          __Pyx_XDECREF_SET(__pyx_v_pval_h, __pyx_t_3);
-          __pyx_t_3 = 0;
-          __Pyx_XDECREF_SET(__pyx_v_new_heads, __pyx_t_7);
-          __pyx_t_7 = 0;
-
 223:                 else:
-
+224:                     miss_frame = try_key, head1, head2
-
        /*else*/ {
-          __pyx_t_8 = PyTuple_New(3); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 224, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_8);
-          __Pyx_INCREF(__pyx_v_try_key);
-          __Pyx_GIVEREF(__pyx_v_try_key);
-          PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_v_try_key);
-          __Pyx_INCREF(__pyx_v_head1);
-          __Pyx_GIVEREF(__pyx_v_head1);
-          PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_v_head1);
-          __Pyx_INCREF(__pyx_v_head2);
-          __Pyx_GIVEREF(__pyx_v_head2);
-          PyTuple_SET_ITEM(__pyx_t_8, 2, __pyx_v_head2);
-          __Pyx_XDECREF_SET(__pyx_v_miss_frame, ((PyObject*)__pyx_t_8));
-          __pyx_t_8 = 0;
-
+225:                     stack.append(miss_frame)
-
          __pyx_t_20 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_miss_frame); if (unlikely(__pyx_t_20 == ((int)-1))) __PYX_ERR(0, 225, __pyx_L1_error)
-
+226:                     continue
-
          goto __pyx_L15_continue;
-        }
-        __pyx_L21:;
-
 227: 
-
+228:                 try_key = (tail1_key, tail2_key)
-
        __pyx_t_8 = __Pyx_PyInt_FromHash_t(__pyx_v_tail1_key); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 228, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __pyx_t_7 = __Pyx_PyInt_FromHash_t(__pyx_v_tail2_key); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 228, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_7);
-        __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 228, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_GIVEREF(__pyx_t_8);
-        PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_t_8);
-        __Pyx_GIVEREF(__pyx_t_7);
-        PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_t_7);
-        __pyx_t_8 = 0;
-        __pyx_t_7 = 0;
-        __Pyx_DECREF_SET(__pyx_v_try_key, ((PyObject*)__pyx_t_3));
-        __pyx_t_3 = 0;
-
+229:                 if try_key in _results:
-
        __pyx_t_13 = (__Pyx_PyDict_ContainsTF(__pyx_v_try_key, __pyx_v__results, Py_EQ)); if (unlikely(__pyx_t_13 < 0)) __PYX_ERR(0, 229, __pyx_L1_error)
-        __pyx_t_14 = (__pyx_t_13 != 0);
-        if (__pyx_t_14) {
-/* … */
-          goto __pyx_L24;
-        }
-
+230:                     pval_t, new_tails = _results[try_key]
-
          __pyx_t_3 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_try_key); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 230, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_3);
-          if ((likely(PyTuple_CheckExact(__pyx_t_3))) || (PyList_CheckExact(__pyx_t_3))) {
-            PyObject* sequence = __pyx_t_3;
-            Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-            if (unlikely(size != 2)) {
-              if (size > 2) __Pyx_RaiseTooManyValuesError(2);
-              else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-              __PYX_ERR(0, 230, __pyx_L1_error)
-            }
-            #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-            if (likely(PyTuple_CheckExact(sequence))) {
-              __pyx_t_7 = PyTuple_GET_ITEM(sequence, 0); 
-              __pyx_t_8 = PyTuple_GET_ITEM(sequence, 1); 
-            } else {
-              __pyx_t_7 = PyList_GET_ITEM(sequence, 0); 
-              __pyx_t_8 = PyList_GET_ITEM(sequence, 1); 
-            }
-            __Pyx_INCREF(__pyx_t_7);
-            __Pyx_INCREF(__pyx_t_8);
-            #else
-            __pyx_t_7 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 230, __pyx_L1_error)
-            __Pyx_GOTREF(__pyx_t_7);
-            __pyx_t_8 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 230, __pyx_L1_error)
-            __Pyx_GOTREF(__pyx_t_8);
-            #endif
-            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-          } else {
-            Py_ssize_t index = -1;
-            __pyx_t_1 = PyObject_GetIter(__pyx_t_3); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 230, __pyx_L1_error)
-            __Pyx_GOTREF(__pyx_t_1);
-            __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-            __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext;
-            index = 0; __pyx_t_7 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_7)) goto __pyx_L25_unpacking_failed;
-            __Pyx_GOTREF(__pyx_t_7);
-            index = 1; __pyx_t_8 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_8)) goto __pyx_L25_unpacking_failed;
-            __Pyx_GOTREF(__pyx_t_8);
-            if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_1), 2) < 0) __PYX_ERR(0, 230, __pyx_L1_error)
-            __pyx_t_9 = NULL;
-            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-            goto __pyx_L26_unpacking_done;
-            __pyx_L25_unpacking_failed:;
-            __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-            __pyx_t_9 = NULL;
-            if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-            __PYX_ERR(0, 230, __pyx_L1_error)
-            __pyx_L26_unpacking_done:;
-          }
-          __Pyx_XDECREF_SET(__pyx_v_pval_t, __pyx_t_7);
-          __pyx_t_7 = 0;
-          __Pyx_XDECREF_SET(__pyx_v_new_tails, __pyx_t_8);
-          __pyx_t_8 = 0;
-
 231:                 else:
-
+232:                     miss_frame = try_key, tail1, tail2
-
        /*else*/ {
-          __pyx_t_3 = PyTuple_New(3); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 232, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_3);
-          __Pyx_INCREF(__pyx_v_try_key);
-          __Pyx_GIVEREF(__pyx_v_try_key);
-          PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_try_key);
-          __Pyx_INCREF(__pyx_v_tail1);
-          __Pyx_GIVEREF(__pyx_v_tail1);
-          PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_tail1);
-          __Pyx_INCREF(__pyx_v_tail2);
-          __Pyx_GIVEREF(__pyx_v_tail2);
-          PyTuple_SET_ITEM(__pyx_t_3, 2, __pyx_v_tail2);
-          __Pyx_XDECREF_SET(__pyx_v_miss_frame, ((PyObject*)__pyx_t_3));
-          __pyx_t_3 = 0;
-
+233:                     stack.append(miss_frame)
-
          __pyx_t_20 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_miss_frame); if (unlikely(__pyx_t_20 == ((int)-1))) __PYX_ERR(0, 233, __pyx_L1_error)
-
+234:                     continue
-
          goto __pyx_L15_continue;
-        }
-        __pyx_L24:;
-
 235: 
-
+236:                 new_head1, new_head2 = new_heads
-
        if ((likely(PyTuple_CheckExact(__pyx_v_new_heads))) || (PyList_CheckExact(__pyx_v_new_heads))) {
-          PyObject* sequence = __pyx_v_new_heads;
-          Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-          if (unlikely(size != 2)) {
-            if (size > 2) __Pyx_RaiseTooManyValuesError(2);
-            else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-            __PYX_ERR(0, 236, __pyx_L1_error)
-          }
-          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-          if (likely(PyTuple_CheckExact(sequence))) {
-            __pyx_t_3 = PyTuple_GET_ITEM(sequence, 0); 
-            __pyx_t_8 = PyTuple_GET_ITEM(sequence, 1); 
-          } else {
-            __pyx_t_3 = PyList_GET_ITEM(sequence, 0); 
-            __pyx_t_8 = PyList_GET_ITEM(sequence, 1); 
-          }
-          __Pyx_INCREF(__pyx_t_3);
-          __Pyx_INCREF(__pyx_t_8);
-          #else
-          __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 236, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_3);
-          __pyx_t_8 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 236, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_8);
-          #endif
-        } else {
-          Py_ssize_t index = -1;
-          __pyx_t_7 = PyObject_GetIter(__pyx_v_new_heads); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 236, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_7);
-          __pyx_t_9 = Py_TYPE(__pyx_t_7)->tp_iternext;
-          index = 0; __pyx_t_3 = __pyx_t_9(__pyx_t_7); if (unlikely(!__pyx_t_3)) goto __pyx_L27_unpacking_failed;
-          __Pyx_GOTREF(__pyx_t_3);
-          index = 1; __pyx_t_8 = __pyx_t_9(__pyx_t_7); if (unlikely(!__pyx_t_8)) goto __pyx_L27_unpacking_failed;
-          __Pyx_GOTREF(__pyx_t_8);
-          if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_7), 2) < 0) __PYX_ERR(0, 236, __pyx_L1_error)
-          __pyx_t_9 = NULL;
-          __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-          goto __pyx_L28_unpacking_done;
-          __pyx_L27_unpacking_failed:;
-          __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-          __pyx_t_9 = NULL;
-          if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-          __PYX_ERR(0, 236, __pyx_L1_error)
-          __pyx_L28_unpacking_done:;
-        }
-        __Pyx_XDECREF_SET(__pyx_v_new_head1, __pyx_t_3);
-        __pyx_t_3 = 0;
-        __Pyx_XDECREF_SET(__pyx_v_new_head2, __pyx_t_8);
-        __pyx_t_8 = 0;
-
+237:                 new_tail1, new_tail2 = new_tails
-
        if ((likely(PyTuple_CheckExact(__pyx_v_new_tails))) || (PyList_CheckExact(__pyx_v_new_tails))) {
-          PyObject* sequence = __pyx_v_new_tails;
-          Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-          if (unlikely(size != 2)) {
-            if (size > 2) __Pyx_RaiseTooManyValuesError(2);
-            else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-            __PYX_ERR(0, 237, __pyx_L1_error)
-          }
-          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-          if (likely(PyTuple_CheckExact(sequence))) {
-            __pyx_t_8 = PyTuple_GET_ITEM(sequence, 0); 
-            __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); 
-          } else {
-            __pyx_t_8 = PyList_GET_ITEM(sequence, 0); 
-            __pyx_t_3 = PyList_GET_ITEM(sequence, 1); 
-          }
-          __Pyx_INCREF(__pyx_t_8);
-          __Pyx_INCREF(__pyx_t_3);
-          #else
-          __pyx_t_8 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 237, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_8);
-          __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 237, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_3);
-          #endif
-        } else {
-          Py_ssize_t index = -1;
-          __pyx_t_7 = PyObject_GetIter(__pyx_v_new_tails); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 237, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_7);
-          __pyx_t_9 = Py_TYPE(__pyx_t_7)->tp_iternext;
-          index = 0; __pyx_t_8 = __pyx_t_9(__pyx_t_7); if (unlikely(!__pyx_t_8)) goto __pyx_L29_unpacking_failed;
-          __Pyx_GOTREF(__pyx_t_8);
-          index = 1; __pyx_t_3 = __pyx_t_9(__pyx_t_7); if (unlikely(!__pyx_t_3)) goto __pyx_L29_unpacking_failed;
-          __Pyx_GOTREF(__pyx_t_3);
-          if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_7), 2) < 0) __PYX_ERR(0, 237, __pyx_L1_error)
-          __pyx_t_9 = NULL;
-          __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-          goto __pyx_L30_unpacking_done;
-          __pyx_L29_unpacking_failed:;
-          __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-          __pyx_t_9 = NULL;
-          if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-          __PYX_ERR(0, 237, __pyx_L1_error)
-          __pyx_L30_unpacking_done:;
-        }
-        __Pyx_XDECREF_SET(__pyx_v_new_tail1, __pyx_t_8);
-        __pyx_t_8 = 0;
-        __Pyx_XDECREF_SET(__pyx_v_new_tail2, __pyx_t_3);
-        __pyx_t_3 = 0;
-
 238: 
-
+239:                 subseq1 = a1 + new_head1 + b1 + new_tail1
-
        __pyx_t_3 = PyNumber_Add(__pyx_v_a1, __pyx_v_new_head1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 239, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __pyx_t_8 = PyNumber_Add(__pyx_t_3, __pyx_v_b1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 239, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        __pyx_t_3 = PyNumber_Add(__pyx_t_8, __pyx_v_new_tail1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 239, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-        __Pyx_XDECREF_SET(__pyx_v_subseq1, __pyx_t_3);
-        __pyx_t_3 = 0;
-
+240:                 subseq2 = a2 + new_head2 + b2 + new_tail2
-
        __pyx_t_3 = PyNumber_Add(__pyx_v_a2, __pyx_v_new_head2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 240, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __pyx_t_8 = PyNumber_Add(__pyx_t_3, __pyx_v_b2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 240, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        __pyx_t_3 = PyNumber_Add(__pyx_t_8, __pyx_v_new_tail2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 240, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-        __Pyx_XDECREF_SET(__pyx_v_subseq2, __pyx_t_3);
-        __pyx_t_3 = 0;
-
 241: 
-
+242:                 res3 = (subseq1, subseq2)
-
        __pyx_t_3 = PyTuple_New(2); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 242, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __Pyx_INCREF(__pyx_v_subseq1);
-        __Pyx_GIVEREF(__pyx_v_subseq1);
-        PyTuple_SET_ITEM(__pyx_t_3, 0, __pyx_v_subseq1);
-        __Pyx_INCREF(__pyx_v_subseq2);
-        __Pyx_GIVEREF(__pyx_v_subseq2);
-        PyTuple_SET_ITEM(__pyx_t_3, 1, __pyx_v_subseq2);
-        __Pyx_XDECREF_SET(__pyx_v_res3, ((PyObject*)__pyx_t_3));
-        __pyx_t_3 = 0;
-
+243:                 val3 = pval_h + pval_t + affinity
-
        __pyx_t_3 = PyNumber_Add(__pyx_v_pval_h, __pyx_v_pval_t); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 243, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_3);
-        __pyx_t_8 = PyNumber_Add(__pyx_t_3, __pyx_v_affinity); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 243, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-        __Pyx_XDECREF_SET(__pyx_v_val3, __pyx_t_8);
-        __pyx_t_8 = 0;
-
+244:                 cand3 = (val3, res3)
-
        __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 244, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_8);
-        __Pyx_INCREF(__pyx_v_val3);
-        __Pyx_GIVEREF(__pyx_v_val3);
-        PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_v_val3);
-        __Pyx_INCREF(__pyx_v_res3);
-        __Pyx_GIVEREF(__pyx_v_res3);
-        PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_v_res3);
-        __Pyx_XDECREF_SET(__pyx_v_cand3, ((PyObject*)__pyx_t_8));
-        __pyx_t_8 = 0;
-
 245:             else:
-
+246:                 cand3 = (-1, None)
-
      /*else*/ {
-        __Pyx_INCREF(__pyx_tuple_);
-        __Pyx_XDECREF_SET(__pyx_v_cand3, __pyx_tuple_);
-      }
-      __pyx_L20:;
-
 247: 
-
 248:             # We solved the frame
-
+249:             _results[key] = max(cand1, cand2, cand3)
-
      __Pyx_INCREF(__pyx_v_cand2);
-      __pyx_t_8 = __pyx_v_cand2;
-      __Pyx_INCREF(__pyx_v_cand3);
-      __pyx_t_21 = __pyx_v_cand3;
-      __Pyx_INCREF(__pyx_v_cand1);
-      __pyx_t_3 = __pyx_v_cand1;
-      __pyx_t_1 = PyObject_RichCompare(__pyx_t_8, __pyx_t_3, Py_GT); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 249, __pyx_L1_error)
-      __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 249, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      if (__pyx_t_14) {
-        __Pyx_INCREF(__pyx_t_8);
-        __pyx_t_7 = __pyx_t_8;
-      } else {
-        __Pyx_INCREF(__pyx_t_3);
-        __pyx_t_7 = __pyx_t_3;
-      }
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_INCREF(__pyx_t_7);
-      __pyx_t_3 = __pyx_t_7;
-      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-      __pyx_t_1 = PyObject_RichCompare(__pyx_t_21, __pyx_t_3, Py_GT); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 249, __pyx_L1_error)
-      __pyx_t_14 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_14 < 0)) __PYX_ERR(0, 249, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      if (__pyx_t_14) {
-        __Pyx_INCREF(__pyx_t_21);
-        __pyx_t_7 = __pyx_t_21;
-      } else {
-        __Pyx_INCREF(__pyx_t_3);
-        __pyx_t_7 = __pyx_t_3;
-      }
-      __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
-      __Pyx_DECREF(__pyx_t_21); __pyx_t_21 = 0;
-      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-      __pyx_t_8 = __pyx_t_7;
-      __Pyx_INCREF(__pyx_t_8);
-      __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
-      if (unlikely(PyDict_SetItem(__pyx_v__results, __pyx_v_key, __pyx_t_8) < 0)) __PYX_ERR(0, 249, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-
+250:         stack.pop()
-
    __pyx_t_8 = __Pyx_PyList_Pop(__pyx_v_stack); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 250, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_8);
-    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-    __pyx_L15_continue:;
-  }
-
 251: 
-
 252:     # The stack pop is our solution
-
+253:     (val, best) = _results[key0]
-
  __pyx_t_8 = __Pyx_PyDict_GetItem(__pyx_v__results, __pyx_v_key0); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 253, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_8);
-  if ((likely(PyTuple_CheckExact(__pyx_t_8))) || (PyList_CheckExact(__pyx_t_8))) {
-    PyObject* sequence = __pyx_t_8;
-    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-    if (unlikely(size != 2)) {
-      if (size > 2) __Pyx_RaiseTooManyValuesError(2);
-      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-      __PYX_ERR(0, 253, __pyx_L1_error)
-    }
-    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-    if (likely(PyTuple_CheckExact(sequence))) {
-      __pyx_t_7 = PyTuple_GET_ITEM(sequence, 0); 
-      __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); 
-    } else {
-      __pyx_t_7 = PyList_GET_ITEM(sequence, 0); 
-      __pyx_t_3 = PyList_GET_ITEM(sequence, 1); 
-    }
-    __Pyx_INCREF(__pyx_t_7);
-    __Pyx_INCREF(__pyx_t_3);
-    #else
-    __pyx_t_7 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 253, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_7);
-    __pyx_t_3 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 253, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_3);
-    #endif
-    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-  } else {
-    Py_ssize_t index = -1;
-    __pyx_t_1 = PyObject_GetIter(__pyx_t_8); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 253, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
-    __pyx_t_9 = Py_TYPE(__pyx_t_1)->tp_iternext;
-    index = 0; __pyx_t_7 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_7)) goto __pyx_L31_unpacking_failed;
-    __Pyx_GOTREF(__pyx_t_7);
-    index = 1; __pyx_t_3 = __pyx_t_9(__pyx_t_1); if (unlikely(!__pyx_t_3)) goto __pyx_L31_unpacking_failed;
-    __Pyx_GOTREF(__pyx_t_3);
-    if (__Pyx_IternextUnpackEndCheck(__pyx_t_9(__pyx_t_1), 2) < 0) __PYX_ERR(0, 253, __pyx_L1_error)
-    __pyx_t_9 = NULL;
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    goto __pyx_L32_unpacking_done;
-    __pyx_L31_unpacking_failed:;
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __pyx_t_9 = NULL;
-    if (__Pyx_IterFinish() == 0) __Pyx_RaiseNeedMoreValuesError(index);
-    __PYX_ERR(0, 253, __pyx_L1_error)
-    __pyx_L32_unpacking_done:;
-  }
-  if (!(likely(PyTuple_CheckExact(__pyx_t_3))||((__pyx_t_3) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "tuple", Py_TYPE(__pyx_t_3)->tp_name), 0))) __PYX_ERR(0, 253, __pyx_L1_error)
-  __pyx_v_val = __pyx_t_7;
-  __pyx_t_7 = 0;
-  __Pyx_DECREF_SET(__pyx_v_best, ((PyObject*)__pyx_t_3));
-  __pyx_t_3 = 0;
-
+254:     found = (best, val)
-
  __pyx_t_8 = PyTuple_New(2); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 254, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_8);
-  __Pyx_INCREF(__pyx_v_best);
-  __Pyx_GIVEREF(__pyx_v_best);
-  PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_v_best);
-  __Pyx_INCREF(__pyx_v_val);
-  __Pyx_GIVEREF(__pyx_v_val);
-  PyTuple_SET_ITEM(__pyx_t_8, 1, __pyx_v_val);
-  __pyx_v_found = ((PyObject*)__pyx_t_8);
-  __pyx_t_8 = 0;
-
+255:     return found
-
  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_found);
-  __pyx_r = __pyx_v_found;
-  goto __pyx_L0;
-
 256: 
-
 257: 
-
+258: cdef tuple balanced_decomp_unsafe_cython(sequence, dict open_to_close):
-
static PyObject *__pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_balanced_decomp_unsafe_cython(PyObject *__pyx_v_sequence, PyObject *__pyx_v_open_to_close) {
-  int __pyx_v_stacklen;
-  int __pyx_v_head_stop;
-  PyObject *__pyx_v_tok_curr = NULL;
-  PyObject *__pyx_v_want_close = NULL;
-  PyObject *__pyx_v_pop_close = NULL;
-  PyObject *__pyx_v_pop_open = NULL;
-  PyObject *__pyx_v_head = NULL;
-  PyObject *__pyx_v_tail = NULL;
-  PyObject *__pyx_v_head_tail = NULL;
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("balanced_decomp_unsafe_cython", 0);
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython.balanced_decomp_unsafe_cython", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_tok_curr);
-  __Pyx_XDECREF(__pyx_v_want_close);
-  __Pyx_XDECREF(__pyx_v_pop_close);
-  __Pyx_XDECREF(__pyx_v_pop_open);
-  __Pyx_XDECREF(__pyx_v_head);
-  __Pyx_XDECREF(__pyx_v_tail);
-  __Pyx_XDECREF(__pyx_v_head_tail);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
+259:     cdef int stacklen = 1  # always +1 in the first iteration
-
  __pyx_v_stacklen = 1;
-
+260:     cdef int head_stop = 1
-
  __pyx_v_head_stop = 1;
-
 261: 
-
+262:     tok_curr = sequence[0]
-
  __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_sequence, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 262, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_v_tok_curr = __pyx_t_1;
-  __pyx_t_1 = 0;
-
+263:     want_close = open_to_close[tok_curr]
-
  if (unlikely(__pyx_v_open_to_close == Py_None)) {
-    PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-    __PYX_ERR(0, 263, __pyx_L1_error)
-  }
-  __pyx_t_1 = __Pyx_PyDict_GetItem(__pyx_v_open_to_close, __pyx_v_tok_curr); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 263, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_v_want_close = __pyx_t_1;
-  __pyx_t_1 = 0;
-
 264: 
-
 265:     # for tok_curr in sequence[1:]:
-
+266:     for head_stop in range(1, len(sequence)):
-
  __pyx_t_2 = PyObject_Length(__pyx_v_sequence); if (unlikely(__pyx_t_2 == ((Py_ssize_t)-1))) __PYX_ERR(0, 266, __pyx_L1_error)
-  __pyx_t_3 = __pyx_t_2;
-  for (__pyx_t_4 = 1; __pyx_t_4 < __pyx_t_3; __pyx_t_4+=1) {
-    __pyx_v_head_stop = __pyx_t_4;
-
+267:         tok_curr = sequence[head_stop]
-
    __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_sequence, __pyx_v_head_stop, int, 1, __Pyx_PyInt_From_int, 0, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 267, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF_SET(__pyx_v_tok_curr, __pyx_t_1);
-    __pyx_t_1 = 0;
-
+268:         stacklen += 1 if tok_curr in open_to_close else -1
-
    if (unlikely(__pyx_v_open_to_close == Py_None)) {
-      PyErr_SetString(PyExc_TypeError, "'NoneType' object is not iterable");
-      __PYX_ERR(0, 268, __pyx_L1_error)
-    }
-    __pyx_t_6 = (__Pyx_PyDict_ContainsTF(__pyx_v_tok_curr, __pyx_v_open_to_close, Py_EQ)); if (unlikely(__pyx_t_6 < 0)) __PYX_ERR(0, 268, __pyx_L1_error)
-    if ((__pyx_t_6 != 0)) {
-      __pyx_t_5 = 1;
-    } else {
-      __pyx_t_5 = -1L;
-    }
-    __pyx_v_stacklen = (__pyx_v_stacklen + __pyx_t_5);
-
+269:         if stacklen == 0 and tok_curr == want_close:
-
    __pyx_t_7 = ((__pyx_v_stacklen == 0) != 0);
-    if (__pyx_t_7) {
-    } else {
-      __pyx_t_6 = __pyx_t_7;
-      goto __pyx_L6_bool_binop_done;
-    }
-    __pyx_t_1 = PyObject_RichCompare(__pyx_v_tok_curr, __pyx_v_want_close, Py_EQ); __Pyx_XGOTREF(__pyx_t_1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 269, __pyx_L1_error)
-    __pyx_t_7 = __Pyx_PyObject_IsTrue(__pyx_t_1); if (unlikely(__pyx_t_7 < 0)) __PYX_ERR(0, 269, __pyx_L1_error)
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-    __pyx_t_6 = __pyx_t_7;
-    __pyx_L6_bool_binop_done:;
-    if (__pyx_t_6) {
-/* … */
-    }
-  }
-  __pyx_L4_break:;
-
+270:             pop_close = sequence[head_stop:head_stop + 1]
-
      __pyx_t_1 = __Pyx_PyObject_GetSlice(__pyx_v_sequence, __pyx_v_head_stop, (__pyx_v_head_stop + 1), NULL, NULL, NULL, 1, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 270, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __pyx_v_pop_close = __pyx_t_1;
-      __pyx_t_1 = 0;
-
+271:             break
-
      goto __pyx_L4_break;
-
 272: 
-
+273:     pop_open = sequence[0:1]
-
  __pyx_t_1 = __Pyx_PyObject_GetSlice(__pyx_v_sequence, 0, 1, NULL, NULL, &__pyx_slice__3, 1, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 273, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_v_pop_open = __pyx_t_1;
-  __pyx_t_1 = 0;
-/* … */
-  __pyx_slice__3 = PySlice_New(__pyx_int_0, __pyx_int_1, Py_None); if (unlikely(!__pyx_slice__3)) __PYX_ERR(0, 273, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_slice__3);
-  __Pyx_GIVEREF(__pyx_slice__3);
-
+274:     head = sequence[1:head_stop]
-
  __pyx_t_1 = __Pyx_PyObject_GetSlice(__pyx_v_sequence, 1, __pyx_v_head_stop, NULL, NULL, NULL, 1, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 274, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_v_head = __pyx_t_1;
-  __pyx_t_1 = 0;
-
+275:     tail = sequence[head_stop + 1:]
-
  __pyx_t_1 = __Pyx_PyObject_GetSlice(__pyx_v_sequence, (__pyx_v_head_stop + 1), 0, NULL, NULL, NULL, 1, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 275, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_v_tail = __pyx_t_1;
-  __pyx_t_1 = 0;
-
+276:     head_tail = head + tail
-
  __pyx_t_1 = PyNumber_Add(__pyx_v_head, __pyx_v_tail); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 276, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_v_head_tail = __pyx_t_1;
-  __pyx_t_1 = 0;
-
+277:     return pop_open, pop_close, head, tail, head_tail
-
  __Pyx_XDECREF(__pyx_r);
-  if (unlikely(!__pyx_v_pop_close)) { __Pyx_RaiseUnboundLocalError("pop_close"); __PYX_ERR(0, 277, __pyx_L1_error) }
-  __pyx_t_1 = PyTuple_New(5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 277, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_INCREF(__pyx_v_pop_open);
-  __Pyx_GIVEREF(__pyx_v_pop_open);
-  PyTuple_SET_ITEM(__pyx_t_1, 0, __pyx_v_pop_open);
-  __Pyx_INCREF(__pyx_v_pop_close);
-  __Pyx_GIVEREF(__pyx_v_pop_close);
-  PyTuple_SET_ITEM(__pyx_t_1, 1, __pyx_v_pop_close);
-  __Pyx_INCREF(__pyx_v_head);
-  __Pyx_GIVEREF(__pyx_v_head);
-  PyTuple_SET_ITEM(__pyx_t_1, 2, __pyx_v_head);
-  __Pyx_INCREF(__pyx_v_tail);
-  __Pyx_GIVEREF(__pyx_v_tail);
-  PyTuple_SET_ITEM(__pyx_t_1, 3, __pyx_v_tail);
-  __Pyx_INCREF(__pyx_v_head_tail);
-  __Pyx_GIVEREF(__pyx_v_head_tail);
-  PyTuple_SET_ITEM(__pyx_t_1, 4, __pyx_v_head_tail);
-  __pyx_r = ((PyObject*)__pyx_t_1);
-  __pyx_t_1 = 0;
-  goto __pyx_L0;
-
 278: 
-
 279: 
-
+280: cdef generate_all_decomp_cython(seq, open_to_close, open_to_node=None):
-
static PyObject *__pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython(PyObject *__pyx_v_seq, PyObject *__pyx_v_open_to_close, struct __pyx_opt_args_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_cython *__pyx_optional_args) {
-  PyObject *__pyx_v_open_to_node = ((PyObject *)Py_None);
-  PyObject *__pyx_v_all_decomp = NULL;
-  PyObject *__pyx_v_stack = NULL;
-  PyObject *__pyx_v_pop_open = NULL;
-  PyObject *__pyx_v_pop_close = NULL;
-  PyObject *__pyx_v_head = NULL;
-  PyObject *__pyx_v_tail = NULL;
-  PyObject *__pyx_v_head_tail = NULL;
-  PyObject *__pyx_v_node = NULL;
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("generate_all_decomp_cython", 0);
-  if (__pyx_optional_args) {
-    if (__pyx_optional_args->__pyx_n > 0) {
-      __pyx_v_open_to_node = __pyx_optional_args->open_to_node;
-    }
-  }
-  __Pyx_INCREF(__pyx_v_seq);
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_XDECREF(__pyx_t_7);
-  __Pyx_XDECREF(__pyx_t_8);
-  __Pyx_XDECREF(__pyx_t_9);
-  __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython.generate_all_decomp_cython", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_all_decomp);
-  __Pyx_XDECREF(__pyx_v_stack);
-  __Pyx_XDECREF(__pyx_v_pop_open);
-  __Pyx_XDECREF(__pyx_v_pop_close);
-  __Pyx_XDECREF(__pyx_v_head);
-  __Pyx_XDECREF(__pyx_v_tail);
-  __Pyx_XDECREF(__pyx_v_head_tail);
-  __Pyx_XDECREF(__pyx_v_node);
-  __Pyx_XDECREF(__pyx_v_seq);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 281:     """
-
 282:     Cython version of :func:`generate_all_decomp`. 
-
 283: 
-
 284:     >>> seq, open_to_close, nodes = random_balanced_sequence(10)
-
 285:     >>> seq, open_to_close, nodes = tree_to_seq(tree, mode='chr', strhack=True)
-
 286:     >>> all_decomp = generate_all_decomp_cython(seq, open_to_close)
-
 287:     """
-
+288:     all_decomp = {}
-
  __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 288, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_v_all_decomp = ((PyObject*)__pyx_t_1);
-  __pyx_t_1 = 0;
-
+289:     stack = [seq]
-
  __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 289, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_INCREF(__pyx_v_seq);
-  __Pyx_GIVEREF(__pyx_v_seq);
-  PyList_SET_ITEM(__pyx_t_1, 0, __pyx_v_seq);
-  __pyx_v_stack = ((PyObject*)__pyx_t_1);
-  __pyx_t_1 = 0;
-
+290:     while stack:
-
  while (1) {
-    __pyx_t_2 = (PyList_GET_SIZE(__pyx_v_stack) != 0);
-    if (!__pyx_t_2) break;
-
+291:         seq = stack.pop()
-
    __pyx_t_1 = __Pyx_PyList_Pop(__pyx_v_stack); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 291, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF_SET(__pyx_v_seq, __pyx_t_1);
-    __pyx_t_1 = 0;
-
+292:         if seq not in all_decomp and seq:
-
    __pyx_t_3 = (__Pyx_PyDict_ContainsTF(__pyx_v_seq, __pyx_v_all_decomp, Py_NE)); if (unlikely(__pyx_t_3 < 0)) __PYX_ERR(0, 292, __pyx_L1_error)
-    __pyx_t_4 = (__pyx_t_3 != 0);
-    if (__pyx_t_4) {
-    } else {
-      __pyx_t_2 = __pyx_t_4;
-      goto __pyx_L6_bool_binop_done;
-    }
-    __pyx_t_4 = __Pyx_PyObject_IsTrue(__pyx_v_seq); if (unlikely(__pyx_t_4 < 0)) __PYX_ERR(0, 292, __pyx_L1_error)
-    __pyx_t_2 = __pyx_t_4;
-    __pyx_L6_bool_binop_done:;
-    if (__pyx_t_2) {
-/* … */
-    }
-  }
-
+293:             pop_open, pop_close, head, tail, head_tail = balanced_decomp_unsafe_cython(seq, open_to_close)
-
      if (!(likely(PyDict_CheckExact(__pyx_v_open_to_close))||((__pyx_v_open_to_close) == Py_None)||(PyErr_Format(PyExc_TypeError, "Expected %.16s, got %.200s", "dict", Py_TYPE(__pyx_v_open_to_close)->tp_name), 0))) __PYX_ERR(0, 293, __pyx_L1_error)
-      __pyx_t_1 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_balanced_decomp_unsafe_cython(__pyx_v_seq, ((PyObject*)__pyx_v_open_to_close)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 293, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      if (likely(__pyx_t_1 != Py_None)) {
-        PyObject* sequence = __pyx_t_1;
-        Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-        if (unlikely(size != 5)) {
-          if (size > 5) __Pyx_RaiseTooManyValuesError(5);
-          else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-          __PYX_ERR(0, 293, __pyx_L1_error)
-        }
-        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-        __pyx_t_5 = PyTuple_GET_ITEM(sequence, 0); 
-        __pyx_t_6 = PyTuple_GET_ITEM(sequence, 1); 
-        __pyx_t_7 = PyTuple_GET_ITEM(sequence, 2); 
-        __pyx_t_8 = PyTuple_GET_ITEM(sequence, 3); 
-        __pyx_t_9 = PyTuple_GET_ITEM(sequence, 4); 
-        __Pyx_INCREF(__pyx_t_5);
-        __Pyx_INCREF(__pyx_t_6);
-        __Pyx_INCREF(__pyx_t_7);
-        __Pyx_INCREF(__pyx_t_8);
-        __Pyx_INCREF(__pyx_t_9);
-        #else
-        {
-          Py_ssize_t i;
-          PyObject** temps[5] = {&__pyx_t_5,&__pyx_t_6,&__pyx_t_7,&__pyx_t_8,&__pyx_t_9};
-          for (i=0; i < 5; i++) {
-            PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 293, __pyx_L1_error)
-            __Pyx_GOTREF(item);
-            *(temps[i]) = item;
-          }
-        }
-        #endif
-        __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      } else {
-        __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 293, __pyx_L1_error)
-      }
-      __Pyx_XDECREF_SET(__pyx_v_pop_open, __pyx_t_5);
-      __pyx_t_5 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_pop_close, __pyx_t_6);
-      __pyx_t_6 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_head, __pyx_t_7);
-      __pyx_t_7 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_tail, __pyx_t_8);
-      __pyx_t_8 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_head_tail, __pyx_t_9);
-      __pyx_t_9 = 0;
-
+294:             node = open_to_node[pop_open[0]]
-
      __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_pop_open, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 294, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_1);
-      __pyx_t_9 = __Pyx_PyObject_GetItem(__pyx_v_open_to_node, __pyx_t_1); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 294, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_9);
-      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-      __Pyx_XDECREF_SET(__pyx_v_node, __pyx_t_9);
-      __pyx_t_9 = 0;
-
+295:             all_decomp[seq] = (node, pop_open, pop_close, head, tail, head_tail)
-
      __pyx_t_9 = PyTuple_New(6); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 295, __pyx_L1_error)
-      __Pyx_GOTREF(__pyx_t_9);
-      __Pyx_INCREF(__pyx_v_node);
-      __Pyx_GIVEREF(__pyx_v_node);
-      PyTuple_SET_ITEM(__pyx_t_9, 0, __pyx_v_node);
-      __Pyx_INCREF(__pyx_v_pop_open);
-      __Pyx_GIVEREF(__pyx_v_pop_open);
-      PyTuple_SET_ITEM(__pyx_t_9, 1, __pyx_v_pop_open);
-      __Pyx_INCREF(__pyx_v_pop_close);
-      __Pyx_GIVEREF(__pyx_v_pop_close);
-      PyTuple_SET_ITEM(__pyx_t_9, 2, __pyx_v_pop_close);
-      __Pyx_INCREF(__pyx_v_head);
-      __Pyx_GIVEREF(__pyx_v_head);
-      PyTuple_SET_ITEM(__pyx_t_9, 3, __pyx_v_head);
-      __Pyx_INCREF(__pyx_v_tail);
-      __Pyx_GIVEREF(__pyx_v_tail);
-      PyTuple_SET_ITEM(__pyx_t_9, 4, __pyx_v_tail);
-      __Pyx_INCREF(__pyx_v_head_tail);
-      __Pyx_GIVEREF(__pyx_v_head_tail);
-      PyTuple_SET_ITEM(__pyx_t_9, 5, __pyx_v_head_tail);
-      if (unlikely(PyDict_SetItem(__pyx_v_all_decomp, __pyx_v_seq, __pyx_t_9) < 0)) __PYX_ERR(0, 295, __pyx_L1_error)
-      __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
-
+296:             stack.append(head_tail)
-
      __pyx_t_10 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_head_tail); if (unlikely(__pyx_t_10 == ((int)-1))) __PYX_ERR(0, 296, __pyx_L1_error)
-
+297:             stack.append(head)
-
      __pyx_t_10 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_head); if (unlikely(__pyx_t_10 == ((int)-1))) __PYX_ERR(0, 297, __pyx_L1_error)
-
+298:             stack.append(tail)
-
      __pyx_t_10 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_tail); if (unlikely(__pyx_t_10 == ((int)-1))) __PYX_ERR(0, 298, __pyx_L1_error)
-
+299:     return all_decomp
-
  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_all_decomp);
-  __pyx_r = __pyx_v_all_decomp;
-  goto __pyx_L0;
-
 300: 
-
 301: 
-
+302: cdef tuple balanced_decomp_prehash_cython(seq, dict open_to_close, open_to_node):
-
static PyObject *__pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_balanced_decomp_prehash_cython(PyObject *__pyx_v_seq, PyObject *__pyx_v_open_to_close, PyObject *__pyx_v_open_to_node) {
-  PyObject *__pyx_v_info = 0;
-  PyObject *__pyx_v_pop_open = NULL;
-  PyObject *__pyx_v_pop_close = NULL;
-  PyObject *__pyx_v_head = NULL;
-  PyObject *__pyx_v_tail = NULL;
-  PyObject *__pyx_v_head_tail = NULL;
-  Py_hash_t __pyx_v_head_key;
-  Py_hash_t __pyx_v_tail_key;
-  Py_hash_t __pyx_v_head_tail_key;
-  PyObject *__pyx_v_node = NULL;
-  PyObject *__pyx_v_a = NULL;
-  PyObject *__pyx_v_b = NULL;
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("balanced_decomp_prehash_cython", 0);
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_3);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython.balanced_decomp_prehash_cython", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_info);
-  __Pyx_XDECREF(__pyx_v_pop_open);
-  __Pyx_XDECREF(__pyx_v_pop_close);
-  __Pyx_XDECREF(__pyx_v_head);
-  __Pyx_XDECREF(__pyx_v_tail);
-  __Pyx_XDECREF(__pyx_v_head_tail);
-  __Pyx_XDECREF(__pyx_v_node);
-  __Pyx_XDECREF(__pyx_v_a);
-  __Pyx_XDECREF(__pyx_v_b);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 303:     """
-
 304:     Cython version of :func:`balanced_decomp_unsafe`. 
-
 305:     """
-
 306:     cdef tuple info
-
+307:     pop_open, pop_close, head, tail, head_tail = balanced_decomp_unsafe_cython(seq, open_to_close)
-
  __pyx_t_1 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_balanced_decomp_unsafe_cython(__pyx_v_seq, __pyx_v_open_to_close); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 307, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  if (likely(__pyx_t_1 != Py_None)) {
-    PyObject* sequence = __pyx_t_1;
-    Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-    if (unlikely(size != 5)) {
-      if (size > 5) __Pyx_RaiseTooManyValuesError(5);
-      else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-      __PYX_ERR(0, 307, __pyx_L1_error)
-    }
-    #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-    __pyx_t_2 = PyTuple_GET_ITEM(sequence, 0); 
-    __pyx_t_3 = PyTuple_GET_ITEM(sequence, 1); 
-    __pyx_t_4 = PyTuple_GET_ITEM(sequence, 2); 
-    __pyx_t_5 = PyTuple_GET_ITEM(sequence, 3); 
-    __pyx_t_6 = PyTuple_GET_ITEM(sequence, 4); 
-    __Pyx_INCREF(__pyx_t_2);
-    __Pyx_INCREF(__pyx_t_3);
-    __Pyx_INCREF(__pyx_t_4);
-    __Pyx_INCREF(__pyx_t_5);
-    __Pyx_INCREF(__pyx_t_6);
-    #else
-    {
-      Py_ssize_t i;
-      PyObject** temps[5] = {&__pyx_t_2,&__pyx_t_3,&__pyx_t_4,&__pyx_t_5,&__pyx_t_6};
-      for (i=0; i < 5; i++) {
-        PyObject* item = PySequence_ITEM(sequence, i); if (unlikely(!item)) __PYX_ERR(0, 307, __pyx_L1_error)
-        __Pyx_GOTREF(item);
-        *(temps[i]) = item;
-      }
-    }
-    #endif
-    __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  } else {
-    __Pyx_RaiseNoneNotIterableError(); __PYX_ERR(0, 307, __pyx_L1_error)
-  }
-  __pyx_v_pop_open = __pyx_t_2;
-  __pyx_t_2 = 0;
-  __pyx_v_pop_close = __pyx_t_3;
-  __pyx_t_3 = 0;
-  __pyx_v_head = __pyx_t_4;
-  __pyx_t_4 = 0;
-  __pyx_v_tail = __pyx_t_5;
-  __pyx_t_5 = 0;
-  __pyx_v_head_tail = __pyx_t_6;
-  __pyx_t_6 = 0;
-
+308:     cdef Py_hash_t head_key = hash(head)
-
  __pyx_t_7 = PyObject_Hash(__pyx_v_head); if (unlikely(__pyx_t_7 == ((Py_hash_t)-1))) __PYX_ERR(0, 308, __pyx_L1_error)
-  __pyx_v_head_key = __pyx_t_7;
-
+309:     cdef Py_hash_t tail_key = hash(tail)
-
  __pyx_t_7 = PyObject_Hash(__pyx_v_tail); if (unlikely(__pyx_t_7 == ((Py_hash_t)-1))) __PYX_ERR(0, 309, __pyx_L1_error)
-  __pyx_v_tail_key = __pyx_t_7;
-
+310:     cdef Py_hash_t head_tail_key = hash(head_tail)
-
  __pyx_t_7 = PyObject_Hash(__pyx_v_head_tail); if (unlikely(__pyx_t_7 == ((Py_hash_t)-1))) __PYX_ERR(0, 310, __pyx_L1_error)
-  __pyx_v_head_tail_key = __pyx_t_7;
-
+311:     node = open_to_node[pop_open[0]]
-
  __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_pop_open, 0, long, 1, __Pyx_PyInt_From_long, 0, 0, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 311, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_6 = __Pyx_PyObject_GetItem(__pyx_v_open_to_node, __pyx_t_1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 311, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-  __pyx_v_node = __pyx_t_6;
-  __pyx_t_6 = 0;
-
+312:     a = pop_open
-
  __Pyx_INCREF(__pyx_v_pop_open);
-  __pyx_v_a = __pyx_v_pop_open;
-
+313:     b = pop_close
-
  __Pyx_INCREF(__pyx_v_pop_close);
-  __pyx_v_b = __pyx_v_pop_close;
-
+314:     info = (node, seq, head, tail, head_tail, head_key, tail_key, head_tail_key, a, b)
-
  __pyx_t_6 = __Pyx_PyInt_FromHash_t(__pyx_v_head_key); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 314, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_6);
-  __pyx_t_1 = __Pyx_PyInt_FromHash_t(__pyx_v_tail_key); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 314, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_5 = __Pyx_PyInt_FromHash_t(__pyx_v_head_tail_key); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 314, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_5);
-  __pyx_t_4 = PyTuple_New(10); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 314, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_4);
-  __Pyx_INCREF(__pyx_v_node);
-  __Pyx_GIVEREF(__pyx_v_node);
-  PyTuple_SET_ITEM(__pyx_t_4, 0, __pyx_v_node);
-  __Pyx_INCREF(__pyx_v_seq);
-  __Pyx_GIVEREF(__pyx_v_seq);
-  PyTuple_SET_ITEM(__pyx_t_4, 1, __pyx_v_seq);
-  __Pyx_INCREF(__pyx_v_head);
-  __Pyx_GIVEREF(__pyx_v_head);
-  PyTuple_SET_ITEM(__pyx_t_4, 2, __pyx_v_head);
-  __Pyx_INCREF(__pyx_v_tail);
-  __Pyx_GIVEREF(__pyx_v_tail);
-  PyTuple_SET_ITEM(__pyx_t_4, 3, __pyx_v_tail);
-  __Pyx_INCREF(__pyx_v_head_tail);
-  __Pyx_GIVEREF(__pyx_v_head_tail);
-  PyTuple_SET_ITEM(__pyx_t_4, 4, __pyx_v_head_tail);
-  __Pyx_GIVEREF(__pyx_t_6);
-  PyTuple_SET_ITEM(__pyx_t_4, 5, __pyx_t_6);
-  __Pyx_GIVEREF(__pyx_t_1);
-  PyTuple_SET_ITEM(__pyx_t_4, 6, __pyx_t_1);
-  __Pyx_GIVEREF(__pyx_t_5);
-  PyTuple_SET_ITEM(__pyx_t_4, 7, __pyx_t_5);
-  __Pyx_INCREF(__pyx_v_a);
-  __Pyx_GIVEREF(__pyx_v_a);
-  PyTuple_SET_ITEM(__pyx_t_4, 8, __pyx_v_a);
-  __Pyx_INCREF(__pyx_v_b);
-  __Pyx_GIVEREF(__pyx_v_b);
-  PyTuple_SET_ITEM(__pyx_t_4, 9, __pyx_v_b);
-  __pyx_t_6 = 0;
-  __pyx_t_1 = 0;
-  __pyx_t_5 = 0;
-  __pyx_v_info = ((PyObject*)__pyx_t_4);
-  __pyx_t_4 = 0;
-
+315:     return info
-
  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_info);
-  __pyx_r = __pyx_v_info;
-  goto __pyx_L0;
-
 316: 
-
 317: 
-
+318: cdef dict generate_all_decomp_prehash_cython(seq, dict open_to_close, open_to_node):
-
static PyObject *__pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_generate_all_decomp_prehash_cython(PyObject *__pyx_v_seq, PyObject *__pyx_v_open_to_close, PyObject *__pyx_v_open_to_node) {
-  PyObject *__pyx_v_all_decomp = 0;
-  PyObject *__pyx_v_stack = 0;
-  PyObject *__pyx_v_info = 0;
-  PyObject *__pyx_v_key = NULL;
-  PyObject *__pyx_v_head = NULL;
-  PyObject *__pyx_v_tail = NULL;
-  PyObject *__pyx_v_head_tail = NULL;
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("generate_all_decomp_prehash_cython", 0);
-  __Pyx_INCREF(__pyx_v_seq);
-/* … */
-  /* function exit code */
-  __pyx_L1_error:;
-  __Pyx_XDECREF(__pyx_t_1);
-  __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_5);
-  __Pyx_XDECREF(__pyx_t_6);
-  __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython.generate_all_decomp_prehash_cython", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __pyx_r = 0;
-  __pyx_L0:;
-  __Pyx_XDECREF(__pyx_v_all_decomp);
-  __Pyx_XDECREF(__pyx_v_stack);
-  __Pyx_XDECREF(__pyx_v_info);
-  __Pyx_XDECREF(__pyx_v_key);
-  __Pyx_XDECREF(__pyx_v_head);
-  __Pyx_XDECREF(__pyx_v_tail);
-  __Pyx_XDECREF(__pyx_v_head_tail);
-  __Pyx_XDECREF(__pyx_v_seq);
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
 319:     """
-
 320:     Cython version of :func:`generate_all_decomp_prehash`. 
-
 321:     """
-
+322:     cdef dict all_decomp = {}
-
  __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 322, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __pyx_v_all_decomp = ((PyObject*)__pyx_t_1);
-  __pyx_t_1 = 0;
-
+323:     cdef list stack = [seq]
-
  __pyx_t_1 = PyList_New(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 323, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-  __Pyx_INCREF(__pyx_v_seq);
-  __Pyx_GIVEREF(__pyx_v_seq);
-  PyList_SET_ITEM(__pyx_t_1, 0, __pyx_v_seq);
-  __pyx_v_stack = ((PyObject*)__pyx_t_1);
-  __pyx_t_1 = 0;
-
 324:     cdef tuple info
-
+325:     while stack:
-
  while (1) {
-    __pyx_t_2 = (PyList_GET_SIZE(__pyx_v_stack) != 0);
-    if (!__pyx_t_2) break;
-
+326:         seq = stack.pop()
-
    __pyx_t_1 = __Pyx_PyList_Pop(__pyx_v_stack); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 326, __pyx_L1_error)
-    __Pyx_GOTREF(__pyx_t_1);
-    __Pyx_DECREF_SET(__pyx_v_seq, __pyx_t_1);
-    __pyx_t_1 = 0;
-
+327:         if seq:
-
    __pyx_t_2 = __Pyx_PyObject_IsTrue(__pyx_v_seq); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 327, __pyx_L1_error)
-    if (__pyx_t_2) {
-/* … */
-    }
-  }
-
 328:             # key = hash(seq)
-
+329:             key = seq
-
      __Pyx_INCREF(__pyx_v_seq);
-      __Pyx_XDECREF_SET(__pyx_v_key, __pyx_v_seq);
-
+330:             if key not in all_decomp:
-
      __pyx_t_2 = (__Pyx_PyDict_ContainsTF(__pyx_v_key, __pyx_v_all_decomp, Py_NE)); if (unlikely(__pyx_t_2 < 0)) __PYX_ERR(0, 330, __pyx_L1_error)
-      __pyx_t_3 = (__pyx_t_2 != 0);
-      if (__pyx_t_3) {
-/* … */
-      }
-
+331:                 info = balanced_decomp_prehash_cython(seq, open_to_close, open_to_node)
-
        __pyx_t_1 = __pyx_f_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_balanced_decomp_prehash_cython(__pyx_v_seq, __pyx_v_open_to_close, __pyx_v_open_to_node); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 331, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_1);
-        __Pyx_XDECREF_SET(__pyx_v_info, ((PyObject*)__pyx_t_1));
-        __pyx_t_1 = 0;
-
+332:                 head, tail, head_tail = info[2:5]
-
        if (unlikely(__pyx_v_info == Py_None)) {
-          PyErr_SetString(PyExc_TypeError, "'NoneType' object is not subscriptable");
-          __PYX_ERR(0, 332, __pyx_L1_error)
-        }
-        __pyx_t_1 = __Pyx_PyTuple_GetSlice(__pyx_v_info, 2, 5); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 332, __pyx_L1_error)
-        __Pyx_GOTREF(__pyx_t_1);
-        if (1) {
-          PyObject* sequence = __pyx_t_1;
-          Py_ssize_t size = __Pyx_PySequence_SIZE(sequence);
-          if (unlikely(size != 3)) {
-            if (size > 3) __Pyx_RaiseTooManyValuesError(3);
-            else if (size >= 0) __Pyx_RaiseNeedMoreValuesError(size);
-            __PYX_ERR(0, 332, __pyx_L1_error)
-          }
-          #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
-          __pyx_t_4 = PyTuple_GET_ITEM(sequence, 0); 
-          __pyx_t_5 = PyTuple_GET_ITEM(sequence, 1); 
-          __pyx_t_6 = PyTuple_GET_ITEM(sequence, 2); 
-          __Pyx_INCREF(__pyx_t_4);
-          __Pyx_INCREF(__pyx_t_5);
-          __Pyx_INCREF(__pyx_t_6);
-          #else
-          __pyx_t_4 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 332, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_4);
-          __pyx_t_5 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 332, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_5);
-          __pyx_t_6 = PySequence_ITEM(sequence, 2); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 332, __pyx_L1_error)
-          __Pyx_GOTREF(__pyx_t_6);
-          #endif
-          __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-        }
-        __Pyx_XDECREF_SET(__pyx_v_head, __pyx_t_4);
-        __pyx_t_4 = 0;
-        __Pyx_XDECREF_SET(__pyx_v_tail, __pyx_t_5);
-        __pyx_t_5 = 0;
-        __Pyx_XDECREF_SET(__pyx_v_head_tail, __pyx_t_6);
-        __pyx_t_6 = 0;
-
+333:                 all_decomp[key] = info
-
        if (unlikely(PyDict_SetItem(__pyx_v_all_decomp, __pyx_v_key, __pyx_v_info) < 0)) __PYX_ERR(0, 333, __pyx_L1_error)
-
+334:                 stack.append(head_tail)
-
        __pyx_t_7 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_head_tail); if (unlikely(__pyx_t_7 == ((int)-1))) __PYX_ERR(0, 334, __pyx_L1_error)
-
+335:                 stack.append(head)
-
        __pyx_t_7 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_head); if (unlikely(__pyx_t_7 == ((int)-1))) __PYX_ERR(0, 335, __pyx_L1_error)
-
+336:                 stack.append(tail)
-
        __pyx_t_7 = __Pyx_PyList_Append(__pyx_v_stack, __pyx_v_tail); if (unlikely(__pyx_t_7 == ((int)-1))) __PYX_ERR(0, 336, __pyx_L1_error)
-
+337:     return all_decomp
-
  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_all_decomp);
-  __pyx_r = __pyx_v_all_decomp;
-  goto __pyx_L0;
-
 338: 
-
 339: 
-
+340: class IdentityDict:
-
  __pyx_t_1 = __Pyx_Py3MetaclassPrepare((PyObject *) NULL, __pyx_empty_tuple, __pyx_n_s_IdentityDict, __pyx_n_s_IdentityDict, (PyObject *) NULL, __pyx_n_s_networkx_algorithms_isomorphism, __pyx_kp_s_Used_when_open_to_node_is_unspe); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 340, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_1);
-/* … */
-  __pyx_t_2 = __Pyx_Py3ClassCreate(((PyObject*)&__Pyx_DefaultClassType), __pyx_n_s_IdentityDict, __pyx_empty_tuple, __pyx_t_1, NULL, 0, 1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 340, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  if (PyDict_SetItem(__pyx_d, __pyx_n_s_IdentityDict, __pyx_t_2) < 0) __PYX_ERR(0, 340, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
-
 341:     """ Used when ``open_to_node`` is unspecified """
-
+342:     def __getitem__(self, key):
-
/* Python wrapper */
-static PyObject *__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict_1__getitem__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static PyMethodDef __pyx_mdef_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict_1__getitem__ = {"__getitem__", (PyCFunction)(void*)(PyCFunctionWithKeywords)__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict_1__getitem__, METH_VARARGS|METH_KEYWORDS, 0};
-static PyObject *__pyx_pw_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict_1__getitem__(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  CYTHON_UNUSED PyObject *__pyx_v_self = 0;
-  PyObject *__pyx_v_key = 0;
-  PyObject *__pyx_r = 0;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__getitem__ (wrapper)", 0);
-  {
-    static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_self,&__pyx_n_s_key,0};
-    PyObject* values[2] = {0,0};
-    if (unlikely(__pyx_kwds)) {
-      Py_ssize_t kw_args;
-      const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args);
-      switch (pos_args) {
-        case  2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-        CYTHON_FALLTHROUGH;
-        case  1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-        CYTHON_FALLTHROUGH;
-        case  0: break;
-        default: goto __pyx_L5_argtuple_error;
-      }
-      kw_args = PyDict_Size(__pyx_kwds);
-      switch (pos_args) {
-        case  0:
-        if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_self)) != 0)) kw_args--;
-        else goto __pyx_L5_argtuple_error;
-        CYTHON_FALLTHROUGH;
-        case  1:
-        if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_key)) != 0)) kw_args--;
-        else {
-          __Pyx_RaiseArgtupleInvalid("__getitem__", 1, 2, 2, 1); __PYX_ERR(0, 342, __pyx_L3_error)
-        }
-      }
-      if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "__getitem__") < 0)) __PYX_ERR(0, 342, __pyx_L3_error)
-      }
-    } else if (PyTuple_GET_SIZE(__pyx_args) != 2) {
-      goto __pyx_L5_argtuple_error;
-    } else {
-      values[0] = PyTuple_GET_ITEM(__pyx_args, 0);
-      values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
-    }
-    __pyx_v_self = values[0];
-    __pyx_v_key = values[1];
-  }
-  goto __pyx_L4_argument_unpacking_done;
-  __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("__getitem__", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 342, __pyx_L3_error)
-  __pyx_L3_error:;
-  __Pyx_AddTraceback("networkx.algorithms.isomorphism._embedding.balanced_sequence_cython.IdentityDict.__getitem__", __pyx_clineno, __pyx_lineno, __pyx_filename);
-  __Pyx_RefNannyFinishContext();
-  return NULL;
-  __pyx_L4_argument_unpacking_done:;
-  __pyx_r = __pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict___getitem__(__pyx_self, __pyx_v_self, __pyx_v_key);
-  int __pyx_lineno = 0;
-  const char *__pyx_filename = NULL;
-  int __pyx_clineno = 0;
-
-  /* function exit code */
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-
-static PyObject *__pyx_pf_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict___getitem__(CYTHON_UNUSED PyObject *__pyx_self, CYTHON_UNUSED PyObject *__pyx_v_self, PyObject *__pyx_v_key) {
-  PyObject *__pyx_r = NULL;
-  __Pyx_RefNannyDeclarations
-  __Pyx_RefNannySetupContext("__getitem__", 0);
-/* … */
-  /* function exit code */
-  __pyx_L0:;
-  __Pyx_XGIVEREF(__pyx_r);
-  __Pyx_RefNannyFinishContext();
-  return __pyx_r;
-}
-/* … */
-  __pyx_tuple__8 = PyTuple_Pack(2, __pyx_n_s_self, __pyx_n_s_key); if (unlikely(!__pyx_tuple__8)) __PYX_ERR(0, 342, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_tuple__8);
-  __Pyx_GIVEREF(__pyx_tuple__8);
-/* … */
-  __pyx_t_2 = __Pyx_CyFunction_New(&__pyx_mdef_8networkx_10algorithms_11isomorphism_10_embedding_24balanced_sequence_cython_12IdentityDict_1__getitem__, 0, __pyx_n_s_IdentityDict___getitem, NULL, __pyx_n_s_networkx_algorithms_isomorphism, __pyx_d, ((PyObject *)__pyx_codeobj__9)); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 342, __pyx_L1_error)
-  __Pyx_GOTREF(__pyx_t_2);
-  if (__Pyx_SetNameInClass(__pyx_t_1, __pyx_n_s_getitem, __pyx_t_2) < 0) __PYX_ERR(0, 342, __pyx_L1_error)
-  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-
+343:         return key
-
  __Pyx_XDECREF(__pyx_r);
-  __Pyx_INCREF(__pyx_v_key);
-  __pyx_r = __pyx_v_key;
-  goto __pyx_L0;
-
-- GitLab From bdbf0f1da5d5773e7fc41a5b0b07fd15fa9afd73 Mon Sep 17 00:00:00 2001 From: joncrall Date: Thu, 10 Sep 2020 18:07:34 -0400 Subject: [PATCH 11/54] Deprecate netharn.export for torch_liberator / liberator --- CHANGELOG.md | 3 + netharn/__init__.py | 3 +- netharn/export/__init__.py | 145 +++++- netharn/export/closer.py | 954 +------------------------------------ netharn/export/deployer.py | 735 +--------------------------- netharn/export/exporter.py | 346 +------------- netharn/fit_harn.py | 53 ++- netharn/mixins.py | 4 +- netharn/prefit/lr_tests.py | 8 +- 9 files changed, 210 insertions(+), 2041 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a89904..0aa0eed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,9 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm * Deprecate `colored` option in `FitHarnPreferences`. Use `NO_COLOR` environ to disable ANSI coloring instead. +* `netharn.export` has been deprecated for `torch_liberator` and `liberator`, + and will be removed in the future. + ## Version 0.5.9 - Released 2020-08-26 diff --git a/netharn/__init__.py b/netharn/__init__.py index 7f01e3a..4add558 100644 --- a/netharn/__init__.py +++ b/netharn/__init__.py @@ -68,7 +68,6 @@ from netharn import criterions from netharn import data from netharn import device from netharn import exceptions -from netharn import export from netharn import fit_harn from netharn import hyperparams from netharn import initializers @@ -90,7 +89,7 @@ __all__ = ['Criterion', 'Dynamics', 'FitHarn', 'HiddenFields', 'HiddenShapes', 'Optimizer', 'OutputShape', 'OutputShapeFor', 'ReceptiveField', 'ReceptiveFieldFor', 'Scheduler', 'XPU', 'analytic_for', 'api', 'configure_hacks', 'configure_workdir', 'criterions', 'data', - 'device', 'exceptions', 'export', 'fit_harn', 'hyperparams', + 'device', 'exceptions', 'fit_harn', 'hyperparams', 'initializers', 'layers', 'metrics', 'mixins', 'models', 'monitor', 'optimizers', 'output_shape_for', 'prefit', 'receptive_field_for', 'schedulers', 'util'] diff --git a/netharn/export/__init__.py b/netharn/export/__init__.py index 9b01c18..5e30c91 100644 --- a/netharn/export/__init__.py +++ b/netharn/export/__init__.py @@ -1,10 +1,153 @@ """ -mkinit ~/code/netharn/netharn/export +NOTICE: ``netharn.export`` has been refactored into the packages ``liberator`` +which performs general code extraction and ``torch_liberator`` which is +specific to pytorch. This module is deprecated and will be removed in the +future. + +For now here are old docs, slightly updated to reference the correct packages: + +The package torch_liberator.deployed contains DeployedModel, which consists of +logic to take the model topology definition along with the "best" snapshot in a +training directory and package it up into a standalone zipfile. The +DeployedModel can also be used to reload model from this zipfile. Thus this +zipfile can be passed around as a pytorch model topology+pretrained weights +transfer format. + +The file torch_liberator.exporter contains the code that simply exports the +model toplogy via code Uses static analysis to export relevant code that +defines the model topology into a stanadlone file. As long as your model +definition is indepenent of your training code, then the exported file can be +passed around in a similar way to a caffe prototext file. + + +CommandLine: + # Runs the following example + xdoctest -m netharn.export __doc__:0 + +Example: + >>> # xdoc: +IGNORE_WANT + >>> # This example will train a small model and then deploy it. + >>> import netharn as nh + >>> import ubelt as ub + >>> # + >>> ################################################# + >>> print('--- STEP 1: TRAIN A MODEL ---') + >>> # This will train a toy model with toy data using netharn + >>> hyper = nh.HyperParams(**{ + >>> 'workdir' : ub.ensure_app_cache_dir('netharn/tests/deploy'), + >>> 'name' : 'deploy_demo', + >>> 'xpu' : nh.XPU.coerce('cpu'), + >>> 'datasets' : { + >>> 'train': nh.data.ToyData2d(size=3, border=1, n=256, rng=0), + >>> 'test': nh.data.ToyData2d(size=3, border=1, n=128, rng=1), + >>> }, + >>> 'loaders' : {'batch_size': 64}, + >>> 'model' : (nh.models.ToyNet2d, {}), + >>> 'optimizer' : (nh.optimizers.SGD, {'lr': 0.0001}), + >>> 'criterion' : (nh.criterions.CrossEntropyLoss, {}), + >>> 'initializer' : (nh.initializers.KaimingNormal, {}), + >>> 'scheduler' : (nh.schedulers.ListedLR, { + >>> 'points': {0: .01, 3: 0.1}, + >>> 'interpolate': True, + >>> }), + >>> 'monitor' : (nh.Monitor, {'max_epoch': 3,}), + >>> }) + >>> harn = nh.FitHarn(hyper) + >>> harn.preferences['use_tensorboard'] = False + >>> harn.preferences['timeout'] = 1 + >>> harn.intervals['test'] = 1 + >>> harn.initialize(reset='delete') + >>> harn.run() + --- STEP 1: TRAIN A MODEL --- + RESET HARNESS BY DELETING EVERYTHING IN TRAINING DIR + Symlink: .../.cache/netharn/tests/deploy/fit/runs/deploy_demo/onnxqaww -> .../.cache/netharn/tests/deploy/_mru + ...... + Symlink: .../.cache/netharn/tests/deploy/fit/runs/deploy_demo/onnxqaww -> .../.cache/netharn/tests/deploy/fit/nice/deploy_demo + ...... + INFO: Model has 824 parameters + INFO: Mounting ToyNet2d model on CPU + INFO: Exported model topology to .../.cache/netharn/tests/deploy/fit/runs/deploy_demo/onnxqaww/ToyNet2d_2a3f49.py + INFO: Initializing model weights with: + INFO: * harn.train_dpath = '.../.cache/netharn/tests/deploy/fit/runs/deploy_demo/onnxqaww' + INFO: * harn.name_dpath = '.../.cache/netharn/tests/deploy/fit/name/deploy_demo' + INFO: Snapshots will save to harn.snapshot_dpath = '.../.cache/netharn/tests/deploy/fit/runs/deploy_demo/onnxqaww/torch_snapshots' + INFO: ARGV: + .../.local/conda/envs/py36/bin/python .../.local/conda/envs/py36/bin/ipython + INFO: === begin training 0 / 3 : deploy_demo === + epoch lr:0.01 │ vloss is unevaluated 0/3... rate=0 Hz, eta=?, total=0:00:00, wall=19:32 EST + train loss:0.717 │ 100.00% of 64x8... rate=2093.02 Hz, eta=0:00:00, total=0:00:00, wall=19:32 EST + test loss:0.674 │ 100.00% of 64x4... rate=14103.48 Hz, eta=0:00:00, total=0:00:00, wall=19:32 EST + Populating the interactive namespace from numpy and matplotlib + INFO: === finish epoch 0 / 3 : deploy_demo === + epoch lr:0.04 │ vloss is unevaluated 1/3... rate=0.87 Hz, eta=0:00:02, total=0:00:01, wall=19:32 EST + train loss:0.712 │ 100.00% of 64x8... rate=2771.29 Hz, eta=0:00:00, total=0:00:00, wall=19:32 EST + test loss:0.663 │ 100.00% of 64x4... rate=15867.59 Hz, eta=0:00:00, total=0:00:00, wall=19:32 EST + INFO: === finish epoch 1 / 3 : deploy_demo === + epoch lr:0.07 │ vloss is unevaluated 2/3... rate=1.04 Hz, eta=0:00:00, total=0:00:01, wall=19:32 EST + train loss:0.686 │ 100.00% of 64x8... rate=2743.56 Hz, eta=0:00:00, total=0:00:00, wall=19:32 EST + test loss:0.636 │ 100.00% of 64x4... rate=14332.63 Hz, eta=0:00:00, total=0:00:00, wall=19:32 EST + INFO: === finish epoch 2 / 3 : deploy_demo === + epoch lr:0.1 │ vloss is unevaluated 3/3... rate=1.11 Hz, eta=0:00:00, total=0:00:02, wall=19:32 EST + INFO: Maximum harn.epoch reached, terminating ... + INFO: + INFO: training completed + INFO: harn.train_dpath = '.../.cache/netharn/tests/deploy/fit/runs/deploy_demo/onnxqaww' + INFO: harn.name_dpath = '.../.cache/netharn/tests/deploy/fit/name/deploy_demo' + INFO: view tensorboard results for this run via: + tensorboard --logdir ~/.cache/netharn/tests/deploy/fit/name + [DEPLOYER] Deployed zipfpath=.../.cache/netharn/tests/deploy/fit/runs/deploy_demo/onnxqaww/deploy_ToyNet2d_onnxqaww_002_TXZBYL.zip + INFO: wrote single-file deployment to: '.../.cache/netharn/tests/deploy/fit/runs/deploy_demo/onnxqaww/deploy_ToyNet2d_onnxqaww_002_TXZBYL.zip' + INFO: exiting fit harness. + Out[1]: '.../.cache/netharn/tests/deploy/fit/runs/deploy_demo/onnxqaww/deploy_ToyNet2d_onnxqaww_002_TXZBYL.zip' + >>> # + >>> ########################################## + >>> print('--- STEP 2: DEPLOY THE MODEL ---') + >>> # First we export the model topology to a standalone file + >>> # (Note: this step is done automatically in `harn.run`, but we do + >>> # it again here for demo purposes) + >>> import torch_liberator + >>> topo_fpath = torch_liberator.export_model_code(harn.train_dpath, harn.hyper.model_cls, harn.hyper.model_params) + >>> # Now create an instance of deployed model that points to the + >>> # Training dpath. (Note the directory structure setup by netharn is + >>> # itself a deployment, it just has multiple files) + >>> deployer = torch_liberator.DeployedModel(harn.train_dpath) + >>> # Use the DeployedModel to package the imporant info in train_dpath + >>> # into a standalone zipfile. + >>> zip_fpath = deployer.package() + >>> print('We exported the topology to: {!r}'.format(topo_fpath)) + >>> print('We exported the topology+weights to: {!r}'.format(zip_fpath)) + --- STEP 2: DEPLOY THE MODEL --- + We exported the topology to: '...tests/deploy/fit/runs/deploy_demo/onnxqaww/ToyNet2d_2a3f49.py' + We exported the topology+weights to: '...tests/deploy/fit/runs/deploy_demo/onnxqaww/deploy_ToyNet2d_onnxqaww_002_HVWCGI.zip' + >>> # + >>> ################################################# + >>> print('--- STEP 3: LOAD THE DEPLOYED MODEL ---') + >>> # Now we can move the zipfile anywhere we want, and we should + >>> # still be able to load it (depending on how coupled the model is). + >>> # Create an instance of DeployedModel that points to the zipfile + >>> # (Note: DeployedModel is used to both package and load models) + >>> loader = torch_liberator.DeployedModel(zip_fpath) + >>> model = loader.load_model() + >>> # This model is now loaded with the corret weights. + >>> # You can use it as normal. + >>> model.eval() + >>> images = harn._demo_batch(0)['input'][0:1] + >>> outputs = model(images) + >>> print('outputs = {!r}'.format(outputs)) + >>> # Not that the loaded model is independent of harn.model + >>> print('model.__module__ = {!r}'.format(model.__module__)) + >>> print('harn.model.module.__module__ = {!r}'.format(harn.model.module.__module__)) + --- STEP 3: LOAD THE DEPLOYED MODEL --- + outputs = tensor([[0.4105, 0.5895]], grad_fn=) + model.__module__ = 'deploy_ToyNet2d_onnxqaww_002_HVWCGI/ToyNet2d_2a3f49' + harn.model.module.__module__ = 'netharn.models.toynet' """ from netharn.export import deployer from netharn.export import exporter from netharn.export.deployer import (DeployedModel,) from netharn.export.exporter import (export_model_code,) +import warnings +warnings.warn('netharn.export is deprecated, use torch_liberator intead', DeprecationWarning) __all__ = ['DeployedModel', 'deployer', 'export_model_code', 'exporter'] diff --git a/netharn/export/closer.py b/netharn/export/closer.py index 3d3910a..5875d1c 100644 --- a/netharn/export/closer.py +++ b/netharn/export/closer.py @@ -1,954 +1,4 @@ # -*- coding: utf-8 -*- -""" -Extracts relevant parts of the source code - -NOTE: - IF THE SOURCE CODE CHANGES WHILE THE RUN IS EXECUTING THEN THIS MAY NOT - WORK CORRECTLY. - -# TODO: -# - [x] Maintain a parse tree instead of raw lines -# - [x] Keep a mapping from "definition names" to the top-level nodes -# in the parse tree that define them. -# - [X] For each extracted node in the parse tree keep track of -# - [X] where it came from -# - [ ] what modifications were made to it -# - [ ] Handle expanding imports nested within functions -# - [ ] Maintain docstring formatting after using the node transformer -""" -from __future__ import absolute_import, division, print_function, unicode_literals -from os.path import isdir -from os.path import join -from os.path import basename -from collections import OrderedDict +from liberator.closer import * # NOQA import warnings -import ast -import astunparse -import inspect -import six -import ubelt as ub -from six.moves import cStringIO -from os.path import abspath -from os.path import sys - - -# There is a bug where closing netharn cant find "HiddenFields" -HACK_FIX_CANNOT_FIND_HIDDEN = 0 - -DEBUG = 0 - - -class Unparser(astunparse.Unparser): - """ - wraps astunparse to fix 2/3 compatibility minor issues - - Notes: - x = np.random.rand(3, 3) - # In python3 this works, but it fails in python2 - x[(..., 2)] - # However, this works in both - x[(Ellipsis, 2)] - # Interestingly, this also works, but is not how astunparse generates code - x[..., 2] - """ - def _Ellipsis(self, t): - # be compatible with python2 if possible - self.write("Ellipsis") - - -def unparse(tree): - """ wraps astunparse to fix 2/3 compatibility minor issues """ - v = cStringIO() - Unparser(tree, file=v) - return v.getvalue() - - -def source_closure(obj, expand_names=[]): - """ - Pulls the minimum amount of code needed to define `obj`. Uses a - combination of dynamic and static introspection. - - Args: - obj (type): the class whose definition will be exported. - - expand_names (List[str]): - EXPERIMENTAL. List of modules that should be expanded into raw - source code. - - Returns: - str: closed_sourcecode: text defining a new python module. - - CommandLine: - xdoctest -m netharn.export.closer source_closure - - Example: - >>> import torchvision - >>> from torchvision import models - >>> got = {} - - >>> model_class = models.AlexNet - >>> text = source_closure(model_class) - >>> assert not undefined_names(text) - >>> got['alexnet'] = ub.hash_data(text) - - >>> model_class = models.DenseNet - >>> text = source_closure(model_class) - >>> assert not undefined_names(text) - >>> got['densenet'] = ub.hash_data(text) - - >>> model_class = models.resnet50 - >>> text = source_closure(model_class) - >>> assert not undefined_names(text) - >>> got['resnet50'] = ub.hash_data(text) - - >>> model_class = models.Inception3 - >>> text = source_closure(model_class) - >>> assert not undefined_names(text) - >>> got['inception3'] = ub.hash_data(text) - - >>> # The hashes will depend on torchvision itself - >>> if torchvision.__version__ == '0.2.1': - >>> # Note: the hashes may change if the exporter changes formats - >>> want = { - >>> 'alexnet': '4b2ab9c8e27b34602bdff99cbc', - >>> 'densenet': 'fef4788586d2b93587ec52dd9', - >>> 'resnet50': '343e6a73e754557fcce3fdb6', - >>> 'inception3': '2e43a58133d0817753383', - >>> } - >>> failed = [] - >>> for k in want: - >>> if not got[k].startswith(want[k]): - >>> item = (k, got[k], want[k]) - >>> print('failed item = {!r}'.format(item)) - >>> failed.append(item) - >>> assert not failed, str(failed) - >>> else: - >>> warnings.warn('Unsupported version of torchvision') - - Example: - >>> # Test a heavier duty class - >>> from netharn.export.closer import * - >>> import netharn as nh - >>> obj = nh.layers.ConvNormNd - >>> expand_names = ['netharn'] - >>> text = source_closure(obj, expand_names) - >>> print(text) - - Ignore: - import netharn as nh - obj = nh.models.yolo2.yolo2.Yolo2 - expand_names = ['netharn'] - expand_names = [] - - print(chr(10).join(closer.logs)) - """ - closer = Closer() - - # First try to add statically (which tends to be slightly nicer) - try: - try: - name = obj.__name__ - modpath = sys.modules[obj.__module__].__file__ - except Exception: - # Otherwise add dynamically - closer.add_dynamic(obj) - else: - closer.add_static(name, modpath) - if expand_names: - closer.expand(expand_names) - closed_sourcecode = closer.current_sourcecode() - except Exception: - print('ERROR IN CLOSING') - print('[[[ START CLOSE LOGS ]]]') - print('closer.logs =\n{}'.format('\n'.join(closer.logs))) - print('[[[ END CLOSE LOGS ]]]') - raise - return closed_sourcecode - - -class Closer(ub.NiceRepr): - """ - Maintains the current state of the source code - - There are 3 major steps: - (a) extract the code to that defines a function or class from a module, - (b) go back to the module and extract extra code required to define any - names that were undefined in the extracted code, and - (c) replace import statements to specified "expand" modules with the actual code - used to define the variables accessed via the imports. - - This results in a standalone file that has absolutely no dependency on the - original module or the specified "expand" modules (the expand module is - usually the module that is doing the training for a network. This means - that you can deploy a model independant of the training framework). - - Note: - This is not designed to work for cases where the code depends on logic - executed in a global scope (e.g. dynamically registering properties) . - I think its actually impossible to statically account for this case in - general. - - Ignore: - >>> from netharn.export.closer import * - >>> import netharn as nh - >>> import fastai.vision - >>> obj = fastai.vision.models.WideResNet - >>> expand_names = ['fastai'] - >>> closer = Closer() - >>> closer.add_dynamic(obj) - >>> closer.expand(expand_names) - >>> #print(ub.repr2(closer.body_defs, si=1)) - >>> print(closer.current_sourcecode()) - - Ignore: - >>> from netharn.export.closer import * - >>> import netharn as nh - >>> from netharn.models.yolo2 import yolo2 - >>> obj = yolo2.Yolo2 - >>> expand_names = ['netharn'] - >>> closer = Closer() - >>> closer.add_static(obj.__name__, sys.modules[obj.__module__].__file__) - >>> closer.expand(expand_names) - >>> #print(ub.repr2(closer.body_defs, si=1)) - >>> print(closer.current_sourcecode()) - """ - def __init__(closer, tag='root'): - closer.header_defs = ub.odict() - closer.body_defs = ub.odict() - closer.visitors = {} - closer.tag = tag - - closer.logs = [] - closer._log_indent = '' - - def debug(closer, msg): - closer.logs.append(closer._log_indent + msg) - - def __nice__(self): - return self.tag - - def _add_definition(closer, d): - closer.debug('_add_definition = {!r}'.format(d)) - import copy - d = copy.deepcopy(d) - # print('ADD DEFINITION d = {!r}'.format(d)) - if 'Import' in d.type: - if d.absname in closer.header_defs: - del closer.header_defs[d.absname] - closer.header_defs[d.absname] = d - else: - if d.absname in closer.body_defs: - del closer.body_defs[d.absname] - closer.body_defs[d.absname] = d - - def current_sourcecode(self): - header_lines = [d.code for d in self.header_defs.values()] - body_lines = [d.code for d in self.body_defs.values()][::-1] - current_sourcecode = '\n'.join(header_lines) - current_sourcecode += '\n\n\n' - current_sourcecode += '\n\n\n'.join(body_lines) - return current_sourcecode - - def add_dynamic(closer, obj): - """ - Add the source to define a live python object - """ - closer.debug('closer.add_dynamic(obj={!r})'.format(obj)) - modname = obj.__module__ - module = sys.modules[modname] - - name = obj.__name__ - - modpath = module.__file__ - if modpath not in closer.visitors: - visitor = ImportVisitor.parse(module=module, modpath=modpath) - closer.visitors[modpath] = visitor - visitor = closer.visitors[modpath] - - d = visitor.extract_definition(name) - closer._add_definition(d) - closer.close(visitor) - - def add_static(closer, name, modpath): - # print('ADD_STATIC name = {} from {}'.format(name, modpath)) - closer.debug('closer.add_static(name={!r}, modpath={!r})'.format(name, modpath)) - if modpath not in closer.visitors: - visitor = ImportVisitor.parse(modpath=modpath) - closer.visitors[modpath] = visitor - visitor = closer.visitors[modpath] - - d = visitor.extract_definition(name) - closer._add_definition(d) - - closer.close(visitor) - - def close(closer, visitor): - """ - Populate all undefined names using the context from a module - """ - # Parse the parent module to find only the relevant global varaibles and - # include those in the extracted source code. - closer.debug('closing') - current_sourcecode = closer.current_sourcecode() - - # Loop until all undefined names are defined - names = True - while names: - # Determine if there are any variables needed from the parent scope - current_sourcecode = closer.current_sourcecode() - # Make sure we process names in the same order for hashability - prev_names = names - names = sorted(undefined_names(current_sourcecode)) - closer.debug(' * undefined_names = {}'.format(names)) - if names == prev_names: - print('visitor.definitions = {}'.format(ub.repr2(visitor.definitions, si=1))) - if DEBUG: - warnings.warn('We were unable do do anything about undefined names') - return - else: - current_sourcecode = closer.current_sourcecode() - print('--- ---') - print('Unable to define names') - print(' * names = {!r}'.format(names)) - print('<<< CURRENT_SOURCE >>>\n{}\n<<<>>>'.format(ub.highlight_code(current_sourcecode))) - print('--- ---') - raise AssertionError('unable to define names: {}'.format(names)) - for name in names: - try: - try: - closer.debug(' * try visitor.extract_definition({})'.format(names)) - d = visitor.extract_definition(name) - except KeyError as ex: - closer.debug(' * encountered issue: {!r}'.format(ex)) - # There is a corner case where we have the definition, - # we just need to move it to the top. - flag = False - for d_ in closer.body_defs.values(): - if name == d_.name: - closer.debug(' * corner case: move definition to top') - closer._add_definition(d_) - flag = True - break - if not flag: - raise - else: - closer.debug(' * add extracted def {}'.format(name)) - closer._add_definition(d) - # type_, text = visitor.extract_definition(name) - except Exception as ex: - closer.debug(' * unable to extracted def {} due to {!r}'.format(name, ex)) - current_sourcecode = closer.current_sourcecode() - print('--- ---') - print('Error computing source code extract_definition') - print(' * failed to close name = {!r}'.format(name)) - # print('<<< CURRENT_SOURCE >>>\n{}\n<<<>>>'.format(ub.highlight_code(current_sourcecode))) - print('--- ---') - if not HACK_FIX_CANNOT_FIND_HIDDEN: - raise - - def expand(closer, expand_names): - """ - Experimental feature. Remove all references to specific modules by - directly copying in the referenced source code. If the code is - referenced from a module, then the references will need to change as - well. - - TODO: - - [ ] Add special unique (mangled) suffixes to all expanded names - to avoid name conflicts. - - Args: - expand_name (List[str]): list of module names. For each module - we expand any reference to that module in the closed source - code by directly copying the referenced code into that file. - This doesn't work in all cases, but it usually does. - Reasons why this wouldn't work include trying to expand - import from C-extension modules and expanding modules with - complicated global-level logic. - - Ignore: - >>> # Test a heavier duty class - >>> from netharn.export.closer import * - >>> import netharn as nh - >>> obj = nh.device.MountedModel - >>> #obj = nh.layers.ConvNormNd - >>> obj = nh.data.CocoDataset - >>> #expand_names = ['ubelt', 'progiter'] - >>> closer = Closer() - >>> closer.add_dynamic(obj) - >>> closer.expand(expand_names) - >>> #print('header_defs = ' + ub.repr2(closer.header_defs, si=1)) - >>> #print('body_defs = ' + ub.repr2(closer.body_defs, si=1)) - >>> print('SOURCE:') - >>> text = closer.current_sourcecode() - >>> print(text) - """ - closer.debug("!!! EXPANDING") - # Expand references to internal modules - flag = True - while flag: - - # Associate all top-level modules with any possible expand_name - # that might trigger them to be expanded. Note this does not - # account for nested imports. - expandable_definitions = ub.ddict(list) - for d in closer.header_defs.values(): - parts = d.native_modname.split('.') - for i in range(1, len(parts) + 1): - root = '.'.join(parts[:i]) - expandable_definitions[root].append(d) - - closer.debug('expandable_definitions = {!r}'.format( - list(expandable_definitions.keys()))) - - flag = False - # current_sourcecode = closer.current_sourcecode() - # closed_visitor = ImportVisitor.parse(source=current_sourcecode) - for root in expand_names: - needs_expansion = expandable_definitions.get(root, []) - - closer.debug('root = {!r}'.format(root)) - closer.debug('needs_expansion = {!r}'.format(needs_expansion)) - for d in needs_expansion: - if d._expanded: - continue - flag = True - # if d.absname == d.native_modname: - if ub.modname_to_modpath(d.absname): - closer.debug('TODO: NEED TO CLOSE module = {}'.format(d)) - # import warnings - # warnings.warn('Closing module {} may not be implemented'.format(d)) - # definition is a module, need to expand its attributes - closer.expand_module_attributes(d) - d._expanded = True - else: - closer.debug('TODO: NEED TO CLOSE attribute varname = {}'.format(d)) - import warnings - # warnings.warn('Closing attribute {} may not be implemented'.format(d)) - # definition is a non-module, directly copy in its code - # We can directly replace this import statement by - # copy-pasting the relevant code from the other module - # (ASSUMING THERE ARE NO NAME CONFLICTS) - - assert d.type == 'ImportFrom' - - try: - native_modpath = ub.modname_to_modpath(d.native_modname) - if native_modpath is None: - raise Exception('Cannot find the module path for modname={!r}. ' - 'Are you missing an __init__.py?'.format(d.native_modname)) - sub_closer = Closer(closer.tag + '.sub') - sub_closer.add_static(d.name, native_modpath) - # sub_visitor = sub_closer.visitors[d.native_modname] - sub_closer.expand(expand_names) - # sub_closer.close(sub_visitor) - except NotAPythonFile as ex: - warnings.warn('CANNOT EXPAND d = {!r}, REASON: {}'.format(d, repr(ex))) - d._expanded = True - raise - continue - except Exception as ex: - warnings.warn('CANNOT EXPAND d = {!r}, REASON: {}'.format(d, repr(ex))) - d._expanded = True - raise - continue - # raise - - # Hack: remove the imported definition and add the explicit definition - # TODO: FIXME: more robust modification and replacement - d._code = '# ' + d.code - d._expanded = True - - for d_ in sub_closer.header_defs.values(): - closer._add_definition(d_) - for d_ in sub_closer.body_defs.values(): - closer._add_definition(d_) - - # print('sub_visitor = {!r}'.format(sub_visitor)) - # closer.close(sub_visitor) - closer.debug('CLOSED attribute d = {}'.format(d)) - - def expand_module_attributes(closer, d): - """ - Args: - d (Definition): the definition to expand - """ - # current_sourcecode = closer.current_sourcecode() - # closed_visitor = ImportVisitor.parse(source=current_sourcecode) - assert 'Import' in d.type - varname = d.name - varmodpath = ub.modname_to_modpath(d.absname) - modname = d.absname - - def _exhaust(varname, modname, modpath): - closer.debug('REWRITE ACCESSOR varname={!r}, modname={}, modpath={}'.format(varname, modname, modpath)) - - # Modify the current node definitions and recompute code - # TODO: make more robust - rewriter = RewriteModuleAccess(varname) - for d_ in closer.body_defs.values(): - rewriter.visit(d_.node) - d_._code = unparse(d_.node) - - closer.debug('rewriter.accessed_attrs = {!r}'.format(rewriter.accessed_attrs)) - - # For each modified attribute, copy in the appropriate source. - for subname in rewriter.accessed_attrs: - submodname = modname + '.' + subname - submodpath = ub.modname_to_modpath(submodname) - if submodpath is not None: - # if the accessor is to another module, exhaust until - # we reach a non-module - closer.debug('EXAUSTING: {}, {}, {}'.format(subname, submodname, submodpath)) - _exhaust(subname, submodname, submodpath) - else: - # Otherwise we can directly add the referenced attribute - closer.debug('FINALIZE: {} from {}'.format(subname, modpath)) - closer.add_static(subname, modpath) - - _exhaust(varname, modname, varmodpath) - d._code = '# ' + d.code - - -def _parse_static_node_value(node): - """ - Extract a constant value from a node if possible - """ - if isinstance(node, ast.Num): - value = node.n - elif isinstance(node, ast.Str): - value = node.s - elif isinstance(node, ast.List): - value = list(map(_parse_static_node_value, node.elts)) - elif isinstance(node, ast.Tuple): - value = tuple(map(_parse_static_node_value, node.elts)) - elif isinstance(node, (ast.Dict)): - keys = map(_parse_static_node_value, node.keys) - values = map(_parse_static_node_value, node.values) - value = OrderedDict(zip(keys, values)) - # value = dict(zip(keys, values)) - elif six.PY3 and isinstance(node, (ast.NameConstant)): - value = node.value - elif (six.PY2 and isinstance(node, ast.Name) and - node.id in ['None', 'True', 'False']): - # disregard pathological python2 corner cases - value = {'None': None, 'True': True, 'False': False}[node.id] - else: - msg = ('Cannot parse a static value from non-static node ' - 'of type: {!r}'.format(type(node))) - # print('node.__dict__ = {!r}'.format(node.__dict__)) - # print('msg = {!r}'.format(msg)) - raise TypeError(msg) - return value - - -def undefined_names(sourcecode): - """ - Parses source code for undefined names - - Example: - >>> print(ub.repr2(undefined_names('x = y'), nl=0)) - {'y'} - """ - import pyflakes.api - import pyflakes.reporter - - class CaptureReporter(pyflakes.reporter.Reporter): - def __init__(reporter, warningStream, errorStream): - reporter.syntax_errors = [] - reporter.messages = [] - reporter.unexpected = [] - - def unexpectedError(reporter, filename, msg): - reporter.unexpected.append(msg) - - def syntaxError(reporter, filename, msg, lineno, offset, text): - reporter.syntax_errors.append(msg) - - def flake(reporter, message): - reporter.messages.append(message) - - names = set() - - reporter = CaptureReporter(None, None) - pyflakes.api.check(sourcecode, '_.py', reporter) - for msg in reporter.messages: - if msg.__class__.__name__.endswith('UndefinedName'): - assert len(msg.message_args) == 1 - names.add(msg.message_args[0]) - return names - - -class RewriteModuleAccess(ast.NodeTransformer): - """ - Refactors attribute accesses into top-level references. - In other words, instances of . change to . - - Any attributes that were modified are stored in `accessed_attrs`. - - Example: - >>> from netharn.export.closer import * - >>> source = ub.codeblock( - ... ''' - ... foo.bar = 3 - ... foo.baz.bar = 3 - ... biz.foo.baz.bar = 3 - ... ''') - >>> pt = ast.parse(source) - >>> visitor = RewriteModuleAccess('foo') - >>> orig = unparse(pt) - >>> print(orig) - foo.bar = 3 - foo.baz.bar = 3 - biz.foo.baz.bar = 3 - >>> visitor.visit(pt) - >>> modified = unparse(pt) - >>> print(modified) - bar = 3 - baz.bar = 3 - biz.foo.baz.bar = 3 - >>> visitor.accessed_attrs - ['bar', 'baz'] - """ - def __init__(self, modname): - self.modname = modname - self.level = 0 - self.accessed_attrs = [] - - def visit_Import(self, node): - # if self.level == 0: - # return None - return node - - def visit_ImportFrom(self, node): - # if self.level == 0: - # return None - return node - - def visit_FunctionDef(self, node): - self.level += 1 - self.generic_visit(node) - self.level -= 1 - return node - - def visit_ClassDef(self, node): - self.level += 1 - self.generic_visit(node) - self.level -= 1 - return node - - def visit_Attribute(self, node): - # print('VISIT ATTR: node = {!r}'.format(node.__dict__)) - self.generic_visit(node) - if isinstance(node.value, ast.Name): - if node.value.id == self.modname: - self.accessed_attrs.append(node.attr) - new_node = ast.Name(node.attr, node.ctx) - old_node = node - return ast.copy_location(new_node, old_node) - return node - - -class Definition(ub.NiceRepr): - def __init__(self, name, node, type=None, code=None, absname=None, - modpath=None, modname=None, native_modname=None): - self.name = name - self.node = node - self.type = type - self._code = code - self.absname = absname - self.modpath = modpath - self.modname = modname - self.native_modname = native_modname - self._expanded = False - - @property - def code(self): - if self._code is None: - try: - if self._expanded or self.type == 'Assign': - # always use astunparse if we have expanded - raise Exception - # Attempt to dynamically extract the source code because it - # keeps formatting better. - module = ub.import_module_from_name(self.modname) - obj = getattr(module, self.name) - self._code = inspect.getsource(obj).strip('\n') - except Exception: - # Fallback on static sourcecode extraction - # (NOTE: it should be possible to keep formatting with a bit of - # work) - self._code = unparse(self.node).strip('\n') - return self._code - - def __nice__(self): - parts = [] - parts.append('name={}'.format(self.name)) - parts.append('type={}'.format(self.type)) - if self.absname is not None: - parts.append('absname={}'.format(self.absname)) - if self.native_modname is not None: - parts.append('native_modname={}'.format(self.native_modname)) - return ', '.join(parts) - - -class NotAPythonFile(ValueError): - pass - - -class ImportVisitor(ast.NodeVisitor, ub.NiceRepr): - """ - Used to search for dependencies in the original module - - References: - https://greentreesnakes.readthedocs.io/en/latest/nodes.html - - Example: - >>> from netharn.export.closer import * - >>> from netharn.export import closer - >>> modpath = closer.__file__ - >>> sourcecode = ub.codeblock( - ... ''' - ... from ubelt.util_const import * - ... import a - ... import b - ... import c.d - ... import e.f as g - ... from . import h - ... from .i import j - ... from . import k, l, m - ... from n import o, p, q - ... r = 3 - ... ''') - >>> visitor = ImportVisitor.parse(source=sourcecode, modpath=modpath) - >>> print(ub.repr2(visitor.definitions, si=1)) - """ - - def __init__(visitor, modpath=None, modname=None, module=None, pt=None): - super(ImportVisitor, visitor).__init__() - visitor.pt = pt - visitor.modpath = modpath - visitor.modname = modname - visitor.module = module - - visitor.definitions = {} - visitor.top_level = True - - def __nice__(self): - if self.modname is not None: - return self.modname - else: - return "" - - @classmethod - def parse(ImportVisitor, source=None, modpath=None, modname=None, - module=None): - if module is not None: - if source is None: - source = inspect.getsource(module) - if modpath is None: - modname = module.__file__ - if modname is None: - modname = module.__name__ - - if modpath is not None: - if modpath.endswith('.pyc'): - modpath = modpath.replace('.pyc', '.py') # python 2 hack - - if isdir(modpath): - modpath = join(modpath, '__init__.py') - if modname is None: - modname = ub.modpath_to_modname(modpath) - - if modpath is not None: - if source is None: - if not modpath.endswith(('.py', '>')): - raise NotAPythonFile('can only parse python files, not {}'.format(modpath)) - source = open(modpath, 'r').read() - - if source is None: - raise ValueError('unable to derive source code') - - source = ub.ensure_unicode(source) - if six.PY2: - try: - pt = ast.parse(source) - except SyntaxError as ex: - if 'encoding declaration in Unicode string' in ex.args[0]: - pt = ast.parse(source.encode()) - else: - raise - else: - pt = ast.parse(source) - visitor = ImportVisitor(modpath, modname, module, pt=pt) - visitor.visit(pt) - return visitor - - def extract_definition(visitor, name): - """ - Given the name of a variable / class / function / moodule, extract the - relevant lines of source code that define that structure from the - visited module. - """ - return visitor.definitions[name] - - def visit_Import(visitor, node): - for d in visitor._import_definitions(node): - visitor.definitions[d.name] = d - visitor.generic_visit(node) - - def visit_ImportFrom(visitor, node): - for d in visitor._import_from_definition(node): - visitor.definitions[d.name] = d - visitor.generic_visit(node) - - def visit_Assign(visitor, node): - for target in node.targets: - key = getattr(target, 'id', None) - if key is not None: - try: - static_val = _parse_static_node_value(node.value) - code = '{} = {}'.format(key, ub.repr2(static_val)) - except TypeError: - #code = unparse(node).strip('\n') - code = None - - if DEBUG: - if key in visitor.definitions: - # OVERLOADED - print('OVERLOADED key = {!r}'.format(key)) - - visitor.definitions[key] = Definition( - key, node, code=code, type='Assign', - modpath=visitor.modpath, - modname=visitor.modname, - absname=visitor.modname + '.' + key, - native_modname=visitor.modname, - ) - - def visit_FunctionDef(visitor, node): - visitor.definitions[node.name] = Definition( - node.name, node, type='FunctionDef', - modpath=visitor.modpath, - modname=visitor.modname, - absname=visitor.modname + '.' + node.name, - native_modname=visitor.modname, - ) - # Ignore any non-top-level imports - if not visitor.top_level: - visitor.generic_visit(node) - # ast.NodeVisitor.generic_visit(visitor, node) - - def visit_ClassDef(visitor, node): - visitor.definitions[node.name] = Definition( - node.name, node, type='ClassDef', - modpath=visitor.modpath, - modname=visitor.modname, - absname=visitor.modname + '.' + node.name, - native_modname=visitor.modname, - ) - # Ignore any non-top-level imports - if not visitor.top_level: - visitor.generic_visit(node) - # ast.NodeVisitor.generic_visit(visitor, node) - - def _import_definitions(visitor, node): - for alias in node.names: - varname = alias.asname or alias.name - if alias.asname: - line = 'import {} as {}'.format(alias.name, alias.asname) - else: - line = 'import {}'.format(alias.name) - absname = alias.name - yield Definition(varname, node, code=line, - absname=absname, - native_modname=absname, - modpath=visitor.modpath, - modname=visitor.modname, - type='Import') - - def _import_from_definition(visitor, node): - """ - Ignore: - from netharn.export.closer import * - visitor = ImportVisitor.parse(module=module) - print('visitor.definitions = {}'.format(ub.repr2(visitor.definitions, sv=1))) - """ - if node.level: - # Handle relative imports - if visitor.modpath is not None: - try: - rel_modpath = ub.split_modpath(abspath(visitor.modpath))[1] - except ValueError: - warnings.warn('modpath={} does not exist'.format(visitor.modpath)) - rel_modpath = basename(abspath(visitor.modpath)) - modparts = rel_modpath.replace('\\', '/').split('/') - parts = modparts[:-node.level] - prefix = '.'.join(parts) - if node.module: - prefix = prefix + '.' - else: - warnings.warn('Unable to rectify absolute import') - prefix = '.' * node.level - else: - prefix = '' - - if node.module is not None: - abs_modname = prefix + node.module - else: - abs_modname = prefix - - for alias in node.names: - varname = alias.asname or alias.name - if alias.asname: - line = 'from {} import {} as {}'.format(abs_modname, alias.name, alias.asname) - else: - line = 'from {} import {}'.format(abs_modname, alias.name) - absname = abs_modname + '.' + alias.name - if varname == '*': - # HACK - abs_modpath = ub.modname_to_modpath(abs_modname) - for d in ImportVisitor.parse(modpath=abs_modpath).definitions.values(): - if not d.name.startswith('_'): - yield d - else: - yield Definition(varname, node, code=line, absname=absname, - modpath=visitor.modpath, - modname=visitor.modname, - native_modname=abs_modname, - type='ImportFrom') - - -def _closefile(fpath, modnames): - """ - An api to remove dependencies from code by "closing" them. - - CommandLine: - xdoctest -m ~/code/netharn/netharn/export/closer.py _closefile - xdoctest -m netharn.export.closer _closefile --fpath=~/code/boltons/tests/test_cmdutils.py --modnames=ubelt, - - Example: - >>> # SCRIPT - >>> # ENTRYPOINT - >>> import scriptconfig as scfg - >>> config = scfg.quick_cli({ - >>> 'fpath': scfg.Path(None), - >>> 'modnames': scfg.Value([]), - >>> }) - >>> fpath = config['fpath'] = ub.expandpath('~/code/boltons/tests/test_cmdutils.py') - >>> modnames = config['modnames'] = ['ubelt'] - >>> _closefile(**config) - """ - from xdoctest import static_analysis as static - modpath = fpath - expand_names = modnames - source = open(fpath, 'r').read() - calldefs = static.parse_calldefs(source, fpath) - calldefs.pop('__doc__', None) - - closer = Closer() - for key in calldefs.keys(): - closer.add_static(key, modpath) - closer.expand(expand_names) - #print(ub.repr2(closer.body_defs, si=1)) - print(closer.current_sourcecode()) +warnings.warn('netharn.export.closer is deprecated, use liberator.closer intead', DeprecationWarning) diff --git a/netharn/export/deployer.py b/netharn/export/deployer.py index 4d37988..affb792 100644 --- a/netharn/export/deployer.py +++ b/netharn/export/deployer.py @@ -1,733 +1,4 @@ # -*- coding: utf-8 -*- -""" -Deployment component of the Pytorch exporter. - -This file contains DeployedModel, which consists of logic to take the -model topology definition along with the "best" snapshot in a training -directory and package it up into a standalone zipfile. The DeployedModel can -also be used to reload model from this zipfile. Thus this zipfile can be passed -around as a pytorch model topology+pretrained weights transfer format. - -The following docstring illustrates how this module may be used. - -CommandLine: - # Runs the following example - xdoctest -m netharn.export.deployer __doc__:0 - - # Runs all the doctests - xdoctest -m netharn.export.deployer all - -Example: - >>> # xdoc: +IGNORE_WANT - >>> # This example will train a small model and then deploy it. - >>> import netharn as nh - >>> # - >>> ################################################# - >>> print('--- STEP 1: TRAIN A MODEL ---') - >>> # This will train a toy model with toy data using netharn - >>> hyper = nh.HyperParams(**{ - >>> 'workdir' : ub.ensure_app_cache_dir('netharn/tests/deploy'), - >>> 'name' : 'deploy_demo', - >>> 'xpu' : nh.XPU.coerce('cpu'), - >>> 'datasets' : { - >>> 'train': nh.data.ToyData2d(size=3, border=1, n=256, rng=0), - >>> 'test': nh.data.ToyData2d(size=3, border=1, n=128, rng=1), - >>> }, - >>> 'loaders' : {'batch_size': 64}, - >>> 'model' : (nh.models.ToyNet2d, {}), - >>> 'optimizer' : (nh.optimizers.SGD, {'lr': 0.0001}), - >>> 'criterion' : (nh.criterions.CrossEntropyLoss, {}), - >>> 'initializer' : (nh.initializers.KaimingNormal, {}), - >>> 'scheduler' : (nh.schedulers.ListedLR, { - >>> 'points': {0: .01, 3: 0.1}, - >>> 'interpolate': True, - >>> }), - >>> 'monitor' : (nh.Monitor, {'max_epoch': 3,}), - >>> }) - >>> harn = nh.FitHarn(hyper) - >>> harn.preferences['use_tensorboard'] = False - >>> harn.preferences['timeout'] = 1 - >>> harn.intervals['test'] = 1 - >>> harn.initialize(reset='delete') - >>> harn.run() - --- STEP 1: TRAIN A MODEL --- - RESET HARNESS BY DELETING EVERYTHING IN TRAINING DIR - Symlink: .../.cache/netharn/tests/deploy/fit/runs/deploy_demo/onnxqaww -> .../.cache/netharn/tests/deploy/_mru - ...... - Symlink: .../.cache/netharn/tests/deploy/fit/runs/deploy_demo/onnxqaww -> .../.cache/netharn/tests/deploy/fit/nice/deploy_demo - ...... - INFO: Model has 824 parameters - INFO: Mounting ToyNet2d model on CPU - INFO: Exported model topology to .../.cache/netharn/tests/deploy/fit/runs/deploy_demo/onnxqaww/ToyNet2d_2a3f49.py - INFO: Initializing model weights with: - INFO: * harn.train_dpath = '.../.cache/netharn/tests/deploy/fit/runs/deploy_demo/onnxqaww' - INFO: * harn.name_dpath = '.../.cache/netharn/tests/deploy/fit/name/deploy_demo' - INFO: Snapshots will save to harn.snapshot_dpath = '.../.cache/netharn/tests/deploy/fit/runs/deploy_demo/onnxqaww/torch_snapshots' - INFO: ARGV: - .../.local/conda/envs/py36/bin/python .../.local/conda/envs/py36/bin/ipython - INFO: === begin training 0 / 3 : deploy_demo === - epoch lr:0.01 │ vloss is unevaluated 0/3... rate=0 Hz, eta=?, total=0:00:00, wall=19:32 EST - train loss:0.717 │ 100.00% of 64x8... rate=2093.02 Hz, eta=0:00:00, total=0:00:00, wall=19:32 EST - test loss:0.674 │ 100.00% of 64x4... rate=14103.48 Hz, eta=0:00:00, total=0:00:00, wall=19:32 EST - Populating the interactive namespace from numpy and matplotlib - INFO: === finish epoch 0 / 3 : deploy_demo === - epoch lr:0.04 │ vloss is unevaluated 1/3... rate=0.87 Hz, eta=0:00:02, total=0:00:01, wall=19:32 EST - train loss:0.712 │ 100.00% of 64x8... rate=2771.29 Hz, eta=0:00:00, total=0:00:00, wall=19:32 EST - test loss:0.663 │ 100.00% of 64x4... rate=15867.59 Hz, eta=0:00:00, total=0:00:00, wall=19:32 EST - INFO: === finish epoch 1 / 3 : deploy_demo === - epoch lr:0.07 │ vloss is unevaluated 2/3... rate=1.04 Hz, eta=0:00:00, total=0:00:01, wall=19:32 EST - train loss:0.686 │ 100.00% of 64x8... rate=2743.56 Hz, eta=0:00:00, total=0:00:00, wall=19:32 EST - test loss:0.636 │ 100.00% of 64x4... rate=14332.63 Hz, eta=0:00:00, total=0:00:00, wall=19:32 EST - INFO: === finish epoch 2 / 3 : deploy_demo === - epoch lr:0.1 │ vloss is unevaluated 3/3... rate=1.11 Hz, eta=0:00:00, total=0:00:02, wall=19:32 EST - INFO: Maximum harn.epoch reached, terminating ... - INFO: - INFO: training completed - INFO: harn.train_dpath = '.../.cache/netharn/tests/deploy/fit/runs/deploy_demo/onnxqaww' - INFO: harn.name_dpath = '.../.cache/netharn/tests/deploy/fit/name/deploy_demo' - INFO: view tensorboard results for this run via: - tensorboard --logdir ~/.cache/netharn/tests/deploy/fit/name - [DEPLOYER] Deployed zipfpath=.../.cache/netharn/tests/deploy/fit/runs/deploy_demo/onnxqaww/deploy_ToyNet2d_onnxqaww_002_TXZBYL.zip - INFO: wrote single-file deployment to: '.../.cache/netharn/tests/deploy/fit/runs/deploy_demo/onnxqaww/deploy_ToyNet2d_onnxqaww_002_TXZBYL.zip' - INFO: exiting fit harness. - Out[1]: '.../.cache/netharn/tests/deploy/fit/runs/deploy_demo/onnxqaww/deploy_ToyNet2d_onnxqaww_002_TXZBYL.zip' - >>> # - >>> ########################################## - >>> print('--- STEP 2: DEPLOY THE MODEL ---') - >>> # First we export the model topology to a standalone file - >>> # (Note: this step is done automatically in `harn.run`, but we do - >>> # it again here for demo purposes) - >>> from netharn.export import exporter - >>> topo_fpath = exporter.export_model_code(harn.train_dpath, harn.hyper.model_cls, harn.hyper.model_params) - >>> # Now create an instance of deployed model that points to the - >>> # Training dpath. (Note the directory structure setup by netharn is - >>> # itself a deployment, it just has multiple files) - >>> deployer = DeployedModel(harn.train_dpath) - >>> # Use the DeployedModel to package the imporant info in train_dpath - >>> # into a standalone zipfile. - >>> zip_fpath = deployer.package() - >>> print('We exported the topology to: {!r}'.format(topo_fpath)) - >>> print('We exported the topology+weights to: {!r}'.format(zip_fpath)) - --- STEP 2: DEPLOY THE MODEL --- - We exported the topology to: '...tests/deploy/fit/runs/deploy_demo/onnxqaww/ToyNet2d_2a3f49.py' - We exported the topology+weights to: '...tests/deploy/fit/runs/deploy_demo/onnxqaww/deploy_ToyNet2d_onnxqaww_002_HVWCGI.zip' - >>> # - >>> ################################################# - >>> print('--- STEP 3: LOAD THE DEPLOYED MODEL ---') - >>> # Now we can move the zipfile anywhere we want, and we should - >>> # still be able to load it (depending on how coupled the model is). - >>> # Create an instance of DeployedModel that points to the zipfile - >>> # (Note: DeployedModel is used to both package and load models) - >>> loader = DeployedModel(zip_fpath) - >>> model = loader.load_model() - >>> # This model is now loaded with the corret weights. - >>> # You can use it as normal. - >>> model.eval() - >>> images = harn._demo_batch(0)['input'][0:1] - >>> outputs = model(images) - >>> print('outputs = {!r}'.format(outputs)) - >>> # Not that the loaded model is independent of harn.model - >>> print('model.__module__ = {!r}'.format(model.__module__)) - >>> print('harn.model.module.__module__ = {!r}'.format(harn.model.module.__module__)) - --- STEP 3: LOAD THE DEPLOYED MODEL --- - outputs = tensor([[0.4105, 0.5895]], grad_fn=) - model.__module__ = 'deploy_ToyNet2d_onnxqaww_002_HVWCGI/ToyNet2d_2a3f49' - harn.model.module.__module__ = 'netharn.models.toynet' -""" -from __future__ import absolute_import, division, print_function, unicode_literals -import glob -import json -import six -import ubelt as ub -# import warnings -import zipfile -import os -from os.path import exists -from os.path import isdir -from os.path import join -from os.path import relpath - -__all__ = ['DeployedModel'] - -if six.PY2: - FileNotFoundError = OSError - - -def existing_snapshots(train_dpath): - # NOTE: Specific to netharn directory structure - import parse - snapshot_dpath = join(train_dpath, 'torch_snapshots/') - prev_states = sorted(glob.glob(join(snapshot_dpath, '_epoch_*.pt'))) - snapshots = {parse.parse('{}_epoch_{num:d}.pt', path).named['num']: path - for path in prev_states} - return snapshots - - -def find_best_snapshot(train_dpath): - """ - Returns snapshot written by monitor if available otherwise takes the last - one. - """ - # NOTE: Specific to netharn directory structure - # Netharn should populate best_snapshot.pt if there is a validation set. - # Other names are to support older codebases. - expected_names = [ - 'best_snapshot.pt', - 'best_snapshot2.pt', - 'final_snapshot.pt', - 'deploy_snapshot.pt', - ] - for snap_fname in expected_names: - snap_fpath = join(train_dpath, snap_fname) - if exists(snap_fpath): - break - - if not exists(snap_fpath): - snap_fpath = None - - if not snap_fpath: - epoch_to_fpath = existing_snapshots(train_dpath) - if epoch_to_fpath: - snap_fpath = epoch_to_fpath[max(epoch_to_fpath)] - return snap_fpath - - -def unpack_model_info(path): - """ - return paths to the most relevant files in a zip or path deployment. - - If path is not a zipfile, this function expects a netharn fit directory - structure. - - Args: - path (PathLike): either a zip deployment or train_dpath. - Preferably this is a zip deployment file or a path to an unzipped - deploy file. If this is a train_dpath, then it should at least - contain a model topology py file and snapshot pt file, otherwise - subsequent usage will likely fail. - """ - info = { - 'train_info_fpath': None, - 'snap_fpath': None, - 'model_fpath': None, - - # TODO: need to rename and allow a list of arbitrary files - 'glance': [], # a list of files in the glance directory - } - def populate(root, fpaths): - # TODO: make more robust - for fpath in fpaths: - # FIXME: make this more general and robust - if fpath.endswith('.json'): - info['train_info_fpath'] = join(root, fpath) - if fpath.endswith('.pt'): - info['snap_fpath'] = join(root, fpath) - if fpath.endswith('.py'): - new_fpath = join(root, fpath) - if info['model_fpath'] is not None: - try: - # Try to take the most recent path if possible. - # This will fail if the file is in a zipfile - # (because we should not package multiple models) - cur_time = os.stat(info['model_fpath']).st_mtime - new_time = os.stat(new_fpath).st_mtime - if new_time < cur_time: - continue # Keep the current path - except OSError: - raise Exception( - 'Multiple model paths! {} and {}'.format( - info['model_fpath'], fpath)) - info['model_fpath'] = new_fpath - # TODO: make including arbitrary files easier - if fpath.startswith(('glance/', 'glance\\')): - info['glance'].append(join(root, fpath)) - - if path.endswith('.zip'): - zipfpath = path - myzip = zipfile.ZipFile(zipfpath, 'r') - with zipfile.ZipFile(zipfpath, 'r') as myzip: - populate(zipfpath, (f.filename for f in myzip.filelist)) - - elif exists(path) and isdir(path): - # Populate core files - populate(path, os.listdir(path)) - # Populate extra glanceable files - populate(path, [ - relpath(p, path) for p in glob.glob(join(path, 'glance/*'))]) - # If there are no snapshots in the root directory, then - # use the latest snapshot from the torch_snapshots dir - if info['snap_fpath'] is None: - info['snap_fpath'] = find_best_snapshot(path) - - else: - raise ValueError('cannot unpack model ' + path) - return info - - -def _make_package_name2(info): - """ - Construct a unique and descriptive name for the deployment - """ - snap_fpath = info['snap_fpath'] - model_fpath = info['model_fpath'] - train_info_fpath = info['train_info_fpath'] - - if train_info_fpath and exists(train_info_fpath): - train_info = json.load(open(train_info_fpath, 'r')) - model_name = train_info['hyper']['model'][0].split('.')[-1] - train_hash = ub.hash_data(train_info['train_id'], hasher='sha512', - base='abc', types=True)[0:8] - else: - model_name = os.path.splitext(os.path.basename(model_fpath))[0] - train_hash = 'UNKNOWN-TRAINID' - print('WARNING: Train info metadata does not exist') - - try: - # netharn models contain epoch info in the weights file - import torch - state = torch.load(snap_fpath, - map_location=lambda storage, location: storage) - epoch = '{:03d}'.format(state['epoch']) - except Exception: - epoch = 'UNKNOWN-EPOCH' - - weights_hash = ub.hash_file(snap_fpath, base='abc', - hasher='sha512')[0:6].upper() - - deploy_name = 'deploy_{model}_{trainid}_{epoch}_{weights}'.format( - model=model_name, trainid=train_hash, epoch=epoch, - weights=weights_hash) - return deploy_name - - -def _package_deploy2(dpath, info, name=None): - """ - Combine the model, weights, and info files into a single deployable file - - Args: - dpath (PathLike): where to dump the deployment - info (Dict): containing model_fpath and snap_fpath and optionally - train_info_fpath and glance, which is a list of extra files. - name (str, default=None): the name of the zipfile to deploy to. - If not specified, one will be constructed. - - Ignore: - dpath = '/home/joncrall/.cache/netharn/tests/_package_custom' - path = '/home/joncrall/work/opir/fit/name/_Sim3-kw6-99-finetune_ML3D_BEST_2018-9-20_LR1e-4_f2_vel0.0_hn0.25_bs64_nr5.0' - info = unpack_model_info(path) - zipfpath = _package_deploy2(dpath, info) - - - """ - model_fpath = info['model_fpath'] - snap_fpath = info['snap_fpath'] - train_info_fpath = info.get('train_info_fpath', None) - - if not snap_fpath: - raise FileNotFoundError('No weights are associated with the model') - - if name is None: - deploy_name = _make_package_name2(info) - deploy_fname = deploy_name + '.zip' - else: - if not name.endswith('.zip'): - raise ValueError('The deployed package name must end in .zip') - deploy_name = os.path.splitext(name)[0] - deploy_fname = name - - def zwrite(myzip, fpath, fname=None): - if fname is None: - fname = relpath(fpath, dpath) - myzip.write(fpath, arcname=join(deploy_name, fname)) - - zipfpath = join(dpath, deploy_fname) - with zipfile.ZipFile(zipfpath, 'w') as myzip: - if train_info_fpath and exists(train_info_fpath): - zwrite(myzip, train_info_fpath, fname='train_info.json') - zwrite(myzip, snap_fpath, fname='deploy_snapshot.pt') - zwrite(myzip, model_fpath, fname=os.path.basename(model_fpath)) - # Add some quick glanceable info - for p in info.get('glance', []): - zwrite(myzip, p, fname=join('glance', os.path.basename(p))) - # for bestacc_fpath in glob.glob(join(train_dpath, 'best_epoch_*')): - # zwrite(myzip, bestacc_fpath) - # for p in glob.glob(join(train_dpath, 'glance/*')): - # zwrite(myzip, p) - print('[DEPLOYER] Deployed zipfpath={}'.format(zipfpath)) - return zipfpath - - -class DeployedModel(ub.NiceRepr): - """ - Can setup an initializer and model from a deployed zipfile or a train path - - CommandLine: - xdoctest -m netharn.export.deployer DeployedModel - - Example: - >>> # Test the train folder as the model deployment - >>> train_dpath = _demodata_trained_dpath() - >>> self = DeployedModel(train_dpath) - >>> model_ = self.model_definition() - >>> initializer_ = self.initializer_definition() - >>> model = model_[0](**model_[1]) - >>> assert initializer_[1].get('fpath', None) is not None, 'initializer isnt setup correctly' - >>> initializer = initializer_[0](**initializer_[1]) - >>> initializer(model) - ... - >>> print('model.__module__ = {!r}'.format(model.__module__)) - - # >>> if six.PY3: - # ... assert model.__module__ == 'ToyNet2d_2a3f49' - # ... else: - # ... assert model.__module__ == 'ToyNet2d_d573a3' - - Example: - >>> # Test the zip file as the model deployment - >>> zip_fpath = _demodata_zip_fpath() - >>> self = DeployedModel(zip_fpath) - >>> model_ = self.model_definition() - >>> initializer_ = self.initializer_definition() - >>> model = model_[0](**model_[1]) - >>> assert initializer_[1].get('fpath', None) is not None, 'initializer isnt setup correctly' - >>> initializer = initializer_[0](**initializer_[1]) - >>> initializer(model) - ... - >>> # NOTE: the module name should be consistent, but due to - >>> # small library changes it often changes, so we are permissive - >>> # with this got/want test - >>> print('model.__module__ = {!r}'.format(model.__module__)) - model.__module__ = 'deploy_ToyNet2d_..._.../ToyNet2d_...' - - model.__module__ = 'deploy_ToyNet2d_mhuhweia_000_.../ToyNet2d_...' - - model.__module__ = 'deploy_ToyNet2d_rljhgepw_000_.../ToyNet2d_2a3f49' - """ - def __init__(self, path): - self.path = path - self._model = None - self._info = None - - @classmethod - def custom(DeployedModel, snap_fpath, model, initkw=None, train_info_fpath=None): - """ - Create a deployed model even if the model wasnt trained with FitHarn - - This just requires specifying a bit more information, which FitHarn - would have tracked. - - Args: - snap_fpath (PathLike): - path to the exported (snapshot) weights file - - model (PathLike or nn.Module): can either be - (1) a path to model topology (created via `export_model_code`) - (2) the model class or an instance of the class - - initkw (Dict): if model is a class or instance, then - you must pass the keyword arguments used to construct it. - - train_info_fpath (PathLike, optional): - path to a json file containing additional training metadata - - Example: - >>> # Setup raw components - >>> train_dpath = _demodata_trained_dpath() - >>> deployed = DeployedModel(train_dpath) - >>> snap_fpath = deployed.info['snap_fpath'] - >>> model, initkw = deployed.model_definition() - >>> train_info_fpath = deployed.info['train_info_fpath'] - >>> # Past raw components to custom - >>> self = DeployedModel.custom(snap_fpath, model, initkw) - >>> dpath = ub.ensure_app_cache_dir('netharn', 'tests/_package_custom') - >>> self.package(dpath) - """ - if isinstance(model, six.string_types): - model_fpath = model - if initkw is not None: - raise ValueError('initkw not used when model is a path') - else: - import tempfile - from netharn.export import exporter - dpath = tempfile.mkdtemp() - model_fpath = exporter.export_model_code(dpath, model, initkw=initkw) - - _info = { - 'model_fpath': model_fpath, - 'snap_fpath': snap_fpath, - 'train_info_fpath': train_info_fpath, - } - self = DeployedModel(None) - self._info = _info - return self - - def __nice__(self): - return self.__json__() - - def __json__(self): - if self.path is None: - if self._info: - return ub.repr2(self._info, nl=0) - else: - return self.path - - def package(self, dpath=None, name=None): - """ - If self.path is a directory, packages important info into a deployable - zipfile. - - Args: - dpath (PathLike, optional): directory to dump your packaged model. - If not specified, it uses the netharn train_dpath if available. - name (str, default=None): the name of the zipfile to deploy to. - If not specified, one will be constructed. - - Returns: - PathLike: path to single-file deployment - """ - if dpath is None: - if self.path is None: - raise ValueError('Must specify dpath for custom deployments') - else: - if self.path.endswith('.zip'): - raise Exception('Deployed model is already a package') - dpath = self.path - - zip_fpath = _package_deploy2(dpath, self.info, name=name) - return zip_fpath - - @property - def info(self): - if self._info is None: - self._info = self.unpack_info() - return self._info - - def unpack_info(self): - return unpack_model_info(self.path) - - def model_definition(self): - model_fpath = self.info['model_fpath'] - module = ub.import_module_from_path(model_fpath) - - export_version = getattr(module, '__pt_export_version__', '0') - export_version = list(map(int, export_version.split('.'))) - if export_version >= [0, 2, 0]: - model_cls = module.get_model_cls() - initkw = module.get_initkw() - else: - # Hack to get information from older versions of pytorch_export - import inspect - from xdoctest import static_analysis - print('Hacking to grab model_cls and initkw') - model = module.make() - model_cls = model.__class__ - source = inspect.getsource(module.make) - print(source) - initkw = static_analysis.parse_static_value('initkw', source=source) - # Try to reconstruct initkw - model_ = (model_cls, initkw) - return model_ - - def initializer_definition(self): - import netharn as nh - initializer_ = (nh.initializers.Pretrained, - {'fpath': self.info['snap_fpath']}) - return initializer_ - - def train_info(self): - import netharn as nh - train_info_fpath = self.info.get('train_info_fpath', None) - if train_info_fpath is not None: - train_info = json.load(nh.util.zopen(train_info_fpath, 'r')) - else: - train_info = None - return train_info - - def load_model(self): - if self._model is not None: - return self._model - - model_cls, model_kw = self.model_definition() - model = model_cls(**model_kw) - - if True: - # Always load models onto the CPU first - # import netharn as nh - model = model.to('cpu') - # devices = {k: item.device for k, item in model.state_dict().items()} - # nh.XPU.from_data(model) - - # TODO: load directly from instead of using initializer self.info['snap_fpath']? - # Actually we can't because we lose the zopen stuff. Its probably ok - # To depend on netharn a little bit. - # import torch - # info = self.unpack_info() - # state_dict = torch.load(self.info['snap_fpath']) - # model.load_state_dict() - - initializer_ = self.initializer_definition() - initializer = initializer_[0](**initializer_[1]) - - assert model is not None - - initializer(model) - return model - - @classmethod - def ensure_mounted_model(cls, deployed, xpu=None, log=print): - """ - Ensure that a deployed model is loaded and mounted. - - Helper method that can accept either a raw model or packaged deployed - model is loaded and mounted on a specific XPU. This provides a one line - solution for applications that may want to ensure that a model is - mounted and ready for predict. When the model is already mounted this - is very fast and just passes the data through. If the input is a - packaged deployed file, then it does the required work to prep the - model. - - Args: - deployed (DeployedModel | PathLike | torch.nn.Module): - either a packed deployed model, a path to a deployed model, or - an already mounted torch Module. - xpu (str | XPU): which device to mount on - log (callable, optional): logging or print function - - Returns: - Tuple[torch.nn.Module, XPU]: - the mounted model, and the device it is mounted on. - """ - import netharn as nh - import torch - if not isinstance(xpu, nh.XPU): - xpu = nh.XPU.coerce(xpu) - - if isinstance(deployed, six.string_types): - deployed = nh.export.DeployedModel(deployed) - - if isinstance(deployed, torch.nn.Module): - # User passed in the model directly - model = deployed - try: - if xpu != nh.XPU.from_data(model): - log('Re-Mount model on {}'.format(xpu)) - model = xpu.mount(model) - except Exception: - log('Re-Mount model on {}'.format(xpu)) - model = xpu.mount(model) - elif isinstance(deployed, nh.export.DeployedModel): - model = deployed.load_model() - log('Mount {} on {}'.format(deployed, xpu)) - model = xpu.mount(model) - else: - raise TypeError('Unable to ensure {!r} as a mounted model'.format( - deployed)) - - return model, xpu - - @classmethod - def coerce(DeployedModel, arg): - """ - Attempt to coerce the argument into a deployed model. - - Args: - arg (DeployedModel | PathLike | torch.nn.Module) : can be: - (1) a DeployedModel object - (2) a path to a deploy file - (3) a live pytorch module - (4) a path to a .pt file in a netharn train snapshot directory. - - Returns: - DeployedModel - """ - from os.path import dirname - import torch - if isinstance(arg, DeployedModel): - # The input is already a DeployedModel - deployed = arg - elif isinstance(arg, torch.nn.Module): - # The argument is a live pytorch model - deployed = DeployedModel(None) - deployed._model = arg - elif isinstance(arg, six.string_types): - # handle the case where we are given a weights file - # use heuristics try and determine model topology - if arg.endswith('.pt'): - snap_fpath = arg - dpath_cands = [] - # Look the pt file's directory for topology and train info - dpath1 = dirname(snap_fpath) - dpath_cands = [dpath1] - # The files might also be in the parent directory - if not exists(join(dpath1, 'train_info.json')): - dpath_cands.append(dirname(dpath1)) - # Search for the files in the candidate directories - train_info_cands = list(ub.find_path( - 'train_info.json', path=dpath_cands, exact=True)) - model_cands = list(ub.find_path( - '*.py', path=dpath_cands, exact=False)) - if len(model_cands) == 0: - raise Exception('Model topology does not exist for {!r}.'.format(arg)) - elif len(model_cands) > 1: - raise Exception('Conflicting model topologies for {!r}.'.format(arg)) - else: - model_fpath = model_cands[0] - if len(train_info_cands) == 0: - train_info_fpath = None - elif len(train_info_cands) > 1: - raise AssertionError('Conflicting train_info.json files') - else: - train_info_fpath = train_info_cands[0] - deployed = DeployedModel.custom(snap_fpath, model_fpath, - train_info_fpath=train_info_fpath) - else: - # Assume we have a netharn deploy path - deployed = DeployedModel(arg) - else: - # Unhandled case - raise TypeError(type(arg)) - return deployed - - -def _demodata_zip_fpath(): - zip_path = DeployedModel(_demodata_trained_dpath()).package() - return zip_path - - -def _demodata_toy_harn(): - # This will train a toy model with toy data using netharn - import netharn as nh - hyper = nh.HyperParams(**{ - 'workdir' : ub.ensure_app_cache_dir('netharn/tests/deploy'), - 'name' : 'deploy_demo_static', - 'xpu' : nh.XPU.coerce('cpu'), - 'datasets' : {'train': nh.data.ToyData2d(size=3, rng=0)}, - 'loaders' : {'batch_size': 64}, - 'model' : (nh.models.ToyNet2d, {}), - 'optimizer' : (nh.optimizers.SGD, {'lr': 0.0001}), - 'criterion' : (nh.criterions.FocalLoss, {}), - 'initializer' : (nh.initializers.KaimingNormal, {}), - 'monitor' : (nh.Monitor, {'max_epoch': 1}), - }) - harn = nh.FitHarn(hyper) - harn.preferences['use_tensorboard'] = False - return harn - - -def _demodata_trained_dpath(): - harn = _demodata_toy_harn() - harn.run() # TODO: make this run faster if we don't need to rerun - if len(list(glob.glob(join(harn.train_dpath, '*.py')))) > 1: - # If multiple models are deployed some hash changed. Need to reset - harn.initialize(reset='delete') - harn.run() # don't relearn if we already finished this one - return harn.train_dpath - - -if __name__ == '__main__': - """ - CommandLine: - xdoctest -m netharn.export.deployer all - """ - import xdoctest - xdoctest.doctest_module(__file__) +from torch_liberator.deployer import * # NOQA +import warnings +warnings.warn('netharn.export.deployer is deprecated, use torch_liberator.deployer intead', DeprecationWarning) diff --git a/netharn/export/exporter.py b/netharn/export/exporter.py index b671897..0736c33 100644 --- a/netharn/export/exporter.py +++ b/netharn/export/exporter.py @@ -1,346 +1,4 @@ # -*- coding: utf-8 -*- -""" -Export component of the Pytorch exporter. - -This is the code that simply exports the model toplogy via code - -Uses static analysis to export relevant code that defines the model topology -into a stanadlone file. As long as your model definition is indepenent of your -training code, then the exported file can be passed around in a similar way to -a caffe prototext file. - -TODO: - - [ ]: Look into: https://www.reddit.com/r/MachineLearning/comments/a856oe/d_pytorch_10_deployment_pipeline/ec9w94c/ - - >>> from torchvision.models import densenet - >>> import torch - >>> model = densenet.DenseNet(growth_rate=16).eval() - >>> traced = torch.jit.trace(model, example_inputs=(torch.randn(2, 3, 224, 224), )) - >>> traced.save("densenet.pt") - >>> model_ = torch.jit.load("densenet.pt") - - -CommandLine: - xdoctest -m netharn.export.exporter export_model_code - xdoctest -m netharn.export.exporter source_closure:1 - - xdoctest -m netharn.export.exporter all -""" -from __future__ import absolute_import, division, print_function, unicode_literals -import ast -import six # NOQA -import re -import hashlib -import io -import pickle -import tokenize -import ubelt as ub +from torch_liberator.exporter import * # NOQA import warnings -from os.path import join -from . import closer - -__all__ = ['export_model_code'] - - -__pt_export_version__ = '0.5.1' - - -def export_model_code(dpath, model, initkw=None, export_modules=[]): - """ - Exports the class used to define a pytorch model as a new python module. - - Exports the minimum amount of code needed to make a self-contained Python - module defining the pytorch model class. This exports the actual source - code. The advantage of using this over pickle is that the original code can - change arbitrarilly because all dependencies on the original code are - removed in the exported code. - - Args: - dpath (str): directory to dump the model - model (tuple or type or object): class or class instance (e.g. torch.nn.Module) - name (str): name to use for the file (defaults to the classname) - initkw (dict): if specified, creates the function `make`, which - initializes the network with the specific arguments. - export_modules (List[str]): A list of modules that the exported code - should not depend on. Any code referenced from these modules will - be statically extracted and copied into the model definition. - Note that this feature is experimental. - - Returns: - str: static_modpath: path to the saved model file. - While you could put the output path in your PYTHONPATH, it is best - to use `ub.import_module_from_path` to "load" the model instead. - - Example: - >>> from netharn.export.exporter import export_model_code - >>> from torchvision.models import densenet - >>> import torchvision - >>> from os.path import basename - >>> initkw = {'growth_rate': 16} - >>> model = densenet.DenseNet(**initkw) - >>> dpath = ub.ensure_app_cache_dir('netharn/tests') - >>> static_modpath = export_model_code(dpath, model, initkw) - >>> print('static_modpath = {!r}'.format(static_modpath)) - ... - >>> mod_fname = (basename(static_modpath)) - >>> print('mod_fname = {!r}'.format(mod_fname)) - >>> if torchvision.__version__ == '0.2.2': - >>> if six.PY2: - >>> assert mod_fname == 'DenseNet_b7ec43.py', 'got={}'.format(mod_fname) - >>> else: - >>> assert mod_fname == 'DenseNet_256629.py', 'got={}'.format(mod_fname) - >>> # now the module can be loaded - >>> module = ub.import_module_from_path(static_modpath) - >>> loaded = module.make() - >>> assert model.features.denseblock1.denselayer1.conv2.out_channels == 16 - >>> assert loaded.features.denseblock1.denselayer1.conv2.out_channels == 16 - >>> assert model is not loaded - """ - if isinstance(model, type): - model_class = model - else: - model_class = model.__class__ - classname = model_class.__name__ - - if initkw is None: - raise NotImplementedError( - 'ERROR: The params passed to the model __init__ must be available') - footer = '' - else: - # First see if we can get away with a simple encoding of initkw - try: - # Do not use repr. The text produced is non-deterministic for - # dictionaries. Instead, use ub.repr2, which is deterministic. - init_text = ub.repr2(initkw, nl=1) - eval(init_text, {}) - init_code = ub.codeblock( - 'initkw = {}' - ).format(init_text) - except Exception: - # fallback to pickle - warnings.warn('Initialization params might not be serialized ' - 'deterministically') - init_bytes = repr(pickle.dumps(initkw, protocol=0)) - init_code = ub.codeblock( - ''' - import pickle - initkw = pickle.loads({}) - ''' - ).format(init_bytes) - init_code = ub.indent(init_code).lstrip() - # create a function to instanciate the class - footer = '\n\n' + ub.codeblock( - ''' - __pt_export_version__ = '{__pt_export_version__}' - - - def get_initkw(): - """ creates an instance of the model """ - {init_code} - return initkw - - - def get_model_cls(): - model_cls = {classname} - return model_cls - - - def make(): - """ creates an instance of the model """ - initkw = get_initkw() - model_cls = get_model_cls() - model = model_cls(**initkw) - return model - ''' - ).format(classname=classname, init_code=init_code, - __pt_export_version__=__pt_export_version__) - - # TODO: assert that the name "make" is not used in the model body - - body = closer.source_closure(model_class, expand_names=export_modules) - - body_footer = body + footer + '\n' - # dont need to hash the header, because comments are removed anyway - - # with open('debug-closer.py', 'w') as file: - # file.write(body_footer) - hashid = hash_code(body_footer) - - header = ub.codeblock( - ''' - """ - This module was autogenerated by netharn/export/exporter.py - original_module={} - classname={} - timestamp={} - hashid={} - """ - ''').format(model_class.__module__, classname, ub.timestamp(), hashid) - - sourcecode = header + '\n' + body_footer - - static_modname = classname + '_' + hashid[0:6] - static_modpath = join(dpath, static_modname + '.py') - with open(static_modpath, 'w') as file: - file.write(sourcecode) - return static_modpath - - -def remove_comments_and_docstrings(source): - r""" - Args: - source (str): uft8 text of source code - - Returns: - str: out: the source with comments and docstrings removed. - - References: - https://stackoverflow.com/questions/1769332/remove-comments-docstrings - - Example: - >>> source = ub.codeblock( - ''' - def foo(): - 'The spaces before this docstring are tokenize.INDENT' - test = [ - 'The spaces before this string do not get a token' - ] - ''') - >>> out = remove_comments_and_docstrings(source) - >>> want = ub.codeblock( - ''' - def foo(): - pass - test = [ - 'The spaces before this string do not get a token' - ]''').splitlines() - >>> got = [o.rstrip() for o in out.splitlines()] - >>> assert got == want - - - >>> source = ub.codeblock( - ''' - def foo(): - " docstring " - ''') - >>> out = remove_comments_and_docstrings(source) - >>> print(out) - >>> source = ub.codeblock( - ''' - class foo(): - r{qqq} - docstring - {qqq} - ''').format(qqq='"' * 3) - >>> out = remove_comments_and_docstrings(source) - >>> print(out) - - """ - source = ub.ensure_unicode(source) - io_obj = io.StringIO(source) - output_parts = [] - prev_toktype = tokenize.INDENT - last_lineno = -1 - last_col = 0 - for tok in tokenize.generate_tokens(io_obj.readline): - token_type = tok[0] - token_string = tok[1] - start_line, start_col = tok[2] - end_line, end_col = tok[3] - # ltext = tok[4] - # The following two conditionals preserve indentation. - # This is necessary because we're not using tokenize.untokenize() - # (because it spits out code with copious amounts of oddly-placed - # whitespace). - if start_line > last_lineno: - last_col = 0 - if start_col > last_col: - output_parts.append((' ' * (start_col - last_col))) - # Remove comments: - if token_type == tokenize.COMMENT: - pass - # This series of conditionals removes docstrings: - elif token_type == tokenize.STRING: - if prev_toktype != tokenize.INDENT: - # This is likely a docstring; double-check we're not inside an - # operator: - if prev_toktype != tokenize.NEWLINE: - # Note regarding NEWLINE vs NL: The tokenize module - # differentiates between newlines that start a new statement - # and newlines inside of operators such as parens, brackes, - # and curly braces. Newlines inside of operators are - # NEWLINE and newlines that start new code are NL. - # Catch whole-module docstrings: - if start_col > 0: - # Unlabelled indentation means we're inside an operator - output_parts.append(token_string) - # Note regarding the INDENT token: The tokenize module does - # not label indentation inside of an operator (parens, - # brackets, and curly braces) as actual indentation. - else: - # NOTE: simply removing docstrings may create invalid code - # in cases where the only body is a docstring (e.g. a - # custom exception). Insert a pass to prevent this. It - # would be nice to detect when this is necessary. - output_parts.append('pass') - else: - output_parts.append(token_string) - prev_toktype = token_type - last_col = end_col - last_lineno = end_line - out = ''.join(output_parts) - return out - - -def hash_code(sourcecode): - r""" - Hashes source code text, but tries to normalize things like whitespace and - comments, so very minor changes wont change the hash. - - Args: - source (str): uft8 text of source code - - Returns: - str: hashid: 128 character (512 byte) hash of the normalized input - - Notes: - The return value of this function is based on the AST parse tree, which - might change between different version of Python. However, within the - same version of Python, the results should be consistent. - - CommandLine: - xdoctest -m /home/joncrall/code/netharn/netharn/export/exporter.py hash_code - - Example: - >>> hashid1 = (hash_code('x = 1')[0:8]) - >>> hashid2 = (hash_code('x=1 # comments and spaces dont matter')[0:8]) - >>> hashid3 = (hash_code('\nx=1')[0:8]) - >>> assert ub.allsame([hashid1, hashid2, hashid3]) - >>> hashid4 = hash_code('x=2')[0:8] - >>> assert hashid1 != hashid4 - """ - # Strip docstrings before making a parse tree - sourcecode = ub.ensure_unicode(sourcecode) - - stripped = remove_comments_and_docstrings(sourcecode) - - # Also remove pytorch_export version info (not sure if correct?) - stripped = re.sub('__pt_export_version__ = .*', '', stripped) - - parse_tree = ast.parse(stripped) - # hashing the parse tree will normalize for a lot possible small changes - ast_dump = ast.dump(parse_tree) - - hasher = hashlib.sha512() - hasher.update(ast_dump.encode('utf8')) - hashid = hasher.hexdigest() - return hashid - - -if __name__ == '__main__': - """ - CommandLine: - xdoctest -m netharn.export.exporter - """ - import xdoctest - xdoctest.doctest_module(__file__) +warnings.warn('netharn.export.exporter is deprecated, use torch_liberator.exporter intead', DeprecationWarning) diff --git a/netharn/fit_harn.py b/netharn/fit_harn.py index d70508b..8acccc3 100644 --- a/netharn/fit_harn.py +++ b/netharn/fit_harn.py @@ -128,6 +128,14 @@ TODO: [ ] - ability to run an iteration of the validation data within an epoch, perhaps we could allow the user to redefine how long an epoch is. + [ ] - Update for torch 1.1 lr scheduler behavior. Allow schedulers to be + called either after each epoch or after each batch iteration (for + schedulers like CyclicLR, OneCycleLR). + + [ ] - Show LR in the batch progress bar (if updated on an iteration basis) + [ ] - How does the netharn scheduler redesign interact with torch 1.1? + [ ] - Stochastic Weight Averaging - https://pytorch.org/docs/stable/optim.html#putting-it-all-together + """ from __future__ import absolute_import, division, print_function, unicode_literals import glob @@ -150,10 +158,10 @@ import numpy as np import ubelt as ub import scriptconfig as scfg +import torch_liberator from netharn import hyperparams from netharn import util -from netharn import export from netharn.util import profiler from netharn.util import strip_ansi from netharn.exceptions import (CannotResume, SkipBatch, StopTraining, @@ -1630,7 +1638,7 @@ class CoreMixin(object): model_class = harn.hyper.model_cls model_params = harn.hyper.model_params export_modules = harn.preferences['export_modules'] - static_modpath = export.export_model_code( + static_modpath = torch_liberator.export_model_code( harn.train_dpath, model_class, initkw=model_params, export_modules=export_modules) harn.info('Exported model topology to {}'.format(static_modpath)) @@ -1652,11 +1660,48 @@ class CoreMixin(object): if True: # HOTFIX: if the best snapshot doesnt exist we need to make one - if export.deployer.find_best_snapshot(harn.train_dpath) is None: + def _find_best_snapshot(train_dpath): + """ + Returns snapshot written by monitor if available otherwise takes the last + one. + + Hack for a hotfix + """ + # NOTE: Specific to netharn directory structure + # Netharn should populate best_snapshot.pt if there is a validation set. + # Other names are to support older codebases. + expected_names = [ + 'best_snapshot.pt', + 'best_snapshot2.pt', + 'final_snapshot.pt', + 'deploy_snapshot.pt', + ] + def _existing_snapshots(train_dpath): + # NOTE: Specific to netharn directory structure + import parse + snapshot_dpath = join(train_dpath, 'torch_snapshots/') + prev_states = sorted(glob.glob(join(snapshot_dpath, '_epoch_*.pt'))) + snapshots = {parse.parse('{}_epoch_{num:d}.pt', path).named['num']: path + for path in prev_states} + return snapshots + for snap_fname in expected_names: + snap_fpath = join(train_dpath, snap_fname) + if exists(snap_fpath): + break + + if not exists(snap_fpath): + snap_fpath = None + + if not snap_fpath: + epoch_to_fpath = _existing_snapshots(train_dpath) + if epoch_to_fpath: + snap_fpath = epoch_to_fpath[max(epoch_to_fpath)] + return snap_fpath + if _find_best_snapshot(harn.train_dpath) is None: harn.save_snapshot() try: - deploy_fpath = export.DeployedModel(harn.train_dpath).package() + deploy_fpath = torch_liberator.DeployedModel(harn.train_dpath).package() harn.info('wrote single-file deployment to: {!r}'.format( deploy_fpath)) diff --git a/netharn/mixins.py b/netharn/mixins.py index f083a02..e8f8cf3 100644 --- a/netharn/mixins.py +++ b/netharn/mixins.py @@ -25,9 +25,9 @@ def _dump_monitor_tensorboard(harn, mode='epoch', special_groupers=['loss'], xdoctest -m netharn.mixins _dump_monitor_tensorboard --profile Example: - >>> from netharn.export.deployer import _demodata_toy_harn + >>> import netharn as nh >>> from netharn.mixins import _dump_monitor_tensorboard - >>> harn = _demodata_toy_harn() + >>> harn = nh.FitHarn.demo() >>> harn.run() >>> try: >>> _dump_monitor_tensorboard(harn) diff --git a/netharn/prefit/lr_tests.py b/netharn/prefit/lr_tests.py index da91694..64ff556 100644 --- a/netharn/prefit/lr_tests.py +++ b/netharn/prefit/lr_tests.py @@ -37,8 +37,8 @@ def lr_range_test(harn, init_value=1e-8, final_value=10., beta=0.98, Example: >>> from netharn.prefit.lr_tests import * - >>> from netharn.export.deployer import _demodata_toy_harn - >>> harn = _demodata_toy_harn().initialize() + >>> import netharn as nh + >>> harn = nh.FitHarn.demo().initialize() >>> result = lr_range_test(harn) >>> print('result = {!r}'.format(result)) >>> # xdoctest: +REQUIRES(--show) @@ -247,8 +247,8 @@ def lr_range_scan(harn, low=1e-6, high=10.0, num=8, niter_train=1, Example: >>> from netharn.prefit.lr_tests import * - >>> from netharn.export.deployer import _demodata_toy_harn - >>> harn = _demodata_toy_harn().initialize() + >>> import netharn as nh + >>> harn = nh.FitHarn.demo().initialize() >>> result = lr_range_scan(harn) >>> print('result = {!r}'.format(result)) >>> # xdoctest: +REQUIRES(--show) -- GitLab From 6541827673c87390e83c821a5d2919b89545db89 Mon Sep 17 00:00:00 2001 From: joncrall Date: Mon, 21 Sep 2020 12:23:34 -0400 Subject: [PATCH 12/54] wip --- netharn/fit_harn.py | 57 +++++++++------- tests/test_run_sequence.py | 136 +++++++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+), 25 deletions(-) create mode 100644 tests/test_run_sequence.py diff --git a/netharn/fit_harn.py b/netharn/fit_harn.py index 8acccc3..b4a243d 100644 --- a/netharn/fit_harn.py +++ b/netharn/fit_harn.py @@ -2298,32 +2298,36 @@ class CoreCallbacks(object): necessary to support distributed training. """ batch = raw_batch - import warnings - warnings.warn( - 'The behavior of prepare_batch will change in the future. ' - 'The new behavior will be a simple no-op ' - 'For maximum compatibility override prepare_batch.', - DeprecationWarning) - try: - if isinstance(raw_batch, (tuple, list)): - batch_inputs, batch_labels = raw_batch - raw_batch = { - 'input': batch_inputs, - 'label': batch_labels, - } - if isinstance(raw_batch, dict): - batch = raw_batch.copy() - batch = harn.xpu.move(batch) - else: - print('ERROR: raw_batch = {}'.format(type(raw_batch))) - raise TypeError( - 'could not prepare raw batch {}'.format(type(raw_batch))) - except Exception: - harn.warn('Error occurred in default prepare_batch. ' - 'Perhaps you should overload it?') - raise - return batch + if harn.preferences['old_prepare_batch']: + import warnings + warnings.warn( + 'The behavior of prepare_batch will change in the future. ' + 'The new behavior will be a simple no-op ' + 'For maximum compatibility override prepare_batch.', + DeprecationWarning) + try: + if isinstance(raw_batch, (tuple, list)): + batch_inputs, batch_labels = raw_batch + raw_batch = { + 'input': batch_inputs, + 'label': batch_labels, + } + if isinstance(raw_batch, dict): + batch = raw_batch.copy() + batch = harn.xpu.move(batch) + else: + print('ERROR: raw_batch = {}'.format(type(raw_batch))) + raise TypeError( + 'could not prepare raw batch {}'.format(type(raw_batch))) + + except Exception: + harn.warn('Error occurred in default prepare_batch. ' + 'Perhaps you should overload it?') + raise + return batch + else: + return batch def run_batch(harn, batch): """ @@ -2855,6 +2859,9 @@ class FitHarnPreferences(scfg.Config): 'allow_unicode': scfg.Value(True, help=( 'allow for unicode characters in messages, otherwise ' ' we approximate them with ascii')), + + # Control deprecated + 'old_prepare_batch': False, } diff --git a/tests/test_run_sequence.py b/tests/test_run_sequence.py new file mode 100644 index 0000000..8659300 --- /dev/null +++ b/tests/test_run_sequence.py @@ -0,0 +1,136 @@ +""" +Tests the order in which things happen in "run" +""" +import numpy as np +import torch.nn.functional as F +import ubelt as ub +import netharn as nh +import torch + + +class Failpoint(Exception): + pass + + +class MyHarn(nh.FitHarn): + + def after_initialize(harn): + harn._all_iters = ub.ddict(list) + pass + + def prepare_batch(harn, raw_batch): + return raw_batch + + def before_epochs(harn): + # change the size of the dataset every epoch + harn.datasets['train'].total = (harn.epoch % 10) + 1 + + def run_batch(harn, raw_batch): + if harn.epoch == harn.failpoint: + raise Failpoint + + x = torch.Tensor([[1, 2]]) + f = torch.nn.Linear(2, 1) + y = f(x) + loss = y.sum() + output = y + harn._all_iters[harn.current_tag].append(harn.iter_index) + # batch = harn.xpu.move(raw_batch) + # output = harn.model(batch['im']) + # log_probs = F.log_softmax(output, dim=1) + # loss_parts = { + # 'nll_loss': F.nll_loss(log_probs, batch['label']), + # } + return output, loss + + +class VariableSizeDataset(torch.utils.data.Dataset): + + def __init__(self, total=100): + self.total = total + self.subdata = nh.data.ToyData2d( + size=3, border=1, n=1000, rng=0) + + def __len__(self): + return self.total + + def __getitem__(self, index): + index = index % len(self.subdata) + image, label = self.subdata[index] + item = { + 'im': image, + 'label': label, + } + return item + + +def test_run_sequence(): + """ + main test function + """ + datasets = { + 'train': VariableSizeDataset(total=1), + 'vali': VariableSizeDataset(total=10), + } + model = nh.models.ToyNet2d() + + hyper = { + # --- data first + 'datasets' : datasets, + 'nice' : 'test_run_sequence', + 'workdir' : ub.ensure_app_cache_dir('netharn/test/test_run_sequence'), + 'loaders' : {'batch_size': 1}, + 'xpu' : nh.XPU.coerce('cpu'), + # --- algorithm second + 'model' : model, + 'optimizer' : nh.api.Optimizer.coerce({'optim': 'sgd'}), + 'initializer' : nh.api.Initializer.coerce({'init': 'noop'}), + 'scheduler' : nh.api.Scheduler.coerce({'scheduler': 'step-3-7'}), + 'dynamics' : nh.api.Dynamics.coerce({'batch_step': 1}), + 'monitor' : (nh.Monitor, {'max_epoch': 10}), + } + harn1 = MyHarn(hyper=hyper) + harn1.preferences['use_tensorboard'] = True + harn1.preferences['eager_dump_tensorboard'] = True + + harn1.intervals['log_iter_train'] = 1 + harn1.intervals['log_iter_vali'] = 1 + harn1.intervals['cleanup'] = 5 + # Delete previous data + harn1.initialize(reset='delete') + + # Cause the harness to fail + try: + harn1.failpoint = 5 + harn1.run() + except Failpoint: + pass + print('\nFAILPOINT REACHED\n') + + # Restarting the harness should begin at the same point + harn2 = MyHarn(hyper=hyper) + harn2.preferences.update(harn1.preferences) + harn2.intervals.update(harn1.intervals) + harn2.failpoint = None + harn2.run() + + idxs1 = harn1._all_iters['train'] + idxs2 = harn2._all_iters['train'] + diff1 = np.diff(idxs1) + diff2 = np.diff(idxs2) + print('idxs1 = {!r}'.format(idxs1)) + print('idxs2 = {!r}'.format(idxs2)) + print('diff1 = {!r}'.format(diff1)) + print('diff2 = {!r}'.format(diff2)) + assert np.all(diff1 == 1) + assert np.all(diff2 == 1) + assert idxs1[0] == 0 + assert idxs1[-1] == (idxs2[0] - 1) + + +if __name__ == '__main__': + """ + CommandLine: + python ~/code/netharn/tests/test_run_sequence.py + """ + test_run_sequence() -- GitLab From d246f756c263ffd790936b534039520770716149 Mon Sep 17 00:00:00 2001 From: joncrall Date: Tue, 22 Sep 2020 19:13:24 -0400 Subject: [PATCH 13/54] wip --- README.rst | 26 +++++------ super_setup.py | 119 +++++++++++++++++++++++++++---------------------- 2 files changed, 79 insertions(+), 66 deletions(-) diff --git a/README.rst b/README.rst index bb1ac3b..a0c4787 100644 --- a/README.rst +++ b/README.rst @@ -92,8 +92,8 @@ Features (continued) * Hyperparameter tracking: The hash of your hyperparameters determines the directory data will be written to. We also allow for a "nicer" means to manage directory structures. Given a ``HyperParams`` object, we create the - symlink ``{workdir}/fit/nice/{nice}`` which points to - ``{workdir}/fit/runs/{nice}/{hashid}``. + symlink ``{workdir}/fit/name/{name}`` which points to + ``{workdir}/fit/runs/{name}/{hashid}``. * Automatic restarts: Calling ``FitHarn.run`` twice restarts training from where you left off by @@ -265,7 +265,7 @@ useful to look at. Its complexity is more than CIFAR but less than YOLO. >>> 'workdir' : ub.ensure_app_cache_dir('netharn/demo'), >>> 'xpu' : netharn.XPU.coerce('auto'), >>> # workdir is a directory where intermediate results can be saved - >>> # "nice" symlinks /fit/name/ -> ../runs/ + >>> # "name" symlinks /fit/name/ -> ../runs/ >>> # XPU auto select a gpu if idle and VRAM>6GB else a cpu >>> # ================ >>> # Data Components @@ -315,7 +315,7 @@ Running this code produes the following output: RESET HARNESS BY DELETING EVERYTHING IN TRAINING DIR Symlink: /home/joncrall/.cache/netharn/demo/fit/runs/demo/lnejaaum -> /home/joncrall/.cache/netharn/demo/_mru ... already exists - Symlink: /home/joncrall/.cache/netharn/demo/fit/runs/demo/lnejaaum -> /home/joncrall/.cache/netharn/demo/fit/nice/demo + Symlink: /home/joncrall/.cache/netharn/demo/fit/runs/demo/lnejaaum -> /home/joncrall/.cache/netharn/demo/fit/name/demo ... already exists ... and points to the right place INFO: Initializing tensorboard (dont forget to start the tensorboard server) @@ -324,12 +324,12 @@ Running this code produes the following output: INFO: Exported model topology to /home/joncrall/.cache/netharn/demo/fit/runs/demo/lnejaaum/ToyNet2d_2a3f49.py INFO: Initializing model weights with: INFO: * harn.train_dpath = '/home/joncrall/.cache/netharn/demo/fit/runs/demo/lnejaaum' - INFO: * harn.nice_dpath = '/home/joncrall/.cache/netharn/demo/fit/nice/demo' + INFO: * harn.name_dpath = '/home/joncrall/.cache/netharn/demo/fit/name/demo' INFO: Snapshots will save to harn.snapshot_dpath = '/home/joncrall/.cache/netharn/demo/fit/runs/demo/lnejaaum/torch_snapshots' INFO: ARGV: /home/joncrall/.local/conda/envs/py36/bin/python /home/joncrall/.local/conda/envs/py36/bin/ipython INFO: dont forget to start: - tensorboard --logdir ~/.cache/netharn/demo/fit/nice + tensorboard --logdir ~/.cache/netharn/demo/fit/name INFO: === begin training 0 / 10 : demo === epoch lr:0.0001 │ vloss is unevaluated 0/10... rate=0 Hz, eta=?, total=0:00:00, wall=19:36 EST train loss:0.173 │ 100.00% of 64x8... rate=11762.01 Hz, eta=0:00:00, total=0:00:00, wall=19:36 EST @@ -366,9 +366,9 @@ Running this code produes the following output: INFO: training completed INFO: harn.train_dpath = '/home/joncrall/.cache/netharn/demo/fit/runs/demo/lnejaaum' - INFO: harn.nice_dpath = '/home/joncrall/.cache/netharn/demo/fit/nice/demo' + INFO: harn.name_dpath = '/home/joncrall/.cache/netharn/demo/fit/name/demo' INFO: view tensorboard results for this run via: - tensorboard --logdir ~/.cache/netharn/demo/fit/nice + tensorboard --logdir ~/.cache/netharn/demo/fit/name [DEPLOYER] Deployed zipfpath=/home/joncrall/.cache/netharn/demo/fit/runs/demo/lnejaaum/deploy_ToyNet2d_lnejaaum_009_GAEYQT.zip INFO: wrote single-file deployment to: '/home/joncrall/.cache/netharn/demo/fit/runs/demo/lnejaaum/deploy_ToyNet2d_lnejaaum_009_GAEYQT.zip' INFO: exiting fit harness. @@ -381,7 +381,7 @@ then it would produce this more detailed description of what it was doing: RESET HARNESS BY DELETING EVERYTHING IN TRAINING DIR Symlink: /home/joncrall/.cache/netharn/demo/fit/runs/demo/lnejaaum -> /home/joncrall/.cache/netharn/demo/_mru ... already exists - Symlink: /home/joncrall/.cache/netharn/demo/fit/runs/demo/lnejaaum -> /home/joncrall/.cache/netharn/demo/fit/nice/demo + Symlink: /home/joncrall/.cache/netharn/demo/fit/runs/demo/lnejaaum -> /home/joncrall/.cache/netharn/demo/fit/name/demo ... already exists ... and points to the right place DEBUG: Initialized logging @@ -476,12 +476,12 @@ then it would produce this more detailed description of what it was doing: INFO: Initializing model weights with: DEBUG: calling harn.initializer= INFO: * harn.train_dpath = '/home/joncrall/.cache/netharn/demo/fit/runs/demo/lnejaaum' - INFO: * harn.nice_dpath = '/home/joncrall/.cache/netharn/demo/fit/nice/demo' + INFO: * harn.name_dpath = '/home/joncrall/.cache/netharn/demo/fit/name/demo' INFO: Snapshots will save to harn.snapshot_dpath = '/home/joncrall/.cache/netharn/demo/fit/runs/demo/lnejaaum/torch_snapshots' INFO: ARGV: /home/joncrall/.local/conda/envs/py36/bin/python /home/joncrall/.local/conda/envs/py36/bin/ipython --verbose INFO: dont forget to start: - tensorboard --logdir ~/.cache/netharn/demo/fit/nice + tensorboard --logdir ~/.cache/netharn/demo/fit/name INFO: === begin training 0 / 10 : demo === DEBUG: epoch lr:0.0001 │ vloss is unevaluated epoch lr:0.0001 │ vloss is unevaluated 0/10... rate=0 Hz, eta=?, total=0:00:00, wall=19:56 EST @@ -570,9 +570,9 @@ then it would produce this more detailed description of what it was doing: INFO: training completed INFO: harn.train_dpath = '/home/joncrall/.cache/netharn/demo/fit/runs/demo/lnejaaum' - INFO: harn.nice_dpath = '/home/joncrall/.cache/netharn/demo/fit/nice/demo' + INFO: harn.name_dpath = '/home/joncrall/.cache/netharn/demo/fit/name/demo' INFO: view tensorboard results for this run via: - tensorboard --logdir ~/.cache/netharn/demo/fit/nice + tensorboard --logdir ~/.cache/netharn/demo/fit/name [DEPLOYER] Deployed zipfpath=/home/joncrall/.cache/netharn/demo/fit/runs/demo/lnejaaum/deploy_ToyNet2d_lnejaaum_000_JWPNDC.zip INFO: wrote single-file deployment to: '/home/joncrall/.cache/netharn/demo/fit/runs/demo/lnejaaum/deploy_ToyNet2d_lnejaaum_000_JWPNDC.zip' INFO: exiting fit harness. diff --git a/super_setup.py b/super_setup.py index 5ef8844..e926a80 100755 --- a/super_setup.py +++ b/super_setup.py @@ -403,10 +403,20 @@ class Repo(ub.NiceRepr): if exists(repo.dpath): raise ValueError('cannot clone into non-empty directory') args = '--recursive' + # NOTE: if the remote branch does not exist this will fail if repo.branch is not None: args += ' -b {}'.format(repo.branch) - command = 'git clone {args} {url} {dpath}'.format(args=args, url=repo.url, dpath=repo.dpath) - repo._cmd(command, cwd=repo.code_dpath) + try: + command = 'git clone {args} {url} {dpath}'.format( + args=args, url=repo.url, dpath=repo.dpath) + repo._cmd(command, cwd=repo.code_dpath) + except Exception as ex: + text = repr(ex) + if 'Remote branch' in text and 'not found' in text: + print('ERROR: It looks like the remote branch you asked for doesnt exist') + print('ERROR: Caused by: ex = {}'.format(text)) + raise Exception('Cannot find branch {} for repo {}'.format(repo.branch, repo)) + raise def _assert_clean(repo): if repo.pygit.is_dirty(): @@ -708,65 +718,68 @@ def determine_code_dpath(): return code_dpath -def make_netharn_registry(): +DEVEL_REPOS = [ + # The util libs + { + 'name': 'kwarray', 'branch': 'dev/0.5.10', 'remote': 'public', + 'remotes': {'public': 'git@gitlab.kitware.com:computer-vision/kwarray.git'}, + }, + { + 'name': 'kwimage', 'branch': 'dev/0.6.6', 'remote': 'public', + 'remotes': {'public': 'git@gitlab.kitware.com:computer-vision/kwimage.git'}, + }, + { + 'name': 'kwannot', 'branch': 'dev/1.1.0', 'remote': 'public', + 'remotes': {'public': 'git@gitlab.kitware.com:computer-vision/kwannot.git'}, + }, + { + 'name': 'kwcoco', 'branch': 'dev/0.1.0', 'remote': 'public', + 'remotes': {'public': 'git@gitlab.kitware.com:computer-vision/kwcoco.git'}, + }, + { + 'name': 'kwplot', 'branch': 'dev/0.4.8', 'remote': 'public', + 'remotes': {'public': 'git@gitlab.kitware.com:computer-vision/kwplot.git'}, + }, + + # Pytorch deployer / exporter + { + 'name': 'liberator', 'branch': 'dev/0.0.2', 'remote': 'public', + 'remotes': {'public': 'git@gitlab.kitware.com:python/liberator.git'}, + }, + { + 'name': 'torch_liberator', 'branch': 'dev/0.0.5', 'remote': 'public', + 'remotes': {'public': 'git@gitlab.kitware.com:computer-vision/torch_liberator.git'}, + }, + + # For example data and CLI + { + 'name': 'scriptconfig', 'branch': 'dev/0.5.8', 'remote': 'public', + 'remotes': {'public': 'git@gitlab.kitware.com:utils/scriptconfig.git'}, + }, + { + 'name': 'ndsampler', 'branch': 'dev/0.5.12', 'remote': 'public', + 'remotes': {'public': 'git@gitlab.kitware.com:computer-vision/ndsampler.git'}, + }, + + # netharn - training harness + { + 'name': 'netharn', 'branch': 'dev/0.5.10', 'remote': 'public', + 'remotes': {'public': 'git@gitlab.kitware.com:computer-vision/netharn.git'}, + }, +] + + +def make_registry(devel_repos): code_dpath = determine_code_dpath() CommonRepo = functools.partial(Repo, code_dpath=code_dpath) - - devel_repos = [ - # The util libs - { - 'name': 'kwarray', 'branch': 'dev/0.5.10', 'remote': 'public', - 'remotes': {'public': 'git@gitlab.kitware.com:computer-vision/kwarray.git'}, - }, - { - 'name': 'kwimage', 'branch': 'dev/0.6.6', 'remote': 'public', - 'remotes': {'public': 'git@gitlab.kitware.com:computer-vision/kwimage.git'}, - }, - { - 'name': 'kwcoco', 'branch': 'dev/0.1.6', 'remote': 'public', - 'remotes': {'public': 'git@gitlab.kitware.com:computer-vision/kwcoco.git'}, - }, - { - 'name': 'kwplot', 'branch': 'dev/0.4.8', 'remote': 'public', - 'remotes': {'public': 'git@gitlab.kitware.com:computer-vision/kwplot.git'}, - }, - - # Pytorch deployer / exporter - { - 'name': 'liberator', 'branch': 'dev/0.0.2', 'remote': 'public', - 'remotes': {'public': 'git@gitlab.kitware.com:python/liberator.git'}, - }, - { - 'name': 'torch_liberator', 'branch': 'dev/0.0.5', 'remote': 'public', - 'remotes': {'public': 'git@gitlab.kitware.com:computer-vision/torch_liberator.git'}, - }, - - # For example data and CLI - { - 'name': 'scriptconfig', 'branch': 'dev/0.5.8', 'remote': 'public', - 'remotes': {'public': 'git@gitlab.kitware.com:utils/scriptconfig.git'}, - }, - { - 'name': 'ndsampler', 'branch': 'dev/0.5.12', 'remote': 'public', - 'remotes': {'public': 'git@gitlab.kitware.com:computer-vision/ndsampler.git'}, - }, - - # netharn - training harness - { - 'name': 'netharn', 'branch': 'dev/0.5.10', 'remote': 'public', - 'remotes': {'public': 'git@gitlab.kitware.com:computer-vision/netharn.git'}, - }, - ] - repos = [CommonRepo(**kw) for kw in devel_repos] - registery = RepoRegistry(repos) return registery def main(): - - registery = make_netharn_registry() + devel_repos = DEVEL_REPOS + registery = make_registry(devel_repos) only = ub.argval('--only', default=None) if only is not None: -- GitLab From a9cbe2aad21a474bb9b25082840b9e83f9d2975e Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 25 Sep 2020 12:43:14 -0400 Subject: [PATCH 14/54] wip --- dev/manage_snapshots.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index ab18442..d6205ef 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -218,7 +218,7 @@ def session_info(dpath): if exists(check_dpath): snapshots = os.listdir(snap_dpath) if exists(snap_dpath) else [] elif exists(snap_dpath): - pass + snapshots = [] else: snapshots = [] dpath = realpath(dpath) @@ -566,6 +566,7 @@ if __name__ == '__main__': python ~/code/netharn/dev/manage_snapshots.py --mode=snapshots --workdir=~/work/voc_yolo2/ --recent 2 --factor 40 python ~/code/netharn/dev/manage_snapshots.py --mode=runs --workdir=~/work/voc_yolo2/ python ~/code/netharn/dev/manage_snapshots.py --mode=monitor --workdir=~/work/voc_yolo2/ + python ~/code/netharn/dev/manage_snapshots.py --mode=monitor --workdir=. Notes: # Remove random files -- GitLab From 48fcc21ff22638b635402350911cab09392f75e9 Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 25 Sep 2020 12:53:54 -0400 Subject: [PATCH 15/54] wip --- dev/manage_snapshots.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index d6205ef..ea12aaa 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -297,7 +297,7 @@ def _devcheck_remove_dead_runs(workdir, dry=True, dead_num_snap_thresh=10, if not (info['has_deploy'] or info['num_snapshots'] or info['has_best']): info['decision'] = 'bad' elif info['num_snapshots'] < dead_num_snap_thresh: - dt = info['last_modified'] + dt = info.get('last_modified', now) if dt < long_time_ago: info['decision'] = 'iffy' else: @@ -567,6 +567,7 @@ if __name__ == '__main__': python ~/code/netharn/dev/manage_snapshots.py --mode=runs --workdir=~/work/voc_yolo2/ python ~/code/netharn/dev/manage_snapshots.py --mode=monitor --workdir=~/work/voc_yolo2/ python ~/code/netharn/dev/manage_snapshots.py --mode=monitor --workdir=. + python ~/code/netharn/dev/manage_snapshots.py --mode=runs --workdir=. Notes: # Remove random files -- GitLab From 0e75616dd83bbe25c35a6c2b1bf225fc837322a6 Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 25 Sep 2020 12:57:20 -0400 Subject: [PATCH 16/54] wip --- dev/manage_snapshots.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index ea12aaa..fbfc3d6 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -463,10 +463,12 @@ def _devcheck_manage_snapshots(workdir, recent=5, factor=10, dry=True): for session in all_sessions: snapshots = session.details['snapshots'] - epoch_to_snap = { - int(parse.parse('{}_epoch_{num:d}.pt', path).named['num']): path - for path in snapshots - } + epoch_to_snap = {} + for path in snapshots: + parsed = parse.parse('{}_epoch_{num:d}.pt', path) + if parsed: + epoch = int(parsed.named['num']) + epoch_to_snap[epoch] = path existing_epochs = sorted(epoch_to_snap.keys()) # print('existing_epochs = {}'.format(ub.repr2(existing_epochs))) toremove = [] @@ -568,6 +570,7 @@ if __name__ == '__main__': python ~/code/netharn/dev/manage_snapshots.py --mode=monitor --workdir=~/work/voc_yolo2/ python ~/code/netharn/dev/manage_snapshots.py --mode=monitor --workdir=. python ~/code/netharn/dev/manage_snapshots.py --mode=runs --workdir=. + python ~/code/netharn/dev/manage_snapshots.py --mode=snapshots --workdir=. --recent 2 --factor 40 Notes: # Remove random files -- GitLab From 19cc4929a31cf5715c370b66b3957a71b877dd89 Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 25 Sep 2020 12:57:59 -0400 Subject: [PATCH 17/54] wip --- dev/manage_snapshots.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index fbfc3d6..cf95658 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -465,6 +465,7 @@ def _devcheck_manage_snapshots(workdir, recent=5, factor=10, dry=True): snapshots = session.details['snapshots'] epoch_to_snap = {} for path in snapshots: + print('path = {!r}'.format(path)) parsed = parse.parse('{}_epoch_{num:d}.pt', path) if parsed: epoch = int(parsed.named['num']) -- GitLab From a3d827d50e915c1cb5129c540fdf4c31f0d750c6 Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 25 Sep 2020 12:58:11 -0400 Subject: [PATCH 18/54] wip --- dev/manage_snapshots.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index cf95658..b86c052 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -467,6 +467,7 @@ def _devcheck_manage_snapshots(workdir, recent=5, factor=10, dry=True): for path in snapshots: print('path = {!r}'.format(path)) parsed = parse.parse('{}_epoch_{num:d}.pt', path) + print('parsed = {!r}'.format(parsed)) if parsed: epoch = int(parsed.named['num']) epoch_to_snap[epoch] = path -- GitLab From ff684d467f8e93f42a6121ec3d16bbf7e1abdc2d Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 25 Sep 2020 13:06:38 -0400 Subject: [PATCH 19/54] wip --- dev/manage_snapshots.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index b86c052..e7d78cc 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -464,10 +464,9 @@ def _devcheck_manage_snapshots(workdir, recent=5, factor=10, dry=True): for session in all_sessions: snapshots = session.details['snapshots'] epoch_to_snap = {} + extra_types = {'prefix': parse.with_pattern('.*')(ub.identity)} for path in snapshots: - print('path = {!r}'.format(path)) - parsed = parse.parse('{}_epoch_{num:d}.pt', path) - print('parsed = {!r}'.format(parsed)) + parsed = parse.parse('{:prefix}_epoch_{num:d}.pt', path, extra_types) if parsed: epoch = int(parsed.named['num']) epoch_to_snap[epoch] = path -- GitLab From be5577eb72b884fd633de15836d5301b1f9fde2c Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 25 Sep 2020 13:08:22 -0400 Subject: [PATCH 20/54] wip --- dev/manage_snapshots.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index e7d78cc..274c1e5 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -217,6 +217,7 @@ def session_info(dpath): check_dpath = join(dpath, 'checkpoints') if exists(check_dpath): snapshots = os.listdir(snap_dpath) if exists(snap_dpath) else [] + snapshots = [join(dpath, fname) for fname in snapshots] elif exists(snap_dpath): snapshots = [] else: -- GitLab From 3ac48a41422dbae2b7c52c22d7adc59b89b7fd50 Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 25 Sep 2020 13:08:45 -0400 Subject: [PATCH 21/54] wip --- dev/manage_snapshots.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index 274c1e5..49d0044 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -217,7 +217,7 @@ def session_info(dpath): check_dpath = join(dpath, 'checkpoints') if exists(check_dpath): snapshots = os.listdir(snap_dpath) if exists(snap_dpath) else [] - snapshots = [join(dpath, fname) for fname in snapshots] + snapshots = [join(snap_dpath, fname) for fname in snapshots] elif exists(snap_dpath): snapshots = [] else: -- GitLab From 98c6c1f126af837d817e83f47fac529bc829fb31 Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 25 Sep 2020 13:09:28 -0400 Subject: [PATCH 22/54] wip --- dev/manage_snapshots.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index 49d0044..9f3157b 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -216,10 +216,11 @@ def session_info(dpath): snap_dpath = join(dpath, 'torch_snapshots') check_dpath = join(dpath, 'checkpoints') if exists(check_dpath): + snapshots = os.listdir(check_dpath) if exists(check_dpath) else [] + snapshots = [join(check_dpath, fname) for fname in snapshots] + elif exists(snap_dpath): snapshots = os.listdir(snap_dpath) if exists(snap_dpath) else [] snapshots = [join(snap_dpath, fname) for fname in snapshots] - elif exists(snap_dpath): - snapshots = [] else: snapshots = [] dpath = realpath(dpath) -- GitLab From 9593c3b9ff39a39a8d6120a3d8ed4178fee3a92c Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 25 Sep 2020 13:15:42 -0400 Subject: [PATCH 23/54] wip --- dev/manage_snapshots.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index 9f3157b..d586816 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -219,6 +219,7 @@ def session_info(dpath): snapshots = os.listdir(check_dpath) if exists(check_dpath) else [] snapshots = [join(check_dpath, fname) for fname in snapshots] elif exists(snap_dpath): + # Old snapshot directory name snapshots = os.listdir(snap_dpath) if exists(snap_dpath) else [] snapshots = [join(snap_dpath, fname) for fname in snapshots] else: @@ -374,11 +375,13 @@ def _devcheck_manage_monitor(workdir, dry=True): all_files = [] factor = 100 + max_keep = 200 def _choose_action(file_infos): import kwarray file_infos = kwarray.shuffle(file_infos, rng=0) n_keep = (len(file_infos) // factor) + 1 + n_keep = min(max_keep, n_keep) for info in file_infos[:n_keep]: info['action'] = 'keep' -- GitLab From ce9ffebdf6dad1fa3daddc52fc64a5ea64ae6b87 Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 25 Sep 2020 13:16:16 -0400 Subject: [PATCH 24/54] wip --- dev/manage_snapshots.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index d586816..3661eca 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -389,6 +389,7 @@ def _devcheck_manage_monitor(workdir, dry=True): info['action'] = 'delete' for session in all_sessions: + print('session = {!r}'.format(session)) dpath = join(session.dpath, 'monitor', 'train', 'batch') fpaths = list(glob.glob(join(dpath, '*.jpg'))) file_infos = [{'size': os.stat(p).st_size, 'fpath': p} -- GitLab From 6e4f1c1661fa84f8a94fe6bf65c121143743f98c Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 25 Sep 2020 13:17:39 -0400 Subject: [PATCH 25/54] wip --- dev/manage_snapshots.py | 43 ++++++++++++++--------------------------- 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index 3661eca..e521e4e 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -389,34 +389,21 @@ def _devcheck_manage_monitor(workdir, dry=True): info['action'] = 'delete' for session in all_sessions: - print('session = {!r}'.format(session)) - dpath = join(session.dpath, 'monitor', 'train', 'batch') - fpaths = list(glob.glob(join(dpath, '*.jpg'))) - file_infos = [{'size': os.stat(p).st_size, 'fpath': p} - for p in fpaths] - _choose_action(file_infos) - all_files.extend(file_infos) - - dpath = join(session.dpath, 'monitor', 'vali', 'batch') - fpaths = list(glob.glob(join(dpath, '*.jpg'))) - file_infos = [{'size': os.stat(p).st_size, 'fpath': p} - for p in fpaths] - _choose_action(file_infos) - all_files.extend(file_infos) - - dpath = join(session.dpath, 'monitor', 'train') - fpaths = list(glob.glob(join(dpath, '*.jpg'))) - file_infos = [{'size': os.stat(p).st_size, 'fpath': p} - for p in fpaths] - _choose_action(file_infos) - all_files.extend(file_infos) - - dpath = join(session.dpath, 'monitor', 'vali') - fpaths = list(glob.glob(join(dpath, '*.jpg'))) - file_infos = [{'size': os.stat(p).st_size, 'fpath': p} - for p in fpaths] - _choose_action(file_infos) - all_files.extend(file_infos) + print('session = {!r}'.format(session.dpath)) + dpaths = [ + join(session.dpath, 'monitor', 'train', 'batch'), + join(session.dpath, 'monitor', 'vali', 'batch'), + join(session.dpath, 'monitor', 'train'), + join(session.dpath, 'monitor', 'vali'), + ] + exts = ['*.jpg', '*.png'] + for dpath in dpaths: + for ext in exts: + fpaths = list(glob.glob(join(dpath, ext))) + file_infos = [{'size': os.stat(p).st_size, 'fpath': p} + for p in fpaths] + _choose_action(file_infos) + all_files.extend(file_infos) grouped_actions = ub.group_items(all_files, lambda x: x['action']) -- GitLab From c03e8864f6a390a3262bdb09a5baee6f4cf79beb Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 25 Sep 2020 13:18:12 -0400 Subject: [PATCH 26/54] wip --- dev/manage_snapshots.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index e521e4e..8cec930 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -374,14 +374,15 @@ def _devcheck_manage_monitor(workdir, dry=True): # (this is a convention and not something netharn does by default) all_files = [] - factor = 100 - max_keep = 200 + # factor = 100 + max_keep = 500 def _choose_action(file_infos): import kwarray file_infos = kwarray.shuffle(file_infos, rng=0) - n_keep = (len(file_infos) // factor) + 1 - n_keep = min(max_keep, n_keep) + n_keep = max_keep + # n_keep = (len(file_infos) // factor) + 1 + # n_keep = min(max_keep, n_keep) for info in file_infos[:n_keep]: info['action'] = 'keep' -- GitLab From bd951ad1e4844a7c0b48da1276d624418ef83b1a Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 25 Sep 2020 13:18:27 -0400 Subject: [PATCH 27/54] wip --- dev/manage_snapshots.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index 8cec930..09e5ef4 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -375,7 +375,7 @@ def _devcheck_manage_monitor(workdir, dry=True): all_files = [] # factor = 100 - max_keep = 500 + max_keep = 300 def _choose_action(file_infos): import kwarray -- GitLab From af52615097ae658f9037a586161694c19f1adde9 Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 25 Sep 2020 13:20:34 -0400 Subject: [PATCH 28/54] wip --- dev/manage_snapshots.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index 09e5ef4..a945cc6 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -250,7 +250,7 @@ def session_info(dpath): best_snapshot_fpath = join(dpath, 'best_snapshot.pt') details = {} details['best_snapshot'] = best_snapshot_fpath if exists(best_snapshot_fpath) else None - details['deployed'] = list(glob.glob(join(dpath, '*.zip'))) + details['deployed'] = [p for p in glob.glob(join(dpath, '*.zip')) if not ub.util_links.islink(p)] details['snapshots'] = snapshots info['dpath'] = dpath -- GitLab From c6a364dd4129974b8b63f38112cf63d238918925 Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 25 Sep 2020 13:22:03 -0400 Subject: [PATCH 29/54] wip --- dev/manage_snapshots.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index a945cc6..138eef9 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -260,7 +260,7 @@ def session_info(dpath): info['size'] = float(ub.cmd('du -s ' + dpath)['out'].split('\t')[0]) if len(snapshots) > 0: contents = [join(dpath, c) for c in os.listdir(dpath)] - timestamps = [get_file_info(c)['last_modified'] for c in contents] + timestamps = [get_file_info(c)['last_modified'] for c in contents if exists(c)] unixtime = max(timestamps) dt = datetime.datetime.fromtimestamp(unixtime) info['last_modified'] = dt -- GitLab From f5fea02095d3da486393fb561727bcf3fb1a225c Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 25 Sep 2020 17:22:27 -0400 Subject: [PATCH 30/54] wip --- dev/manage_snapshots.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index 138eef9..412dff9 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -417,7 +417,7 @@ def _devcheck_manage_monitor(workdir, dry=True): else: delete = grouped_actions.get('delete', []) delete_fpaths = [item['fpath'] for item in delete] - for p in delete_fpaths: + for p in ub.ProgIter(delete_fpaths, desc='deleting'): ub.delete(p) -- GitLab From 943169d1c151b9eda9ed095a0c8b24180596b0d1 Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 25 Sep 2020 17:26:14 -0400 Subject: [PATCH 31/54] wip --- dev/manage_snapshots.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index 412dff9..6a1ae29 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -183,7 +183,7 @@ def collect_sessions(workdir): training_dpaths = list(glob.glob(join(run_dpath, '*/*'))) all_sessions = [] - for dpath in training_dpaths: + for dpath in ub.ProgIter(training_dpaths, desc='collect sessions'): session = Session(dpath) all_sessions.append(session) return all_sessions @@ -389,8 +389,7 @@ def _devcheck_manage_monitor(workdir, dry=True): for info in file_infos[n_keep:]: info['action'] = 'delete' - for session in all_sessions: - print('session = {!r}'.format(session.dpath)) + for session in ub.ProgIter(all_sessions, desc='checking monitor files'): dpaths = [ join(session.dpath, 'monitor', 'train', 'batch'), join(session.dpath, 'monitor', 'vali', 'batch'), -- GitLab From 0b7818c8bbbf6f8a5c2a9a3041433633665e33b1 Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 25 Sep 2020 17:27:13 -0400 Subject: [PATCH 32/54] wip --- dev/manage_snapshots.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index 6a1ae29..d8c801c 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -513,8 +513,9 @@ def _devcheck_manage_snapshots(workdir, recent=5, factor=10, dry=True): print('Use -f to confirm and force cleanup') else: print('About to free {}'.format(byte_str(total))) - for path in ub.flatten(all_remove): - ub.delete(path, verbose=True) + fpaths = list(ub.flatten(all_remove)) + for path in ub.ProgIter(fpaths, desc='deleting'): + ub.delete(path) def main(): @@ -564,7 +565,7 @@ if __name__ == '__main__': python ~/code/netharn/dev/manage_snapshots.py --mode=monitor --workdir=~/work/voc_yolo2/ python ~/code/netharn/dev/manage_snapshots.py --mode=monitor --workdir=. python ~/code/netharn/dev/manage_snapshots.py --mode=runs --workdir=. - python ~/code/netharn/dev/manage_snapshots.py --mode=snapshots --workdir=. --recent 2 --factor 40 + python ~/code/netharn/dev/manage_snapshots.py --mode=snapshots --workdir=. --recent 2 --factor 40 -f Notes: # Remove random files -- GitLab From 55b8109c1e1898baf24f5628c11372cadd8c2cee Mon Sep 17 00:00:00 2001 From: joncrall Date: Sat, 26 Sep 2020 18:52:28 -0400 Subject: [PATCH 33/54] Initial style transfer example --- dev/manage_snapshots.py | 4 +- netharn/examples/style_transfer.py | 664 +++++++++++++++++++++++++++++ 2 files changed, 666 insertions(+), 2 deletions(-) create mode 100644 netharn/examples/style_transfer.py diff --git a/dev/manage_snapshots.py b/dev/manage_snapshots.py index d8c801c..83b3c03 100755 --- a/dev/manage_snapshots.py +++ b/dev/manage_snapshots.py @@ -183,7 +183,7 @@ def collect_sessions(workdir): training_dpaths = list(glob.glob(join(run_dpath, '*/*'))) all_sessions = [] - for dpath in ub.ProgIter(training_dpaths, desc='collect sessions'): + for dpath in ub.ProgIter(training_dpaths, desc='collect sessions', freq=1): session = Session(dpath) all_sessions.append(session) return all_sessions @@ -563,7 +563,7 @@ if __name__ == '__main__': python ~/code/netharn/dev/manage_snapshots.py --mode=snapshots --workdir=~/work/voc_yolo2/ --recent 2 --factor 40 python ~/code/netharn/dev/manage_snapshots.py --mode=runs --workdir=~/work/voc_yolo2/ python ~/code/netharn/dev/manage_snapshots.py --mode=monitor --workdir=~/work/voc_yolo2/ - python ~/code/netharn/dev/manage_snapshots.py --mode=monitor --workdir=. + python ~/code/netharn/dev/manage_snapshots.py --mode=monitor --workdir=. -f python ~/code/netharn/dev/manage_snapshots.py --mode=runs --workdir=. python ~/code/netharn/dev/manage_snapshots.py --mode=snapshots --workdir=. --recent 2 --factor 40 -f diff --git a/netharn/examples/style_transfer.py b/netharn/examples/style_transfer.py new file mode 100644 index 0000000..430b0f0 --- /dev/null +++ b/netharn/examples/style_transfer.py @@ -0,0 +1,664 @@ +""" +Adapated from : https://github.com/rrmina/fast-neural-style-pytorch/blob/master/video.py +""" +from torchvision import models, transforms +import sys +import torch +import torch.nn as nn +import numpy as np +import ubelt as ub +import ndsampler +import netharn as nh +import scriptconfig as scfg +import kwimage + + +class StyleTransferConfig(scfg.Config): + default = { + 'name': scfg.Value('style_example', help='A human readable tag that is "name" for humans'), + 'workdir': scfg.Path('~/work/netharn', help='Dump all results in your workdir'), + + 'workers': scfg.Value(2, help='number of parallel dataloading jobs'), + 'xpu': scfg.Value('auto', help='See netharn.XPU for details. can be auto/cpu/xpu/cuda0/0,1,2,3)'), + + 'datasets': scfg.Value('special:shapes256', help='Either a special key or a coco file'), + 'train_dataset': scfg.Value(None), + 'vali_dataset': scfg.Value(None), + 'test_dataset': scfg.Value(None), + + 'sampler_backend': scfg.Value(None, help='ndsampler backend'), + + 'channels': scfg.Value('rgb', help='special channel code. See ChannelSpec'), + + # 'arch': scfg.Value('resnet50', help='Network architecture code'), + 'optim': scfg.Value('adam', help='Weight optimizer. Can be SGD, ADAM, ADAMW, etc..'), + + 'input_dims': scfg.Value((256, 256), help='Window size to input to the network'), + + # TODO + 'normalize_inputs': scfg.Value(True, help=( + 'if True, precompute training mean and std for data whitening')), + + 'balance': scfg.Value(None, help='balance strategy. Can be category or None'), + # 'augmenter': scfg.Value('simple', help='type of training dataset augmentation'), + + 'batch_size': scfg.Value(3, help='number of items per batch'), + 'num_batches': scfg.Value('auto', help='Number of batches per epoch (mainly for balanced batch sampling)'), + + 'max_epoch': scfg.Value(140, help='Maximum number of epochs'), + 'patience': scfg.Value(140, help='Maximum "bad" validation epochs before early stopping'), + + 'lr': scfg.Value(1e-4, help='Base learning rate'), + 'decay': scfg.Value(1e-5, help='Base weight decay'), + 'schedule': scfg.Value( + 'step90-120', help=( + 'Special coercible netharn code. Eg: onecycle50, step50, gamma, ReduceLROnPlateau-p10-c10')), + 'init': scfg.Value('noop', help='How to initialized weights: e.g. noop, kaiming_normal, path-to-a-pretrained-model)'), + # 'pretrained': scfg.Path(help=('alternative way to specify a path to a pretrained model')), + } + + +class StyleTransferHarn(nh.FitHarn): + + def after_initialize(harn): + STYLE_IMAGE_PATH = ub.grabdata('https://raw.githubusercontent.com/iamRusty/fast-neural-style-pytorch/master/images/mosaic.jpg') + + device = harn.xpu.device + harn.MSELoss = nn.MSELoss().to(device) + + vgg_path = ub.grabdata('https://web.eecs.umich.edu/~justincj/models/vgg16-00b39a1b.pth') + + # TODO: should be tracked + harn.vgg = VGG16(**{'vgg_path': vgg_path}) + harn.vgg = harn.xpu.move(harn.vgg) + + def itot(img, max_size=None): + # Rescale the image + if (max_size is None): + itot_t = transforms.Compose([ + # transforms.ToPILImage(), + transforms.ToTensor(), + transforms.Lambda(lambda x: x.mul(255)) + ]) + else: + H, W, C = img.shape + image_size = tuple( + [int((float(max_size) / max([H, W])) * x) for x in [H, W]]) + itot_t = transforms.Compose([ + transforms.ToPILImage(), + transforms.Resize(image_size), + transforms.ToTensor(), + transforms.Lambda(lambda x: x.mul(255)) + ]) + + # Convert image to tensor + tensor = itot_t(img) + + # Add the batch_size dimension + tensor = tensor.unsqueeze(dim=0) + return tensor + + # Get Style Features + imagenet_neg_mean = torch.tensor( + [-103.939, -116.779, -123.68], dtype=torch.float32).reshape(1, 3, 1, 1).to(device) + style_image = kwimage.imread(STYLE_IMAGE_PATH) + style_tensor = itot(style_image).to(device) + style_tensor = style_tensor.add(imagenet_neg_mean) + B, C, H, W = style_tensor.shape + + harn.imagenet_neg_mean = imagenet_neg_mean + harn.style_tensor = style_tensor + + batch_size = harn.script_config['batch_size'] + im = style_tensor.expand([batch_size, C, H, W]) + + style_features = harn.vgg(im) + style_gram = {} + for key, value in style_features.items(): + style_gram[key] = gram(value) + harn.style_gram = style_gram + + def run_batch(harn, batch): + """ + Ignore: + import sys, ubelt + sys.path.append(ubelt.expandpath('~/code/netharn')) + from netharn.examples.style_transfer import * # NOQA + kw = {} + cmdline = False + harn = setup_harn() + harn.initialize() + batch = harn._demo_batch() + harn.run_batch(batch) + """ + # Current Batch size in case of odd batches + content_batch, _ = batch + curr_batch_size = content_batch.shape[0] + + model = harn.model + # Zero-out Gradients + + # Generate images and get features + content_batch = harn.xpu.move(content_batch[:, [2, 1, 0]]) + + generated_batch = model(content_batch) + + generated_batch = harn.model(content_batch) + content_features = harn.vgg(content_batch.add(harn.imagenet_neg_mean)) + generated_features = harn.vgg(generated_batch.add(harn.imagenet_neg_mean)) + + # Content Loss + CONTENT_WEIGHT = 17 + STYLE_WEIGHT = 50 + + content_loss = CONTENT_WEIGHT * \ + harn.MSELoss( + content_features['relu2_2'], + generated_features['relu2_2']) + + # Style Loss + style_loss = 0 + for key, value in generated_features.items(): + s_loss = harn.MSELoss( + gram(value), + harn.style_gram[key][:curr_batch_size] + ) + style_loss += s_loss + style_loss *= STYLE_WEIGHT + + # Total Loss + loss_parts = { + 'content_loss': content_loss, + 'style_loss': style_loss, + } + return generated_batch, loss_parts + + def on_batch(harn, batch, generated_batch, loss): + _do_draw = harn.batch_index % 500 == 0 + _do_draw |= harn.batch_index < 4 + if _do_draw: + # Save sample generated image + from os.path import join + dpath = ub.ensuredir((harn.train_dpath, 'monitor', harn.current_tag)) + sample_tensor = generated_batch[0].clone().detach().unsqueeze(dim=0) + sample_image = sample_tensor.clone().detach().cpu().numpy().transpose(1, 2, 0) + sample_image_path = join(dpath, "sample0_" + str(harn.batch_index) + '_' + str(harn.batch_index) + ".png") + kwimage.imwrite(sample_image_path, sample_image.clip(0, 255)) + print("Saved sample tranformed image at {}".format(sample_image_path)) + + +class SamplerDataset(torch.utils.data.Dataset): + def __init__(self, sampler, transform=None, return_style='torchvision'): + self.sampler = sampler + self.transform = transform + self.return_style = return_style + self.input_id = self.sampler.hashid + + def __len__(self): + return len(self.sampler) + + def __getitem__(self, index): + item = self.sampler.load_item(index) + numpy_im = item['im'] + + if self.transform: + from PIL import Image + pil_im = Image.fromarray(numpy_im) + torch_chw = self.transform(pil_im) + else: + torch_chw = torch.from_numpy(numpy_im).permute(2, 0, 1).float() + # raise NotImplementedError + + if self.return_style == 'torchvision': + cid = item['tr']['category_id'] + cidx = self.sampler.classes.id_to_idx[cid] + return torch_chw, cidx + else: + raise NotImplementedError + + def make_loader(self, batch_size=16, num_batches='auto', num_workers=0, + shuffle=False, pin_memory=False, drop_last=False, + balance=None): + + import kwarray + if len(self) == 0: + raise Exception('must have some data') + + def worker_init_fn(worker_id): + for i in range(worker_id + 1): + seed = np.random.randint(0, int(2 ** 32) - 1) + seed = seed + worker_id + kwarray.seed_global(seed) + # if self.augmenter: + # rng = kwarray.ensure_rng(None) + # self.augmenter.seed_(rng) + + loaderkw = { + 'num_workers': num_workers, + 'pin_memory': pin_memory, + 'worker_init_fn': worker_init_fn, + } + if balance is None: + loaderkw['shuffle'] = shuffle + loaderkw['batch_size'] = batch_size + loaderkw['drop_last'] = drop_last + elif balance == 'classes': + from netharn.data.batch_samplers import BalancedBatchSampler + index_to_cid = [ + cid for cid in self.sampler.regions.targets['category_id'] + ] + batch_sampler = BalancedBatchSampler( + index_to_cid, batch_size=batch_size, + shuffle=shuffle, num_batches=num_batches) + loaderkw['batch_sampler'] = batch_sampler + else: + raise KeyError(balance) + + loader = torch.utils.data.DataLoader(self, **loaderkw) + return loader + + +def setup_harn(cmdline=False, **kw): + """ + Ignore: + kw = {} + cmdline = False + harn = setup_harn() + harn.initialize() + batch = harn._demo_batch() + """ + config = StyleTransferConfig(default=kw) + config.load(cmdline=cmdline) + print('config = {}'.format(ub.repr2(config.asdict()))) + + nh.configure_hacks(config) + + dataset_info = coerce_datasets(config) + + # input_stats = dataset_info['input_stats'] + + model = (TransformerNetwork, {}) + + hyper = nh.HyperParams( + name=config['name'], + + workdir=config['workdir'], + xpu=nh.XPU.coerce(config['xpu']), + + datasets=dataset_info['torch_datasets'], + loaders=dataset_info['torch_loaders'], + + model=model, + criterion=None, + + optimizer=nh.Optimizer.coerce(config), + dynamics=nh.Dynamics.coerce(config), + scheduler=nh.Scheduler.coerce(config), + + initializer=None, + + monitor=(nh.Monitor, { + 'minimize': ['loss'], + 'patience': config['patience'], + 'max_epoch': config['max_epoch'], + 'smoothing': 0.0, + }), + other={ + 'name': config['name'], + 'batch_size': config['batch_size'], + 'balance': config['balance'], + }, + extra={ + 'argv': sys.argv, + 'config': ub.repr2(config.asdict()), + } + ) + harn = StyleTransferHarn(hyper=hyper) + harn.preferences.update({ + 'num_keep': 3, + 'keep_freq': 10, + 'tensorboard_groups': ['loss'], + 'eager_dump_tensorboard': True, + }) + harn.intervals.update({}) + harn.script_config = config + return harn + + +def gram(tensor): + B, C, H, W = tensor.shape + x = tensor.view(B, C, H * W) + x_t = x.transpose(1, 2) + return torch.bmm(x, x_t) / (C * H * W) + + +class VGG16(nn.Module): + def __init__(self, vgg_path="models/vgg16-00b39a1b.pth"): + super(VGG16, self).__init__() + self.vgg_path = vgg_path + # Load VGG Skeleton, Pretrained Weights + vgg16_features = models.vgg16(pretrained=False) + vgg16_features.load_state_dict(torch.load(vgg_path), strict=False) + self.features = vgg16_features.features + + # Turn-off Gradient History + for param in self.features.parameters(): + param.requires_grad = False + + def forward(self, x): + layers = { + '3': 'relu1_2', + '8': 'relu2_2', + '15': 'relu3_3', + '22': 'relu4_3'} + features = {} + for name, layer in self.features._modules.items(): + x = layer(x) + if name in layers: + features[layers[name]] = x + if name == '22': + break + + return features + + +class TransformerNetwork(nn.Module): + """Feedforward Transformation Network without Tanh + reference: https://arxiv.org/abs/1603.08155 + exact architecture: https://cs.stanford.edu/people/jcjohns/papers/fast-style/fast-style-supp.pdf + """ + + def __init__(self): + super().__init__() + self.ConvBlock = nn.Sequential( + ConvLayer(3, 32, 9, 1), + nn.ReLU(), + ConvLayer(32, 64, 3, 2), + nn.ReLU(), + ConvLayer(64, 128, 3, 2), + nn.ReLU() + ) + self.ResidualBlock = nn.Sequential( + ResidualLayer(128, 3), + ResidualLayer(128, 3), + ResidualLayer(128, 3), + ResidualLayer(128, 3), + ResidualLayer(128, 3) + ) + self.DeconvBlock = nn.Sequential( + DeconvLayer(128, 64, 3, 2, 1), + nn.ReLU(), + DeconvLayer(64, 32, 3, 2, 1), + nn.ReLU(), + ConvLayer(32, 3, 9, 1, norm="None") + ) + + def forward(self, x): + x = self.ConvBlock(x) + x = self.ResidualBlock(x) + out = self.DeconvBlock(x) + return out + + +class TransformerNetworkTanh(TransformerNetwork): + """A modification of the transformation network that uses Tanh function as output + This follows more closely the architecture outlined in the original paper's supplementary material + his net produces darker images and provides retro styling effect + Reference: https://cs.stanford.edu/people/jcjohns/papers/fast-style/fast-style-supp.pdf + """ + # override __init__ method + + def __init__(self, tanh_multiplier=150): + super(TransformerNetworkTanh, self).__init__() + # Add a Tanh layer before output + self.DeconvBlock = nn.Sequential( + DeconvLayer(128, 64, 3, 2, 1), + nn.ReLU(), + DeconvLayer(64, 32, 3, 2, 1), + nn.ReLU(), + ConvLayer(32, 3, 9, 1, norm="None"), + nn.Tanh() + ) + self.tanh_multiplier = tanh_multiplier + + # Override forward method + def forward(self, x): + return super(TransformerNetworkTanh, self).forward( + x) * self.tanh_multiplier + + +class ConvLayer(nn.Module): + def __init__(self, in_channels, out_channels, + kernel_size, stride, norm="instance"): + super(ConvLayer, self).__init__() + # Padding Layers + padding_size = kernel_size // 2 + self.reflection_pad = nn.ReflectionPad2d(padding_size) + + # Convolution Layer + self.conv_layer = nn.Conv2d( + in_channels, out_channels, kernel_size, stride) + + # Normalization Layers + self.norm_type = norm + if (norm == "instance"): + self.norm_layer = nn.InstanceNorm2d(out_channels, affine=True) + elif (norm == "batch"): + self.norm_layer = nn.BatchNorm2d(out_channels, affine=True) + + def forward(self, x): + x = self.reflection_pad(x) + x = self.conv_layer(x) + if (self.norm_type == "None"): + out = x + else: + out = self.norm_layer(x) + return out + + +class ResidualLayer(nn.Module): + """ + Deep Residual Learning for Image Recognition + + https://arxiv.org/abs/1512.03385 + """ + + def __init__(self, channels=128, kernel_size=3): + super(ResidualLayer, self).__init__() + self.conv1 = ConvLayer(channels, channels, kernel_size, stride=1) + self.relu = nn.ReLU() + self.conv2 = ConvLayer(channels, channels, kernel_size, stride=1) + + def forward(self, x): + identity = x # preserve residual + out = self.relu(self.conv1(x)) # 1st conv layer + activation + out = self.conv2(out) # 2nd conv layer + out = out + identity # add residual + return out + + +class DeconvLayer(nn.Module): + def __init__(self, in_channels, out_channels, kernel_size, + stride, output_padding, norm="instance"): + super(DeconvLayer, self).__init__() + + # Transposed Convolution + padding_size = kernel_size // 2 + self.conv_transpose = nn.ConvTranspose2d( + in_channels, + out_channels, + kernel_size, + stride, + padding_size, + output_padding) + + # Normalization Layers + self.norm_type = norm + if (norm == "instance"): + self.norm_layer = nn.InstanceNorm2d(out_channels, affine=True) + elif (norm == "batch"): + self.norm_layer = nn.BatchNorm2d(out_channels, affine=True) + + def forward(self, x): + x = self.conv_transpose(x) + if (self.norm_type == "None"): + out = x + else: + out = self.norm_layer(x) + return out + + +def coerce_datasets(config): + coco_datasets = nh.api.Datasets.coerce(config) + print('coco_datasets = {}'.format(ub.repr2(coco_datasets, nl=1))) + for tag, dset in coco_datasets.items(): + dset._build_hashid(hash_pixels=False) + + workdir = ub.ensuredir(ub.expandpath(config['workdir'])) + samplers = { + tag: ndsampler.CocoSampler(dset, workdir=workdir, backend=config['sampler_backend']) + for tag, dset in coco_datasets.items() + } + + for tag, sampler in ub.ProgIter(list(samplers.items()), desc='prepare frames'): + sampler.frames.prepare(workers=config['workers']) + + # TODO: basic ndsampler torch dataset, likely has to support the transforms + # API, bleh. + + TRAIN_IMAGE_SIZE = 256 + transform = transforms.Compose([ + transforms.Resize(TRAIN_IMAGE_SIZE), + transforms.CenterCrop(TRAIN_IMAGE_SIZE), + transforms.ToTensor(), + transforms.Lambda(lambda x: x.mul(255)) + ]) + + torch_datasets = { + key: SamplerDataset( + sapmler, transform=transform, + # input_dims=config['input_dims'], + # augmenter=config['augmenter'] if key == 'train' else None, + ) + for key, sapmler in samplers.items() + } + # self = torch_dset = torch_datasets['train'] + + if config['normalize_inputs']: + # Get stats on the dataset (todo: turn off augmentation for this) + import kwarray + _dset = torch_datasets['train'] + stats_idxs = kwarray.shuffle(np.arange(len(_dset)), rng=0)[0:min(1000, len(_dset))] + stats_subset = torch.utils.data.Subset(_dset, stats_idxs) + + cacher = ub.Cacher('dset_mean', cfgstr=_dset.input_id + 'v3') + input_stats = cacher.tryload() + + from netharn.data.channel_spec import ChannelSpec + channels = ChannelSpec.coerce(config['channels']) + + if input_stats is None: + # Use parallel workers to load data faster + from netharn.data.data_containers import container_collate + from functools import partial + collate_fn = partial(container_collate, num_devices=1) + + loader = torch.utils.data.DataLoader( + stats_subset, + collate_fn=collate_fn, + num_workers=config['workers'], + shuffle=True, + batch_size=config['batch_size']) + + # Track moving average of each fused channel stream + channel_stats = {key: nh.util.RunningStats() + for key in channels.keys()} + assert len(channel_stats) == 1, ( + 'only support one fused stream for now') + for batch in ub.ProgIter(loader, desc='estimate mean/std'): + if isinstance(batch, (tuple, list)): + inputs = {'rgb': batch[0]} # make assumption + else: + inputs = batch['inputs'] + + for key, val in inputs.items(): + try: + for part in val.numpy(): + channel_stats[key].update(part) + except ValueError: # final batch broadcast error + pass + + perchan_input_stats = {} + for key, running in channel_stats.items(): + running = ub.peek(channel_stats.values()) + perchan_stats = running.simple(axis=(1, 2)) + perchan_input_stats[key] = { + 'std': perchan_stats['mean'].round(3), + 'mean': perchan_stats['std'].round(3), + } + + input_stats = ub.peek(perchan_input_stats.values()) + cacher.save(input_stats) + else: + input_stats = {} + + torch_loaders = { + tag: dset.make_loader( + batch_size=config['batch_size'], + num_batches=config['num_batches'], + num_workers=config['workers'], + shuffle=(tag == 'train'), + balance=(config['balance'] if tag == 'train' else None), + pin_memory=True) + for tag, dset in torch_datasets.items() + } + + dataset_info = { + 'torch_datasets': torch_datasets, + 'torch_loaders': torch_loaders, + 'input_stats': input_stats + } + return dataset_info + + +def load_cifar(key='cifar10', workdir=None, transform=None): + """ + key = 'cifar10' + load_cifar(key, workdir=None) + """ + import torchvision + import pickle + import os + if workdir is None: + workdir = ub.ensure_app_cache_dir('netharn') + + if key == 'cifar10': + DATASET = torchvision.datasets.CIFAR10 + dset = DATASET(root=workdir, download=True, transform=transform) + meta_fpath = os.path.join(dset.root, dset.base_folder, 'batches.meta') + meta_dict = pickle.load(open(meta_fpath, 'rb')) + dset.classes = meta_dict['label_names'] + # For some reason the torchvision objects dont have the label names + # in the dataset. But the download directory will have them. + # classes = [ + # 'airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', + # 'horse', 'ship', 'truck', + # ] + elif key == 'cifar100': + DATASET = torchvision.datasets.CIFAR100 + dset = DATASET(root=workdir, download=True, transform=transform) + meta_fpath = os.path.join(dset.root, dset.base_folder, 'meta') + meta_dict = pickle.load(open(meta_fpath, 'rb')) + dset.classes = meta_dict['fine_label_names'] + return dset + + +if __name__ == '__main__': + """ + CommandLine: + python ~/code/netharn/netharn/examples/style_transfer.py \ + --xpu=0 \ + --train_dataset=shapes1024 \ + """ + harn = setup_harn() + harn.run() -- GitLab From babd5391cb4ae6979975cc4c5309b53dbcabffdc Mon Sep 17 00:00:00 2001 From: joncrall Date: Sat, 26 Sep 2020 19:03:51 -0400 Subject: [PATCH 34/54] Experimental API to make handling datasets easier --- netharn/api.py | 205 +++++++++ netharn/examples/style_transfer.py | 229 +--------- netharn/examples/style_transfer_orig.py | 583 ++++++++++++++++++++++++ 3 files changed, 792 insertions(+), 225 deletions(-) create mode 100644 netharn/examples/style_transfer_orig.py diff --git a/netharn/api.py b/netharn/api.py index cb75bc6..f34c65a 100644 --- a/netharn/api.py +++ b/netharn/api.py @@ -43,6 +43,211 @@ class Datasets(object): return torch_datasets +class DatasetInfo(object): + """ + experimental, attempts to do more heavy lifting + """ + @staticmethod + def coerce(config={}, **kw): + """ + Accepts 'datasets', 'train_dataset', 'vali_dataset', and 'test_dataset'. + + Args: + config (dict | str): coercable configuration dictionary. + """ + config = _update_defaults(config, kw) + dataset_info = _coerce_datasets(config) + return dataset_info + + +def _coerce_datasets(config): + import netharn as nh + import ndsampler + import numpy as np + from torchvision import transforms + coco_datasets = nh.api.Datasets.coerce(config) + print('coco_datasets = {}'.format(ub.repr2(coco_datasets, nl=1))) + for tag, dset in coco_datasets.items(): + dset._build_hashid(hash_pixels=False) + + workdir = ub.ensuredir(ub.expandpath(config['workdir'])) + samplers = { + tag: ndsampler.CocoSampler(dset, workdir=workdir, backend=config['sampler_backend']) + for tag, dset in coco_datasets.items() + } + + for tag, sampler in ub.ProgIter(list(samplers.items()), desc='prepare frames'): + sampler.frames.prepare(workers=config['workers']) + + # TODO: basic ndsampler torch dataset, likely has to support the transforms + # API, bleh. + + transform = transforms.Compose([ + transforms.Resize(config['input_dims']), + transforms.CenterCrop(config['input_dims']), + transforms.ToTensor(), + transforms.Lambda(lambda x: x.mul(255)) + ]) + + torch_datasets = { + key: SamplerDataset( + sapmler, transform=transform, + # input_dims=config['input_dims'], + # augmenter=config['augmenter'] if key == 'train' else None, + ) + for key, sapmler in samplers.items() + } + # self = torch_dset = torch_datasets['train'] + + if config['normalize_inputs']: + # Get stats on the dataset (todo: turn off augmentation for this) + import kwarray + _dset = torch_datasets['train'] + stats_idxs = kwarray.shuffle(np.arange(len(_dset)), rng=0)[0:min(1000, len(_dset))] + stats_subset = torch.utils.data.Subset(_dset, stats_idxs) + + cacher = ub.Cacher('dset_mean', cfgstr=_dset.input_id + 'v3') + input_stats = cacher.tryload() + + from netharn.data.channel_spec import ChannelSpec + channels = ChannelSpec.coerce(config['channels']) + + if input_stats is None: + # Use parallel workers to load data faster + from netharn.data.data_containers import container_collate + from functools import partial + collate_fn = partial(container_collate, num_devices=1) + + loader = torch.utils.data.DataLoader( + stats_subset, + collate_fn=collate_fn, + num_workers=config['workers'], + shuffle=True, + batch_size=config['batch_size']) + + # Track moving average of each fused channel stream + channel_stats = {key: nh.util.RunningStats() + for key in channels.keys()} + assert len(channel_stats) == 1, ( + 'only support one fused stream for now') + for batch in ub.ProgIter(loader, desc='estimate mean/std'): + if isinstance(batch, (tuple, list)): + inputs = {'rgb': batch[0]} # make assumption + else: + inputs = batch['inputs'] + + for key, val in inputs.items(): + try: + for part in val.numpy(): + channel_stats[key].update(part) + except ValueError: # final batch broadcast error + pass + + perchan_input_stats = {} + for key, running in channel_stats.items(): + running = ub.peek(channel_stats.values()) + perchan_stats = running.simple(axis=(1, 2)) + perchan_input_stats[key] = { + 'std': perchan_stats['mean'].round(3), + 'mean': perchan_stats['std'].round(3), + } + + input_stats = ub.peek(perchan_input_stats.values()) + cacher.save(input_stats) + else: + input_stats = {} + + torch_loaders = { + tag: dset.make_loader( + batch_size=config['batch_size'], + num_batches=config['num_batches'], + num_workers=config['workers'], + shuffle=(tag == 'train'), + balance=(config['balance'] if tag == 'train' else None), + pin_memory=True) + for tag, dset in torch_datasets.items() + } + + dataset_info = { + 'torch_datasets': torch_datasets, + 'torch_loaders': torch_loaders, + 'input_stats': input_stats + } + return dataset_info + + +class SamplerDataset(torch.utils.data.Dataset): + def __init__(self, sampler, transform=None, return_style='torchvision'): + self.sampler = sampler + self.transform = transform + self.return_style = return_style + self.input_id = self.sampler.hashid + + def __len__(self): + return len(self.sampler) + + def __getitem__(self, index): + item = self.sampler.load_item(index) + numpy_im = item['im'] + + if self.transform: + from PIL import Image + pil_im = Image.fromarray(numpy_im) + torch_chw = self.transform(pil_im) + else: + torch_chw = torch.from_numpy(numpy_im).permute(2, 0, 1).float() + # raise NotImplementedError + + if self.return_style == 'torchvision': + cid = item['tr']['category_id'] + cidx = self.sampler.classes.id_to_idx[cid] + return torch_chw, cidx + else: + raise NotImplementedError + + def make_loader(self, batch_size=16, num_batches='auto', num_workers=0, + shuffle=False, pin_memory=False, drop_last=False, + balance=None): + + import kwarray + if len(self) == 0: + raise Exception('must have some data') + + def worker_init_fn(worker_id): + import numpy as np + for i in range(worker_id + 1): + seed = np.random.randint(0, int(2 ** 32) - 1) + seed = seed + worker_id + kwarray.seed_global(seed) + # if self.augmenter: + # rng = kwarray.ensure_rng(None) + # self.augmenter.seed_(rng) + + loaderkw = { + 'num_workers': num_workers, + 'pin_memory': pin_memory, + 'worker_init_fn': worker_init_fn, + } + if balance is None: + loaderkw['shuffle'] = shuffle + loaderkw['batch_size'] = batch_size + loaderkw['drop_last'] = drop_last + elif balance == 'classes': + from netharn.data.batch_samplers import BalancedBatchSampler + index_to_cid = [ + cid for cid in self.sampler.regions.targets['category_id'] + ] + batch_sampler = BalancedBatchSampler( + index_to_cid, batch_size=batch_size, + shuffle=shuffle, num_batches=num_batches) + loaderkw['batch_sampler'] = batch_sampler + else: + raise KeyError(balance) + + loader = torch.utils.data.DataLoader(self, **loaderkw) + return loader + + class Initializer(object): """ Base class for all netharn initializers diff --git a/netharn/examples/style_transfer.py b/netharn/examples/style_transfer.py index 430b0f0..af47dc4 100644 --- a/netharn/examples/style_transfer.py +++ b/netharn/examples/style_transfer.py @@ -5,9 +5,7 @@ from torchvision import models, transforms import sys import torch import torch.nn as nn -import numpy as np import ubelt as ub -import ndsampler import netharn as nh import scriptconfig as scfg import kwimage @@ -181,91 +179,18 @@ class StyleTransferHarn(nh.FitHarn): from os.path import join dpath = ub.ensuredir((harn.train_dpath, 'monitor', harn.current_tag)) sample_tensor = generated_batch[0].clone().detach().unsqueeze(dim=0) - sample_image = sample_tensor.clone().detach().cpu().numpy().transpose(1, 2, 0) + sample_image = sample_tensor.clone().detach().cpu().squeeze().numpy().transpose(1, 2, 0) sample_image_path = join(dpath, "sample0_" + str(harn.batch_index) + '_' + str(harn.batch_index) + ".png") kwimage.imwrite(sample_image_path, sample_image.clip(0, 255)) print("Saved sample tranformed image at {}".format(sample_image_path)) -class SamplerDataset(torch.utils.data.Dataset): - def __init__(self, sampler, transform=None, return_style='torchvision'): - self.sampler = sampler - self.transform = transform - self.return_style = return_style - self.input_id = self.sampler.hashid - - def __len__(self): - return len(self.sampler) - - def __getitem__(self, index): - item = self.sampler.load_item(index) - numpy_im = item['im'] - - if self.transform: - from PIL import Image - pil_im = Image.fromarray(numpy_im) - torch_chw = self.transform(pil_im) - else: - torch_chw = torch.from_numpy(numpy_im).permute(2, 0, 1).float() - # raise NotImplementedError - - if self.return_style == 'torchvision': - cid = item['tr']['category_id'] - cidx = self.sampler.classes.id_to_idx[cid] - return torch_chw, cidx - else: - raise NotImplementedError - - def make_loader(self, batch_size=16, num_batches='auto', num_workers=0, - shuffle=False, pin_memory=False, drop_last=False, - balance=None): - - import kwarray - if len(self) == 0: - raise Exception('must have some data') - - def worker_init_fn(worker_id): - for i in range(worker_id + 1): - seed = np.random.randint(0, int(2 ** 32) - 1) - seed = seed + worker_id - kwarray.seed_global(seed) - # if self.augmenter: - # rng = kwarray.ensure_rng(None) - # self.augmenter.seed_(rng) - - loaderkw = { - 'num_workers': num_workers, - 'pin_memory': pin_memory, - 'worker_init_fn': worker_init_fn, - } - if balance is None: - loaderkw['shuffle'] = shuffle - loaderkw['batch_size'] = batch_size - loaderkw['drop_last'] = drop_last - elif balance == 'classes': - from netharn.data.batch_samplers import BalancedBatchSampler - index_to_cid = [ - cid for cid in self.sampler.regions.targets['category_id'] - ] - batch_sampler = BalancedBatchSampler( - index_to_cid, batch_size=batch_size, - shuffle=shuffle, num_batches=num_batches) - loaderkw['batch_sampler'] = batch_sampler - else: - raise KeyError(balance) - - loader = torch.utils.data.DataLoader(self, **loaderkw) - return loader - - def setup_harn(cmdline=False, **kw): """ Ignore: kw = {} cmdline = False harn = setup_harn() - harn.initialize() - batch = harn._demo_batch() """ config = StyleTransferConfig(default=kw) config.load(cmdline=cmdline) @@ -273,10 +198,9 @@ def setup_harn(cmdline=False, **kw): nh.configure_hacks(config) - dataset_info = coerce_datasets(config) + dataset_info = nh.api.DatasetInfo.coerce(config) # input_stats = dataset_info['input_stats'] - model = (TransformerNetwork, {}) hyper = nh.HyperParams( @@ -290,13 +214,12 @@ def setup_harn(cmdline=False, **kw): model=model, criterion=None, + initializer=None, optimizer=nh.Optimizer.coerce(config), dynamics=nh.Dynamics.coerce(config), scheduler=nh.Scheduler.coerce(config), - initializer=None, - monitor=(nh.Monitor, { 'minimize': ['loss'], 'patience': config['patience'], @@ -508,157 +431,13 @@ class DeconvLayer(nn.Module): return out -def coerce_datasets(config): - coco_datasets = nh.api.Datasets.coerce(config) - print('coco_datasets = {}'.format(ub.repr2(coco_datasets, nl=1))) - for tag, dset in coco_datasets.items(): - dset._build_hashid(hash_pixels=False) - - workdir = ub.ensuredir(ub.expandpath(config['workdir'])) - samplers = { - tag: ndsampler.CocoSampler(dset, workdir=workdir, backend=config['sampler_backend']) - for tag, dset in coco_datasets.items() - } - - for tag, sampler in ub.ProgIter(list(samplers.items()), desc='prepare frames'): - sampler.frames.prepare(workers=config['workers']) - - # TODO: basic ndsampler torch dataset, likely has to support the transforms - # API, bleh. - - TRAIN_IMAGE_SIZE = 256 - transform = transforms.Compose([ - transforms.Resize(TRAIN_IMAGE_SIZE), - transforms.CenterCrop(TRAIN_IMAGE_SIZE), - transforms.ToTensor(), - transforms.Lambda(lambda x: x.mul(255)) - ]) - - torch_datasets = { - key: SamplerDataset( - sapmler, transform=transform, - # input_dims=config['input_dims'], - # augmenter=config['augmenter'] if key == 'train' else None, - ) - for key, sapmler in samplers.items() - } - # self = torch_dset = torch_datasets['train'] - - if config['normalize_inputs']: - # Get stats on the dataset (todo: turn off augmentation for this) - import kwarray - _dset = torch_datasets['train'] - stats_idxs = kwarray.shuffle(np.arange(len(_dset)), rng=0)[0:min(1000, len(_dset))] - stats_subset = torch.utils.data.Subset(_dset, stats_idxs) - - cacher = ub.Cacher('dset_mean', cfgstr=_dset.input_id + 'v3') - input_stats = cacher.tryload() - - from netharn.data.channel_spec import ChannelSpec - channels = ChannelSpec.coerce(config['channels']) - - if input_stats is None: - # Use parallel workers to load data faster - from netharn.data.data_containers import container_collate - from functools import partial - collate_fn = partial(container_collate, num_devices=1) - - loader = torch.utils.data.DataLoader( - stats_subset, - collate_fn=collate_fn, - num_workers=config['workers'], - shuffle=True, - batch_size=config['batch_size']) - - # Track moving average of each fused channel stream - channel_stats = {key: nh.util.RunningStats() - for key in channels.keys()} - assert len(channel_stats) == 1, ( - 'only support one fused stream for now') - for batch in ub.ProgIter(loader, desc='estimate mean/std'): - if isinstance(batch, (tuple, list)): - inputs = {'rgb': batch[0]} # make assumption - else: - inputs = batch['inputs'] - - for key, val in inputs.items(): - try: - for part in val.numpy(): - channel_stats[key].update(part) - except ValueError: # final batch broadcast error - pass - - perchan_input_stats = {} - for key, running in channel_stats.items(): - running = ub.peek(channel_stats.values()) - perchan_stats = running.simple(axis=(1, 2)) - perchan_input_stats[key] = { - 'std': perchan_stats['mean'].round(3), - 'mean': perchan_stats['std'].round(3), - } - - input_stats = ub.peek(perchan_input_stats.values()) - cacher.save(input_stats) - else: - input_stats = {} - - torch_loaders = { - tag: dset.make_loader( - batch_size=config['batch_size'], - num_batches=config['num_batches'], - num_workers=config['workers'], - shuffle=(tag == 'train'), - balance=(config['balance'] if tag == 'train' else None), - pin_memory=True) - for tag, dset in torch_datasets.items() - } - - dataset_info = { - 'torch_datasets': torch_datasets, - 'torch_loaders': torch_loaders, - 'input_stats': input_stats - } - return dataset_info - - -def load_cifar(key='cifar10', workdir=None, transform=None): - """ - key = 'cifar10' - load_cifar(key, workdir=None) - """ - import torchvision - import pickle - import os - if workdir is None: - workdir = ub.ensure_app_cache_dir('netharn') - - if key == 'cifar10': - DATASET = torchvision.datasets.CIFAR10 - dset = DATASET(root=workdir, download=True, transform=transform) - meta_fpath = os.path.join(dset.root, dset.base_folder, 'batches.meta') - meta_dict = pickle.load(open(meta_fpath, 'rb')) - dset.classes = meta_dict['label_names'] - # For some reason the torchvision objects dont have the label names - # in the dataset. But the download directory will have them. - # classes = [ - # 'airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', - # 'horse', 'ship', 'truck', - # ] - elif key == 'cifar100': - DATASET = torchvision.datasets.CIFAR100 - dset = DATASET(root=workdir, download=True, transform=transform) - meta_fpath = os.path.join(dset.root, dset.base_folder, 'meta') - meta_dict = pickle.load(open(meta_fpath, 'rb')) - dset.classes = meta_dict['fine_label_names'] - return dset - - if __name__ == '__main__': """ CommandLine: python ~/code/netharn/netharn/examples/style_transfer.py \ --xpu=0 \ --train_dataset=shapes1024 \ + --vali_dataset=shapes1024 \ """ harn = setup_harn() harn.run() diff --git a/netharn/examples/style_transfer_orig.py b/netharn/examples/style_transfer_orig.py new file mode 100644 index 0000000..ba87031 --- /dev/null +++ b/netharn/examples/style_transfer_orig.py @@ -0,0 +1,583 @@ +from torchvision import datasets, models, transforms +import cv2 +import torch +import torch.nn as nn +import torch.optim as optim +import random +import numpy as np +import time +import ubelt as ub + +notes = """ +# GLOBAL SETTINGS + +!wget https://web.eecs.umich.edu/~justincj/models/vgg16-00b39a1b.pth + +# download style image +!wget https://raw.githubusercontent.com/iamRusty/fast-neural-style-pytorch/master/images/mosaic.jpg +""" + + +SAVE_MODEL_EVERY = 500 # 2,000 Images with batch size 4 +SEED = 35 +BATCH_SIZE = 4 +CONTENT_WEIGHT = 17 +STYLE_WEIGHT = 50 +TV_WEIGHT = 1e-6 +ADAM_LR = 0.001 +NUM_EPOCHS = 1 + + +class VGG19(nn.Module): + def __init__(self, vgg_path="models/vgg19-d01eb7cb.pth"): + super(VGG19, self).__init__() + # Load VGG Skeleton, Pretrained Weights + vgg19_features = models.vgg19(pretrained=False) + vgg19_features.load_state_dict(torch.load(vgg_path), strict=False) + self.features = vgg19_features.features + + # Turn-off Gradient History + for param in self.features.parameters(): + param.requires_grad = False + + def forward(self, x): + layers = { + '3': 'relu1_2', + '8': 'relu2_2', + '17': 'relu3_4', + '22': 'relu4_2', + '26': 'relu4_4', + '35': 'relu5_4'} + features = {} + for name, layer in self.features._modules.items(): + x = layer(x) + if name in layers: + features[layers[name]] = x + + return features + + +class VGG16(nn.Module): + def __init__(self, vgg_path="models/vgg16-00b39a1b.pth"): + super(VGG16, self).__init__() + # Load VGG Skeleton, Pretrained Weights + vgg16_features = models.vgg16(pretrained=False) + vgg16_features.load_state_dict(torch.load(vgg_path), strict=False) + self.features = vgg16_features.features + + # Turn-off Gradient History + for param in self.features.parameters(): + param.requires_grad = False + + def forward(self, x): + layers = { + '3': 'relu1_2', + '8': 'relu2_2', + '15': 'relu3_3', + '22': 'relu4_3'} + features = {} + for name, layer in self.features._modules.items(): + x = layer(x) + if name in layers: + features[layers[name]] = x + if (name == '22'): + break + + return features + +# Gram Matrix + + +def gram(tensor): + B, C, H, W = tensor.shape + x = tensor.view(B, C, H * W) + x_t = x.transpose(1, 2) + return torch.bmm(x, x_t) / (C * H * W) + +# Load image file + + +def load_image(path): + # Images loaded as BGR + img = cv2.imread(path) + return img + +# Show image + + +def show(img): + import matplotlib.pyplot as plt + # Convert from BGR to RGB + img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) + + # imshow() only accepts float [0,1] or int [0,255] + img = np.array(img / 255).clip(0, 1) + + plt.figure(figsize=(10, 5)) + plt.imshow(img) + plt.show() + + +def saveimg(img, image_path): + img = img.clip(0, 255) + cv2.imwrite(image_path, img) + +# Preprocessing ~ Image to Tensor + + +def itot(img, max_size=None): + # Rescale the image + if (max_size is None): + itot_t = transforms.Compose([ + # transforms.ToPILImage(), + transforms.ToTensor(), + transforms.Lambda(lambda x: x.mul(255)) + ]) + else: + H, W, C = img.shape + image_size = tuple( + [int((float(max_size) / max([H, W])) * x) for x in [H, W]]) + itot_t = transforms.Compose([ + transforms.ToPILImage(), + transforms.Resize(image_size), + transforms.ToTensor(), + transforms.Lambda(lambda x: x.mul(255)) + ]) + + # Convert image to tensor + tensor = itot_t(img) + + # Add the batch_size dimension + tensor = tensor.unsqueeze(dim=0) + return tensor + +# Preprocessing ~ Tensor to Image + + +def ttoi(tensor): + # Add the means + # ttoi_t = transforms.Compose([ + # transforms.Normalize([-103.939, -116.779, -123.68],[1,1,1])]) + + # Remove the batch_size dimension + tensor = tensor.squeeze() + #img = ttoi_t(tensor) + img = tensor.cpu().numpy() + + # Transpose from [C, H, W] -> [H, W, C] + img = img.transpose(1, 2, 0) + return img + + +def transfer_color(src, dest): + """ + Transfer Color using YIQ colorspace. Useful in preserving colors in style transfer. + This method assumes inputs of shape [Height, Width, Channel] in BGR Color Space + """ + src, dest = src.clip(0, 255), dest.clip(0, 255) + + # Resize src to dest's size + H, W, _ = src.shape + dest = cv2.resize(dest, dsize=(W, H), interpolation=cv2.INTER_CUBIC) + + # 1 Extract the Destination's luminance + dest_gray = cv2.cvtColor(dest, cv2.COLOR_BGR2GRAY) + # 2 Convert the Source from BGR to YIQ/YCbCr + src_yiq = cv2.cvtColor(src, cv2.COLOR_BGR2YCrCb) + # 3 Combine Destination's luminance and Source's IQ/CbCr + src_yiq[..., 0] = dest_gray + + return cv2.cvtColor(src_yiq, cv2.COLOR_YCrCb2BGR).clip( + 0, 255) # 4 Convert new image from YIQ back to BGR + + +def plot_loss_hist(c_loss, s_loss, total_loss, title="Loss History"): + import matplotlib.pyplot as plt + x = [i for i in range(len(total_loss))] + plt.figure(figsize=[10, 6]) + plt.plot(x, c_loss, label="Content Loss") + plt.plot(x, s_loss, label="Style Loss") + plt.plot(x, total_loss, label="Total Loss") + + plt.legend() + plt.xlabel('Every 500 iterations') + plt.ylabel('Loss') + plt.title(title) + plt.show() + + +class ImageFolderWithPaths(datasets.ImageFolder): + """Custom dataset that includes image file paths. + Extends torchvision.datasets.ImageFolder() + Reference: https://discuss.pytorch.org/t/dataloader-filenames-in-each-batch/4212/2 + """ + # override the __getitem__ method. this is the method dataloader calls + + def __getitem__(self, index): + # this is what ImageFolder normally returns + original_tuple = super(ImageFolderWithPaths, self).__getitem__(index) + + # the image file path + path = self.imgs[index][0] + + # make a new tuple that includes original and the path + tuple_with_path = (*original_tuple, path) + return tuple_with_path + + +class TransformerNetwork(nn.Module): + """Feedforward Transformation Network without Tanh + reference: https://arxiv.org/abs/1603.08155 + exact architecture: https://cs.stanford.edu/people/jcjohns/papers/fast-style/fast-style-supp.pdf + """ + + def __init__(self): + super().__init__() + self.ConvBlock = nn.Sequential( + ConvLayer(3, 32, 9, 1), + nn.ReLU(), + ConvLayer(32, 64, 3, 2), + nn.ReLU(), + ConvLayer(64, 128, 3, 2), + nn.ReLU() + ) + self.ResidualBlock = nn.Sequential( + ResidualLayer(128, 3), + ResidualLayer(128, 3), + ResidualLayer(128, 3), + ResidualLayer(128, 3), + ResidualLayer(128, 3) + ) + self.DeconvBlock = nn.Sequential( + DeconvLayer(128, 64, 3, 2, 1), + nn.ReLU(), + DeconvLayer(64, 32, 3, 2, 1), + nn.ReLU(), + ConvLayer(32, 3, 9, 1, norm="None") + ) + + def forward(self, x): + x = self.ConvBlock(x) + x = self.ResidualBlock(x) + out = self.DeconvBlock(x) + return out + + +class TransformerNetworkTanh(TransformerNetwork): + """A modification of the transformation network that uses Tanh function as output + This follows more closely the architecture outlined in the original paper's supplementary material + his net produces darker images and provides retro styling effect + Reference: https://cs.stanford.edu/people/jcjohns/papers/fast-style/fast-style-supp.pdf + """ + # override __init__ method + + def __init__(self, tanh_multiplier=150): + super(TransformerNetworkTanh, self).__init__() + # Add a Tanh layer before output + self.DeconvBlock = nn.Sequential( + DeconvLayer(128, 64, 3, 2, 1), + nn.ReLU(), + DeconvLayer(64, 32, 3, 2, 1), + nn.ReLU(), + ConvLayer(32, 3, 9, 1, norm="None"), + nn.Tanh() + ) + self.tanh_multiplier = tanh_multiplier + + # Override forward method + def forward(self, x): + return super(TransformerNetworkTanh, self).forward( + x) * self.tanh_multiplier + + +class ConvLayer(nn.Module): + def __init__(self, in_channels, out_channels, + kernel_size, stride, norm="instance"): + super(ConvLayer, self).__init__() + # Padding Layers + padding_size = kernel_size // 2 + self.reflection_pad = nn.ReflectionPad2d(padding_size) + + # Convolution Layer + self.conv_layer = nn.Conv2d( + in_channels, out_channels, kernel_size, stride) + + # Normalization Layers + self.norm_type = norm + if (norm == "instance"): + self.norm_layer = nn.InstanceNorm2d(out_channels, affine=True) + elif (norm == "batch"): + self.norm_layer = nn.BatchNorm2d(out_channels, affine=True) + + def forward(self, x): + x = self.reflection_pad(x) + x = self.conv_layer(x) + if (self.norm_type == "None"): + out = x + else: + out = self.norm_layer(x) + return out + + +class ResidualLayer(nn.Module): + """ + Deep Residual Learning for Image Recognition + + https://arxiv.org/abs/1512.03385 + """ + + def __init__(self, channels=128, kernel_size=3): + super(ResidualLayer, self).__init__() + self.conv1 = ConvLayer(channels, channels, kernel_size, stride=1) + self.relu = nn.ReLU() + self.conv2 = ConvLayer(channels, channels, kernel_size, stride=1) + + def forward(self, x): + identity = x # preserve residual + out = self.relu(self.conv1(x)) # 1st conv layer + activation + out = self.conv2(out) # 2nd conv layer + out = out + identity # add residual + return out + + +class DeconvLayer(nn.Module): + def __init__(self, in_channels, out_channels, kernel_size, + stride, output_padding, norm="instance"): + super(DeconvLayer, self).__init__() + + # Transposed Convolution + padding_size = kernel_size // 2 + self.conv_transpose = nn.ConvTranspose2d( + in_channels, + out_channels, + kernel_size, + stride, + padding_size, + output_padding) + + # Normalization Layers + self.norm_type = norm + if (norm == "instance"): + self.norm_layer = nn.InstanceNorm2d(out_channels, affine=True) + elif (norm == "batch"): + self.norm_layer = nn.BatchNorm2d(out_channels, affine=True) + + def forward(self, x): + x = self.conv_transpose(x) + if (self.norm_type == "None"): + out = x + else: + out = self.norm_layer(x) + return out + + +def load_cifar(key='cifar10', workdir=None, transform=None): + """ + key = 'cifar10' + load_cifar(key, workdir=None) + """ + import torchvision + import pickle + import os + if workdir is None: + workdir = ub.ensure_app_cache_dir('netharn') + + if key == 'cifar10': + DATASET = torchvision.datasets.CIFAR10 + dset = DATASET(root=workdir, download=True, transform=transform) + meta_fpath = os.path.join(dset.root, dset.base_folder, 'batches.meta') + meta_dict = pickle.load(open(meta_fpath, 'rb')) + dset.classes = meta_dict['label_names'] + # For some reason the torchvision objects dont have the label names + # in the dataset. But the download directory will have them. + # classes = [ + # 'airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', + # 'horse', 'ship', 'truck', + # ] + elif key == 'cifar100': + DATASET = torchvision.datasets.CIFAR100 + dset = DATASET(root=workdir, download=True, transform=transform) + meta_fpath = os.path.join(dset.root, dset.base_folder, 'meta') + meta_dict = pickle.load(open(meta_fpath, 'rb')) + dset.classes = meta_dict['fine_label_names'] + return dset + + +def train(): + """ + CommandLine: + xdoctest -m /home/joncrall/code/netharn/netharn/examples/style_transfer.py train + + Example: + >>> import sys, ubelt + >>> sys.path.append(ubelt.expandpath('~/code/netharn')) + >>> from netharn.examples.style_transfer import * # NOQA + >>> train() + """ + + STYLE_IMAGE_PATH = ub.grabdata('https://raw.githubusercontent.com/iamRusty/fast-neural-style-pytorch/master/images/mosaic.jpg') + vgg_path = ub.grabdata('https://web.eecs.umich.edu/~justincj/models/vgg16-00b39a1b.pth') + workdir = ub.ensure_app_cache_dir('netharn') + + # Seeds + torch.manual_seed(SEED) + torch.cuda.manual_seed(SEED) + np.random.seed(SEED) + random.seed(SEED) + + # Device + device = ("cuda" if torch.cuda.is_available() else "cpu") + + # Dataset and Dataloader + TRAIN_IMAGE_SIZE = 256 + transform = transforms.Compose([ + transforms.Resize(TRAIN_IMAGE_SIZE), + transforms.CenterCrop(TRAIN_IMAGE_SIZE), + transforms.ToTensor(), + transforms.Lambda(lambda x: x.mul(255)) + ]) + + SAVE_MODEL_PATH = workdir + SAVE_IMAGE_PATH = workdir + # DATASET_PATH = "/content/train" + # train_dataset = datasets.ImageFolder(DATASET_PATH, transform=transform) + + train_dataset = load_cifar(transform=transform) + train_loader = torch.utils.data.DataLoader( + train_dataset, batch_size=BATCH_SIZE, shuffle=True) + + # Load networks + model = VGG16(vgg_path).to(device) + + # Get Style Features + imagenet_neg_mean = torch.tensor( + [-103.939, -116.779, -123.68], dtype=torch.float32).reshape(1, 3, 1, 1).to(device) + style_image = load_image(STYLE_IMAGE_PATH) + style_tensor = itot(style_image).to(device) + style_tensor = style_tensor.add(imagenet_neg_mean) + B, C, H, W = style_tensor.shape + style_features = model(style_tensor.expand([BATCH_SIZE, C, H, W])) + style_gram = {} + for key, value in style_features.items(): + style_gram[key] = gram(value) + + # Optimizer settings + params = list(model.parameters()) + optimizer = optim.Adam(params, lr=ADAM_LR) + + # Loss trackers + content_loss_history = [] + style_loss_history = [] + total_loss_history = [] + batch_content_loss_sum = 0 + batch_style_loss_sum = 0 + batch_total_loss_sum = 0 + + # Optimization/Training Loop + batch_count = 1 + start_time = time.time() + for epoch in range(1, NUM_EPOCHS + 1): + print("========Epoch {}/{}========".format(epoch, NUM_EPOCHS + 1)) + for batch_id, (content_batch, _) in enumerate(train_loader): + # Current Batch size in case of odd batches + curr_batch_size = content_batch.shape[0] + + # Zero-out Gradients + optimizer.zero_grad() + + # Generate images and get features + content_batch = content_batch[:, [2, 1, 0]].to(device) + generated_batch = model(content_batch) + content_features = model(content_batch.add(imagenet_neg_mean)) + generated_features = model(generated_batch.add(imagenet_neg_mean)) + + # Content Loss + MSELoss = nn.MSELoss().to(device) + content_loss = CONTENT_WEIGHT * \ + MSELoss( + content_features['relu2_2'], + generated_features['relu2_2']) + batch_content_loss_sum += content_loss + + # Style Loss + style_loss = 0 + for key, value in generated_features.items(): + s_loss = MSELoss(gram(value), + style_gram[key][:curr_batch_size]) + style_loss += s_loss + style_loss *= STYLE_WEIGHT + batch_style_loss_sum += style_loss + + # Total Loss + total_loss = content_loss + style_loss + batch_total_loss_sum += total_loss.item() + + # Backprop and Weight Update + total_loss.backward() + optimizer.step() + + # Save Model and Print Losses + if (((batch_count - 1) % SAVE_MODEL_EVERY == 0) or (batch_count == NUM_EPOCHS * len(train_loader))): + # Print Losses + print("========Iteration {}/{}========".format(batch_count, + NUM_EPOCHS * len(train_loader))) + print( + "\tContent Loss:\t{:.2f}".format( + batch_content_loss_sum / + batch_count)) + print( + "\tStyle Loss:\t{:.2f}".format( + batch_style_loss_sum / + batch_count)) + print( + "\tTotal Loss:\t{:.2f}".format( + batch_total_loss_sum / + batch_count)) + print( + "Time elapsed:\t{} seconds".format( + time.time() - start_time)) + + # Save Model + checkpoint_path = SAVE_MODEL_PATH + \ + "checkpoint_" + str(batch_count - 1) + ".pth" + torch.save(TransformerNetwork.state_dict(), checkpoint_path) + print( + "Saved TransformerNetwork checkpoint file at {}".format(checkpoint_path)) + + # Save sample generated image + sample_tensor = generated_batch[0].clone( + ).detach().unsqueeze(dim=0) + sample_image = ttoi(sample_tensor.clone().detach()) + sample_image_path = SAVE_IMAGE_PATH + \ + "sample0_" + str(batch_count - 1) + ".png" + saveimg(sample_image, sample_image_path) + # show(sample_image) + print( + "Saved sample tranformed image at {}".format(sample_image_path)) + + # Save loss histories + content_loss_history.append(batch_total_loss_sum / batch_count) + style_loss_history.append(batch_style_loss_sum / batch_count) + total_loss_history.append(batch_total_loss_sum / batch_count) + + # Iterate Batch Counter + batch_count += 1 + + stop_time = time.time() + # Print loss histories + print("Done Training the Transformer Network!") + print("Training Time: {} seconds".format(stop_time - start_time)) + print("========Content Loss========") + print(content_loss_history) + print("========Style Loss========") + print(style_loss_history) + print("========Total Loss========") + print(total_loss_history) + + # Save TransformerNetwork weights + TransformerNetwork.eval() + TransformerNetwork.cpu() + final_path = SAVE_MODEL_PATH + "transformer_weight.pth" + print("Saving TransformerNetwork weights at {}".format(final_path)) + torch.save(TransformerNetwork.state_dict(), final_path) + print("Done saving final net") -- GitLab From 3db7eda1aa5624b3a4003e8594f3380999cda40e Mon Sep 17 00:00:00 2001 From: joncrall Date: Mon, 5 Oct 2020 13:15:30 -0400 Subject: [PATCH 35/54] wip --- super_setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/super_setup.py b/super_setup.py index e926a80..5cf7cdf 100755 --- a/super_setup.py +++ b/super_setup.py @@ -725,7 +725,7 @@ DEVEL_REPOS = [ 'remotes': {'public': 'git@gitlab.kitware.com:computer-vision/kwarray.git'}, }, { - 'name': 'kwimage', 'branch': 'dev/0.6.6', 'remote': 'public', + 'name': 'kwimage', 'branch': 'dev/0.6.7', 'remote': 'public', 'remotes': {'public': 'git@gitlab.kitware.com:computer-vision/kwimage.git'}, }, { @@ -733,7 +733,7 @@ DEVEL_REPOS = [ 'remotes': {'public': 'git@gitlab.kitware.com:computer-vision/kwannot.git'}, }, { - 'name': 'kwcoco', 'branch': 'dev/0.1.0', 'remote': 'public', + 'name': 'kwcoco', 'branch': 'dev/0.1.7', 'remote': 'public', 'remotes': {'public': 'git@gitlab.kitware.com:computer-vision/kwcoco.git'}, }, { -- GitLab From 065d5d04dfb76ae612fcfd220ff39dc6d237fd1e Mon Sep 17 00:00:00 2001 From: joncrall Date: Wed, 7 Oct 2020 13:48:25 -0400 Subject: [PATCH 36/54] wip --- super_setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/super_setup.py b/super_setup.py index 5cf7cdf..4d8aa47 100755 --- a/super_setup.py +++ b/super_setup.py @@ -729,7 +729,7 @@ DEVEL_REPOS = [ 'remotes': {'public': 'git@gitlab.kitware.com:computer-vision/kwimage.git'}, }, { - 'name': 'kwannot', 'branch': 'dev/1.1.0', 'remote': 'public', + 'name': 'kwannot', 'branch': 'dev/0.1.0', 'remote': 'public', 'remotes': {'public': 'git@gitlab.kitware.com:computer-vision/kwannot.git'}, }, { -- GitLab From 9c031a2f8a69cdb910b25ff695292158758b25b7 Mon Sep 17 00:00:00 2001 From: joncrall Date: Wed, 7 Oct 2020 13:50:16 -0400 Subject: [PATCH 37/54] wip --- netharn/api.py | 2 +- netharn/initializers/pretrained.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/netharn/api.py b/netharn/api.py index f34c65a..aa4809a 100644 --- a/netharn/api.py +++ b/netharn/api.py @@ -355,7 +355,7 @@ class Initializer(object): initializer_ = (nh.initializers.Pretrained, { 'fpath': ub.expandpath(config['pretrained_fpath']), 'leftover': kw.get('leftover', None), - 'mangle': kw.get('mangle', True), + 'mangle': kw.get('mangle', False), 'association': kw.get('association', None), }) elif config['init'] == 'cls': diff --git a/netharn/initializers/pretrained.py b/netharn/initializers/pretrained.py index 751b8de..5634e98 100644 --- a/netharn/initializers/pretrained.py +++ b/netharn/initializers/pretrained.py @@ -41,7 +41,8 @@ class Pretrained(api.Initializer, ub.NiceRepr): classification layer if class indexes are not aligned. association (str): controls how we search for the association between - the two model states. Can be strict, module-hack, prefix-hack, or embedding. + the two model states. Can be strict, module-hack, prefix-hack, or + embedding. info (dict, optional): specify explicit history info -- GitLab From fa0e1987b327fe4d836c9ce5af0e3c904c6d7bff Mon Sep 17 00:00:00 2001 From: joncrall Date: Mon, 12 Oct 2020 15:01:43 -0400 Subject: [PATCH 38/54] Bugfix in DataContainers.to --- netharn/data/data_containers.py | 11 +- netharn/util/util_json.py | 275 +++++++++++++++++++++----------- 2 files changed, 190 insertions(+), 96 deletions(-) diff --git a/netharn/data/data_containers.py b/netharn/data/data_containers.py index bda1696..2307900 100644 --- a/netharn/data/data_containers.py +++ b/netharn/data/data_containers.py @@ -152,12 +152,11 @@ class BatchContainer(ub.NiceRepr): def to(self, device): """ inplace move data onto a device """ - for item in self.data: - if torch.is_tensor(item): - item.to(item) - else: - for subitem in item: - subitem.to(device) + from netharn.util.util_json import IndexableWalker + walker = IndexableWalker(self.data) + for path, val in walker: + if torch.is_tensor(val): + walker[path] = val.to(device) return self diff --git a/netharn/util/util_json.py b/netharn/util/util_json.py index e4fc85c..ea4091a 100644 --- a/netharn/util/util_json.py +++ b/netharn/util/util_json.py @@ -6,6 +6,7 @@ import six import torch import numpy as np import ubelt as ub +from collections.abc import Generator from collections import OrderedDict @@ -139,6 +140,20 @@ def ensure_json_serializable(dict_, normalize_containers=False, verbose=0): if True, normalizes dict containers to be standard python structures. + Example: + >>> data = ub.ddict(lambda: int) + >>> data['foo'] = ub.ddict(lambda: int) + >>> data['bar'] = np.array([1, 2, 3]) + >>> data['foo']['a'] = 1 + >>> data['foo']['b'] = (1, np.array([1, 2, 3]), {3: np.int(3), 4: np.float16(1.0)}) + >>> dict_ = data + >>> print(ub.repr2(data, nl=-1)) + >>> assert list(find_json_unserializable(data)) + >>> result = ensure_json_serializable(data, normalize_containers=True) + >>> print(ub.repr2(result, nl=-1)) + >>> assert not list(find_json_unserializable(result)) + >>> assert type(result) is dict + Example: >>> data = ub.ddict(lambda: int) >>> data['foo'] = ub.ddict(lambda: int) @@ -161,100 +176,180 @@ def ensure_json_serializable(dict_, normalize_containers=False, verbose=0): c = dict(c) return c - # inplace convert any ndarrays to lists - def _walk_json(data, prefix=[]): - items = None - if isinstance(data, list): - items = enumerate(data) - elif isinstance(data, tuple): - items = enumerate(data) - elif isinstance(data, dict): - items = data.items() - else: - raise TypeError(type(data)) + walker = IndexableWalker(dict_) + for prefix, value in walker: + if isinstance(value, tuple): + new_value = list(value) + walker[prefix] = new_value + elif isinstance(value, np.ndarray): + new_value = value.tolist() + walker[prefix] = new_value + elif isinstance(value, torch.Tensor): + new_value = value.data.cpu().numpy().tolist() + walker[prefix] = new_value + elif isinstance(value, (np.integer)): + new_value = int(value) + walker[prefix] = new_value + elif isinstance(value, (np.floating)): + new_value = float(value) + walker[prefix] = new_value + elif isinstance(value, (np.complex)): + new_value = complex(value) + walker[prefix] = new_value + elif hasattr(value, '__json__'): + new_value = value.__json__() + walker[prefix] = new_value + elif normalize_containers: + if isinstance(value, dict): + new_value = _norm_container(value) + walker[prefix] = new_value + + if normalize_containers: + # normalize the outer layer + dict_ = _norm_container(dict_) + return dict_ - root = prefix - level = {} - for key, value in items: - level[key] = value - # yield a dict so the user can choose to not walk down a path - yield root, level +class IndexableWalker(Generator): + """ + Traverses through a nested tree-liked indexable structure. + + Generates a path and value to each node in the structure. The path is a + list of indexes which if applied in order will reach the value. + + The ``__setitem__`` method can be used to modify a nested value based on the + path returned by the generator. + + When generating values, you can use "send" to prevent traversal of a + particular branch. + + Example: + >>> # Create nested data + >>> import numpy as np + >>> data = ub.ddict(lambda: int) + >>> data['foo'] = ub.ddict(lambda: int) + >>> data['bar'] = np.array([1, 2, 3]) + >>> data['foo']['a'] = 1 + >>> data['foo']['b'] = np.array([1, 2, 3]) + >>> data['foo']['c'] = [1, 2, 3] + >>> data['baz'] = 3 + >>> print('data = {}'.format(ub.repr2(data, nl=True))) + >>> # We can walk through every node in the nested tree + >>> walker = IndexableWalker(data) + >>> for path, value in walker: + >>> print('walk path = {}'.format(ub.repr2(path, nl=0))) + >>> if path[-1] == 'c': + >>> # Use send to prevent traversing this branch + >>> got = walker.send(False) + >>> # We can modify the value based on the returned path + >>> walker[path] = 'changed the value of c' + >>> print('data = {}'.format(ub.repr2(data, nl=True))) + >>> assert data['foo']['c'] == 'changed the value of c' + """ + + def __init__(self, data, dict_cls=(dict,), list_cls=(list, tuple)): + self.data = data + self.dict_cls = dict_cls + self.list_cls = list_cls + self.indexable_cls = self.dict_cls + self.list_cls + + self._walk_gen = None + + def __iter__(self): + """ + Iterates through the indexable ``self.data`` - for key, value in level.items(): - if isinstance(value, (dict, list, tuple)): - path = prefix + [key] - for _ in _walk_json(value, prefix=path): - yield _ + Can send a False flag to prevent a branch from being traversed - def _convert(dict_, root, key, new_value): - d = dict_ - for k in root: + Yields: + Tuple[List, Any] : + path (List): list of index operations to arrive at the value + value (object): the value at the path + """ + return self + + def __next__(self): + """ returns next item from this generator """ + if self._walk_gen is None: + self._walk_gen = self._walk(self.data, prefix=[]) + return next(self._walk_gen) + + def send(self, arg): + """ + send(arg) -> send 'arg' into generator, + return next yielded value or raise StopIteration. + """ + # Note: this will error if called before __next__ + self._walk_gen.send(arg) + + def throw(self, type=None, value=None, traceback=None): + """ + throw(typ[,val[,tb]]) -> raise exception in generator, + return next yielded value or raise StopIteration. + """ + raise StopIteration + + def __setitem__(self, path, value): + """ + Set nested value by path + + Args: + path (List): list of indexes into the nested structure + value (object): new value + """ + d = self.data + *prefix, key = path + for k in prefix: d = d[k] - d[key] = new_value + d[key] = value - def _flatmap(func, data): - if isinstance(data, list): - return [_flatmap(func, item) for item in data] - else: - return func(data) - - to_convert = [] - for root, level in ub.ProgIter(_walk_json(dict_), desc='walk json', - verbose=verbose): - for key, value in level.items(): - if isinstance(value, tuple): - # Convert tuples on the fly so they become mutable - new_value = list(value) - _convert(dict_, root, key, new_value) - elif isinstance(value, np.ndarray): - new_value = value.tolist() - if 0: - if len(value.shape) == 1: - if value.dtype.kind in {'i', 'u'}: - new_value = list(map(int, new_value)) - elif value.dtype.kind in {'f'}: - new_value = list(map(float, new_value)) - elif value.dtype.kind in {'c'}: - new_value = list(map(complex, new_value)) - else: - pass - else: - if value.dtype.kind in {'i', 'u'}: - new_value = _flatmap(int, new_value) - elif value.dtype.kind in {'f'}: - new_value = _flatmap(float, new_value) - elif value.dtype.kind in {'c'}: - new_value = _flatmap(complex, new_value) - else: - pass - # raise TypeError(value.dtype) - to_convert.append((root, key, new_value)) - elif isinstance(value, torch.Tensor): - new_value = value.data.cpu().numpy().tolist() - to_convert.append((root, key, new_value)) - elif isinstance(value, (np.int16, np.int32, np.int64, - np.uint16, np.uint32, np.uint64)): - new_value = int(value) - to_convert.append((root, key, new_value)) - elif isinstance(value, (np.float32, np.float64)): - new_value = float(value) - to_convert.append((root, key, new_value)) - elif isinstance(value, (np.complex64, np.complex128)): - new_value = complex(value) - to_convert.append((root, key, new_value)) - elif hasattr(value, '__json__'): - new_value = value.__json__() - to_convert.append((root, key, new_value)) - elif normalize_containers: - if isinstance(value, dict): - new_value = _norm_container(value) - to_convert.append((root, key, new_value)) - - for root, key, new_value in to_convert: - _convert(dict_, root, key, new_value) + def __delitem__(self, path): + """ + Remove nested value by path - if normalize_containers: - # normalize the outer layer - dict_ = _norm_container(dict_) - return dict_ + Note: + It can be dangerous to use this while iterating (because we may try + to descend into a deleted location) or on leaf items that are + list-like (because the indexes of all subsequent items will be + modified). + + Args: + path (List): list of indexes into the nested structure. + The item at the last index will be removed. + """ + d = self.data + *prefix, key = path + for k in prefix: + d = d[k] + del d[key] + + def _walk(self, data, prefix=[]): + """ + Defines the underlying generator used by IndexableWalker + """ + stack = [(data, prefix)] + while stack: + _data, _prefix = stack.pop() + # Create an items iterable of depending on the indexable data type + if isinstance(_data, self.list_cls): + items = enumerate(_data) + elif isinstance(_data, self.dict_cls): + items = _data.items() + else: + raise TypeError(type(_data)) + + for key, value in items: + # Yield the full path to this position and its value + path = _prefix + [key] + message = yield path, value + # If the value at this path is also indexable, then continue + # the traversal, unless the False message was explicitly sent + # by the caller. + if isinstance(value, self.indexable_cls): + if message is False: + # Because the `send` method will return the next value, + # we yield a dummy value so we don't clobber the next + # item in the traversal. + yield None + else: + stack.append((value, path)) -- GitLab From 3cdbf5fcdffc6b829e46be19950c420516989838 Mon Sep 17 00:00:00 2001 From: joncrall Date: Tue, 13 Oct 2020 17:33:00 -0400 Subject: [PATCH 39/54] wip --- netharn/device.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/netharn/device.py b/netharn/device.py index 6d8a482..8cc9255 100644 --- a/netharn/device.py +++ b/netharn/device.py @@ -116,10 +116,10 @@ class XPU(ub.NiceRepr): if check: if not XPU.exists(item): if isinstance(item, int) and not torch.cuda.is_available(): - raise ValueError('XPU {} does not exist. ' + raise ValueError('XPU {!r} does not exist. ' 'CUDA is not available'.format(item)) else: - raise ValueError('XPU {} does not exist.'.format(item)) + raise ValueError('XPU {!r} does not exist.'.format(item)) if item is None: xpu._main_device_id = None -- GitLab From af0dfbb692bed173cc16668626e201ff0f321bc4 Mon Sep 17 00:00:00 2001 From: joncrall Date: Thu, 15 Oct 2020 21:57:54 -0400 Subject: [PATCH 40/54] wip --- docs/bugs.md | 18 +++++++ netharn/hyperparams.py | 49 +++++++++++++++++++ .../initializers/_nx_ext/balanced_sequence.py | 7 +++ .../initializers/_nx_ext/tree_embedding.py | 2 +- netharn/initializers/functional.py | 45 +++++++++++++++-- 5 files changed, 117 insertions(+), 4 deletions(-) diff --git a/docs/bugs.md b/docs/bugs.md index 0e6f1cd..cfb77be 100644 --- a/docs/bugs.md +++ b/docs/bugs.md @@ -4,3 +4,21 @@ * The per-batch iteration metrics seem to jump on the x-axis in the tensorboard logs. Not sure why this is. Perhaps there is a scheduler bug? + + +* If PyQt5 is installed and there is a problem with the matplotlib qt backend + then you may just get an error that crashes the system: + + ``` + QObject::moveToThread: Current thread (0x5636e99e0690) is not the object's thread (0x5636ea1e26b0). + Cannot move to target thread (0x5636e99e0690) + + qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "$HOME/.local/conda/envs/py38/lib/python3.8/site-packages/cv2/qt/plugins" even though it was found. + This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem. + + Available platform plugins are: xcb, eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, wayland-egl, wayland, wayland-xcomposite-egl, wayland-xcomposite-glx, webgl. + +``` + +The workaround is to uninstall PyQt5, but that's not great. Need to detect that +this will happen before it does so we can warn and avoid it. diff --git a/netharn/hyperparams.py b/netharn/hyperparams.py index 740eaff..71ae294 100644 --- a/netharn/hyperparams.py +++ b/netharn/hyperparams.py @@ -906,6 +906,9 @@ class HyperParams(object): temp_initializer = hyper.make_initializer() init_history = temp_initializer.history() + # TODO: software versions + + train_info = ub.odict([ ('train_hashid', train_hashid), @@ -1004,6 +1007,52 @@ class HyperParams(object): }) return hyper + +def module_version_infos(): + """ + + References: + https://packaging.python.org/guides/single-sourcing-package-version/ + """ + try: + from importlib import metadata + except ImportError: + # Running on pre-3.8 Python; use importlib-metadata package + import importlib_metadata as metadata + import sys + modnames = ['torch', 'cv2', 'netharn', 'PIL', 'numpy'] + infos = [] + for modname in modnames: + info = {'name': modname} + + try: + module = sys.modules[modname] + version_0 = getattr(module, '__version__', None) + except Exception: + version_0 = None + + try: + version_1 = metadata.version(modname) + except Exception: + version_1 = None + + possible_versions = {version_1, version_0} - {None} + if len(possible_versions) == 1: + info['version'] = ub.peek(possible_versions) + else: + info['possible_versions'] = possible_versions + + if modname == 'torch': + info['torch.version.cuda'] = torch.version.cuda + info['torch.cuda.is_available()'] = torch.cuda.is_available() + + infos.append(info) + + # The conda info step is too slow (3 seconds) + from netharn.util.collect_env import get_env_info + env_info = get_env_info()._asdict() + info['__env__'] = env_info + if __name__ == '__main__': r""" CommandLine: diff --git a/netharn/initializers/_nx_ext/balanced_sequence.py b/netharn/initializers/_nx_ext/balanced_sequence.py index 3ac524b..509b7c2 100644 --- a/netharn/initializers/_nx_ext/balanced_sequence.py +++ b/netharn/initializers/_nx_ext/balanced_sequence.py @@ -80,6 +80,13 @@ def longest_common_balanced_sequence( open_to_node = IdentityDict() full_seq1 = seq1 full_seq2 = seq2 + if impl == 'auto': + if _cython_lcs_backend(): + impl = 'iter-alt2-cython' + else: + impl = 'iter-alt2' + print('impl = {!r}'.format(impl)) + if impl == 'recurse': _memo = {} _seq_memo = {} diff --git a/netharn/initializers/_nx_ext/tree_embedding.py b/netharn/initializers/_nx_ext/tree_embedding.py index faac200..0374c70 100644 --- a/netharn/initializers/_nx_ext/tree_embedding.py +++ b/netharn/initializers/_nx_ext/tree_embedding.py @@ -7,7 +7,7 @@ from .balanced_sequence import longest_common_balanced_sequence, UnbalancedExcep def maximum_common_ordered_tree_embedding( - tree1, tree2, node_affinity='auto', impl='iter-alt2', mode='chr'): + tree1, tree2, node_affinity='auto', impl='auto', mode='chr'): """ Finds the maximum common subtree-embedding between two ordered trees. diff --git a/netharn/initializers/functional.py b/netharn/initializers/functional.py index 0d8ff87..e261f14 100644 --- a/netharn/initializers/functional.py +++ b/netharn/initializers/functional.py @@ -343,7 +343,43 @@ def load_partial_state(model, model_state_dict, leftover=None, # I believe this is the correct way to solve the problem paths1 = sorted(other_keys) paths2 = sorted(self_state) - subpaths1, subpaths2 = maximum_common_ordered_subpaths(paths1, paths2) + + if 1: + # hack to filter to reduce tree size in embedding problem + def shrink_paths(paths): + new_paths = [] + for p in paths: + p = p.replace('.0', ':0') + p = p.replace('.1', ':1') + p = p.replace('.2', ':2') + p = p.replace('.3', ':3') + p = p.replace('.4', ':4') + p = p.replace('.5', ':5') + p = p.replace('.6', ':6') + p = p.replace('.7', ':7') + p = p.replace('.8', ':8') + p = p.replace('.9', ':9') + p = p.replace('.weight', ':weight') + p = p.replace('.bias', ':bias') + p = p.replace('.num_batches_tracked', ':num_batches_tracked') + p = p.replace('.running_mean', ':running_mean') + p = p.replace('.running_var', ':running_var') + p = p.replace('.conv1', ':conv1') + p = p.replace('.conv2', ':conv2') + p = p.replace('.conv3', ':conv3') + p = p.replace('.bn1', ':bn1') + p = p.replace('.bn2', ':bn2') + p = p.replace('.bn3', ':bn3') + new_paths.append(p) + return new_paths + + paths1_ = shrink_paths(paths1) + paths2_ = shrink_paths(paths2) + + # Reducing the depth saves a lot of time + subpaths1, subpaths2 = maximum_common_ordered_subpaths(paths1_, paths2_, sep='.') + subpaths1 = [p.replace(':', '.') for p in subpaths1] + subpaths2 = [p.replace(':', '.') for p in subpaths2] mapping = ub.dzip(subpaths1, subpaths2) if verbose > 1: print('mapping = {}'.format(ub.repr2(mapping, nl=1))) @@ -710,8 +746,11 @@ def maximum_common_ordered_subpaths(paths1, paths2, sep='.'): tree1 = paths_to_tree(paths1) tree2 = paths_to_tree(paths2) - # _print_forest(tree1) - # _print_forest(tree2) + # from netharn.initializers._nx_ext.tree_embedding import forest_str + print(len(tree1.nodes)) + print(len(tree2.nodes)) + # print(forest_str(tree1)) + # print(forest_str(tree2)) # if 0: # DiGM = isomorphism.DiGraphMatcher(tree1, tree2) -- GitLab From 2393e8c1b0c0d9b287ef37e3d0b883d93e1d50e3 Mon Sep 17 00:00:00 2001 From: joncrall Date: Thu, 15 Oct 2020 21:58:07 -0400 Subject: [PATCH 41/54] wip --- netharn/initializers/_nx_ext/balanced_sequence.py | 1 - 1 file changed, 1 deletion(-) diff --git a/netharn/initializers/_nx_ext/balanced_sequence.py b/netharn/initializers/_nx_ext/balanced_sequence.py index 509b7c2..576bdda 100644 --- a/netharn/initializers/_nx_ext/balanced_sequence.py +++ b/netharn/initializers/_nx_ext/balanced_sequence.py @@ -85,7 +85,6 @@ def longest_common_balanced_sequence( impl = 'iter-alt2-cython' else: impl = 'iter-alt2' - print('impl = {!r}'.format(impl)) if impl == 'recurse': _memo = {} -- GitLab From 5b6090a1f743cbec74ae18289620e22a3a1ed60a Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 16 Oct 2020 17:00:10 -0400 Subject: [PATCH 42/54] wip --- netharn/api.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/netharn/api.py b/netharn/api.py index aa4809a..0ee6de3 100644 --- a/netharn/api.py +++ b/netharn/api.py @@ -460,27 +460,27 @@ class Optimizer(object): }) else: from netharn.util import util_inspect + + _lut = {} + try: import torch_optimizer except Exception: torch_optimizer = None - - _lut = {} - - if torch_optimizer is not None: - # known = ['AccSGD', 'AdaBound', 'AdaMod', 'DiffGrad', 'Lamb', - # 'Lookahead', 'NovoGrad', 'RAdam', 'SGDW', 'Yogi'] - # if 0: - # for key in known: - # cls = getattr(torch_optimizer, key, None) - # print('cls = {!r}'.format(cls)) - # defaultkw = util_inspect.default_kwargs(cls) - # print('defaultkw = {!r}'.format(defaultkw)) - # _lut.update({k.lower(): k for k in known}) + else: _lut.update({ k: c.__name__ for k, c in torch_optimizer._NAME_OPTIM_MAP.items()}) + try: + import adabelief_pytorch + except Exception: + adabelief_pytorch = None + else: + _lut.update({ + 'AdaBelief': adabelief_pytorch.AdaBelief + }) + _lut.update({ k.lower(): k for k in dir(torch.optim) if not k.startswith('_')}) -- GitLab From ca56aec3c80b63e8c7cb66fe1b62418de1160859 Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 16 Oct 2020 17:06:01 -0400 Subject: [PATCH 43/54] wip --- netharn/api.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/netharn/api.py b/netharn/api.py index 0ee6de3..d368bb7 100644 --- a/netharn/api.py +++ b/netharn/api.py @@ -473,6 +473,9 @@ class Optimizer(object): for k, c in torch_optimizer._NAME_OPTIM_MAP.items()}) try: + """ + pip install adabelief_pytorch + """ import adabelief_pytorch except Exception: adabelief_pytorch = None -- GitLab From 78aa3872cb8b60696a4802bbad192c00faebe889 Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 16 Oct 2020 17:10:20 -0400 Subject: [PATCH 44/54] wip --- netharn/api.py | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/netharn/api.py b/netharn/api.py index d368bb7..69a3031 100644 --- a/netharn/api.py +++ b/netharn/api.py @@ -460,28 +460,37 @@ class Optimizer(object): }) else: from netharn.util import util_inspect - _lut = {} + optim_modules = [ + torch.optim, + ] + try: import torch_optimizer except Exception: torch_optimizer = None else: + optim_modules.append(torch_optimizer) _lut.update({ - k: c.__name__ + k.lower(): c.__name__ for k, c in torch_optimizer._NAME_OPTIM_MAP.items()}) try: """ pip install adabelief_pytorch + python -c "import adabelief_pytorch; adabelief_pytorch.AdaBelief" """ import adabelief_pytorch except Exception: adabelief_pytorch = None else: + optim_modules.append(adabelief_pytorch) _lut.update({ - 'AdaBelief': adabelief_pytorch.AdaBelief + cls.__name__.lower(): cls + for cls in [ + adabelief_pytorch.AdaBelief, + ] }) _lut.update({ @@ -490,23 +499,18 @@ class Optimizer(object): key = _lut[key] - cls = getattr(torch.optim, key, None) - if cls is not None: - defaultkw = util_inspect.default_kwargs(cls) - kw = defaultkw.copy() - kw.update() - optim_ = (cls, kw) - else: - if torch_optimizer is None: - raise KeyError(key) - cls = getattr(torch_optimizer, key, None) + cls = None + for module in optim_modules: + cls = getattr(module, key, None) if cls is not None: defaultkw = util_inspect.default_kwargs(cls) kw = defaultkw.copy() kw.update() optim_ = (cls, kw) - else: - raise KeyError(key) + break + + if cls is None: + raise KeyError(key) return optim_ -- GitLab From bb37e125ef6490829409031151df61e93b4d91ad Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 16 Oct 2020 17:10:59 -0400 Subject: [PATCH 45/54] wip --- netharn/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netharn/api.py b/netharn/api.py index 69a3031..f5ffbdb 100644 --- a/netharn/api.py +++ b/netharn/api.py @@ -487,7 +487,7 @@ class Optimizer(object): else: optim_modules.append(adabelief_pytorch) _lut.update({ - cls.__name__.lower(): cls + cls.__name__.lower(): cls.__name__ for cls in [ adabelief_pytorch.AdaBelief, ] -- GitLab From dacd38ee8b27639ddb58c7ad3226e7ff0bc7524f Mon Sep 17 00:00:00 2001 From: joncrall Date: Wed, 21 Oct 2020 13:11:55 -0400 Subject: [PATCH 46/54] Update readme, tweaks to nx_ext, IndexableWalker fixes, data container helpers --- CHANGELOG.md | 4 + README.rst | 11 ++ netharn/data/data_containers.py | 65 ++++++- .../initializers/_nx_ext/tree_embedding.py | 172 +++++++++++------- netharn/initializers/functional.py | 31 ++++ netharn/util/util_json.py | 14 +- requirements/optional.txt | 1 + 7 files changed, 219 insertions(+), 79 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0aa0eed..28b2527 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm * `allow_unicode` option to `FitHarnPreferences`, which can be set to False to disable utf8 characters in output formatting. +* `IndexableWalker` in `netharn.util.util_json` (also exists in kwcoco) + +* New helper methods in `data_containers.BatchContainer` + ### Fixed * Typo: directory `explit_checkpoints` renamed to `explicit_checkpoints`. diff --git a/README.rst b/README.rst index a0c4787..7671bfc 100644 --- a/README.rst +++ b/README.rst @@ -577,6 +577,17 @@ then it would produce this more detailed description of what it was doing: INFO: wrote single-file deployment to: '/home/joncrall/.cache/netharn/demo/fit/runs/demo/lnejaaum/deploy_ToyNet2d_lnejaaum_000_JWPNDC.zip' INFO: exiting fit harness. +Related Packages +================ + +pytorch-lightning (https://github.com/PyTorchLightning/pytorch-lightning) has +very similar goals to netharn. Currently, there are strengths and weaknesses to +both, but in the future I do see one consuming functionality of the other. +Currently (2020-10-21), pytorch-lightning does distributed training better, +whereas netharn's logging and hyperparameter management outshines +pytorch-lightning. + + .. |Pypi| image:: https://img.shields.io/pypi/v/netharn.svg :target: https://pypi.python.org/pypi/netharn diff --git a/netharn/data/data_containers.py b/netharn/data/data_containers.py index 2307900..3a733a7 100644 --- a/netharn/data/data_containers.py +++ b/netharn/data/data_containers.py @@ -54,16 +54,16 @@ class BatchContainer(ub.NiceRepr): outputs or a set of items that have already been collated. Attributes: - data (List): Unlike ItemContainer, data is always a list where - len(data) is the number of devices this batch will run on. - Each item in the list may be either a pre-batched Tensor (in the - case where the each item in the batch has the same shape) or a list - of individual item Tensors (in the case where different batch items + data (List[Any]): Unlike ItemContainer, data is always a list where + len(data) is the number of devices this batch will run on. Each + item in the list may be either a pre-batched Tensor (in the case + where the each item in the batch has the same shape) or a list of + individual item Tensors (in the case where different batch items may have different shapes). """ def __init__(self, data, stack=False, padding_value=-1, cpu_only=False, pad_dims=2): - self.data = data + self.data = data # type: list self.meta = { 'stack': stack, 'padding_value': padding_value, @@ -71,9 +71,45 @@ class BatchContainer(ub.NiceRepr): 'pad_dims': pad_dims, } + @property + def nestshape(self): + return nestshape(self.data) + + def numel(self): + """ + The number of scalar elements held by this container + """ + shapes = self.nestshape + total = sum([np.prod(s) for s in shapes]) + return total + + @property + def packshape(self): + """ + The shape of this data if it was packed + """ + # shape = np.maximum.reduce(self.nestshape) + # return shape + dim = 0 + if self.stack: + # Should be a straight forward concatenation + shapes = [d.shape for d in self.data] + max_shape = np.maximum.reduce(shapes) # should all be the same here + stacked_dim = sum([s[dim] for s in shapes]) + max_shape[dim] = stacked_dim + pack_shape = tuple(max_shape.tolist()) + return pack_shape + else: + shapes = nestshape(self.data) + max_shape = np.maximum.reduce(shapes) + stacked_dim = sum([s[dim] for s in shapes]) + max_shape[dim] = stacked_dim + pack_shape = tuple(max_shape.tolist()) + return pack_shape + def __nice__(self): try: - shape_repr = ub.repr2(nestshape(self.data), nl=-2) + shape_repr = ub.repr2(self.nestshape, nl=-2) return 'nestshape(data)={}'.format(shape_repr) except Exception: return super().__repr__() @@ -183,13 +219,16 @@ class ItemContainer(ub.NiceRepr): 'pad_dims': pad_dims, } + @property + def nestshape(self): + return nestshape(self.data) + def __nice__(self): try: - shape_repr = ub.repr2(nestshape(self.data), nl=-2) + shape_repr = ub.repr2(self.nestshape, nl=-2) return 'nestshape(data)={}'.format(shape_repr) except Exception: return super().__repr__() - # return 'nestshape(data)={}, **{}'.format(shape_repr, ub.repr2(self.meta, nl=0)) @classmethod def demo(cls, key='img', rng=None, **kwargs): @@ -868,6 +907,14 @@ class ContainerXPU(XPU): def nestshape(data): + """ + Examine nested shape of the data + + Example: + >>> data = [np.arange(10), np.arange(13)] + >>> nestshape(data) + [(10,), (13,)] + """ import ubelt as ub def _recurse(d): diff --git a/netharn/initializers/_nx_ext/tree_embedding.py b/netharn/initializers/_nx_ext/tree_embedding.py index 0374c70..9978eb7 100644 --- a/netharn/initializers/_nx_ext/tree_embedding.py +++ b/netharn/initializers/_nx_ext/tree_embedding.py @@ -77,14 +77,14 @@ def maximum_common_ordered_tree_embedding( >>> tree1 = random_ordered_tree(7, seed=3257073545741117277206611) >>> tree2 = random_ordered_tree(7, seed=123568587133124688238689717) >>> print('tree1') - >>> forest_str(tree1, eager=1) + >>> forest_str(tree1, write=print) >>> print('tree2') - >>> forest_str(tree2, eager=1) + >>> forest_str(tree2, write=print) >>> embedding1, embedding2 = maximum_common_ordered_tree_embedding(tree1, tree2 ) >>> print('embedding1') - >>> forest_str(embedding1, eager=1) + >>> forest_str(embedding1, write=print) >>> print('embedding2') - >>> forest_str(embedding2, eager=1) + >>> forest_str(embedding2, write=print) tree1 └── 1 ├── 6 @@ -405,101 +405,147 @@ def invert_dict(dict_, unique_vals=True): return inverted -def forest_str(graph, eager=False, write=None, use_labels=True): +def forest_str(graph, use_labels=True, sources=None, write=None): """ Creates a nice utf8 representation of a directed forest Parameters ---------- - graph : nx.DiGraph - graph to represent (must be a tree, forest, or the empty graph) + graph : nx.DiGraph | nx.Graph + Graph to represent (must be a tree, forest, or the empty graph) - eager : bool - if True, the text will be written directly to stdout or the write - function if specified + use_labels : bool + If True will use the "label" attribute of a node to display if it + exists otherwise it will use the node value itself. Defaults to True. - write : callable - function to use to write to, if None new lines are appended to - a list and returned + sources : List + Mainly relevant for undirected forests, specifies which nodes to list + first. If unspecified the root nodes of each tree will be used for + directed forests; for undirected forests this defaults to the nodes + with the smallest degree. - use_labels : bool - if True will use the "label" attribute of a node to display if it - exists otherwise it will use the node value itself. + write : callable + Function to use to write to, if None new lines are appended to + a list and returned. If set to the `print` function, lines will + be written to stdout as they are generated. If specified, + this function will return None. Defaults to None. Returns ------- - str : + str | None : utf8 representation of the tree / forest - TODO - ---- - - [ ] Is this a generally useful utility? - Example ------- >>> import networkx as nx >>> graph = nx.balanced_tree(r=2, h=3, create_using=nx.DiGraph) >>> print(forest_str(graph)) - └── 0 - ├── 2 - │   ├── 6 - │   │   ├── 14 - │   │   └── 13 - │   └── 5 - │   ├── 12 - │   └── 11 - └── 1 - ├── 4 - │   ├── 10 - │   └── 9 - └── 3 - ├── 8 - └── 7 + ╙── 0 + ├─╼ 2 + │   ├─╼ 6 + │   │   ├─╼ 14 + │   │   └─╼ 13 + │   └─╼ 5 + │   ├─╼ 12 + │   └─╼ 11 + └─╼ 1 + ├─╼ 4 + │   ├─╼ 10 + │   └─╼ 9 + └─╼ 3 + ├─╼ 8 + └─╼ 7 + + >>> graph = nx.balanced_tree(r=1, h=2, create_using=nx.Graph) + >>> print(nx.forest_str(graph)) + ╟── 1 + ╎   ├── 2 + ╎   └── 0 """ + import networkx as nx + printbuf = [] - if eager: - if write is None: - lazyprint = print - else: - lazyprint = write + if write is None: + _write = printbuf.append else: - lazyprint = printbuf.append + _write = write if len(graph.nodes) == 0: - lazyprint('') + _write("╙") else: - assert nx.is_forest(graph) - sources = [n for n in graph.nodes if graph.in_degree[n] == 0] + if not nx.is_forest(graph): + raise nx.NetworkXNotImplemented("input must be a forest or the empty graph") + + is_directed = graph.is_directed() + succ = graph.succ if is_directed else graph.adj + if sources is None: + if is_directed: + # use real source nodes for directed trees + sources = [n for n in graph.nodes if graph.in_degree[n] == 0] + else: + # use arbitrary sources for undirected trees + sources = sorted(graph.nodes, key=lambda n: graph.degree[n]) + + seen = set() stack = [] for idx, node in enumerate(sources): - # islast_next = (idx == len(sources)) - islast_next = (idx == 0) - stack.append((node, '', islast_next)) + islast_next = idx == 0 + stack.append((node, "", islast_next)) while stack: node, indent, islast = stack.pop() - if islast: - this_prefix = indent + '└── ' - next_prefix = indent + ' ' + if node in seen: + continue + seen.add(node) + + # Notes on available box and arrow characters + # https://en.wikipedia.org/wiki/Box-drawing_character + # https://stackoverflow.com/questions/2701192/triangle-arrow + if not indent: + # Top level items (i.e. trees in the forest) get different + # glyphs to indicate they are not actually connected + if islast: + this_prefix = indent + "╙── " + next_prefix = indent + " " + else: + this_prefix = indent + "╟── " + next_prefix = indent + "╎   " + else: - this_prefix = indent + '├── ' - next_prefix = indent + '│   ' - label = graph.nodes[node].get('label', node) + # For individual forests distinguish between directed and + # undirected cases + if is_directed: + if islast: + this_prefix = indent + "└─╼ " + next_prefix = indent + " " + else: + this_prefix = indent + "├─╼ " + next_prefix = indent + "│   " + else: + if islast: + this_prefix = indent + "└── " + next_prefix = indent + " " + else: + this_prefix = indent + "├── " + next_prefix = indent + "│   " + + if use_labels: + label = graph.nodes[node].get("label", node) + else: + label = node + + _write(this_prefix + str(label)) - lazyprint(this_prefix + str(label)) - graph.succ[node] - children = graph.succ[node] + children = [child for child in succ[node] if child not in seen] for idx, child in enumerate(children, start=1): - # islast_next = (idx == len(children)) - islast_next = (idx <= 1) + islast_next = idx <= 1 try_frame = (child, next_prefix, islast_next) stack.append(try_frame) - if printbuf: - return '\n'.join(printbuf) - else: - return '' + if write is None: + # Only return a string if the custom write function was not specified + return "\n".join(printbuf) if __name__ == '__main__': diff --git a/netharn/initializers/functional.py b/netharn/initializers/functional.py index e261f14..c5599dd 100644 --- a/netharn/initializers/functional.py +++ b/netharn/initializers/functional.py @@ -300,6 +300,37 @@ def load_partial_state(model, model_state_dict, leftover=None, """ other_keys = set(model_state_dict) self_keys = set(self_state) + + if 0: + # Automatic way to reduce nodes in the trees? + # If node b always follows node a, can we contract it? + nodes1 = [n for p in other_keys for n in p.split('.')] + nodes2 = [n for p in self_keys for n in p.split('.')] + tups1 = list(tup for key in other_keys for tup in ub.iter_window(key.split('.'), 2)) + tups2 = list(tup for key in self_keys for tup in ub.iter_window(key.split('.'), 2)) + x = ub.ddict(list) + for a, b in tups1: + x[a].append(b) + for a, b in tups2: + x[a].append(b) + + nodehist = ub.dict_hist(nodes1 + nodes2) + + for k, v in x.items(): + print('----') + print(k) + print(nodehist[k]) + follow_hist = ub.dict_hist(v) + print(follow_hist) + total = sum(follow_hist.values()) + if ub.allsame(follow_hist.values()) and total == nodehist[k]: + print('CONTRACT') + + # pair_freq = ub.dict_hist(ub.flatten([tups1, tups2])) + from netharn.initializers._nx_ext.tree_embedding import forest_str + from netharn.initializers._nx_ext.path_embedding import paths_to_otree + print(forest_str(paths_to_otree(other_keys, '.'))) + common_keys = other_keys.intersection(self_keys) if not common_keys: if association == 'strict': diff --git a/netharn/util/util_json.py b/netharn/util/util_json.py index ea4091a..f5c38af 100644 --- a/netharn/util/util_json.py +++ b/netharn/util/util_json.py @@ -345,11 +345,11 @@ class IndexableWalker(Generator): # If the value at this path is also indexable, then continue # the traversal, unless the False message was explicitly sent # by the caller. - if isinstance(value, self.indexable_cls): - if message is False: - # Because the `send` method will return the next value, - # we yield a dummy value so we don't clobber the next - # item in the traversal. - yield None - else: + if message is False: + # Because the `send` method will return the next value, + # we yield a dummy value so we don't clobber the next + # item in the traversal. + yield None + else: + if isinstance(value, self.indexable_cls): stack.append((value, path)) diff --git a/requirements/optional.txt b/requirements/optional.txt index 2a8035b..b8adb76 100644 --- a/requirements/optional.txt +++ b/requirements/optional.txt @@ -23,3 +23,4 @@ kwcoco >= 0.1.0 colormath torch-optimizer >= 0.0.1a9 ;python_version>='3.6' +adabelief_pytorch -- GitLab From cc88bcc7c2ae9a184ad8326f964850cb1100248b Mon Sep 17 00:00:00 2001 From: joncrall Date: Wed, 21 Oct 2020 20:03:22 -0400 Subject: [PATCH 47/54] ChannelSpec helpers --- netharn/data/channel_spec.py | 176 ++++++++++++++++++++++++++++++++++- 1 file changed, 173 insertions(+), 3 deletions(-) diff --git a/netharn/data/channel_spec.py b/netharn/data/channel_spec.py index 08e2f21..3f1c5f9 100644 --- a/netharn/data/channel_spec.py +++ b/netharn/data/channel_spec.py @@ -166,6 +166,46 @@ class ChannelSpec(ub.NiceRepr): for spec in stream_specs: yield spec + def streams(self): + """ + Breaks this spec up into one spec for each early-fused input stream + """ + streams = [self.__class__(spec) for spec in self.keys()] + return streams + + def difference(self, other): + """ + Set difference + + Example: + >>> self = ChannelSpec('rgb|disparity,flowx|flowy') + >>> other = ChannelSpec('rgb') + >>> self.difference(other) + >>> other = ChannelSpec('flowx') + >>> self.difference(other) + """ + assert len(list(other.keys())) == 1, 'can take diff with one stream' + other_norm = ub.oset(ub.peek(other.normalize().values())) + self_norm = self.normalize() + + new_streams = [] + for key, parts in self_norm.items(): + new_parts = ub.oset(parts) - ub.oset(other_norm) + # shrink the representation of a complex r|g|b to an alias if + # possible. + # TODO: make this more efficient + for alias, alias_spec in self._known.items(): + alias_parts = ub.oset(alias_spec.split('|')) + index = subsequence_index(new_parts, alias_parts) + if index is not None: + oset_delitem(new_parts, index) + oset_insert(new_parts, index.start, alias) + new_stream = '|'.join(new_parts) + new_streams.append(new_stream) + new_spec = ','.join(new_streams) + new = self.__class__(new_spec) + return new + def sizes(self): """ Number of dimensions for each fused stream channel @@ -244,12 +284,12 @@ class ChannelSpec(ub.NiceRepr): stream. Args: - item (dict): a batch item + item (Dict[str, Tensor]): a batch item containing unfused parts axis (int, default=0): concatenation dimension Returns: - Dict[str, Tensor]: mapping between input stream and its early fused - tensor input. + Dict[str, Tensor]: + mapping between input stream and its early fused tensor input. Example: >>> import torch @@ -284,6 +324,9 @@ class ChannelSpec(ub.NiceRepr): """ break an early fused item into its components + Args: + inputs (Dict[str, Tensor]): dictionary of components + Example: >>> import torch >>> dims = (4, 4) @@ -313,6 +356,133 @@ class ChannelSpec(ub.NiceRepr): idx1 = idx2 return components + def component_indices(self, axis=2): + """ + Look up component indices within fused streams + + Example: + >>> import torch + >>> dims = (4, 4) + >>> inputs = ['flowx', 'flowy', 'disparity'] + >>> self = ChannelSpec('disparity,flowx|flowy') + >>> inputs = self.component_indices(components) + >>> from netharn.data import data_containers + >>> item = {k: data_containers.ItemContainer(v, stack=True) + >>> for k, v in inputs.items()} + >>> batch = data_containers.container_collate([item, item]) + >>> components = self.decode(batch) + """ + parsed = self.parse() + component_indices = dict() + for key, parts in parsed.items(): + idx1 = 0 + for part in parts: + size = self._size_lut.get(part, 1) + idx2 = idx1 + size + index = ([slice(None)] * axis + [slice(idx1, idx2)]) + idx1 = idx2 + component_indices[part] = (key, index) + return component_indices + + +def subsequence_index(oset1, oset2): + """ + Returns a slice into the first items indicating the position of + the second items if they exist. + + This is a variant of the substring problem. + + Returns: + None | slice + + Example: + >>> oset1 = ub.oset([1, 2, 3, 4, 5, 6]) + >>> oset2 = ub.oset([2, 3, 4]) + >>> index = subsequence_index(oset1, oset2) + >>> assert index + + >>> oset1 = ub.oset([1, 2, 3, 4, 5, 6]) + >>> oset2 = ub.oset([2, 4, 3]) + >>> index = subsequence_index(oset1, oset2) + >>> assert not index + """ + if len(oset2) == 0: + base = 0 + else: + item1 = oset2[0] + try: + base = oset1.index(item1) + except (IndexError, KeyError): + base = None + + index = None + if base is not None: + sl = slice(base, base + len(oset2)) + subset = oset1[sl] + if subset == oset2: + index = sl + return index + + +def oset_insert(self, index, obj): + """ + self = ub.oset() + oset_insert(self, 0, 'a') + oset_insert(self, 0, 'b') + oset_insert(self, 0, 'c') + oset_insert(self, 1, 'd') + oset_insert(self, 2, 'e') + oset_insert(self, 0, 'f') + """ + if obj not in self: + # Bump index of every item after the insert position + for key in self.items[index:]: + self.map[key] = self.map[key] + 1 + self.items.insert(index, obj) + self.map[obj] = index + + +def oset_delitem(self, index): + """ + for ubelt oset, todo contribute back to luminosoinsight + + >>> self = ub.oset([1, 2, 3, 4, 5, 6, 7, 8, 9]) + >>> index = slice(3, 5) + >>> oset_delitem(self, index) + + self = ub.oset(['r', 'g', 'b', 'disparity']) + index = slice(0, 3) + oset_delitem(self, index) + + """ + if isinstance(index, slice) and index == ub.orderedset.SLICE_ALL: + self.clear() + else: + if ub.orderedset.is_iterable(index): + to_remove = [self.items[i] for i in index] + elif isinstance(index, slice) or hasattr(index, "__index__"): + to_remove = self.items[index] + else: + raise TypeError("Don't know how to index an OrderedSet by %r" % index) + + if isinstance(to_remove, list): + # Modified version of discard slightly more efficient for multiple + # items + remove_idxs = sorted([self.map[key] for key in to_remove], reverse=True) + + for key in to_remove: + del self.map[key] + + for idx in remove_idxs: + del self.items[idx] + + for k, v in self.map.items(): + # I think there is a more efficient way to do this? + num_after = sum(v >= i for i in remove_idxs) + if num_after: + self.map[k] = v - num_after + else: + self.discard(to_remove) if __name__ == '__main__': """ -- GitLab From ecca307b02eceb438d70440fd27f530ca5c3678e Mon Sep 17 00:00:00 2001 From: joncrall Date: Thu, 22 Oct 2020 09:34:32 -0400 Subject: [PATCH 48/54] Fix tests --- netharn/api.py | 2 +- netharn/data/channel_spec.py | 8 ++----- netharn/examples/style_transfer_orig.py | 1 + netharn/export/__init__.py | 4 ++-- netharn/fit_harn.py | 32 ++++++++++++++++++------- netharn/util/util_json.py | 2 -- 6 files changed, 30 insertions(+), 19 deletions(-) diff --git a/netharn/api.py b/netharn/api.py index f5ffbdb..b1edea8 100644 --- a/netharn/api.py +++ b/netharn/api.py @@ -307,7 +307,7 @@ class Initializer(object): >>> print(ub.repr2(nh.Initializer.coerce(config))) ( , - {... 'fpath': '/fit/nice/untitled', 'leftover': None, 'mangle': True}, + {... 'fpath': '/fit/nice/untitled', 'leftover': None, 'mangle': False}, ) >>> print(ub.repr2(nh.Initializer.coerce({'init': 'kaiming_normal'}))) ( diff --git a/netharn/data/channel_spec.py b/netharn/data/channel_spec.py index 3f1c5f9..06f653d 100644 --- a/netharn/data/channel_spec.py +++ b/netharn/data/channel_spec.py @@ -365,12 +365,8 @@ class ChannelSpec(ub.NiceRepr): >>> dims = (4, 4) >>> inputs = ['flowx', 'flowy', 'disparity'] >>> self = ChannelSpec('disparity,flowx|flowy') - >>> inputs = self.component_indices(components) - >>> from netharn.data import data_containers - >>> item = {k: data_containers.ItemContainer(v, stack=True) - >>> for k, v in inputs.items()} - >>> batch = data_containers.container_collate([item, item]) - >>> components = self.decode(batch) + >>> component_indices = self.component_indices() + >>> print('component_indices = {!r}'.format(component_indices)) """ parsed = self.parse() component_indices = dict() diff --git a/netharn/examples/style_transfer_orig.py b/netharn/examples/style_transfer_orig.py index ba87031..3ee7275 100644 --- a/netharn/examples/style_transfer_orig.py +++ b/netharn/examples/style_transfer_orig.py @@ -409,6 +409,7 @@ def train(): xdoctest -m /home/joncrall/code/netharn/netharn/examples/style_transfer.py train Example: + >>> # xdoctest: +SKIP >>> import sys, ubelt >>> sys.path.append(ubelt.expandpath('~/code/netharn')) >>> from netharn.examples.style_transfer import * # NOQA diff --git a/netharn/export/__init__.py b/netharn/export/__init__.py index 5e30c91..15794cc 100644 --- a/netharn/export/__init__.py +++ b/netharn/export/__init__.py @@ -25,7 +25,7 @@ CommandLine: xdoctest -m netharn.export __doc__:0 Example: - >>> # xdoc: +IGNORE_WANT + >>> # xdoctest: +IGNORE_WANT >>> # This example will train a small model and then deploy it. >>> import netharn as nh >>> import ubelt as ub @@ -131,7 +131,7 @@ Example: >>> # This model is now loaded with the corret weights. >>> # You can use it as normal. >>> model.eval() - >>> images = harn._demo_batch(0)['input'][0:1] + >>> images = harn._demo_batch(0)[0][0:1] >>> outputs = model(images) >>> print('outputs = {!r}'.format(outputs)) >>> # Not that the loaded model is independent of harn.model diff --git a/netharn/fit_harn.py b/netharn/fit_harn.py index b4a243d..b5d3f42 100644 --- a/netharn/fit_harn.py +++ b/netharn/fit_harn.py @@ -2333,7 +2333,11 @@ class CoreCallbacks(object): """ Basic connection inputs -> model -> outputs -> criterion -> loss - Overload Encouraged, but not always necessary + This is the meat and potatoes of your deep learning algorithm, + everything else is boilerplate. You define how to pass your inputs into + your model and then compute your loss here. We provide a default + implementation that will work for basic tasks as long as the model and + loss are well defined, but you will typically need to overload this. Note: You may return loss as a flat dictionary mapping string keys to @@ -2341,22 +2345,35 @@ class CoreCallbacks(object): and each loss component will be automatically logged. Args: - batch (object): the current batch + batch (object): the current batch as generated by the data loader. + Note: use :func:`ExtraMixins.._demo_batch` (i.e. + ``harn._demo_batch()``) to generate an example batch for + interactive / testing / other usage. Returns: - Tuple[object, Tensor|Dict]: (outputs, loss) + Tuple[object, Tensor|Dict]: + tuple containing: + outputs - whatever the output of the model was + loss - either a single scalar loss or a dictionary of + scalar losses (the harness use the keys as labels to + track different losses). """ # Simple forward prop and loss computation try: if isinstance(batch, dict): + # The extensible case where your batch is a dictionary with + # keys "input" and "label", which themselves are usually + # dictionaries. outputs = harn.model(batch['input']) loss = harn.criterion(outputs, batch['label']) - elif isinstance(batch, tuple): + elif isinstance(batch, (tuple, list)) and len(batch) == 2: + # The "standard" non-extensible case you see in tutorials where + # items from the dataset are returned as a input / label tuple inputs, labels = batch - outputs = harn.model(*inputs) - loss = harn.criterion(outputs, *labels) + outputs = harn.model(inputs) + loss = harn.criterion(outputs, labels) else: - raise TypeError('Could not run batch') + raise TypeError('Could not run batch: {}'.format(type(batch))) except Exception: if harn.criterion: harn.error('You must overwrite run_batch if ' @@ -2604,7 +2621,6 @@ class FitHarn(ExtraMixins, InitializeMixin, ProgMixin, LogMixin, SnapshotMixin, monitors performance of the validation set. SeeAlso `netharn.monitor`. - Note: hyper is optional. If you choose not to specify it then you must overwrite harn._setup_modules and create the requires class instances diff --git a/netharn/util/util_json.py b/netharn/util/util_json.py index f5c38af..2347c2d 100644 --- a/netharn/util/util_json.py +++ b/netharn/util/util_json.py @@ -148,10 +148,8 @@ def ensure_json_serializable(dict_, normalize_containers=False, verbose=0): >>> data['foo']['b'] = (1, np.array([1, 2, 3]), {3: np.int(3), 4: np.float16(1.0)}) >>> dict_ = data >>> print(ub.repr2(data, nl=-1)) - >>> assert list(find_json_unserializable(data)) >>> result = ensure_json_serializable(data, normalize_containers=True) >>> print(ub.repr2(result, nl=-1)) - >>> assert not list(find_json_unserializable(result)) >>> assert type(result) is dict Example: -- GitLab From e22f54786fc158442fc4fbb78d5cb84dc78d35af Mon Sep 17 00:00:00 2001 From: joncrall Date: Thu, 22 Oct 2020 09:34:54 -0400 Subject: [PATCH 49/54] wip --- netharn/util/collect_env.py | 440 ++++++++++++++++++++++++++++++++++++ 1 file changed, 440 insertions(+) create mode 100644 netharn/util/collect_env.py diff --git a/netharn/util/collect_env.py b/netharn/util/collect_env.py new file mode 100644 index 0000000..f0bdee1 --- /dev/null +++ b/netharn/util/collect_env.py @@ -0,0 +1,440 @@ +""" +Adapted from +https://raw.githubusercontent.com/pytorch/pytorch/master/torch/utils/collect_env.py +""" +# This script outputs relevant system environment info +# Run it with `python collect_env.py`. +import locale +import re +import subprocess +import sys +import os +from collections import namedtuple + +import ubelt as ub +try: + from xdev import profile +except Exception: + profile = ub.profile + +try: + import torch + TORCH_AVAILABLE = True +except (ImportError, NameError, AttributeError): + TORCH_AVAILABLE = False + +# System Environment Information +SystemEnv = namedtuple('SystemEnv', [ + 'torch_version', + 'is_debug_build', + 'cuda_compiled_version', + 'gcc_version', + 'clang_version', + 'cmake_version', + 'os', + 'python_version', + 'is_cuda_available', + 'cuda_runtime_version', + 'nvidia_driver_version', + 'nvidia_gpu_models', + 'cudnn_version', + 'pip_version', # 'pip' or 'pip3' + 'pip_packages', + 'conda_packages', + 'hip_compiled_version', + 'hip_runtime_version', + 'miopen_runtime_version', +]) + + +def run(command): + """Returns (return-code, stdout, stderr)""" + p = subprocess.Popen(command, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, shell=True) + raw_output, raw_err = p.communicate() + rc = p.returncode + enc = locale.getpreferredencoding() + output = raw_output.decode(enc) + err = raw_err.decode(enc) + return rc, output.strip(), err.strip() + + +def run_and_read_all(run_lambda, command): + """Runs command using run_lambda; reads and returns entire output if rc is 0""" + rc, out, _ = run_lambda(command) + if rc != 0: + return None + return out + + +def run_and_parse_first_match(run_lambda, command, regex): + """Runs command using run_lambda, returns the first regex match if it exists""" + rc, out, _ = run_lambda(command) + if rc != 0: + return None + match = re.search(regex, out) + if match is None: + return None + return match.group(1) + + +@profile +def get_conda_packages(run_lambda): + # If we are not in cond do nothing + if os.path.exists(os.path.join(sys.prefix, 'conda-meta')): + if get_platform() == 'win32': + system_root = os.environ.get('SystemRoot', 'C:\\Windows') + findstr_cmd = os.path.join(system_root, 'System32', 'findstr') + grep_cmd = r'{} /R "torch numpy cudatoolkit soumith mkl magma"'.format(findstr_cmd) + else: + grep_cmd = r'grep "torch\|numpy\|cudatoolkit\|soumith\|mkl\|magma"' + conda = os.environ.get('CONDA_EXE', 'conda') + out = run_and_read_all(run_lambda, conda + ' list | ' + grep_cmd) + if out is not None: + # Comment starting at beginning of line + comment_regex = re.compile(r'^#.*\n') + return re.sub(comment_regex, '', out) + + +def get_gcc_version(run_lambda): + return run_and_parse_first_match(run_lambda, 'gcc --version', r'gcc (.*)') + + +def get_clang_version(run_lambda): + return run_and_parse_first_match(run_lambda, 'clang --version', r'clang version (.*)') + + +def get_cmake_version(run_lambda): + return run_and_parse_first_match(run_lambda, 'cmake --version', r'cmake (.*)') + + +def get_nvidia_driver_version(run_lambda): + if get_platform() == 'darwin': + cmd = 'kextstat | grep -i cuda' + return run_and_parse_first_match(run_lambda, cmd, + r'com[.]nvidia[.]CUDA [(](.*?)[)]') + smi = get_nvidia_smi() + return run_and_parse_first_match(run_lambda, smi, r'Driver Version: (.*?) ') + + +def get_gpu_info(run_lambda): + if get_platform() == 'darwin' or torch.version.hip is not None: + if TORCH_AVAILABLE and torch.cuda.is_available(): + return torch.cuda.get_device_name(None) + return None + smi = get_nvidia_smi() + uuid_regex = re.compile(r' \(UUID: .+?\)') + rc, out, _ = run_lambda(smi + ' -L') + if rc != 0: + return None + # Anonymize GPUs by removing their UUID + return re.sub(uuid_regex, '', out) + + +def get_running_cuda_version(run_lambda): + return run_and_parse_first_match(run_lambda, 'nvcc --version', r'V(.*)$') + + +def get_cudnn_version(run_lambda): + """This will return a list of libcudnn.so; it's hard to tell which one is being used""" + if get_platform() == 'win32': + system_root = os.environ.get('SystemRoot', 'C:\\Windows') + cuda_path = os.environ.get('CUDA_PATH', "%CUDA_PATH%") + where_cmd = os.path.join(system_root, 'System32', 'where') + cudnn_cmd = '{} /R "{}\\bin" cudnn*.dll'.format(where_cmd, cuda_path) + elif get_platform() == 'darwin': + # CUDA libraries and drivers can be found in /usr/local/cuda/. See + # https://docs.nvidia.com/cuda/cuda-installation-guide-mac-os-x/index.html#install + # https://docs.nvidia.com/deeplearning/sdk/cudnn-install/index.html#installmac + # Use CUDNN_LIBRARY when cudnn library is installed elsewhere. + cudnn_cmd = 'ls /usr/local/cuda/lib/libcudnn*' + else: + cudnn_cmd = 'ldconfig -p | grep libcudnn | rev | cut -d" " -f1 | rev' + rc, out, _ = run_lambda(cudnn_cmd) + # find will return 1 if there are permission errors or if not found + if len(out) == 0 or (rc != 1 and rc != 0): + lib = os.environ.get('CUDNN_LIBRARY') + if lib is not None and os.path.isfile(lib): + return os.path.realpath(lib) + return None + files_set = set() + for fn in out.split('\n'): + fn = os.path.realpath(fn) # eliminate symbolic links + if os.path.isfile(fn): + files_set.add(fn) + if not files_set: + return None + # Alphabetize the result because the order is non-deterministic otherwise + files = list(sorted(files_set)) + if len(files) == 1: + return files[0] + result = '\n'.join(files) + return 'Probably one of the following:\n{}'.format(result) + + +def get_nvidia_smi(): + # Note: nvidia-smi is currently available only on Windows and Linux + smi = 'nvidia-smi' + if get_platform() == 'win32': + smi = '"C:\\Program Files\\NVIDIA Corporation\\NVSMI\\%s"' % smi + return smi + + +def get_platform(): + if sys.platform.startswith('linux'): + return 'linux' + elif sys.platform.startswith('win32'): + return 'win32' + elif sys.platform.startswith('cygwin'): + return 'cygwin' + elif sys.platform.startswith('darwin'): + return 'darwin' + else: + return sys.platform + + +def get_mac_version(run_lambda): + return run_and_parse_first_match(run_lambda, 'sw_vers -productVersion', r'(.*)') + + +def get_windows_version(run_lambda): + system_root = os.environ.get('SystemRoot', 'C:\\Windows') + wmic_cmd = os.path.join(system_root, 'System32', 'Wbem', 'wmic') + findstr_cmd = os.path.join(system_root, 'System32', 'findstr') + return run_and_read_all(run_lambda, '{} os get Caption | {} /v Caption'.format(wmic_cmd, findstr_cmd)) + + +def get_lsb_version(run_lambda): + return run_and_parse_first_match(run_lambda, 'lsb_release -a', r'Description:\t(.*)') + + +def check_release_file(run_lambda): + return run_and_parse_first_match(run_lambda, 'cat /etc/*-release', + r'PRETTY_NAME="(.*)"') + + +def get_os(run_lambda): + from platform import machine + platform = get_platform() + + if platform == 'win32' or platform == 'cygwin': + return get_windows_version(run_lambda) + + if platform == 'darwin': + version = get_mac_version(run_lambda) + if version is None: + return None + return 'Mac OSX {} ({})'.format(version, machine()) + + if platform == 'linux': + # Ubuntu/Debian based + desc = get_lsb_version(run_lambda) + if desc is not None: + return '{} ({})'.format(desc, machine()) + + # Try reading /etc/*-release + desc = check_release_file(run_lambda) + if desc is not None: + return '{} ({})'.format(desc, machine()) + + return '{} ({})'.format(platform, machine()) + + # Unknown platform + return platform + + +@profile +def get_pip_packages(run_lambda): + """Returns `pip list` output. Note: will also find conda-installed pytorch + and numpy packages.""" + + # MODIFICATION: just run with whatever python we are using + pip = sys.executable + ' -m pip' + + if get_platform() == 'win32': + system_root = os.environ.get('SystemRoot', 'C:\\Windows') + findstr_cmd = os.path.join(system_root, 'System32', 'findstr') + grep_cmd = r'{} /R "numpy torch"'.format(findstr_cmd) + else: + grep_cmd = r'grep "torch\|numpy"' + out = run_and_read_all(run_lambda, pip + ' list --format=freeze | ' + grep_cmd) + return 'pip', out + + +@profile +def get_env_info(): + run_lambda = run + + if TORCH_AVAILABLE: + version_str = torch.__version__ + debug_mode_str = str(torch.version.debug) + cuda_available_str = str(torch.cuda.is_available()) + cuda_version_str = torch.version.cuda + else: + version_str = debug_mode_str = cuda_available_str = cuda_version_str = 'N/A' + + if torch.version.hip is None: # cuda version + gpu_info = dict( + is_cuda_available=cuda_available_str, + cuda_compiled_version=cuda_version_str, + cuda_runtime_version=get_running_cuda_version(run_lambda), + nvidia_gpu_models=get_gpu_info(run_lambda), + nvidia_driver_version=get_nvidia_driver_version(run_lambda), + cudnn_version=get_cudnn_version(run_lambda), + hip_compiled_version='N/A', + hip_runtime_version='N/A', + miopen_runtime_version='N/A', + ) + else: # HIP version + cfg = torch._C._show_config().split('\n') + hip_runtime_version = [s.rsplit(None, 1)[-1] for s in cfg if 'HIP Runtime' in s][0] + miopen_runtime_version = [s.rsplit(None, 1)[-1] for s in cfg if 'MIOpen' in s][0] + gpu_info = dict( + is_cuda_available=cuda_available_str, + cuda_compiled_version='N/A', + hip_compiled_version=torch.version.hip, + hip_runtime_version=hip_runtime_version, + miopen_runtime_version=miopen_runtime_version, + cuda_runtime_version='N/A', + nvidia_gpu_models=get_gpu_info(run_lambda), + nvidia_driver_version=get_nvidia_driver_version(run_lambda), + cudnn_version='N/A', + ) + + pip_version, pip_list_output = get_pip_packages(run_lambda) + conda_packages = get_conda_packages(run_lambda) + gcc_version = get_gcc_version(run_lambda) + clang_version = get_clang_version(run_lambda) + cmake_version = get_cmake_version(run_lambda) + os_version = get_os(run_lambda) + + return SystemEnv( + torch_version=version_str, + is_debug_build=debug_mode_str, + python_version='{}.{} ({}-bit runtime)'.format(sys.version_info[0], sys.version_info[1], sys.maxsize.bit_length() + 1), + pip_version=pip_version, + pip_packages=pip_list_output, + conda_packages=conda_packages, + os=os_version, + gcc_version=gcc_version, + clang_version=clang_version, + cmake_version=cmake_version, + **gpu_info + ) + +env_info_fmt = """ +PyTorch version: {torch_version} +Is debug build: {is_debug_build} +CUDA used to build PyTorch: {cuda_compiled_version} +ROCM used to build PyTorch: {hip_compiled_version} + +OS: {os} +GCC version: {gcc_version} +Clang version: {clang_version} +CMake version: {cmake_version} + +Python version: {python_version} +Is CUDA available: {is_cuda_available} +CUDA runtime version: {cuda_runtime_version} +GPU models and configuration: {nvidia_gpu_models} +Nvidia driver version: {nvidia_driver_version} +cuDNN version: {cudnn_version} +HIP runtime version: {hip_runtime_version} +MIOpen runtime version: {miopen_runtime_version} + +Versions of relevant libraries: +{pip_packages} +{conda_packages} +""".strip() + + +def pretty_str(envinfo): + def replace_nones(dct, replacement='Could not collect'): + for key in dct.keys(): + if dct[key] is not None: + continue + dct[key] = replacement + return dct + + def replace_bools(dct, true='Yes', false='No'): + for key in dct.keys(): + if dct[key] is True: + dct[key] = true + elif dct[key] is False: + dct[key] = false + return dct + + def prepend(text, tag='[prepend]'): + lines = text.split('\n') + updated_lines = [tag + line for line in lines] + return '\n'.join(updated_lines) + + def replace_if_empty(text, replacement='No relevant packages'): + if text is not None and len(text) == 0: + return replacement + return text + + def maybe_start_on_next_line(string): + # If `string` is multiline, prepend a \n to it. + if string is not None and len(string.split('\n')) > 1: + return '\n{}\n'.format(string) + return string + + mutable_dict = envinfo._asdict() + + # If nvidia_gpu_models is multiline, start on the next line + mutable_dict['nvidia_gpu_models'] = \ + maybe_start_on_next_line(envinfo.nvidia_gpu_models) + + # If the machine doesn't have CUDA, report some fields as 'No CUDA' + dynamic_cuda_fields = [ + 'cuda_runtime_version', + 'nvidia_gpu_models', + 'nvidia_driver_version', + ] + all_cuda_fields = dynamic_cuda_fields + ['cudnn_version'] + all_dynamic_cuda_fields_missing = all( + mutable_dict[field] is None for field in dynamic_cuda_fields) + if TORCH_AVAILABLE and not torch.cuda.is_available() and all_dynamic_cuda_fields_missing: + for field in all_cuda_fields: + mutable_dict[field] = 'No CUDA' + if envinfo.cuda_compiled_version is None: + mutable_dict['cuda_compiled_version'] = 'None' + + # Replace True with Yes, False with No + mutable_dict = replace_bools(mutable_dict) + + # Replace all None objects with 'Could not collect' + mutable_dict = replace_nones(mutable_dict) + + # If either of these are '', replace with 'No relevant packages' + mutable_dict['pip_packages'] = replace_if_empty(mutable_dict['pip_packages']) + mutable_dict['conda_packages'] = replace_if_empty(mutable_dict['conda_packages']) + + # Tag conda and pip packages with a prefix + # If they were previously None, they'll show up as ie '[conda] Could not collect' + if mutable_dict['pip_packages']: + mutable_dict['pip_packages'] = prepend(mutable_dict['pip_packages'], + '[{}] '.format(envinfo.pip_version)) + if mutable_dict['conda_packages']: + mutable_dict['conda_packages'] = prepend(mutable_dict['conda_packages'], + '[conda] ') + return env_info_fmt.format(**mutable_dict) + + +def get_pretty_env_info(): + return pretty_str(get_env_info()) + + +def main(): + print("Collecting environment information...") + output = get_pretty_env_info() + print(output) + + +if __name__ == '__main__': + """ + CommandLine: + python ~/code/netharn/netharn/util/collect_env.py --profile + """ + main() -- GitLab From 0bcc84c192e343c4a5392834c1e1a6e0ec2d3631 Mon Sep 17 00:00:00 2001 From: joncrall Date: Thu, 22 Oct 2020 09:35:30 -0400 Subject: [PATCH 50/54] wip --- dev/debug_memory.py | 259 +++++++++++++++++++++++++++++++++++++++++++ dev/list_deployed.py | 60 ++++++++++ 2 files changed, 319 insertions(+) create mode 100644 dev/debug_memory.py create mode 100644 dev/list_deployed.py diff --git a/dev/debug_memory.py b/dev/debug_memory.py new file mode 100644 index 0000000..aea3ff7 --- /dev/null +++ b/dev/debug_memory.py @@ -0,0 +1,259 @@ +""" +Experiment Script Related to Pytorch Memory Leak Issue + +References: + https://github.com/pytorch/pytorch/issues/13246 + https://gist.github.com/mprostock/2850f3cd465155689052f0fa3a177a50 +""" +from torch.utils.data import Dataset, DataLoader +import numpy as np +import torch +import psutil +import ubelt as ub +import sys + + +class DataIter(Dataset): + def __init__(self, storage_mode='numpy', return_mode='tensor', total=24e7): + self.return_mode = return_mode + self.storage_mode = storage_mode + + assert self.return_mode in {'tensor', 'dict', 'tuple', 'list'} + + if storage_mode == 'numpy': + self.data = np.array([x for x in range(int(total))]) + elif storage_mode == 'python': + self.data = [x for x in range(int(total))] + elif storage_mode == 'ndsampler': + import ndsampler + assert total <= 1000 + self.data = ndsampler.CocoSampler.demo('shapes{}'.format(total)) + else: + raise KeyError(storage_mode) + + def __len__(self): + return len(self.data) + + def __getitem__(self, idx): + if self.storage_mode == 'ndsampler': + data = self.data.load_item(idx)['im'].ravel()[0:1].astype(np.float32) + data_pt = torch.from_numpy(data) + else: + data = self.data[idx] + data = np.array([data], dtype=np.int64) + data_pt = torch.tensor(data) + + if self.return_mode == 'tensor': + item = data_pt + elif self.return_mode == 'dict': + item = { + 'data': data_pt + } + elif self.return_mode == 'tuple': + item = (data_pt,) + elif self.return_mode == 'list': + item = [data_pt] + return item + + +def getsize(*objs): + """ + sum size of object & members. + https://stackoverflow.com/questions/449560/how-do-i-determine-the-size-of-an-object-in-python + """ + import sys + from types import ModuleType, FunctionType + from gc import get_referents + # Custom objects know their class. + # Function objects seem to know way too much, including modules. + # Exclude modules as well. + blocklist = (type, ModuleType, FunctionType) + # if isinstance(obj, blocklist): + # raise TypeError('getsize() does not take argument of type: ' + str(type(obj))) + seen_ids = set() + size = 0 + objects = objs + while objects: + need_referents = [] + for obj in objects: + if not isinstance(obj, blocklist) and id(obj) not in seen_ids: + seen_ids.add(id(obj)) + size += sys.getsizeof(obj) + need_referents.append(obj) + objects = get_referents(*need_referents) + return size, len(seen_ids) + + +def byte_str(num, unit='auto', precision=2): + """ + Automatically chooses relevant unit (KB, MB, or GB) for displaying some + number of bytes. + + Args: + num (int): number of bytes + unit (str): which unit to use, can be auto, B, KB, MB, GB, TB, PB, EB, + ZB, or YB. + + References: + https://en.wikipedia.org/wiki/Orders_of_magnitude_(data) + + Returns: + str: string representing the number of bytes with appropriate units + + Example: + >>> num_list = [1, 100, 1024, 1048576, 1073741824, 1099511627776] + >>> result = ub.repr2(list(map(byte_str, num_list)), nl=0) + >>> print(result) + ['0.00 KB', '0.10 KB', '1.00 KB', '1.00 MB', '1.00 GB', '1.00 TB'] + """ + abs_num = abs(num) + if unit == 'auto': + if abs_num < 2.0 ** 10: + unit = 'KB' + elif abs_num < 2.0 ** 20: + unit = 'KB' + elif abs_num < 2.0 ** 30: + unit = 'MB' + elif abs_num < 2.0 ** 40: + unit = 'GB' + elif abs_num < 2.0 ** 50: + unit = 'TB' + elif abs_num < 2.0 ** 60: + unit = 'PB' + elif abs_num < 2.0 ** 70: + unit = 'EB' + elif abs_num < 2.0 ** 80: + unit = 'ZB' + else: + unit = 'YB' + if unit.lower().startswith('b'): + num_unit = num + elif unit.lower().startswith('k'): + num_unit = num / (2.0 ** 10) + elif unit.lower().startswith('m'): + num_unit = num / (2.0 ** 20) + elif unit.lower().startswith('g'): + num_unit = num / (2.0 ** 30) + elif unit.lower().startswith('t'): + num_unit = num / (2.0 ** 40) + elif unit.lower().startswith('p'): + num_unit = num / (2.0 ** 50) + elif unit.lower().startswith('e'): + num_unit = num / (2.0 ** 60) + elif unit.lower().startswith('z'): + num_unit = num / (2.0 ** 70) + elif unit.lower().startswith('y'): + num_unit = num / (2.0 ** 80) + else: + raise ValueError('unknown num={!r} unit={!r}'.format(num, unit)) + return ub.repr2(num_unit, precision=precision) + ' ' + unit + + +def main(storage_mode='numpy', return_mode='tensor', total=24e5, shuffle=True): + """ + Args: + storage_mode : how the dataset is stored in backend datasets + + return_mode : how each data item is returned + + total : size of backend storage + + """ + mem = psutil.virtual_memory() + start_mem = mem.used + mem_str = byte_str(start_mem) + print('Starting used system memory = {!r}'.format(mem_str)) + + train_data = DataIter( + storage_mode=storage_mode, + return_mode=return_mode, + total=total) + # self = train_data + + if storage_mode == 'numpy': + total_storate_bytes = train_data.data.dtype.itemsize * train_data.data.size + else: + total_storate_bytes = sys.getsizeof(train_data.data) + # total_storate_bytes = getsize(self.data) + print('total_storage_size = {!r}'.format(byte_str(total_storate_bytes))) + + mem = psutil.virtual_memory() + mem_str = byte_str(mem.used - start_mem) + print('After init DataIter memory = {!r}'.format(mem_str)) + + print('shuffle = {!r}'.format(shuffle)) + + num_workers = 2 + train_loader = DataLoader(train_data, batch_size=300, + shuffle=shuffle, + drop_last=True, + pin_memory=False, + num_workers=num_workers) + + used_nbytes = psutil.virtual_memory().used - start_mem + print('After init DataLoader memory = {!r}'.format(byte_str(used_nbytes))) + + if True: + # Estimate peak usage + import gc + all_obj_nbytes, num_objects = getsize(*gc.get_objects()) + python_ptr_size = int((np.log2(sys.maxsize) + 1) / 8) + assert python_ptr_size == 8, 'should be 8 bytes on 64bit python' + all_ptr_nbytes = (num_objects * python_ptr_size) + + prog_nbytes_estimated_1 = all_ptr_nbytes + all_obj_nbytes + prog_nbytes_measured_2 = psutil.virtual_memory().used - start_mem + print('prog_nbytes_estimated_1 = {!r}'.format(byte_str(prog_nbytes_estimated_1))) + print('prog_nbytes_measured_2 = {!r}'.format(byte_str(prog_nbytes_measured_2))) + + peak_bytes_est1 = prog_nbytes_estimated_1 * (num_workers + 1) + peak_bytes_est2 = prog_nbytes_measured_2 * (num_workers + 1) + print('peak_bytes_est1 = {!r}'.format(byte_str(peak_bytes_est1))) + print('peak_bytes_est2 = {!r}'.format(byte_str(peak_bytes_est2))) + + max_bytes = -float('inf') + prog = ub.ProgIter(train_loader) + for item in prog: + used_bytes = psutil.virtual_memory().used - start_mem + max_bytes = max(max_bytes, used_bytes) + prog.set_extra(' Mem=' + byte_str(used_bytes)) + + used_bytes = psutil.virtual_memory().used - start_mem + print('measured final usage: {}'.format(byte_str(used_bytes))) + print('measured peak usage: {}'.format(byte_str(max_bytes))) + + +if __name__ == '__main__': + """ + CommandLine: + python debug_memory.py numpy tensor --total=24e5 --shuffle=True + + cd ~/code/netharn/dev + + python debug_memory.py --storage_mode=numpy --total=24e5 --shuffle=True + python debug_memory.py --storage_mode=numpy --total=24e5 --shuffle=False + python debug_memory.py --storage_mode=python --total=24e5 --shuffle=True + python debug_memory.py --storage_mode=python --total=24e5 --shuffle=False + + python debug_memory.py --storage_mode=ndsampler --total=1000 --shuffle=True + + python debug_memory.py numpy dict 24e5 + python debug_memory.py python list 24e7 + + Conclusions: + + * It seems like it is ok if the return type is a dictionary + the problem seems to be localized to the storage type. + """ + import fire + fire.Fire(main) + +""" + +@VitalyFedyunin Let me see if I understand correctly, when you access an item +in a list you create a new reference to it, which will force its refcount to be +incremented (i.e. be written to). + +pages are typically 4096 bytes. + +""" diff --git a/dev/list_deployed.py b/dev/list_deployed.py new file mode 100644 index 0000000..49e20ed --- /dev/null +++ b/dev/list_deployed.py @@ -0,0 +1,60 @@ +""" +Simple script that prints the deployed models in a given netharn work directory +""" +import scriptconfig as scfg +import ubelt as ub +import glob +from os.path import join, exists + + +class ListDeployedConfig(scfg.Config): + """ + Given a netharn work directory list all deployed models + """ + default = { + 'workdir': scfg.Value(None, help='work directory'), + 'name': scfg.Value(None, help='"nice" name of the run'), + } + + +def main(cmdline=True, **kw): + config = ListDeployedConfig(cmdline=cmdline, default=kw) + print('config = {}'.format(ub.repr2(dict(config), nl=1))) + + runs_dpath = join(config['workdir'], 'fit/runs') + if not exists(runs_dpath): + print('Workdir does not seem to contain a runs dpath') + print('Checking for alternates? TODO') + raise NotImplementedError + + workdirs = [config['workdir']] + for workdir in workdirs: + run_name = config['name'] + if run_name is None: + named_run_dpath = join(runs_dpath, '*') + dpath_exists = exists(named_run_dpath) + print('dpath_exists = {!r}'.format(dpath_exists)) + else: + named_run_dpath = join(runs_dpath, run_name) + dpath_exists = exists(named_run_dpath) + print('dpath_exists = {!r}'.format(dpath_exists)) + + # TODO: do we want to remove deploy.zip symlinks here? + deployed_fpaths = glob.glob(join(named_run_dpath, '*/*.zip')) + + SHRINK = 1 + if SHRINK: + # Make output text smaller, and more likely to work cross-system + deployed_fpaths = [ + ub.shrinkuser(fpath, home='$HOME') + for fpath in deployed_fpaths] + + print('deployed_fpaths = {}'.format(ub.repr2(deployed_fpaths, nl=1))) + + +if __name__ == '__main__': + """ + CommandLine: + python ~/code/netharn/dev/list_deployed.py --workdir $HOME/work/netharn + """ + main() -- GitLab From ef1a49eb74e6ed8f1a05976823690ae8bd1c7254 Mon Sep 17 00:00:00 2001 From: joncrall Date: Thu, 22 Oct 2020 16:14:03 -0400 Subject: [PATCH 51/54] Fixed bug with bad epoch 0 written. Tweaked logging of warmup and progress info --- CHANGELOG.md | 9 +++ netharn/fit_harn.py | 139 +++++++++++++++++++++---------------- netharn/mixins.py | 2 +- netharn/models/toynet.py | 4 ++ tests/test_run_sequence.py | 78 +++++++-------------- 5 files changed, 117 insertions(+), 115 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28b2527..91df45d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,15 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Fixed * Typo: directory `explit_checkpoints` renamed to `explicit_checkpoints`. +* Fixed bug where epoch 0 would write a snapshot if it failed. + + +### Changed + +* ProgIter information will now written to the log file pending release of ubelt 0.9.3. + +* Progress information now includes warmup LR information in the first epoch. + ### Deprecated * Deprecate `colored` option in `FitHarnPreferences`. Use `NO_COLOR` environ to diff --git a/netharn/fit_harn.py b/netharn/fit_harn.py index b5d3f42..2929f4d 100644 --- a/netharn/fit_harn.py +++ b/netharn/fit_harn.py @@ -531,7 +531,8 @@ class InitializeMixin(object): # this allows us to print logging calls to the terminal stdout_handler = logging.StreamHandler(sys.stdout) stdout_handler.setFormatter(s_formatter) - if ub.argflag('--verbose'): + + if harn.preferences['verbose'] > 1 or ub.argflag('--verbose'): stdout_handler.setLevel(logging.DEBUG) else: stdout_handler.setLevel(logging.INFO) @@ -541,6 +542,9 @@ class InitializeMixin(object): _log.addHandler(a_handler) _log.addHandler(stdout_handler) + # hack in attribute for internal use + _log._stdout_handler = stdout_handler + harn._log = _log harn.debug('Initialized logging') @@ -758,6 +762,14 @@ class ProgMixin(object): str : the message to be used in the progress bar """ parts = ['{}:{:.4g}'.format(k, v) for k, v in metric_dict.items()] + + if learn and harn.epoch == 0: + HACK_WARMUP = bool(harn.dynamics['warmup_iters']) + if HACK_WARMUP: + lrs = set(harn._current_lrs()) + lr_str = ','.join(['{:.4g}'.format(lr) for lr in lrs]) + parts.append('lr=' + lr_str) + if harn.preferences['prog_backend'] == 'progiter': if learn and harn.scheduler and getattr(harn.scheduler, '__batchaware__', False): lr = harn.scheduler.get_lr() @@ -798,9 +810,10 @@ class ProgMixin(object): desc = 'epoch lr:{} │ {}'.format(lr_str, harn.monitor.message()) if not harn.preferences['colored']: desc = strip_ansi(desc) - harn.debug(desc) harn.main_prog.set_description(desc, refresh=False) if isinstance(harn.main_prog, ub.ProgIter): + # Write progress message to the log file + harn.debug(harn.main_prog.format_message().strip()) if not harn.main_prog.started: # harn.main_prog.ensure_newline() harn.main_prog.clearline = False @@ -808,6 +821,7 @@ class ProgMixin(object): harn.main_prog.adjust = False harn.main_prog.begin() else: + harn.debug(desc) harn._update_prog_postfix(harn.main_prog) @@ -905,6 +919,12 @@ class LogMixin(object): msg (str): a debug message to log """ if harn._log: + + if harn._log._stdout_handler.level <= logging.DEBUG: + # Use our hacked attribute to ensure newlines if we are + # writting debug info to stdout + harn._ensure_prog_newline() + msg = strip_ansi(six.text_type(msg)) # Encode to prevent errors on windows terminals # On windows there is a sometimes a UnicodeEncodeError: @@ -1140,7 +1160,7 @@ class SnapshotMixin(object): save_fname = '_epoch_{:08d}.pt'.format(harn.epoch) elif mode == 'initial': dpath = ub.ensuredir((harn.train_dpath, 'initial_state')) - save_fname = 'initial_state.pt'.format(harn.epoch) + save_fname = 'initial_state.pt'.format() else: raise KeyError(mode) @@ -1165,6 +1185,9 @@ class SnapshotMixin(object): def best_snapshot(harn): """ Return the path to the current "best" snapshot. + + Returns: + str - find the path to the best """ # Netharn should populate best_snapshot.pt if there is a validation set. # Other names are to support older codebases. @@ -1191,9 +1214,8 @@ class SnapshotMixin(object): if epoch_to_fpath: fpath = epoch_to_fpath[max(epoch_to_fpath)] - if fpath is None: - raise Exception('cannot find / determine the best snapshot') - + # if fpath is None: + # raise Exception('cannot find / determine the best snapshot') return fpath @@ -1331,15 +1353,15 @@ class ScheduleMixin(object): warmup_iters = harn.dynamics['warmup_iters'] warmup_ratio = harn.dynamics['warmup_ratio'] # 1.0 / 3.0 if cur_iters < warmup_iters: - for cur_iters in range(0, warmup_iters): - regular_lr = _get_optimizer_values(harn.optimizer, 'initial_lr') - if warmup == 'linear': - k = (1 - (cur_iters + 1) / warmup_iters) * (1 - warmup_ratio) - warmup_lr = [_lr * (1 - k) for _lr in regular_lr] - else: - raise KeyError(warmup) - # harn.debug('warmup_lr = {}'.format(warmup_lr)) - _set_optimizer_values(harn.optimizer, 'lr', warmup_lr) + # for cur_iters in range(0, warmup_iters): + regular_lr = _get_optimizer_values(harn.optimizer, 'initial_lr') + if warmup == 'linear': + k = (1 - (cur_iters + 1) / warmup_iters) * (1 - warmup_ratio) + warmup_lr = [_lr * (1 - k) for _lr in regular_lr] + else: + raise KeyError(warmup) + # harn.debug('warmup_lr = {}'.format(warmup_lr)) + _set_optimizer_values(harn.optimizer, 'lr', warmup_lr) # TODO: REFACTOR SO NETHARN HAS A PROPER ITERATION MODE if getattr(harn.scheduler, '__batchaware__', False): @@ -1655,53 +1677,24 @@ class CoreMixin(object): Returns: str: path to the deploy zipfile. """ - harn._export() + static_modpath = harn._export() harn.debug('packaging deploying model') if True: - # HOTFIX: if the best snapshot doesnt exist we need to make one - def _find_best_snapshot(train_dpath): - """ - Returns snapshot written by monitor if available otherwise takes the last - one. - - Hack for a hotfix - """ - # NOTE: Specific to netharn directory structure - # Netharn should populate best_snapshot.pt if there is a validation set. - # Other names are to support older codebases. - expected_names = [ - 'best_snapshot.pt', - 'best_snapshot2.pt', - 'final_snapshot.pt', - 'deploy_snapshot.pt', - ] - def _existing_snapshots(train_dpath): - # NOTE: Specific to netharn directory structure - import parse - snapshot_dpath = join(train_dpath, 'torch_snapshots/') - prev_states = sorted(glob.glob(join(snapshot_dpath, '_epoch_*.pt'))) - snapshots = {parse.parse('{}_epoch_{num:d}.pt', path).named['num']: path - for path in prev_states} - return snapshots - for snap_fname in expected_names: - snap_fpath = join(train_dpath, snap_fname) - if exists(snap_fpath): - break - - if not exists(snap_fpath): - snap_fpath = None - - if not snap_fpath: - epoch_to_fpath = _existing_snapshots(train_dpath) - if epoch_to_fpath: - snap_fpath = epoch_to_fpath[max(epoch_to_fpath)] - return snap_fpath - if _find_best_snapshot(harn.train_dpath) is None: - harn.save_snapshot() + snap_fpath = harn.best_snapshot() + if snap_fpath is None: + # if the best snapshot doesnt exist we need to make one + harn.debug( + 'Cannot find "best" snapshot, write an explit one instead') + snap_fpath = harn.save_snapshot(explicit=True) try: - deploy_fpath = torch_liberator.DeployedModel(harn.train_dpath).package() + train_info_fpath = join(harn.train_dpath, 'train_info.json') + deploy_fpath = torch_liberator.DeployedModel.custom( + snap_fpath=snap_fpath, + model=static_modpath, + train_info_fpath=train_info_fpath, + ).package(harn.train_dpath) harn.info('wrote single-file deployment to: {!r}'.format( deploy_fpath)) @@ -1938,6 +1931,8 @@ class CoreMixin(object): ### THIS IS THE CRITICAL LOOP ### ################################# + STEP_LR_BEFORE = True + for bx in range(n_batches): if DEMO and bx > DEMO_BX: break @@ -1951,6 +1946,12 @@ class CoreMixin(object): harn.bxs[tag] = bx # harn.debug('{} batch iteration {}'.format(tag, bx)) + if STEP_LR_BEFORE: + if learn: + # Some schedulers update every batch + # TODO: needs further rectification + harn._step_scheduler_batch() + batch = harn.prepare_batch(raw_batch) if is_profiling: @@ -2030,14 +2031,26 @@ class CoreMixin(object): # hack to force progiter to reach 100% at the end # This should be fixed in progiter. steps_taken = (bx - prog._iter_idx) + 1 - prog.update(steps_taken) + if bx == 0: + # HACK, after ubelt 0.9.3 we can use force=True + prog._iter_idx += steps_taken + prog._update_measurements() + prog._update_estimates() + prog.display_message() + harn.debug(prog.format_message().strip()) + else: + prog_updated = prog.update(steps_taken) + if prog_updated: + harn.debug(prog.format_message().strip()) if use_tqdm: harn._update_prog_postfix(prog) - # Some schedulers update every batch - if learn: - harn._step_scheduler_batch() + if not STEP_LR_BEFORE: + # old way that I think is buggy + if learn: + # Some schedulers update every batch + harn._step_scheduler_batch() except SkipBatch: harn.warn('skipping batch') if harn.check_interval('display_' + tag, bx): @@ -2057,6 +2070,8 @@ class CoreMixin(object): # harn.optimizer.zero_grad() prog.refresh() + if not use_tqdm: + harn.debug(prog.format_message().strip()) prog.close() harn.epoch_prog = None @@ -2878,6 +2893,8 @@ class FitHarnPreferences(scfg.Config): # Control deprecated 'old_prepare_batch': False, + + 'verbose': scfg.Value(1, help='verbosity level'), } diff --git a/netharn/mixins.py b/netharn/mixins.py index e8f8cf3..58d0052 100644 --- a/netharn/mixins.py +++ b/netharn/mixins.py @@ -41,7 +41,7 @@ def _dump_monitor_tensorboard(harn, mode='epoch', special_groupers=['loss'], import six from six.moves import cPickle as pickle - harn.debug('Plotting tensorboard data. serial={}, mode={}'.format(serial, mode)) + # harn.debug('Plotting tensorboard data. serial={}, mode={}'.format(serial, mode)) train_dpath = harn.train_dpath diff --git a/netharn/models/toynet.py b/netharn/models/toynet.py index 4b59621..7a1ac7d 100644 --- a/netharn/models/toynet.py +++ b/netharn/models/toynet.py @@ -17,6 +17,8 @@ class ToyNet1d(layers.Module): """ def __init__(self, input_channels=2, num_classes=2): super(ToyNet1d, self).__init__() + self.input_channels = input_channels + self.num_classes = num_classes self.layers = torch.nn.Sequential(*[ torch.nn.Linear(input_channels, 8), @@ -55,6 +57,8 @@ class ToyNet2d(layers.Module): """ def __init__(self, input_channels=1, num_classes=2): super(ToyNet2d, self).__init__() + self.input_channels = input_channels + self.num_classes = num_classes self.layers = torch.nn.Sequential(*[ torch.nn.Conv2d(input_channels, 8, kernel_size=3, padding=1, bias=False), diff --git a/tests/test_run_sequence.py b/tests/test_run_sequence.py index 8659300..5ea8172 100644 --- a/tests/test_run_sequence.py +++ b/tests/test_run_sequence.py @@ -1,8 +1,8 @@ """ Tests the order in which things happen in "run" """ +# import torch.nn.functional as F import numpy as np -import torch.nn.functional as F import ubelt as ub import netharn as nh import torch @@ -14,19 +14,8 @@ class Failpoint(Exception): class MyHarn(nh.FitHarn): - def after_initialize(harn): - harn._all_iters = ub.ddict(list) - pass - - def prepare_batch(harn, raw_batch): - return raw_batch - - def before_epochs(harn): - # change the size of the dataset every epoch - harn.datasets['train'].total = (harn.epoch % 10) + 1 - def run_batch(harn, raw_batch): - if harn.epoch == harn.failpoint: + if harn.epoch == harn.failpoint and harn.batch_index >= 4: raise Failpoint x = torch.Tensor([[1, 2]]) @@ -34,7 +23,8 @@ class MyHarn(nh.FitHarn): y = f(x) loss = y.sum() output = y - harn._all_iters[harn.current_tag].append(harn.iter_index) + + # harn._all_iters[harn.current_tag].append(harn.iter_index) # batch = harn.xpu.move(raw_batch) # output = harn.model(batch['im']) # log_probs = F.log_softmax(output, dim=1) @@ -44,33 +34,13 @@ class MyHarn(nh.FitHarn): return output, loss -class VariableSizeDataset(torch.utils.data.Dataset): - - def __init__(self, total=100): - self.total = total - self.subdata = nh.data.ToyData2d( - size=3, border=1, n=1000, rng=0) - - def __len__(self): - return self.total - - def __getitem__(self, index): - index = index % len(self.subdata) - image, label = self.subdata[index] - item = { - 'im': image, - 'label': label, - } - return item - - def test_run_sequence(): """ main test function """ datasets = { - 'train': VariableSizeDataset(total=1), - 'vali': VariableSizeDataset(total=10), + 'train': nh.data.ToyData2d(size=3, border=1, n=7, rng=0), + 'vali': nh.data.ToyData2d(size=3, border=1, n=3, rng=0), } model = nh.models.ToyNet2d() @@ -86,12 +56,13 @@ def test_run_sequence(): 'optimizer' : nh.api.Optimizer.coerce({'optim': 'sgd'}), 'initializer' : nh.api.Initializer.coerce({'init': 'noop'}), 'scheduler' : nh.api.Scheduler.coerce({'scheduler': 'step-3-7'}), - 'dynamics' : nh.api.Dynamics.coerce({'batch_step': 1}), - 'monitor' : (nh.Monitor, {'max_epoch': 10}), + 'dynamics' : nh.api.Dynamics.coerce({'batch_step': 1, 'warmup_iters': 6}), + 'monitor' : (nh.Monitor, {'max_epoch': 4}), } harn1 = MyHarn(hyper=hyper) - harn1.preferences['use_tensorboard'] = True - harn1.preferences['eager_dump_tensorboard'] = True + harn1.preferences['verbose'] = 1 + harn1.preferences['use_tensorboard'] = False + harn1.preferences['eager_dump_tensorboard'] = False harn1.intervals['log_iter_train'] = 1 harn1.intervals['log_iter_vali'] = 1 @@ -101,7 +72,7 @@ def test_run_sequence(): # Cause the harness to fail try: - harn1.failpoint = 5 + harn1.failpoint = 0 harn1.run() except Failpoint: pass @@ -114,18 +85,19 @@ def test_run_sequence(): harn2.failpoint = None harn2.run() - idxs1 = harn1._all_iters['train'] - idxs2 = harn2._all_iters['train'] - diff1 = np.diff(idxs1) - diff2 = np.diff(idxs2) - print('idxs1 = {!r}'.format(idxs1)) - print('idxs2 = {!r}'.format(idxs2)) - print('diff1 = {!r}'.format(diff1)) - print('diff2 = {!r}'.format(diff2)) - assert np.all(diff1 == 1) - assert np.all(diff2 == 1) - assert idxs1[0] == 0 - assert idxs1[-1] == (idxs2[0] - 1) + if 0: + idxs1 = harn1._all_iters['train'] + idxs2 = harn2._all_iters['train'] + diff1 = np.diff(idxs1) + diff2 = np.diff(idxs2) + print('idxs1 = {!r}'.format(idxs1)) + print('idxs2 = {!r}'.format(idxs2)) + print('diff1 = {!r}'.format(diff1)) + print('diff2 = {!r}'.format(diff2)) + assert np.all(diff1 == 1) + assert np.all(diff2 == 1) + assert idxs1[0] == 0 + assert idxs1[-1] == (idxs2[0] - 1) if __name__ == '__main__': -- GitLab From 34fc9e5beb19da1524730a66d35e454f497a1129 Mon Sep 17 00:00:00 2001 From: joncrall Date: Thu, 22 Oct 2020 16:27:01 -0400 Subject: [PATCH 52/54] Fixed bugs --- README.rst | 1 + netharn/fit_harn.py | 35 ++++++++++++++++------------------- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/README.rst b/README.rst index 7671bfc..93d4cb3 100644 --- a/README.rst +++ b/README.rst @@ -303,6 +303,7 @@ useful to look at. Its complexity is more than CIFAR but less than YOLO. >>> harn = netharn.FitHarn(hyper) >>> # non-algorithmic behavior preferences (do not change learned models) >>> harn.preferences['num_keep'] = 10 + >>> harn.preferences['auto_prepare_batch'] = True >>> # start training. >>> harn.initialize(reset='delete') # delete removes an existing run >>> harn.run() # note: run calls initialize it hasn't already been called. diff --git a/netharn/fit_harn.py b/netharn/fit_harn.py index 2929f4d..3d54202 100644 --- a/netharn/fit_harn.py +++ b/netharn/fit_harn.py @@ -88,6 +88,7 @@ Example: >>> # non-algorithmic behavior configs (do not change learned models) >>> harn.preferences['use_tensorboard'] = False >>> harn.preferences['timeout'] = 0.5 + >>> harn.preferences['auto_prepare_batch'] = True >>> # start training. >>> harn.initialize(reset='delete') >>> harn.run() # note: run calls initialize it hasn't already been called. @@ -132,7 +133,7 @@ TODO: called either after each epoch or after each batch iteration (for schedulers like CyclicLR, OneCycleLR). - [ ] - Show LR in the batch progress bar (if updated on an iteration basis) + [X] - Show LR in the batch progress bar (if updated on an iteration basis) [ ] - How does the netharn scheduler redesign interact with torch 1.1? [ ] - Stochastic Weight Averaging - https://pytorch.org/docs/stable/optim.html#putting-it-all-together @@ -2314,21 +2315,12 @@ class CoreCallbacks(object): """ batch = raw_batch - if harn.preferences['old_prepare_batch']: - import warnings - warnings.warn( - 'The behavior of prepare_batch will change in the future. ' - 'The new behavior will be a simple no-op ' - 'For maximum compatibility override prepare_batch.', - DeprecationWarning) + if harn.preferences['auto_prepare_batch']: + # Automatically move data try: if isinstance(raw_batch, (tuple, list)): - batch_inputs, batch_labels = raw_batch - raw_batch = { - 'input': batch_inputs, - 'label': batch_labels, - } - if isinstance(raw_batch, dict): + batch = harn.xpu.move(raw_batch) + elif isinstance(raw_batch, dict): batch = raw_batch.copy() batch = harn.xpu.move(batch) else: @@ -2879,6 +2871,16 @@ class FitHarnPreferences(scfg.Config): 'limits the amount of time training can take') ), + 'auto_prepare_batch': scfg.Value(False, help=( + 'In the case where prepare_batch is not overwritten, ' + 'changes the behavior of the default prepare_batch ' + 'to automatically move tensors onto the model XPU' + )), + + 'verbose': scfg.Value(1, help=( + 'verbosity level, ' + 'if >1 shows debug info in stdout')), + # Deprecated 'use_tqdm': scfg.Value(None, help='deprecated'), @@ -2890,11 +2892,6 @@ class FitHarnPreferences(scfg.Config): 'allow_unicode': scfg.Value(True, help=( 'allow for unicode characters in messages, otherwise ' ' we approximate them with ascii')), - - # Control deprecated - 'old_prepare_batch': False, - - 'verbose': scfg.Value(1, help='verbosity level'), } -- GitLab From 0795b460ef6c42492aaa7bab6600e6dc2f77d802 Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 23 Oct 2020 08:47:41 -0400 Subject: [PATCH 53/54] Use AdaBelief from torch-optimizer --- .gitlab-ci.yml | 55 --------------------------------------- CHANGELOG.md | 2 ++ netharn/api.py | 18 +------------ requirements/optional.txt | 1 - 4 files changed, 3 insertions(+), 73 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 51383c7..50a7141 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -303,58 +303,3 @@ test_full/cp36-cp36m-linux: # image: # python:3.6 - -# --------------- -# Python 3.5 Jobs - -build/cp35-cp35m-linux: - <<: - - *build_template - image: - python:3.5 - -test_full/cp35-cp35m-linux: - <<: - - *test_full_template - image: - python:3.5 - -#gpgsign/cp35-cp35m-linux: -# <<: -# - *gpgsign_template -# image: -# python:3.5 - -#deploy/cp35-cp35m-linux: -# <<: -# - *deploy_template -# image: -# python:3.5 - - -# --------------- -# Python 2.7 Jobs - -#build/cp27-cp27mu-linux: -# <<: -# - *build_template -# image: -# python:2.7 - -#test_full/cp27-cp27mu-linux: -# <<: -# - *test_full_template -# image: -# python:2.7 - -#gpgsign/cp27-cp27mu-linux: -# <<: -# - *gpgsign_template -# image: -# python:2.7 - -#deploy/cp27-cp27mu-linux: -# <<: -# - *deploy_template -# image: -# python:2.7 diff --git a/CHANGELOG.md b/CHANGELOG.md index 91df45d..627f408 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Changed +* Removed Python 3.5 support + * ProgIter information will now written to the log file pending release of ubelt 0.9.3. * Progress information now includes warmup LR information in the first epoch. diff --git a/netharn/api.py b/netharn/api.py index b1edea8..72f7ccf 100644 --- a/netharn/api.py +++ b/netharn/api.py @@ -467,6 +467,7 @@ class Optimizer(object): ] try: + # Allow coerce to use torch_optimizer package if available import torch_optimizer except Exception: torch_optimizer = None @@ -476,23 +477,6 @@ class Optimizer(object): k.lower(): c.__name__ for k, c in torch_optimizer._NAME_OPTIM_MAP.items()}) - try: - """ - pip install adabelief_pytorch - python -c "import adabelief_pytorch; adabelief_pytorch.AdaBelief" - """ - import adabelief_pytorch - except Exception: - adabelief_pytorch = None - else: - optim_modules.append(adabelief_pytorch) - _lut.update({ - cls.__name__.lower(): cls.__name__ - for cls in [ - adabelief_pytorch.AdaBelief, - ] - }) - _lut.update({ k.lower(): k for k in dir(torch.optim) if not k.startswith('_')}) diff --git a/requirements/optional.txt b/requirements/optional.txt index b8adb76..2a8035b 100644 --- a/requirements/optional.txt +++ b/requirements/optional.txt @@ -23,4 +23,3 @@ kwcoco >= 0.1.0 colormath torch-optimizer >= 0.0.1a9 ;python_version>='3.6' -adabelief_pytorch -- GitLab From bdad18205f09bbe93c1ef3c7878bdca585ad0ccf Mon Sep 17 00:00:00 2001 From: joncrall Date: Fri, 23 Oct 2020 17:43:37 -0400 Subject: [PATCH 54/54] support for new progiter and add torch_liberator to requirements --- netharn/fit_harn.py | 18 +++++++++++++----- requirements/runtime.txt | 1 + 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/netharn/fit_harn.py b/netharn/fit_harn.py index 3d54202..bb831f0 100644 --- a/netharn/fit_harn.py +++ b/netharn/fit_harn.py @@ -38,8 +38,7 @@ Note: CommandLine: xdoctest netharn.fit_harn __doc__:0 - xdoctest netharn.fit_harn __doc__:0 --progiter - xdoctest netharn.fit_harn __doc__:0 --progiter --profile --xpu=cpu + xdoctest netharn.fit_harn __doc__:0 --profile --xpu=cpu Example: >>> import netharn as nh @@ -153,6 +152,7 @@ import traceback from os.path import join from os.path import exists from os.path import dirname +from distutils.version import LooseVersion import torch import numpy as np @@ -727,6 +727,7 @@ class ProgMixin(object): def _make_prog(harn, *args, **kw): chunksize = kw.pop('chunksize', None) + show_wall = kw.pop('show_wall', False) if harn.preferences['use_tqdm'] is not None: import warnings @@ -746,8 +747,14 @@ class ProgMixin(object): import tqdm # NOQA Prog = tqdm.tqdm elif harn.preferences['prog_backend'] == 'progiter': - Prog = functools.partial( - ub.ProgIter, chunksize=chunksize, verbose=1, time_thresh=2.0) + if LooseVersion(ub.__version__) >= LooseVersion('0.9.3'): + Prog = functools.partial( + ub.ProgIter, chunksize=chunksize, verbose=1, + time_thresh=2.0, show_wall=show_wall) + else: + Prog = functools.partial( + ub.ProgIter, chunksize=chunksize, verbose=1, + time_thresh=2.0) else: raise KeyError(harn.preferences['prog_backend']) return Prog(*args, **kw) @@ -1498,7 +1505,8 @@ class CoreMixin(object): total=harn.monitor.max_epoch, disable=not harn.preferences['show_prog'], leave=True, dynamic_ncols=True, - position=0, initial=harn.epoch) + show_wall=True, position=0, + initial=harn.epoch) harn._update_main_prog_desc() # Loader dict should be ordered diff --git a/requirements/runtime.txt b/requirements/runtime.txt index b947a61..33256f3 100644 --- a/requirements/runtime.txt +++ b/requirements/runtime.txt @@ -29,3 +29,4 @@ kwimage >= 0.4.0 kwplot >= 0.4.0 qualname>=0.1.0;python_version < '3.0' +torch_liberator >= 0.0.4 -- GitLab