Skip to content

Commit 16dc001

Browse files
authored
Merge branch 'master' into lint_targets
2 parents 23ae9ab + b098e98 commit 16dc001

16 files changed

+241
-40
lines changed

.github/workflows/benchmarks.yml

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: Benchmarks
2+
3+
on:
4+
push:
5+
branches: [master]
6+
7+
jobs:
8+
build:
9+
runs-on: ubuntu-latest
10+
11+
steps:
12+
- uses: actions/checkout@v2
13+
- name: Set up Python 3.9
14+
uses: actions/setup-python@v2
15+
with:
16+
python-version: 3.9
17+
- name: Install dependencies
18+
run: |
19+
python -m pip install --upgrade pip
20+
pip install .[benchmark]
21+
- name: Benchmark with asv
22+
run: |
23+
asv machine --yes
24+
asv run

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,6 @@ dmypy.json
128128

129129
# Pyre type checker
130130
.pyre/
131+
132+
# asv
133+
.asv

asv.conf.json

+160
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
{
2+
// The version of the config file format. Do not change, unless
3+
// you know what you are doing.
4+
"version": 1,
5+
6+
// The name of the project being benchmarked
7+
"project": "ac-library-python",
8+
9+
// The project's homepage
10+
"project_url": "https://github.com/not522/ac-library-python",
11+
12+
// The URL or local path of the source code repository for the
13+
// project being benchmarked
14+
"repo": ".",
15+
16+
// The Python project's subdirectory in your repo. If missing or
17+
// the empty string, the project is assumed to be located at the root
18+
// of the repository.
19+
// "repo_subdir": "",
20+
21+
// Customizable commands for building, installing, and
22+
// uninstalling the project. See asv.conf.json documentation.
23+
//
24+
// "install_command": ["in-dir={env_dir} python -mpip install {wheel_file}"],
25+
// "uninstall_command": ["return-code=any python -mpip uninstall -y {project}"],
26+
// "build_command": [
27+
// "python setup.py build",
28+
// "PIP_NO_BUILD_ISOLATION=false python -mpip wheel --no-deps --no-index -w {build_cache_dir} {build_dir}"
29+
// ],
30+
31+
// List of branches to benchmark. If not provided, defaults to "master"
32+
// (for git) or "default" (for mercurial).
33+
// "branches": ["master"], // for git
34+
// "branches": ["default"], // for mercurial
35+
36+
// The DVCS being used. If not set, it will be automatically
37+
// determined from "repo" by looking at the protocol in the URL
38+
// (if remote), or by looking for special directories, such as
39+
// ".git" (if local).
40+
// "dvcs": "git",
41+
42+
// The tool to use to create environments. May be "conda",
43+
// "virtualenv" or other value depending on the plugins in use.
44+
// If missing or the empty string, the tool will be automatically
45+
// determined by looking for tools on the PATH environment
46+
// variable.
47+
"environment_type": "virtualenv",
48+
49+
// timeout in seconds for installing any dependencies in environment
50+
// defaults to 10 min
51+
//"install_timeout": 600,
52+
53+
// the base URL to show a commit for the project.
54+
"show_commit_url": "https://github.com/not522/ac-library-python/commit/",
55+
56+
// The Pythons you'd like to test against. If not provided, defaults
57+
// to the current version of Python used to run `asv`.
58+
// "pythons": ["2.7", "3.6"],
59+
60+
// The list of conda channel names to be searched for benchmark
61+
// dependency packages in the specified order
62+
// "conda_channels": ["conda-forge", "defaults"],
63+
64+
// The matrix of dependencies to test. Each key is the name of a
65+
// package (in PyPI) and the values are version numbers. An empty
66+
// list or empty string indicates to just test against the default
67+
// (latest) version. null indicates that the package is to not be
68+
// installed. If the package to be tested is only available from
69+
// PyPi, and the 'environment_type' is conda, then you can preface
70+
// the package name by 'pip+', and the package will be installed via
71+
// pip (with all the conda available packages installed first,
72+
// followed by the pip installed packages).
73+
//
74+
// "matrix": {
75+
// "numpy": ["1.6", "1.7"],
76+
// "six": ["", null], // test with and without six installed
77+
// "pip+emcee": [""], // emcee is only available for install with pip.
78+
// },
79+
80+
// Combinations of libraries/python versions can be excluded/included
81+
// from the set to test. Each entry is a dictionary containing additional
82+
// key-value pairs to include/exclude.
83+
//
84+
// An exclude entry excludes entries where all values match. The
85+
// values are regexps that should match the whole string.
86+
//
87+
// An include entry adds an environment. Only the packages listed
88+
// are installed. The 'python' key is required. The exclude rules
89+
// do not apply to includes.
90+
//
91+
// In addition to package names, the following keys are available:
92+
//
93+
// - python
94+
// Python version, as in the *pythons* variable above.
95+
// - environment_type
96+
// Environment type, as above.
97+
// - sys_platform
98+
// Platform, as in sys.platform. Possible values for the common
99+
// cases: 'linux2', 'win32', 'cygwin', 'darwin'.
100+
//
101+
// "exclude": [
102+
// {"python": "3.2", "sys_platform": "win32"}, // skip py3.2 on windows
103+
// {"environment_type": "conda", "six": null}, // don't run without six on conda
104+
// ],
105+
//
106+
// "include": [
107+
// // additional env for python2.7
108+
// {"python": "2.7", "numpy": "1.8"},
109+
// // additional env if run on windows+conda
110+
// {"platform": "win32", "environment_type": "conda", "python": "2.7", "libpython": ""},
111+
// ],
112+
113+
// The directory (relative to the current directory) that benchmarks are
114+
// stored in. If not provided, defaults to "benchmarks"
115+
// "benchmark_dir": "benchmarks",
116+
117+
// The directory (relative to the current directory) to cache the Python
118+
// environments in. If not provided, defaults to "env"
119+
"env_dir": ".asv/env",
120+
121+
// The directory (relative to the current directory) that raw benchmark
122+
// results are stored in. If not provided, defaults to "results".
123+
"results_dir": ".asv/results",
124+
125+
// The directory (relative to the current directory) that the html tree
126+
// should be written to. If not provided, defaults to "html".
127+
"html_dir": ".asv/html",
128+
129+
// The number of characters to retain in the commit hashes.
130+
// "hash_length": 8,
131+
132+
// `asv` will cache results of the recent builds in each
133+
// environment, making them faster to install next time. This is
134+
// the number of builds to keep, per environment.
135+
// "build_cache_size": 2,
136+
137+
// The commits after which the regression search in `asv publish`
138+
// should start looking for regressions. Dictionary whose keys are
139+
// regexps matching to benchmark names, and values corresponding to
140+
// the commit (exclusive) after which to start looking for
141+
// regressions. The default is to start from the first commit
142+
// with results. If the commit is `null`, regression detection is
143+
// skipped for the matching benchmark.
144+
//
145+
// "regressions_first_commits": {
146+
// "some_benchmark": "352cdf", // Consider regressions only after this commit
147+
// "another_benchmark": null, // Skip regression detection altogether
148+
// },
149+
150+
// The thresholds for relative change in results, after which `asv
151+
// publish` starts reporting regressions. Dictionary of the same
152+
// form as in ``regressions_first_commits``, with values
153+
// indicating the thresholds. If multiple entries match, the
154+
// maximum is taken. If no entry matches, the default is 5%.
155+
//
156+
// "regressions_thresholds": {
157+
// "some_benchmark": 0.01, // Threshold of 1%
158+
// "another_benchmark": 0.5, // Threshold of 50%
159+
// },
160+
}

