vectorized
This commit is contained in:
@@ -1,20 +1,21 @@
|
|||||||
import math
|
import numpy as np
|
||||||
|
from numpy.typing import NDArray
|
||||||
|
|
||||||
from .primitive import Operation
|
from .primitive import Operation
|
||||||
|
|
||||||
|
type Value = NDArray[np.float64]
|
||||||
|
|
||||||
# Унарные операции
|
# Унарные операции
|
||||||
NEG = Operation("-", 1, lambda x: -x[0])
|
NEG = Operation("-", 1, lambda x: -x[0])
|
||||||
SIN = Operation("sin", 1, lambda x: math.sin(x[0]))
|
SIN = Operation("sin", 1, lambda x: np.sin(x[0]))
|
||||||
COS = Operation("cos", 1, lambda x: math.cos(x[0]))
|
COS = Operation("cos", 1, lambda x: np.cos(x[0]))
|
||||||
|
|
||||||
|
|
||||||
def _safe_exp(a: float) -> float:
|
def _safe_exp(v: Value) -> Value:
|
||||||
if a < 700.0:
|
v_clipped = np.clip(v, -10.0, 10.0)
|
||||||
if a > -700.0:
|
out = np.exp(v_clipped)
|
||||||
return math.exp(a)
|
out[np.isnan(out) | np.isinf(out)] = 0.0
|
||||||
return 0.0
|
return out
|
||||||
else:
|
|
||||||
return float("inf")
|
|
||||||
|
|
||||||
|
|
||||||
EXP = Operation("exp", 1, lambda x: _safe_exp(x[0]))
|
EXP = Operation("exp", 1, lambda x: _safe_exp(x[0]))
|
||||||
@@ -24,28 +25,34 @@ EXP = Operation("exp", 1, lambda x: _safe_exp(x[0]))
|
|||||||
ADD = Operation("+", 2, lambda x: x[0] + x[1])
|
ADD = Operation("+", 2, lambda x: x[0] + x[1])
|
||||||
SUB = Operation("-", 2, lambda x: x[0] - x[1])
|
SUB = Operation("-", 2, lambda x: x[0] - x[1])
|
||||||
MUL = Operation("*", 2, lambda x: x[0] * x[1])
|
MUL = Operation("*", 2, lambda x: x[0] * x[1])
|
||||||
DIV = Operation("/", 2, lambda x: x[0] / x[1] if x[1] != 0 else float("inf"))
|
|
||||||
|
|
||||||
|
|
||||||
def safe_pow(a, b):
|
def _safe_div(a: Value, b: Value) -> Value:
|
||||||
# 0 в отрицательной степени
|
eps = 1e-12
|
||||||
if abs(a) <= 1e-12 and b < 0:
|
denom = np.where(np.abs(b) >= eps, b, eps)
|
||||||
return float("inf")
|
out = np.divide(a, denom)
|
||||||
# отрицательное основание при нецелой степени
|
out = np.where(np.isnan(out) | np.isinf(out), 0.0, out)
|
||||||
if a < 0 and abs(b - round(b)) > 1e-12:
|
return out
|
||||||
return float("inf")
|
|
||||||
# грубое насыщение (настрой пороги под задачу)
|
|
||||||
if abs(a) > 1 and b > 20:
|
|
||||||
return float("inf")
|
|
||||||
if abs(a) < 1 and b < -20:
|
|
||||||
return float("inf")
|
|
||||||
try:
|
|
||||||
return a**b
|
|
||||||
except (OverflowError, ValueError):
|
|
||||||
return float("inf")
|
|
||||||
|
|
||||||
|
|
||||||
POW = Operation("^", 2, lambda x: safe_pow(x[0], x[1]))
|
DIV = Operation("/", 2, lambda x: _safe_div(x[0], x[1]))
|
||||||
|
|
||||||
|
|
||||||
|
def _safe_pow(a: Value, b: Value) -> Value:
|
||||||
|
a_clip = np.clip(a, -1e3, 1e3)
|
||||||
|
b_clip = np.clip(b, -3.0, 3.0)
|
||||||
|
|
||||||
|
# 0 в отрицательной степени → 0
|
||||||
|
mask_zero_neg = (a_clip == 0.0) & (b_clip < 0.0)
|
||||||
|
with np.errstate(over="ignore", invalid="ignore", divide="ignore", under="ignore"):
|
||||||
|
out = np.power(a_clip, b_clip)
|
||||||
|
|
||||||
|
out[mask_zero_neg] = 0.0
|
||||||
|
out[np.isnan(out) | np.isinf(out)] = 0.0
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
POW = Operation("^", 2, lambda x: _safe_pow(x[0], x[1]))
|
||||||
|
|
||||||
# Все операции в либе
|
# Все операции в либе
|
||||||
ALL = (NEG, SIN, COS, EXP, ADD, SUB, MUL, DIV, POW)
|
ALL = (NEG, SIN, COS, EXP, ADD, SUB, MUL, DIV, POW)
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
from typing import TYPE_CHECKING, Callable, Protocol
|
from typing import TYPE_CHECKING, Callable, Protocol
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
from numpy.typing import NDArray
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .chromosome import Chromosome
|
from .chromosome import Chromosome
|
||||||
from .node import Node
|
from .node import Node
|
||||||
from .primitive import Primitive
|
from .primitive import Primitive
|
||||||
|
|
||||||
type InitFunc = Callable[["Chromosome"], "Node"]
|
type Population = list[Chromosome]
|
||||||
type Value = float
|
type InitFunc = Callable[[Chromosome], Node]
|
||||||
|
type Value = NDArray[np.float64]
|
||||||
|
|
||||||
|
|
||||||
class Context(Protocol):
|
class Context(Protocol):
|
||||||
def __getitem__(self, key: "Primitive", /) -> Value: ...
|
def __getitem__(self, key: Primitive, /) -> Value: ...
|
||||||
|
|||||||
29
lab4/gp/utils.py
Normal file
29
lab4/gp/utils.py
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
from typing import Sequence
|
||||||
|
|
||||||
|
from .chromosome import Chromosome
|
||||||
|
from .primitive import Primitive
|
||||||
|
from .types import Population
|
||||||
|
|
||||||
|
|
||||||
|
def ramped_initialization(
|
||||||
|
chromosomes_per_variation: int,
|
||||||
|
depths: list[int],
|
||||||
|
terminals: Sequence[Primitive],
|
||||||
|
operations: Sequence[Primitive],
|
||||||
|
) -> Population:
|
||||||
|
"""Комбинация методов grow и full инициализации хромосом для инициализации начальной
|
||||||
|
популяции.
|
||||||
|
"""
|
||||||
|
population: Population = []
|
||||||
|
|
||||||
|
for depth in depths:
|
||||||
|
population.extend(
|
||||||
|
Chromosome.full_init(terminals, operations, depth)
|
||||||
|
for _ in range(chromosomes_per_variation)
|
||||||
|
)
|
||||||
|
population.extend(
|
||||||
|
Chromosome.grow_init(terminals, operations, depth)
|
||||||
|
for _ in range(chromosomes_per_variation)
|
||||||
|
)
|
||||||
|
|
||||||
|
return population
|
||||||
31
lab4/main.py
31
lab4/main.py
@@ -1,3 +1,5 @@
|
|||||||
|
import numpy as np
|
||||||
|
|
||||||
from gp import Chromosome, ops
|
from gp import Chromosome, ops
|
||||||
from gp.population import ramped_initialization
|
from gp.population import ramped_initialization
|
||||||
from gp.primitive import Var
|
from gp.primitive import Var
|
||||||
@@ -10,16 +12,25 @@ print("Depth:", chrom.root.get_subtree_depth())
|
|||||||
print("Formula:", chrom)
|
print("Formula:", chrom)
|
||||||
print("Tree:\n", chrom.root.to_str_tree())
|
print("Tree:\n", chrom.root.to_str_tree())
|
||||||
|
|
||||||
values = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0]
|
values = [
|
||||||
|
np.array([1.0]),
|
||||||
|
np.array([2.0]),
|
||||||
|
np.array([3.0]),
|
||||||
|
np.array([4.0]),
|
||||||
|
np.array([5.0]),
|
||||||
|
np.array([6.0]),
|
||||||
|
np.array([7.0]),
|
||||||
|
np.array([8.0]),
|
||||||
|
]
|
||||||
context = {var: value for var, value in zip(terminals, values)}
|
context = {var: value for var, value in zip(terminals, values)}
|
||||||
print("Value for ", values, ":", chrom.root.eval(context))
|
print("Value for ", values, ":", chrom.root.eval(context))
|
||||||
|
|
||||||
# population = ramped_initialization(
|
population = ramped_initialization(
|
||||||
# 5,
|
5,
|
||||||
# [3, 4, 5, 6, 7, 8],
|
[3, 4, 5, 6, 7, 8],
|
||||||
# terminals,
|
terminals,
|
||||||
# operations,
|
operations,
|
||||||
# )
|
)
|
||||||
# print("Population size:", len(population))
|
print("Population size:", len(population))
|
||||||
# print("Population:")
|
print("Population:")
|
||||||
# [print(str(chrom)) for chrom in population]
|
[print(str(chrom)) for chrom in population]
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
name = "lab4"
|
name = "lab4"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
requires-python = ">=3.14"
|
requires-python = ">=3.14"
|
||||||
dependencies = []
|
dependencies = [
|
||||||
|
"numpy>=2.3.4",
|
||||||
|
]
|
||||||
|
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
target-version = "py314"
|
target-version = "py314"
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
# Tests for gp library
|
|
||||||
|
|
||||||
@@ -1,304 +0,0 @@
|
|||||||
import math
|
|
||||||
import sys
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
# Добавляем путь к родительской директории для корректных импортов
|
|
||||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
||||||
|
|
||||||
from gp.chromosome import Chromosome
|
|
||||||
from gp.operation import Operation
|
|
||||||
from gp.ops import ADD, COS, DIV, EXP, MUL, NEG, SIN, SUB
|
|
||||||
from gp.terminal import Terminal
|
|
||||||
|
|
||||||
|
|
||||||
class TestChromosomeEval:
|
|
||||||
"""Тесты для метода eval класса Chromosome."""
|
|
||||||
|
|
||||||
def test_eval_single_terminal(self):
|
|
||||||
"""Тест вычисления хромосомы с одним терминалом."""
|
|
||||||
x = Terminal("x")
|
|
||||||
|
|
||||||
def init_single_terminal(chr: Chromosome) -> Chromosome.Node:
|
|
||||||
return Chromosome.Node(x, [])
|
|
||||||
|
|
||||||
chromosome = Chromosome([ADD], [x], init_single_terminal)
|
|
||||||
|
|
||||||
result = chromosome.eval([5.0])
|
|
||||||
assert result == 5.0
|
|
||||||
|
|
||||||
result = chromosome.eval([-3.5])
|
|
||||||
assert result == -3.5
|
|
||||||
|
|
||||||
def test_eval_addition(self):
|
|
||||||
"""Тест вычисления простого сложения: x + y."""
|
|
||||||
x = Terminal("x")
|
|
||||||
y = Terminal("y")
|
|
||||||
|
|
||||||
def init_addition(chr: Chromosome) -> Chromosome.Node:
|
|
||||||
# Создаём дерево: x + y
|
|
||||||
return Chromosome.Node(
|
|
||||||
ADD,
|
|
||||||
[
|
|
||||||
Chromosome.Node(x, []),
|
|
||||||
Chromosome.Node(y, []),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
chromosome = Chromosome([ADD], [x, y], init_addition)
|
|
||||||
|
|
||||||
result = chromosome.eval([3.0, 4.0])
|
|
||||||
assert result == 7.0
|
|
||||||
|
|
||||||
result = chromosome.eval([10.0, -5.0])
|
|
||||||
assert result == 5.0
|
|
||||||
|
|
||||||
def test_eval_subtraction(self):
|
|
||||||
"""Тест вычисления вычитания: x - y."""
|
|
||||||
x = Terminal("x")
|
|
||||||
y = Terminal("y")
|
|
||||||
|
|
||||||
def init_subtraction(chr: Chromosome) -> Chromosome.Node:
|
|
||||||
return Chromosome.Node(
|
|
||||||
SUB,
|
|
||||||
[
|
|
||||||
Chromosome.Node(x, []),
|
|
||||||
Chromosome.Node(y, []),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
chromosome = Chromosome([SUB], [x, y], init_subtraction)
|
|
||||||
|
|
||||||
result = chromosome.eval([10.0, 3.0])
|
|
||||||
assert result == 7.0
|
|
||||||
|
|
||||||
result = chromosome.eval([5.0, 8.0])
|
|
||||||
assert result == -3.0
|
|
||||||
|
|
||||||
def test_eval_multiplication(self):
|
|
||||||
"""Тест вычисления умножения: x * y."""
|
|
||||||
x = Terminal("x")
|
|
||||||
y = Terminal("y")
|
|
||||||
|
|
||||||
def init_multiplication(chr: Chromosome) -> Chromosome.Node:
|
|
||||||
return Chromosome.Node(
|
|
||||||
MUL,
|
|
||||||
[
|
|
||||||
Chromosome.Node(x, []),
|
|
||||||
Chromosome.Node(y, []),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
chromosome = Chromosome([MUL], [x, y], init_multiplication)
|
|
||||||
|
|
||||||
result = chromosome.eval([3.0, 4.0])
|
|
||||||
assert result == 12.0
|
|
||||||
|
|
||||||
result = chromosome.eval([-2.0, 5.0])
|
|
||||||
assert result == -10.0
|
|
||||||
|
|
||||||
def test_eval_division(self):
|
|
||||||
"""Тест вычисления деления: x / y."""
|
|
||||||
x = Terminal("x")
|
|
||||||
y = Terminal("y")
|
|
||||||
|
|
||||||
def init_division(chr: Chromosome) -> Chromosome.Node:
|
|
||||||
return Chromosome.Node(
|
|
||||||
DIV,
|
|
||||||
[
|
|
||||||
Chromosome.Node(x, []),
|
|
||||||
Chromosome.Node(y, []),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
chromosome = Chromosome([DIV], [x, y], init_division)
|
|
||||||
|
|
||||||
result = chromosome.eval([10.0, 2.0])
|
|
||||||
assert result == 5.0
|
|
||||||
|
|
||||||
result = chromosome.eval([7.0, 2.0])
|
|
||||||
assert result == 3.5
|
|
||||||
|
|
||||||
def test_eval_division_by_zero(self):
|
|
||||||
"""Тест деления на ноль (должно вернуть inf)."""
|
|
||||||
x = Terminal("x")
|
|
||||||
y = Terminal("y")
|
|
||||||
|
|
||||||
def init_division(chr: Chromosome) -> Chromosome.Node:
|
|
||||||
return Chromosome.Node(
|
|
||||||
DIV,
|
|
||||||
[
|
|
||||||
Chromosome.Node(x, []),
|
|
||||||
Chromosome.Node(y, []),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
chromosome = Chromosome([DIV], [x, y], init_division)
|
|
||||||
|
|
||||||
result = chromosome.eval([10.0, 0.0])
|
|
||||||
assert result == float("inf")
|
|
||||||
|
|
||||||
def test_eval_unary_negation(self):
|
|
||||||
"""Тест вычисления унарного минуса: -x."""
|
|
||||||
x = Terminal("x")
|
|
||||||
|
|
||||||
def init_negation(chr: Chromosome) -> Chromosome.Node:
|
|
||||||
return Chromosome.Node(NEG, [Chromosome.Node(x, [])])
|
|
||||||
|
|
||||||
chromosome = Chromosome([NEG], [x], init_negation)
|
|
||||||
|
|
||||||
result = chromosome.eval([5.0])
|
|
||||||
assert result == -5.0
|
|
||||||
|
|
||||||
result = chromosome.eval([-3.0])
|
|
||||||
assert result == 3.0
|
|
||||||
|
|
||||||
def test_eval_sin(self):
|
|
||||||
"""Тест вычисления синуса: sin(x)."""
|
|
||||||
x = Terminal("x")
|
|
||||||
|
|
||||||
def init_sin(chr: Chromosome) -> Chromosome.Node:
|
|
||||||
return Chromosome.Node(SIN, [Chromosome.Node(x, [])])
|
|
||||||
|
|
||||||
chromosome = Chromosome([SIN], [x], init_sin)
|
|
||||||
|
|
||||||
result = chromosome.eval([0.0])
|
|
||||||
assert result == pytest.approx(0.0)
|
|
||||||
|
|
||||||
result = chromosome.eval([math.pi / 2])
|
|
||||||
assert result == pytest.approx(1.0)
|
|
||||||
|
|
||||||
result = chromosome.eval([math.pi])
|
|
||||||
assert result == pytest.approx(0.0, abs=1e-10)
|
|
||||||
|
|
||||||
def test_eval_cos(self):
|
|
||||||
"""Тест вычисления косинуса: cos(x)."""
|
|
||||||
x = Terminal("x")
|
|
||||||
|
|
||||||
def init_cos(chr: Chromosome) -> Chromosome.Node:
|
|
||||||
return Chromosome.Node(COS, [Chromosome.Node(x, [])])
|
|
||||||
|
|
||||||
chromosome = Chromosome([COS], [x], init_cos)
|
|
||||||
|
|
||||||
result = chromosome.eval([0.0])
|
|
||||||
assert result == pytest.approx(1.0)
|
|
||||||
|
|
||||||
result = chromosome.eval([math.pi / 2])
|
|
||||||
assert result == pytest.approx(0.0, abs=1e-10)
|
|
||||||
|
|
||||||
result = chromosome.eval([math.pi])
|
|
||||||
assert result == pytest.approx(-1.0)
|
|
||||||
|
|
||||||
def test_eval_complex_expression(self):
|
|
||||||
"""Тест вычисления сложного выражения: (x + y) * (x - y)."""
|
|
||||||
x = Terminal("x")
|
|
||||||
y = Terminal("y")
|
|
||||||
|
|
||||||
def init_complex(chr: Chromosome) -> Chromosome.Node:
|
|
||||||
# (x + y) * (x - y)
|
|
||||||
return Chromosome.Node(
|
|
||||||
MUL,
|
|
||||||
[
|
|
||||||
Chromosome.Node(
|
|
||||||
ADD,
|
|
||||||
[
|
|
||||||
Chromosome.Node(x, []),
|
|
||||||
Chromosome.Node(y, []),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Chromosome.Node(
|
|
||||||
SUB,
|
|
||||||
[
|
|
||||||
Chromosome.Node(x, []),
|
|
||||||
Chromosome.Node(y, []),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
chromosome = Chromosome([ADD, SUB, MUL], [x, y], init_complex)
|
|
||||||
|
|
||||||
# (5 + 3) * (5 - 3) = 8 * 2 = 16
|
|
||||||
result = chromosome.eval([5.0, 3.0])
|
|
||||||
assert result == 16.0
|
|
||||||
|
|
||||||
# (10 + 2) * (10 - 2) = 12 * 8 = 96
|
|
||||||
result = chromosome.eval([10.0, 2.0])
|
|
||||||
assert result == 96.0
|
|
||||||
|
|
||||||
def test_eval_nested_expression(self):
|
|
||||||
"""Тест вычисления вложенного выражения: sin(x + y)."""
|
|
||||||
x = Terminal("x")
|
|
||||||
y = Terminal("y")
|
|
||||||
|
|
||||||
def init_nested(chr: Chromosome) -> Chromosome.Node:
|
|
||||||
# sin(x + y)
|
|
||||||
return Chromosome.Node(
|
|
||||||
SIN,
|
|
||||||
[
|
|
||||||
Chromosome.Node(
|
|
||||||
ADD,
|
|
||||||
[
|
|
||||||
Chromosome.Node(x, []),
|
|
||||||
Chromosome.Node(y, []),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
chromosome = Chromosome([ADD, SIN], [x, y], init_nested)
|
|
||||||
|
|
||||||
result = chromosome.eval([math.pi / 4, math.pi / 4])
|
|
||||||
# sin(π/4 + π/4) = sin(π/2) = 1
|
|
||||||
assert result == pytest.approx(1.0)
|
|
||||||
|
|
||||||
def test_eval_exp(self):
|
|
||||||
"""Тест вычисления экспоненты: exp(x)."""
|
|
||||||
x = Terminal("x")
|
|
||||||
|
|
||||||
def init_exp(chr: Chromosome) -> Chromosome.Node:
|
|
||||||
return Chromosome.Node(EXP, [Chromosome.Node(x, [])])
|
|
||||||
|
|
||||||
chromosome = Chromosome([EXP], [x], init_exp)
|
|
||||||
|
|
||||||
result = chromosome.eval([0.0])
|
|
||||||
assert result == pytest.approx(1.0)
|
|
||||||
|
|
||||||
result = chromosome.eval([1.0])
|
|
||||||
assert result == pytest.approx(math.e)
|
|
||||||
|
|
||||||
result = chromosome.eval([2.0])
|
|
||||||
assert result == pytest.approx(math.e**2)
|
|
||||||
|
|
||||||
def test_eval_multiple_calls(self):
|
|
||||||
"""Тест многократного вызова eval с разными значениями."""
|
|
||||||
x = Terminal("x")
|
|
||||||
y = Terminal("y")
|
|
||||||
|
|
||||||
def init_mul(chr: Chromosome) -> Chromosome.Node:
|
|
||||||
return Chromosome.Node(
|
|
||||||
MUL,
|
|
||||||
[
|
|
||||||
Chromosome.Node(x, []),
|
|
||||||
Chromosome.Node(y, []),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
chromosome = Chromosome([MUL], [x, y], init_mul)
|
|
||||||
|
|
||||||
# Проверяем, что терминалы правильно обновляются
|
|
||||||
assert chromosome.eval([2.0, 3.0]) == 6.0
|
|
||||||
assert chromosome.eval([4.0, 5.0]) == 20.0
|
|
||||||
assert chromosome.eval([10.0, 0.5]) == 5.0
|
|
||||||
|
|
||||||
def test_eval_without_root_raises_error(self):
|
|
||||||
"""Тест, что eval вызывает ошибку, если root = None."""
|
|
||||||
|
|
||||||
def init_none(chr: Chromosome) -> Chromosome.Node:
|
|
||||||
return None # type: ignore
|
|
||||||
|
|
||||||
chromosome = Chromosome([ADD], [Terminal("x")], init_none)
|
|
||||||
|
|
||||||
with pytest.raises(ValueError, match="Chromosome is not initialized"):
|
|
||||||
chromosome.eval([1.0])
|
|
||||||
44
lab4/uv.lock
generated
Normal file
44
lab4/uv.lock
generated
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
version = 1
|
||||||
|
revision = 3
|
||||||
|
requires-python = ">=3.14"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lab4"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = { virtual = "." }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "numpy" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.metadata]
|
||||||
|
requires-dist = [{ name = "numpy", specifier = ">=2.3.4" }]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "numpy"
|
||||||
|
version = "2.3.4"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/b5/f4/098d2270d52b41f1bd7db9fc288aaa0400cb48c2a3e2af6fa365d9720947/numpy-2.3.4.tar.gz", hash = "sha256:a7d018bfedb375a8d979ac758b120ba846a7fe764911a64465fd87b8729f4a6a", size = 20582187, upload-time = "2025-10-15T16:18:11.77Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/72/71/ae6170143c115732470ae3a2d01512870dd16e0953f8a6dc89525696069b/numpy-2.3.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:81c3e6d8c97295a7360d367f9f8553973651b76907988bb6066376bc2252f24e", size = 20955580, upload-time = "2025-10-15T16:17:02.509Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/af/39/4be9222ffd6ca8a30eda033d5f753276a9c3426c397bb137d8e19dedd200/numpy-2.3.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:7c26b0b2bf58009ed1f38a641f3db4be8d960a417ca96d14e5b06df1506d41ff", size = 14188056, upload-time = "2025-10-15T16:17:04.873Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6c/3d/d85f6700d0a4aa4f9491030e1021c2b2b7421b2b38d01acd16734a2bfdc7/numpy-2.3.4-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:62b2198c438058a20b6704351b35a1d7db881812d8512d67a69c9de1f18ca05f", size = 5116555, upload-time = "2025-10-15T16:17:07.499Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bf/04/82c1467d86f47eee8a19a464c92f90a9bb68ccf14a54c5224d7031241ffb/numpy-2.3.4-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:9d729d60f8d53a7361707f4b68a9663c968882dd4f09e0d58c044c8bf5faee7b", size = 6643581, upload-time = "2025-10-15T16:17:09.774Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0c/d3/c79841741b837e293f48bd7db89d0ac7a4f2503b382b78a790ef1dc778a5/numpy-2.3.4-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bd0c630cf256b0a7fd9d0a11c9413b42fef5101219ce6ed5a09624f5a65392c7", size = 14299186, upload-time = "2025-10-15T16:17:11.937Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e8/7e/4a14a769741fbf237eec5a12a2cbc7a4c4e061852b6533bcb9e9a796c908/numpy-2.3.4-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d5e081bc082825f8b139f9e9fe42942cb4054524598aaeb177ff476cc76d09d2", size = 16638601, upload-time = "2025-10-15T16:17:14.391Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/93/87/1c1de269f002ff0a41173fe01dcc925f4ecff59264cd8f96cf3b60d12c9b/numpy-2.3.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:15fb27364ed84114438fff8aaf998c9e19adbeba08c0b75409f8c452a8692c52", size = 16074219, upload-time = "2025-10-15T16:17:17.058Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cd/28/18f72ee77408e40a76d691001ae599e712ca2a47ddd2c4f695b16c65f077/numpy-2.3.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:85d9fb2d8cd998c84d13a79a09cc0c1091648e848e4e6249b0ccd7f6b487fa26", size = 18576702, upload-time = "2025-10-15T16:17:19.379Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c3/76/95650169b465ececa8cf4b2e8f6df255d4bf662775e797ade2025cc51ae6/numpy-2.3.4-cp314-cp314-win32.whl", hash = "sha256:e73d63fd04e3a9d6bc187f5455d81abfad05660b212c8804bf3b407e984cd2bc", size = 6337136, upload-time = "2025-10-15T16:17:22.886Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/dc/89/a231a5c43ede5d6f77ba4a91e915a87dea4aeea76560ba4d2bf185c683f0/numpy-2.3.4-cp314-cp314-win_amd64.whl", hash = "sha256:3da3491cee49cf16157e70f607c03a217ea6647b1cea4819c4f48e53d49139b9", size = 12920542, upload-time = "2025-10-15T16:17:24.783Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0d/0c/ae9434a888f717c5ed2ff2393b3f344f0ff6f1c793519fa0c540461dc530/numpy-2.3.4-cp314-cp314-win_arm64.whl", hash = "sha256:6d9cd732068e8288dbe2717177320723ccec4fb064123f0caf9bbd90ab5be868", size = 10480213, upload-time = "2025-10-15T16:17:26.935Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/83/4b/c4a5f0841f92536f6b9592694a5b5f68c9ab37b775ff342649eadf9055d3/numpy-2.3.4-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:22758999b256b595cf0b1d102b133bb61866ba5ceecf15f759623b64c020c9ec", size = 21052280, upload-time = "2025-10-15T16:17:29.638Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3e/80/90308845fc93b984d2cc96d83e2324ce8ad1fd6efea81b324cba4b673854/numpy-2.3.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:9cb177bc55b010b19798dc5497d540dea67fd13a8d9e882b2dae71de0cf09eb3", size = 14302930, upload-time = "2025-10-15T16:17:32.384Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3d/4e/07439f22f2a3b247cec4d63a713faae55e1141a36e77fb212881f7cda3fb/numpy-2.3.4-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:0f2bcc76f1e05e5ab58893407c63d90b2029908fa41f9f1cc51eecce936c3365", size = 5231504, upload-time = "2025-10-15T16:17:34.515Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ab/de/1e11f2547e2fe3d00482b19721855348b94ada8359aef5d40dd57bfae9df/numpy-2.3.4-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:8dc20bde86802df2ed8397a08d793da0ad7a5fd4ea3ac85d757bf5dd4ad7c252", size = 6739405, upload-time = "2025-10-15T16:17:36.128Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3b/40/8cd57393a26cebe2e923005db5134a946c62fa56a1087dc7c478f3e30837/numpy-2.3.4-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5e199c087e2aa71c8f9ce1cb7a8e10677dc12457e7cc1be4798632da37c3e86e", size = 14354866, upload-time = "2025-10-15T16:17:38.884Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/93/39/5b3510f023f96874ee6fea2e40dfa99313a00bf3ab779f3c92978f34aace/numpy-2.3.4-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85597b2d25ddf655495e2363fe044b0ae999b75bc4d630dc0d886484b03a5eb0", size = 16703296, upload-time = "2025-10-15T16:17:41.564Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/41/0d/19bb163617c8045209c1996c4e427bccbc4bbff1e2c711f39203c8ddbb4a/numpy-2.3.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:04a69abe45b49c5955923cf2c407843d1c85013b424ae8a560bba16c92fe44a0", size = 16136046, upload-time = "2025-10-15T16:17:43.901Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e2/c1/6dba12fdf68b02a21ac411c9df19afa66bed2540f467150ca64d246b463d/numpy-2.3.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e1708fac43ef8b419c975926ce1eaf793b0c13b7356cfab6ab0dc34c0a02ac0f", size = 18652691, upload-time = "2025-10-15T16:17:46.247Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f8/73/f85056701dbbbb910c51d846c58d29fd46b30eecd2b6ba760fc8b8a1641b/numpy-2.3.4-cp314-cp314t-win32.whl", hash = "sha256:863e3b5f4d9915aaf1b8ec79ae560ad21f0b8d5e3adc31e73126491bb86dee1d", size = 6485782, upload-time = "2025-10-15T16:17:48.872Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/17/90/28fa6f9865181cb817c2471ee65678afa8a7e2a1fb16141473d5fa6bacc3/numpy-2.3.4-cp314-cp314t-win_amd64.whl", hash = "sha256:962064de37b9aef801d33bc579690f8bfe6c5e70e29b61783f60bcba838a14d6", size = 13113301, upload-time = "2025-10-15T16:17:50.938Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/54/23/08c002201a8e7e1f9afba93b97deceb813252d9cfd0d3351caed123dcf97/numpy-2.3.4-cp314-cp314t-win_arm64.whl", hash = "sha256:8b5a9a39c45d852b62693d9b3f3e0fe052541f804296ff401a72a1b60edafb29", size = 10547532, upload-time = "2025-10-15T16:17:53.48Z" },
|
||||||
|
]
|
||||||
Reference in New Issue
Block a user