logo Netzschleuder network catalog, repository, and centrifuge

History of jlaw_citegraph

The changes to the source code of this entry in the repository, newest first, each with the differences it made to the entry's files. They are also listed on GitLab.

[entries] Add the date when each entry was added, and remove icon_hash by Tiago de Paula Peixoto beff7c9
The dates are those of the commits that first added the entries' files
(2020-08-11 for the entries of the initial commit); renamed entries keep
the date of their first name.

Changed: none
diff --git a/entries/jlaw_citegraph/__init__.py b/entries/jlaw_citegraph/__init__.py
index e0f5e8f..b324241 100644
--- a/entries/jlaw_citegraph/__init__.py
+++ b/entries/jlaw_citegraph/__init__.py
@@ -53,7 +53,7 @@ url = ['https://huggingface.co/datasets/yabooung/jp-law-citation-graph',
        'https://laws.e-gov.go.jp/']
 citation = [('yabooung, "JLaw-CiteGraph: a citation graph of Japanese statutory law." Hugging Face dataset, versions 2.0-2.5 (2026)',
              'https://huggingface.co/datasets/yabooung/jp-law-citation-graph')]
-icon_hash = None
+date_added = '2026-10-31'
 upstream_license = ("CC BY 4.0 (data derived from e-Gov 法令検索, Digital Agency of Japan)",
                     "https://creativecommons.org/licenses/by/4.0/")
 
