|
| 1 | +#!/usr/bin/env python |
| 2 | +# coding: utf-8 |
| 3 | + |
| 4 | +# In[ ]: |
| 5 | + |
| 6 | +AS = [(), (0,), (1,), (2,), (3,), (4,), (5,), (0, 2), (1, 4), (3, 5)] |
| 7 | + |
| 8 | +import numpy as np |
| 9 | + |
| 10 | +# Coefficients C[0] = C₁, C[1] = C₂, C[2] = C₃ |
| 11 | +# (Julia is 1-based; Python is 0-based) |
| 12 | +C = np.array([np.sqrt(0.75), np.sqrt(315 / 604), np.sqrt(277200 / 655177)]) |
| 13 | + |
| 14 | +# --- B-spline definitions --- |
| 15 | + |
| 16 | + |
| 17 | +def b_spline_2(x): |
| 18 | + C_2 = C[0] |
| 19 | + if 0.0 <= x < 0.5: |
| 20 | + return C_2 * 4 * x |
| 21 | + elif 0.5 <= x < 1.0: |
| 22 | + return C_2 * 4 * (1 - x) |
| 23 | + else: |
| 24 | + raise ValueError("B-spline 2: x out of range [0,1)") |
| 25 | + |
| 26 | + |
| 27 | +def b_spline_4(x): |
| 28 | + C_4 = C[1] |
| 29 | + if 0.0 <= x < 0.25: |
| 30 | + return C_4 * (128 / 3) * x**3 |
| 31 | + elif 0.25 <= x < 0.5: |
| 32 | + return C_4 * (8 / 3 - 32 * x + 128 * x**2 - 128 * x**3) |
| 33 | + elif 0.5 <= x < 0.75: |
| 34 | + return C_4 * (-88 / 3 - 256 * x**2 + 160 * x + 128 * x**3) |
| 35 | + elif 0.75 <= x < 1.0: |
| 36 | + return C_4 * (128 / 3 - 128 * x + 128 * x**2 - (128 / 3) * x**3) |
| 37 | + else: |
| 38 | + raise ValueError("B-spline 4: x out of range [0,1)") |
| 39 | + |
| 40 | + |
| 41 | +def b_spline_6(x): |
| 42 | + C_6 = C[2] |
| 43 | + if 0.0 <= x < 1.0 / 6: |
| 44 | + return C_6 * (1944 / 5) * x**5 |
| 45 | + elif 1.0 / 6 <= x < 2.0 / 6: |
| 46 | + return C_6 * ( |
| 47 | + 3 / 10 - 9 * x + 108 * x**2 - 648 * x**3 + 1944 * x**4 - 1944 * x**5 |
| 48 | + ) |
| 49 | + elif 2.0 / 6 <= x < 0.5: |
| 50 | + return C_6 * ( |
| 51 | + -237 / 10 + 351 * x - 2052 * x**2 + 5832 * x**3 - 7776 * x**4 + 3888 * x**5 |
| 52 | + ) |
| 53 | + elif 0.5 <= x < 4.0 / 6: |
| 54 | + return C_6 * ( |
| 55 | + 2193 / 10 |
| 56 | + + 7668 * x**2 |
| 57 | + - 2079 * x |
| 58 | + + 11664 * x**4 |
| 59 | + - 13608 * x**3 |
| 60 | + - 3888 * x**5 |
| 61 | + ) |
| 62 | + elif 4.0 / 6 <= x < 5.0 / 6: |
| 63 | + return C_6 * ( |
| 64 | + -5487 / 10 |
| 65 | + + 3681 * x |
| 66 | + - 9612 * x**2 |
| 67 | + + 12312 * x**3 |
| 68 | + - 7776 * x**4 |
| 69 | + + 1944 * x**5 |
| 70 | + ) |
| 71 | + elif 5.0 / 6 <= x < 1.0: |
| 72 | + return C_6 * ( |
| 73 | + 1944 / 5 |
| 74 | + - 1944 * x |
| 75 | + + 3888 * x**2 |
| 76 | + - 3888 * x**3 |
| 77 | + + 1944 * x**4 |
| 78 | + - (1944 / 5) * x**5 |
| 79 | + ) |
| 80 | + else: |
| 81 | + raise ValueError("B-spline 6: x out of range [0,1)") |
| 82 | + |
| 83 | + |
| 84 | +# --- Block structure --- |
| 85 | + |
| 86 | +m1 = [0, 2] # 1-based [1, 3] |
| 87 | +m2 = [1, 4] # 2-based [2, 5] |
| 88 | +m3 = [3, 5] # 3-based [4, 6] |
| 89 | + |
| 90 | +# --- Transformed function f(x) --- |
| 91 | + |
| 92 | + |
| 93 | +def trans(x): |
| 94 | + return x + 1 if x < 0 else x |
| 95 | + |
| 96 | + |
| 97 | +def f(x): |
| 98 | + x = np.asarray(x) |
| 99 | + if x.shape != (6,): |
| 100 | + raise ValueError("f(x): Input must be 6-dimensional.") |
| 101 | + if np.any(x < -0.5) or np.any(x > 0.5): |
| 102 | + raise ValueError("f(x): All entries must be in [-0.5, 0.5].") |
| 103 | + |
| 104 | + xT = np.where(x < 0, x + 1, x) # vectorized 'trans' |
| 105 | + return ( |
| 106 | + np.prod([b_spline_2(xT[i]) for i in m1]) |
| 107 | + + np.prod([b_spline_4(xT[i]) for i in m2]) |
| 108 | + + np.prod([b_spline_6(xT[i]) for i in m3]) |
| 109 | + ) |
| 110 | + |
| 111 | + |
| 112 | +# --- sinc and b(k, r) function --- |
| 113 | + |
| 114 | + |
| 115 | +def sinc(x): |
| 116 | + return 1.0 if x == 0.0 else np.sin(x) / x |
| 117 | + |
| 118 | + |
| 119 | +def b(k, r): |
| 120 | + idx = r // 2 - 1 # Adjust for Python 0-based indexing |
| 121 | + return C[idx] * (sinc(np.pi * k / r) ** r) * np.cos(np.pi * k) |
| 122 | + |
| 123 | + |
| 124 | +# --- Fourier coefficients fc(k) --- |
| 125 | + |
| 126 | + |
| 127 | +def fc(k): |
| 128 | + if len(k) != 6: |
| 129 | + raise ValueError("fc(k): k must be 6-dimensional.") |
| 130 | + |
| 131 | + ind = np.array([int(ki != 0) for ki in k]) |
| 132 | + |
| 133 | + b2_block = np.sum(ind) == np.sum(ind[m1]) |
| 134 | + b4_block = np.sum(ind) == np.sum(ind[m2]) |
| 135 | + b6_block = np.sum(ind) == np.sum(ind[m3]) |
| 136 | + |
| 137 | + val = 0.0 |
| 138 | + if b2_block: |
| 139 | + val += np.prod([b(k[i], 2) for i in m1]) |
| 140 | + if b4_block: |
| 141 | + val += np.prod([b(k[i], 4) for i in m2]) |
| 142 | + if b6_block: |
| 143 | + val += np.prod([b(k[i], 6) for i in m3]) |
| 144 | + return val |
| 145 | + |
| 146 | + |
| 147 | +# --- Norm computation --- |
| 148 | + |
| 149 | + |
| 150 | +def norm(): |
| 151 | + result = 3.0 |
| 152 | + for i in range(1, 3): # i = 1, 2 |
| 153 | + for j in range(i + 1, 4): # j = 2, 3 |
| 154 | + result += 2 * b(0, 2 * i) ** 2 * b(0, 2 * j) ** 2 |
| 155 | + return np.sqrt(result) |
0 commit comments