atcoder/_scc.py

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import copy
21
import sys
32
import typing
43

@@ -15,7 +14,7 @@ def __init__(
1514
for i in range(1, n + 1):
1615
self.start[i] += self.start[i - 1]
1716

18-
counter = copy.deepcopy(self.start)
17+
counter = self.start.copy()
1918
for e in edges:
2019
self.elist[counter[e[0]]] = e[1]
2120
counter[e[0]] += 1

atcoder/mincostflow.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,12 @@ def get_edge(self, i: int) -> Edge:
5151
def edges(self) -> List[Edge]:
5252
return [self.get_edge(i) for i in range(len(self._edges))]
5353

54-
def flow(self, s: int, t: int, flow_limit: Optional[int] = None) -> Tuple[int, int]:
54+
def flow(self, s: int, t: int,
55+
flow_limit: Optional[int] = None) -> Tuple[int, int]:
5556
return self.slope(s, t, flow_limit)[-1]
5657

57-
def slope(self, s: int, t: int, flow_limit: Optional[int] = None) -> List[Tuple[int, int]]:
58+
def slope(self, s: int, t: int,
59+
flow_limit: Optional[int] = None) -> List[Tuple[int, int]]:
5860
assert 0 <= s < self._n
5961
assert 0 <= t < self._n
6062
assert s != t

benchmarks/__init__.py

Whitespace-only changes.

benchmarks/benchmark_dsu.py

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import random
2+
3+
from atcoder.dsu import DSU
4+
5+
6+
class DSUSuite:
7+
8+
def setup(self) -> None:
9+
random.seed(0)
10+
self.n = 100000
11+
self.pairs = []
12+
for _ in range(1000000):
13+
a = random.randrange(0, self.n)
14+
b = random.randrange(0, self.n)
15+
self.pairs.append((a, b))
16+
17+
def time_dsu_merge(self) -> None:
18+
dsu = DSU(self.n)
19+
for i, j in self.pairs:
20+
dsu.merge(i, j)

example/__init__.py

Whitespace-only changes.

example/lazysegtree_practice_k.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# https://atcoder.jp/contests/practice2/tasks/practice2_k
22

33
import sys
4+
from typing import Tuple
45

56
from atcoder.lazysegtree import LazySegTree
67
from atcoder.modint import ModContext, Modint
@@ -11,16 +12,18 @@ def main() -> None:
1112
n, q = map(int, sys.stdin.readline().split())
1213
a = [(Modint(ai), 1) for ai in map(int, sys.stdin.readline().split())]
1314

14-
def op(x: (Modint, int), y: (Modint, int)) -> (Modint, int):
15+
def op(x: Tuple[Modint, int],
16+
y: Tuple[Modint, int]) -> Tuple[Modint, int]:
1517
return x[0] + y[0], x[1] + y[1]
1618

1719
e = Modint(0), 0
1820

19-
def mapping(x: (Modint, Modint), y: (Modint, int)) -> (Modint, int):
21+
def mapping(x: Tuple[Modint, Modint],
22+
y: Tuple[Modint, int]) -> Tuple[Modint, int]:
2023
return x[0] * y[0] + x[1] * y[1], y[1]
2124

22-
def composition(x: (Modint, Modint),
23-
y: (Modint, Modint)) -> (Modint, Modint):
25+
def composition(x: Tuple[Modint, Modint],
26+
y: Tuple[Modint, Modint]) -> Tuple[Modint, Modint]:
2427
return x[0] * y[0], x[0] * y[1] + x[1]
2528

2629
id_ = Modint(1), Modint(0)

example/lazysegtree_practice_k_wo_modint.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# https://atcoder.jp/contests/practice2/tasks/practice2_k
22

33
import sys
4+
from typing import Tuple
45

56
from atcoder.lazysegtree import LazySegTree
67

@@ -11,15 +12,15 @@ def main() -> None:
1112
n, q = map(int, sys.stdin.readline().split())
1213
a = [(ai, 1) for ai in map(int, sys.stdin.readline().split())]
1314

14-
def op(x: (int, int), y: (int, int)) -> (int, int):
15+
def op(x: Tuple[int, int], y: Tuple[int, int]) -> Tuple[int, int]:
1516
return (x[0] + y[0]) % mod, x[1] + y[1]
1617

1718
e = 0, 0
1819

19-
def mapping(x: (int, int), y: (int, int)) -> (int, int):
20+
def mapping(x: Tuple[int, int], y: Tuple[int, int]) -> Tuple[int, int]:
2021
return (x[0] * y[0] + x[1] * y[1]) % mod, y[1]
2122

22-
def composition(x: (int, int), y: (int, int)) -> (int, int):
23+
def composition(x: Tuple[int, int], y: Tuple[int, int]) -> Tuple[int, int]:
2324
return (x[0] * y[0]) % mod, (x[0] * y[1] + x[1]) % mod
2425

2526
id_ = 1, 0

example/lazysegtree_practice_l.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# https://atcoder.jp/contests/practice2/tasks/practice2_l
22

33
import sys
4+
from typing import Tuple
45

56
from atcoder.lazysegtree import LazySegTree
67

@@ -14,12 +15,13 @@ def main() -> None:
1415
else:
1516
a.append((0, 1, 0))
1617

17-
def op(x: (int, int, int), y: (int, int, int)) -> (int, int, int):
18+
def op(x: Tuple[int, int, int],
19+
y: Tuple[int, int, int]) -> Tuple[int, int, int]:
1820
return x[0] + y[0], x[1] + y[1], x[2] + y[2] + x[1] * y[0]
1921

2022
e = (0, 0, 0)
2123

22-
def mapping(x: bool, y: (int, int, int)) -> (int, int, int):
24+
def mapping(x: bool, y: Tuple[int, int, int]) -> Tuple[int, int, int]:
2325
if not x:
2426
return y
2527
return y[1], y[0], y[0] * y[1] - y[2]

example/maxflow_practice.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# https://atcoder.jp/contests/practice2/tasks/practice2_d
22

33
import sys
4+
from typing import Tuple
45

56
from atcoder.maxflow import MFGraph
67

@@ -15,7 +16,7 @@ def main() -> None:
1516
def enc(i: int, j: int) -> int:
1617
return i * m + j
1718

18-
def dec(v: int) -> (int, int):
19+
def dec(v: int) -> Tuple[int, int]:
1920
return v // m, v % m
2021

2122
for i in range(n):
@@ -58,8 +59,8 @@ def dec(v: int) -> (int, int):
5859
grid[i][j] = '>'
5960
grid[ii][jj] = '<'
6061

61-
for s in grid:
62-
print("".join(s))
62+
for r in grid:
63+
print("".join(r))
6364

6465

6566
if __name__ == '__main__':

example/mincostflow_practice.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# https://atcoder.jp/contests/practice2/tasks/practice2_e
22

33
import sys
4+
from typing import List
45

56
from atcoder.mincostflow import MCFGraph
67

@@ -12,7 +13,7 @@ def main() -> None:
1213
g = MCFGraph(t + 1)
1314
grid = [list(map(int, sys.stdin.readline().split())) for _ in range(n)]
1415
big = 10 ** 9
15-
edges = list([] for _ in range(n))
16+
edges: List[List[int]] = list([] for _ in range(n))
1617
for i in range(n):
1718
g.add_edge(s, i, k, 0)
1819
g.add_edge(i + n, t, k, 0)
@@ -29,8 +30,8 @@ def main() -> None:
2930
if g.get_edge(edges[i][j]).flow > 0:
3031
result[i][j] = 'X'
3132

32-
for s in result:
33-
print("".join(s))
33+
for r in result:
34+
print("".join(r))
3435

3536

3637
if __name__ == '__main__':

example/scc_practice.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ def main() -> None:
1616
scc = g.scc()
1717

1818
print(len(scc))
19-
for v in scc:
20-
print(len(v), end='')
21-
for x in v:
19+
for c in scc:
20+
print(len(c), end='')
21+
for x in c:
2222
print(f' {x}', end='')
2323
print('')
2424

0 commit comments

Comments
 (0)