[entries] Prefix the properties in the descriptions with (Node), (Edge) or (Graph) by Tiago de Paula Peixoto bc3dbbd
The lists of properties at the end of the descriptions marked edge
properties with "Edge" but left node properties unmarked, or grouped
them in "Nodes: `a`, ...; `b`, ..." items, so the kind of a property
was often unclear. Every item now starts with (Node), (Edge) or (Graph),
followed by the property names, a colon and the explanation, one item
per property or group of properties; qualifications (kinds of nodes,
networks) follow the names in parentheses. Properties that were only
named got a short explanation, and a few items that named the wrong
kind of property were corrected.
diff --git a/entries/jlaw_citegraph/__init__.py b/entries/jlaw_citegraph/__init__.py
index 3c3cba9..e0f5e8f 100644
--- a/entries/jlaw_citegraph/__init__.py
+++ b/entries/jlaw_citegraph/__init__.py
@@ -32,21 +32,21 @@ The nodes are identified by the e-Gov law ids (e.g. `129AC0000000089` for the Ci
 
 The `laws_<date>` networks have the following properties:
 
-- `law_id`: the e-Gov law id; `name`: the title of the law (in Japanese); `type`: its type (`法律`, `政令`, `府省令`, `規則`, `勅令`, `憲法`); `url`: the page of the law on e-Gov.
-- `enforcement_date`: the date on which the version of the law in the data came into force (`YYYYMMDD`); `next_enforcement_date`: the date of the next amendment that is already decided (empty if none); `pending_versions`: the number of amendments that are decided but not yet in force.
-- Edge `count`: the number of citations (pairs of citing provision and cited provision of the two laws).
+- (Node) `law_id`: the e-Gov law id; `name`: the title of the law (in Japanese); `type`: its type (`法律`, `政令`, `府省令`, `規則`, `勅令`, `憲法`); `url`: the page of the law on e-Gov.
+- (Node) `enforcement_date`: the date on which the version of the law in the data came into force (`YYYYMMDD`); `next_enforcement_date`: the date of the next amendment that is already decided (empty if none); `pending_versions`: the number of amendments that are decided but not yet in force.
+- (Edge) `count`: the number of citations (pairs of citing provision and cited provision of the two laws).
 
 The `provisions_<date>` networks have the following properties:
 
-- `node_id`: the identifier of the provision (see above).
-- `level`: its kind: `law`, `article`, `paragraph`, `item`, `supplementary_article` or `attachment`.
-- `law_id`, `law_name`, `law_type`: the id, the title and the type of the law that contains the provision.
-- Edge `relation`: `CITES`, `DELEGATES_TO`, `REFERS_TO_ATTACHMENT` or `AMENDS`.
-- Edge `raw`: the text of the reference (e.g. `前項`, `第一条`, `民法第七百九条`).
-- Edge `extracted_from`: how the reference was resolved (e.g. `canonical`, `alias`, `same_as_last`, `INTERNAL_PAT`, `REFERENTIAL/前項`; see the data card).
-- Edge `fallback_level`: how precisely the target was located (e.g. `exact`, or the enclosing provision when the cited one was not found; empty if not given).
-- Edge `confidence`: the confidence of the resolution given by the authors (NaN if not given).
-- Edge `pre_amendment`: whether the citation names the text of the law before an amendment (e.g. "the former act"), whereas only the current text is in the graph."""
+- (Node) `node_id`: the identifier of the provision (see above).
+- (Node) `level`: its kind: `law`, `article`, `paragraph`, `item`, `supplementary_article` or `attachment`.
+- (Node) `law_id`, `law_name`, `law_type`: the id, the title and the type of the law that contains the provision.
+- (Edge) `relation`: `CITES`, `DELEGATES_TO`, `REFERS_TO_ATTACHMENT` or `AMENDS`.
+- (Edge) `raw`: the text of the reference (e.g. `前項`, `第一条`, `民法第七百九条`).
+- (Edge) `extracted_from`: how the reference was resolved (e.g. `canonical`, `alias`, `same_as_last`, `INTERNAL_PAT`, `REFERENTIAL/前項`; see the data card).
+- (Edge) `fallback_level`: how precisely the target was located (e.g. `exact`, or the enclosing provision when the cited one was not found; empty if not given).
+- (Edge) `confidence`: the confidence of the resolution given by the authors (NaN if not given).
+- (Edge) `pre_amendment`: whether the citation names the text of the law before an amendment (e.g. "the former act"), whereas only the current text is in the graph."""
 tags = ['Informational', 'Citation', 'Legal', 'Weighted', 'Multigraph', 'Metadata']
 url = ['https://huggingface.co/datasets/yabooung/jp-law-citation-graph',
        'https://github.com/yabooung/jp-law-citation-graph',
[entries] New entry: jlaw_citegraph by Tiago de Paula Peixoto c597c01
diff --git a/entries/jlaw_citegraph/__init__.py b/entries/jlaw_citegraph/__init__.py
new file mode 100644
index 0000000..3c3cba9
--- /dev/null
+++ b/entries/jlaw_citegraph/__init__.py
@@ -0,0 +1,167 @@
+#! /usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2026 Tiago de Paula Peixoto <tiago@skewed.de>
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License along
+# with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+from .. import *
+import json
+
+title = "Japanese statutory law citations (JLaw-CiteGraph, 2026)"
+description = r"""Directed networks of the citations between the national laws of Japan in force in September and October 2026, from JLaw-CiteGraph (versions 2.0 to 2.5), a dataset built by automatic extraction of the references in the texts of the laws of e-Gov 法令検索 (e-Gov Law Search, the official law database of the Japanese Digital Agency), from its bulk downloads. The laws are the national statutes in force (in the latest snapshot, of 20 October 2026, 8,981 laws: 法律 acts 2,100, 政令 cabinet orders 2,310, 府省令 ministerial ordinances 4,095, 規則 rules 409, 勅令 imperial ordinances 66, and the constitution), each at the version in force on the date of the snapshot; local ordinances, case law, administrative circulars, treaties, repealed laws and amending acts are not included as nodes, and the citations to them are left out. The references were extracted by rules (exact titles and law numbers of the cited laws, abbreviations, anaphoric references such as 同法 "the same act" and 前条 "the preceding article"), with resolution rates reported by the authors of 93 % for references within a law, 82 % between laws and 92 % for relative references.
+
+There are two networks for each of the six snapshots of the e-Gov data in the history of the dataset (2026-09-27, 2026-09-28, 2026-10-01, 2026-10-03, 2026-10-19 and 2026-10-20; the dataset was rebuilt from each new e-Gov bulk download), named `laws_<date>` and `provisions_<date>` (e.g. `laws_2026-10-20`):
+
+- `laws_<date>`: each node is a law (all of them, including those without citations), and a directed edge from law A to law B means that the text of A cites B (citations within the same law are not included), weighted by the number of citing provisions (70,774 edges in the latest snapshot).
+- `provisions_<date>`: each node is a provision of a law (an article, a paragraph, an item, an article of the supplementary provisions, or an attached table, form or figure), or a law as a whole, and a directed edge from A to B is a reference from provision A to B, of one of four kinds: `CITES` (a citation of another provision, in the same law or another one), `DELEGATES_TO` (a delegation, such as "as provided by cabinet order", from a provision to the law that it delegates to, as a whole), `REFERS_TO_ATTACHMENT` (a reference to an attached table, form, etc.) and `AMENDS`. Only the provisions that take part in some reference are included. The network is a multigraph: a few pairs of provisions are joined by references of different kinds. The hierarchy of the provisions (law, chapter, article, paragraph, item) is not included as edges; it can be recovered from the identifiers of the nodes.
+
+The nodes are identified by the e-Gov law ids (e.g. `129AC0000000089` for the Civil Code), followed for provisions by their position within the law (e.g. `129AC0000000089_a709` for article 709 of the Civil Code, `…_a10-2_p3_i12-2` for item 12-2 of paragraph 3 of article 10-2, `…_asup-sp1-2` for article 2 of the supplementary provisions, `…_at-style-1` for form 1). 
+
+The `laws_<date>` networks have the following properties:
+
+- `law_id`: the e-Gov law id; `name`: the title of the law (in Japanese); `type`: its type (`法律`, `政令`, `府省令`, `規則`, `勅令`, `憲法`); `url`: the page of the law on e-Gov.
+- `enforcement_date`: the date on which the version of the law in the data came into force (`YYYYMMDD`); `next_enforcement_date`: the date of the next amendment that is already decided (empty if none); `pending_versions`: the number of amendments that are decided but not yet in force.
+- Edge `count`: the number of citations (pairs of citing provision and cited provision of the two laws).
+
+The `provisions_<date>` networks have the following properties:
+
+- `node_id`: the identifier of the provision (see above).
+- `level`: its kind: `law`, `article`, `paragraph`, `item`, `supplementary_article` or `attachment`.
+- `law_id`, `law_name`, `law_type`: the id, the title and the type of the law that contains the provision.
+- Edge `relation`: `CITES`, `DELEGATES_TO`, `REFERS_TO_ATTACHMENT` or `AMENDS`.
+- Edge `raw`: the text of the reference (e.g. `前項`, `第一条`, `民法第七百九条`).
+- Edge `extracted_from`: how the reference was resolved (e.g. `canonical`, `alias`, `same_as_last`, `INTERNAL_PAT`, `REFERENTIAL/前項`; see the data card).
+- Edge `fallback_level`: how precisely the target was located (e.g. `exact`, or the enclosing provision when the cited one was not found; empty if not given).
+- Edge `confidence`: the confidence of the resolution given by the authors (NaN if not given).
+- Edge `pre_amendment`: whether the citation names the text of the law before an amendment (e.g. "the former act"), whereas only the current text is in the graph."""
+tags = ['Informational', 'Citation', 'Legal', 'Weighted', 'Multigraph', 'Metadata']
+url = ['https://huggingface.co/datasets/yabooung/jp-law-citation-graph',
+       'https://github.com/yabooung/jp-law-citation-graph',
+       'https://laws.e-gov.go.jp/']
+citation = [('yabooung, "JLaw-CiteGraph: a citation graph of Japanese statutory law." Hugging Face dataset, versions 2.0-2.5 (2026)',
+             'https://huggingface.co/datasets/yabooung/jp-law-citation-graph')]
+icon_hash = None
+upstream_license = ("CC BY 4.0 (data derived from e-Gov 法令検索, Digital Agency of Japan)",
+                    "https://creativecommons.org/licenses/by/4.0/")
+
+# The snapshots of the dataset (e-Gov snapshot date: pinned commit); for
+# snapshots that were committed twice (2026-09-27, 2026-09-28), the later
+# commit (the data files are the same)
+_snapshots = {"2026-09-27": "fa9742dc69211d450d9479da6fe197c58e1c5990",
+              "2026-09-28": "66d6d96f99ca7c9cd438b23e9909723723cc1350",
+              "2026-10-01": "0f38492c8628561feda6615ce91b72611d3de099",
+              "2026-10-03": "da72019c57c179be8f4ca9915ec864dc2621a645",
+              "2026-10-19": "39afbbeb8e60e9c5649d2c751c78b5141ddad770",
+              "2026-10-20": "0888de66c2d65f08ae6c098a11b4bfd243d38b17"}
+upstream_prefix = 'https://huggingface.co/datasets/yabooung/jp-law-citation-graph/resolve'
+files = []
+for _d, _c in _snapshots.items():
+    files += [((f"{_c}/data/laws.csv", f"{_c}/data/cites_law_to_law.csv"),
+               f"laws_{_d}", None),
+              ((f"{_c}/data/laws.csv", f"{_c}/data/cites_all_edges.jsonl.gz",
+                f"{_c}/data/cites_edges.jsonl.gz"), f"provisions_{_d}", None)]
+
+def fetch_upstream(force=False):
+    return fetch_upstream_files(__name__.split(".")[-1], upstream_prefix, files,
+                                force)
+
+def _read_laws(name, fname):
+    with open_upstream_file(name, fname, "r") as f:
+        return list(csv.DictReader(f))
+
+def _level(node):
+    if "_" not in node:
+        return "law"
+    last = node.rsplit("_", 1)[1]
+    if last.startswith("asup"):
+        return "supplementary_article"
+    if last.startswith("at-"):
+        return "attachment"
+    return {"a": "article", "p": "paragraph", "i": "item"}.get(last[0], last)
+
+# For checks only: if set, only this many lines are read of each file
+_check_rows = None
+
+@cache_network()
+@coerce_props()
+@annotate()
+def parse(alts=None):
+    name = __name__.split(".")[-1]
+    for fnames, alt, fmt in files:
+        if alts is not None and alt not in alts:
+            continue
+        laws = _read_laws(name, fnames[0])
+        lidx = {r["law_id"]: i for i, r in enumerate(laws)}
+        if alt.startswith("laws_"):
+            g = Graph(directed=True)
+            g.add_vertex(len(laws))
+            for k in ["law_id", "name", "type", "url", "enforcement_date",
+                      "next_enforcement_date"]:
+                g.vp[k] = g.new_vp("string", vals=[r[k] for r in laws])
+            g.vp.pending_versions = g.new_vp("int", vals=[int(r["pending_versions"] or 0)
+                                                          for r in laws])
+            edges = []
+            with open_upstream_file(name, fnames[1], "r") as f:
+                for r in csv.DictReader(f):
+                    edges.append((lidx[r["src_law_id"]], lidx[r["tgt_law_id"]],
+                                  int(r["n_citations"])))
+            g.ep.count = g.new_ep("int")
+            g.add_edge_list(edges, eprops=[g.ep.count])
+        else:
+            # the citations that name the text before an amendment
+            pre = set()
+            with open_upstream_file(name, fnames[2], "r") as f:
+                for n, line in enumerate(f):
+                    if _check_rows is not None and n >= _check_rows:
+                        break
+                    o = json.loads(line)
+                    if o.get("version") == "pre_amendment":
+                        pre.add((o["src_node"], o["tgt_node"]))
+            idx = {}
+            edges = []
+            ep = defaultdict(list)
+            with open_upstream_file(name, fnames[1], "r") as f:
+                for n, line in enumerate(f):
+                    if _check_rows is not None and n >= _check_rows:
+                        break
+                    o = json.loads(line)
+                    for k in ("source", "target"):
+                        if o[k] not in idx:
+                            idx[o[k]] = len(idx)
+                    edges.append((idx[o["source"]], idx[o["target"]]))
+                    ep["relation"].append(o["rel"])
+                    ep["raw"].append(o.get("raw") or "")
+                    ep["extracted_from"].append(o.get("extracted_from") or "")
+                    ep["fallback_level"].append(o.get("fallback_level") or "")
+                    c = o.get("confidence")
+                    ep["confidence"].append(numpy.nan if c is None else float(c))
+                    ep["pre_amendment"].append((o["source"], o["target"]) in pre)
+            g = Graph(directed=True)
+            g.add_vertex(len(idx))
+            g.add_edge_list(edges)
+            del edges
+            nodes = list(idx)
+            g.vp.node_id = g.new_vp("string", vals=nodes)
+            g.vp.level = g.new_vp("string", vals=[_level(n) for n in nodes])
+            law_ids = [n.split("_", 1)[0] for n in nodes]
+            g.vp.law_id = g.new_vp("string", vals=law_ids)
+            for k, c in [("law_name", "name"), ("law_type", "type")]:
+                g.vp[k] = g.new_vp("string", vals=[laws[lidx[l]][c] if l in lidx else ""
+                                                   for l in law_ids])
+            for k, vals in ep.items():
+                t = {"confidence": "double", "pre_amendment": "bool"}.get(k, "string")
+                g.ep[k] = g.new_ep(t, vals=vals)
+        yield alt, g