作用
たとえば、山の上から下の町までボールが転がる道を考える。道は一本ではないよ。まっすぐ急に下る道、少し遠回りする道、途中で上り下りする道、なだらかに曲がる道、普通いろいろな道が「あり得ます」。物理学では、それぞれの道について、運動全体をまとめた点数のようなものを計算します。それが
作用Sです。
作用そのものの難しい計算ではなく、実際に物体が通る道を、ほんの少しだけ別の道へずらしてみる、という考え方。
一本道だけを見るのではない
普通に考えると、今この場所にいるから、次はここへ動くと、一点ずつ決めているように見える。でも作用の原理では、運動を最初から最後までの一本の履歴として見える。
実際の道を A とする。
そのすぐ隣に、少しだけ違う道 Bを考える。
出発点 ●────────● 到着点
道A
出発点 ●────╮───● 到着点
道B
道Aと道Bはほとんど同じですが、途中だけ少し違います。
それぞれの作用を、
とする。
そして差を取ります。
実際の運動経路では、道をほんの少し変えても、作用が一次的にはほとんど変わりません。
これが「作用が停留する」という意味になる。
谷の底で考える
お椀の底にボールがあるとします。底からほんの少し右へ動かしても、少し左へ動かしても、高さはあまり変わりません。
\ /
一方、坂の途中なら、少し左右へ動かしただけでも高さが変わります。作用についても似ています。実際の経路は、近くの経路へ少しずらしたときに、作用の変化がまずゼロになる場所です。ただし、必ずしも「最小」とは限らない。山の頂上のように最大の場合や、方向によって増減する場合もあるので、正確には最小作用の原理より停留作用の原理と呼ぶほうがよいのかも。
別の履歴との差を見る
たとえば、投げたボールが放物線を描いたとします。
実際の軌道だけを見れば、
という一本の線です。
しかし物理学の計算では、その近くにある、
少し高く飛ぶ軌道
少し低く飛ぶ軌道
途中だけ曲がった軌道も仮に考えます。そして、
を調べる。
実際の軌道では、この差が最初の段階で消えます。
ただし、自然が本当に比較しているとは限らない
物体が頭の中で、「この道と、この道と、この道を比べて決めよう」と計算しているわけではないよね。作用の原理は、自然の運動を非常にうまくまとめて表せる数学的な見方。なので正確には、「自然が別の履歴を実際に見て選んでいる」というより、「実際の運動は、近くの仮想的な履歴との差を計算すると、作用の一次差分がゼロになる」ということ。
物体の動きは「今どこにいるか」だけで決まるようにも書けるが、別の見方をすると、最初から最後までの道全体の中で、少し違う道との差が消える特別な道を通っている。
作用の差分――自然は「力」より経路の違いを見る
δS=0
ここで作用 は、
普通は「作用が最小になる」と説明されるけど、厳密には、ある経路をほんの少しずらしたとき、
という
経路間の差分が一次では現れない、という意味になる。
現在の一点だけを見ているのではなく、
近くにあり得た別の履歴との差を見て、実際の経路を決めているとも読める。
Atra的に言えば、絶対的な現在値ではなく、「 実際の経験経路 − 隣接する可能な経験経路」が運動を立たせるという意味にもなる。
離散化すると「加速度」は二階差分になる
連続的な運動方程式は、
だけど、時間を刻み で表すと、
になる。
これは単なる「前との差」ではない。
なので、
今回の差分と、前回の差分との差
になる。
つまり加速度とは、位置の変化ではなく、
変化そのものが、どう変化したか。
これは
Atraの
cue や
carry を考えるうえでも近い。
単に、
だけではなく、
を見ると、単なる入力変化ではなく、変化の向き、勢い、反転、ためらいが出るから。
差分から波が生まれる
波動方程式は、
離散化すると、
となる。
右側の、
は空間方向の二階差分。平坦ならゼロ。中央だけ盛り上がれば周囲との差が生じ、その差が次の時間の変化になる。
波とは、
場所ごとの値が移動しているというより、
周囲との不一致が次の不一致を生み続けている
これは、「差分を消さずに肯定する」に近い。
均してゼロにするのではなく、局所的な差が周囲へ伝播し、別の場所の変化を起こす。
電磁気学も、差分が循環すると場になる
ファラデーの法則は、
磁場が時間的に変化すると、電場の「回り込み」が発生する。
逆にマクスウェル方程式では、
電場の変化が磁場の循環を生む。
真空では、
という相互差分が自走し、電磁波になる。「物質が運んでいる」のではなく、場の差分が、別の場の差分を誘発し続けるということ。
「差分だけが物理量になる」ゲージ理論
量子力学では、波動関数の位相、
について、絶対位相 θ 自体は直接観測できません。意味を持つのは位相差、
二つの経路を通った波が再会すると、
の中に位相差が入り、干渉縞が現れます。特にアハラノフ=ボーム型の関係では、
となり、粒子が通った場所で磁場がゼロでも、二つの経路が持つ位相差によって干渉結果が変わります。
ここでは、各経路が単独で何だったかより、二つの履歴が再接触したときの差が現実になるという構造。
これはAtraの trace、位相、干渉、複数の想起経路に近いよね。
「経験差分方程式」
物理学の既存公式そのものでないけどね、Atra的な場へ移すなら、例えば、
と置ける。
それぞれ、
は自分自身の時間差分、
は周囲との相関差分、
は現在のcue。
さらに二階差分を入れると、
となる。これは、「現在の状態がcueに反応する」のではなく、「経験の変化速度が、場との不一致によって変化する」式になる。
かなり生命的でしょ?w
-
作用の変分
現実の経路と、あり得た隣接経路との差。
-
二階差分
変化ではなく、「変化の変化」。
-
位相差
単独では見えない履歴が、再会したとき現実になる。
うちの研究に一番深く入りそうなのは、値の差分より「履歴同士の差分」かな。
現在値を引き算するだけではなく、異なる経路のtraceが同じ接相面に立ったとき、その位相差や向きの差が発火を生む。これは単なる微分より、変分原理と干渉の組合せに近いね。
ばね振り子
通常式
質量 m の物体をばねにつけると、
離散時間にすると、
これは、現在位置 xn に応じて元へ戻るだけです。
結果は、
左右に周期運動する
理想状態では振幅が減らない
現在の変位だけが復元力を決める
となるよね。
差分を加えた式
ここに、
を加えちゃう。
離散式では、
になる。通常式との差は、この部分。
現在位置だけではなく、直前から、どちらへ、どれくらい変化したかが次の運動へ影響する。
-- 結果 --
γ>0 なら、差分と反対向きの力になるので、
振動が次第に小さくなる
最終的に停止する
過去からの運動方向を抑える
となる。
これは普通の減衰振動。ところが符号を逆にして、
とすると、
動いている方向へさらに力を加える
振幅が大きくなる
小さな差が増幅される
条件によっては発散する
という現象になる。
つまり同じ差分でも、
なら忘却・摩擦、
なら励起・成長となる。
差分が大きいときだけ反応する
単純な減衰より、Atraの実験には近いやつ。
例えば、
とする。
これは、「小さな変化には反応しないが、一定以上の差が生じたときだけ力が立つ」仕組。
通常式との違い
通常式:
位置が同じなら、必ず同じ力です。
差分式:
同じ位置にいても、
によって、次の運動が変わります。
通常の位置だけの式では、
なら状態は同じ。
しかし差分を入れると、
と、
は別の状態になる。
同じ現在位置でも、履歴が違えば次が違う。
重力落下に差分を入れる
通常の自由落下
離散式:
これは、どんな落ち方をしていても重力加速度は一定。
差分に反応する重力
実験用の仮想式として、
を入れる。すると落下速度が上がるほど、差分項が大きくなります。
γ>0 なら、運動方向と反対向きに働くので空気抵抗に似た挙動になります。少し面白くするなら、
ここで、
は「速度の変化の差」、つまり二階差分です。
すると、単に速く落ちているかではなく、落ち方が急に変わったかに反応する。
これは衝撃検出に使える。
着地の瞬間や、途中で力を加えた瞬間だけ、大きな値が立つという考え方。
複数セルで差分を伝える
これは見た目が面白いかも。
横一列にセルを並べ、
各セルが隣との違いに反応するようにします。
独立した通常式
各セルは、それぞれ独立して振動します。
一つを動かしても、隣には伝わりません。
隣接差分を入れた式
中央の項は、
左右の差分の差です。
これを入れると、一つのセルを押しただけで、
差が隣へ伝わる
波になる
端で反射する
二つの波が干渉する
差が一度消えて、再び現れる
という現象になる。
通常式では「一つの点の運動」だったものが、差分を入れると場の運動になる。
比較実験
3種類を同時に並べる。
A:通常ばね
同じ周期で振動し続ける。
B:一次差分を追加
過去からの運動を引きずりながら減衰する。
C:差分が一定以上のときだけ追加
は閾値を超えると1になる関数。
小さな揺れは残り、大きな変化だけ抑えられます。
結果として、
Aは永遠に同じ
Bは滑らかに停止
Cは大きな動きだけ変化し、小さな揺れが残る
という明確な違いが出る。
さらにAtra寄りにする式
差分を単に消すのではなく、記憶として残します。
そして、
とする。
は、過去の差分の残りです。
なら徐々に薄れる。
この式では、現在の入力がなくなっても、
なら運動への影響が残る。
つまり、
通常式:現在位置だけで次が決まる
差分式:直前の変化で次が変わる
蓄積差分式:過去の変化の残りで次が変わる
という三段階を比較できるという話。
Atraのcarry に近いのは、最後。ただし単なる経過時間ではなく、実際に生じた差分だけが残る。 最初に作るなら、ブラウザ上で「通常ばね・一次差分・蓄積差分」の3本を同時に動かす実験が一番いいかも。位置、速度、差分、蓄積差分をグラフ表示すれば、差分によって同じ初期状態から運動がどう分岐するか、かなり鮮明に出るはず。
-----------------------ばね振り子に差分遊び Python---------------------------
import numpy as np
import matplotlib.pyplot as plt
m = 1.0
g = 9.81
T_total = 2.0
v0 = g * T_total / 2.0
steps = 2001
t = np.linspace(0.0, T_total, steps)
dt = t[1] - t[0]
y_physical = v0 * t - 0.5 * g * t**2
eta = np.sin(np.pi * t / T_total)
def action(y):
velocity = np.gradient(y, dt)
kinetic = 0.5 * m * velocity**2
potential = m * g * y
lagrangian = kinetic - potential
return np.trapezoid(lagrangian, t)
eps_values = np.linspace(-2.0, 2.0, 161)
actions = np.array([
action(y_physical + eps * eta)
for eps in eps_values
])
S0 = action(y_physical)
small_eps = 1e-3
dS_deps = (
action(y_physical + small_eps * eta)
- action(y_physical - small_eps * eta)
) / (2.0 * small_eps)
plt.figure(figsize=(10, 5))
plt.plot(t, y_physical - 1.2 * eta, label=r"$q(t)-1.2\eta(t)$")
plt.plot(t, y_physical, label=r"physical path $q(t)$", linewidth=2.5)
plt.plot(t, y_physical + 1.2 * eta, label=r"$q(t)+1.2\eta(t)$")
plt.axhline(0, linewidth=0.8)
plt.xlabel("time t [s]")
plt.ylabel("height y [m]")
plt.title("Nearby paths with the same start and end points")
plt.grid(True)
plt.legend()
plt.tight_layout()
plt.show()
plt.figure(figsize=(10, 5))
plt.plot(eps_values, actions)
plt.scatter([0], [S0], s=60, label="physical path: ε = 0")
plt.axvline(0, linewidth=0.8)
plt.xlabel(r"path deformation $\varepsilon$")
plt.ylabel(r"action $S(\varepsilon)$")
plt.title("The physical path is stationary with respect to nearby paths")
plt.grid(True)
plt.legend()
plt.tight_layout()
plt.show()
print(f"S(0) = {S0:.8f}")
print(f"dS/dε at ε=0 ≈ {dS_deps:.8e}")
---------------html----------------
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>停留作用の実験 / Stationary Action Experiment</title>
<style>
body {
font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
margin: 0;
background: #f7f7f7;
color: #222;
}
.wrap {
max-width: 1100px;
margin: 0 auto;
padding: 24px;
}
h1 { margin: 0 0 8px; font-size: 28px; }
p { line-height: 1.7; }
.panel {
background: white;
border: 1px solid #ddd;
border-radius: 14px;
padding: 18px;
margin-top: 16px;
box-shadow: 0 4px 18px rgba(0,0,0,0.05);
}
.controls {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 14px 20px;
align-items: center;
}
label { font-weight: 600; }
input[type="range"] { width: 100%; }
.value {
display: inline-block;
min-width: 80px;
font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
}
canvas {
width: 100%;
height: 360px;
border: 1px solid #ddd;
border-radius: 10px;
background: white;
}
.stats {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
margin-top: 14px;
}
.stat {
background: #fafafa;
border: 1px solid #e2e2e2;
border-radius: 10px;
padding: 12px;
}
.stat b { display:block; margin-bottom: 4px; }
.mono { font-family: ui-monospace, SFMono-Regular, Consolas, monospace; }
button {
border: 0;
border-radius: 10px;
padding: 10px 16px;
font-weight: 700;
cursor: pointer;
}
@media (max-width: 700px) {
.controls, .stats { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<div class="wrap">
<h1>停留作用の実験</h1>
<p>
同じ出発点と到着点を結ぶ経路を少しだけ変え、
作用 <span class="mono">S = ∫(T − V)dt</span> がどう変わるかを見ます。
<span class="mono">ε = 0</span> が重力の運動方程式を満たす経路です。
</p>
<div class="panel controls">
<div>
<label for="epsilon">経路の膨らみ ε:</label>
<span id="epsilonValue" class="value">0.00</span>
<input id="epsilon" type="range" min="-2" max="2" step="0.01" value="0">
</div>
<div>
<label for="deformMode">変形の形:</label>
<select id="deformMode">
<option value="sin1">sin(πt/T)</option>
<option value="sin2">sin(2πt/T)</option>
<option value="bump">中央だけ膨らむ</option>
</select>
</div>
<div>
<label for="gravity">重力加速度 g:</label>
<span id="gravityValue" class="value">9.81</span>
<input id="gravity" type="range" min="1" max="20" step="0.01" value="9.81">
</div>
<div>
<label for="flightTime">飛行時間 T:</label>
<span id="flightTimeValue" class="value">2.00 s</span>
<input id="flightTime" type="range" min="0.5" max="5" step="0.01" value="2">
</div>
<div>
<button id="reset">初期値に戻す</button>
</div>
</div>
<div class="panel">
<h2>経路</h2>
<canvas id="pathCanvas" width="1000" height="360"></canvas>
</div>
<div class="panel">
<h2>作用 S(ε)</h2>
<canvas id="actionCanvas" width="1000" height="360"></canvas>
<div class="stats">
<div class="stat">
<b>現在の作用 S(ε)</b>
<span id="currentAction" class="mono"></span>
</div>
<div class="stat">
<b>基準作用 S(0)</b>
<span id="baseAction" class="mono"></span>
</div>
<div class="stat">
<b>ε=0 付近の傾き dS/dε</b>
<span id="slopeValue" class="mono"></span>
</div>
</div>
</div>
</div>
<script>
const pathCanvas = document.getElementById('pathCanvas');
const actionCanvas = document.getElementById('actionCanvas');
const pctx = pathCanvas.getContext('2d');
const actx = actionCanvas.getContext('2d');
const epsilonEl = document.getElementById('epsilon');
const gravityEl = document.getElementById('gravity');
const flightTimeEl = document.getElementById('flightTime');
const deformModeEl = document.getElementById('deformMode');
const epsilonValue = document.getElementById('epsilonValue');
const gravityValue = document.getElementById('gravityValue');
const flightTimeValue = document.getElementById('flightTimeValue');
function deformation(mode, t, T) {
const u = t / T;
if (mode === 'sin2') return Math.sin(2 * Math.PI * u);
if (mode === 'bump') return 16 * u * u * (1 - u) * (1 - u);
return Math.sin(Math.PI * u);
}
function computePath(epsilon, g, T, mode, steps=1001) {
const dt = T / (steps - 1);
const v0 = g * T / 2;
const t = [];
const y = [];
for (let i = 0; i < steps; i++) {
const ti = i * dt;
const physical = v0 * ti - 0.5 * g * ti * ti;
t.push(ti);
y.push(physical + epsilon * deformation(mode, ti, T));
}
return { t, y, dt };
}
function computeAction(epsilon, g, T, mode) {
const m = 1;
const { t, y, dt } = computePath(epsilon, g, T, mode, 2001);
let S = 0;
for (let i = 1; i < y.length - 1; i++) {
const v = (y[i+1] - y[i-1]) / (2 * dt);
const kinetic = 0.5 * m * v * v;
const potential = m * g * y[i];
S += (kinetic - potential) * dt;
}
return S;
}
function drawAxes(ctx, W, H, left, top, right, bottom, xLabel, yLabel) {
ctx.clearRect(0, 0, W, H);
ctx.strokeStyle = '#444';
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(left, top);
ctx.lineTo(left, H-bottom);
ctx.lineTo(W-right, H-bottom);
ctx.stroke();
ctx.fillStyle = '#222';
ctx.font = '14px sans-serif';
ctx.fillText(xLabel, W/2 - 20, H-10);
ctx.save();
ctx.translate(16, H/2 + 30);
ctx.rotate(-Math.PI/2);
ctx.fillText(yLabel, 0, 0);
ctx.restore();
}
function drawPathGraph(epsilon, g, T, mode) {
const W = pathCanvas.width, H = pathCanvas.height;
const left=60, right=25, top=20, bottom=45;
const physical = computePath(0, g, T, mode);
const selected = computePath(epsilon, g, T, mode);
let ymin = Math.min(...selected.y, ...physical.y, 0);
let ymax = Math.max(...selected.y, ...physical.y, 0);
const pad = Math.max(0.5, (ymax-ymin)*0.12);
ymin -= pad; ymax += pad;
drawAxes(pctx, W, H, left, top, right, bottom, '時間 t', '高さ y');
function mapX(t) { return left + (t/T)*(W-left-right); }
function mapY(y) { return top + (ymax-y)/(ymax-ymin)*(H-top-bottom); }
function plot(path, stroke, width) {
pctx.strokeStyle = stroke;
pctx.lineWidth = width;
pctx.beginPath();
for (let i=0; i<path.t.length; i++) {
const x = mapX(path.t[i]), y = mapY(path.y[i]);
if (i===0) pctx.moveTo(x,y); else pctx.lineTo(x,y);
}
pctx.stroke();
}
plot(physical, '#222', 2.5);
plot(selected, '#777', 2);
pctx.fillStyle = '#222';
pctx.fillText('黒: 実際の経路 ε=0', left+10, top+18);
pctx.fillStyle = '#777';
pctx.fillText('灰: 選択した近接経路', left+170, top+18);
}
function drawActionGraph(epsilon, g, T, mode) {
const W = actionCanvas.width, H = actionCanvas.height;
const left=70, right=25, top=20, bottom=45;
const epsMin=-2, epsMax=2, count=161;
const eps = [];
const actions = [];
for (let i=0; i<count; i++) {
const e = epsMin + (epsMax-epsMin)*i/(count-1);
eps.push(e);
actions.push(computeAction(e, g, T, mode));
}
let ymin = Math.min(...actions), ymax = Math.max(...actions);
const pad = Math.max(0.2, (ymax-ymin)*0.1);
ymin -= pad; ymax += pad;
drawAxes(actx, W, H, left, top, right, bottom, '経路の膨らみ ε', '作用 S');
function mapX(e) { return left + (e-epsMin)/(epsMax-epsMin)*(W-left-right); }
function mapY(s) { return top + (ymax-s)/(ymax-ymin)*(H-top-bottom); }
actx.strokeStyle = '#333';
actx.lineWidth = 2;
actx.beginPath();
for (let i=0; i<count; i++) {
const x = mapX(eps[i]), y = mapY(actions[i]);
if (i===0) actx.moveTo(x,y); else actx.lineTo(x,y);
}
actx.stroke();
const Scur = computeAction(epsilon, g, T, mode);
const S0 = computeAction(0, g, T, mode);
actx.fillStyle = '#111';
actx.beginPath();
actx.arc(mapX(epsilon), mapY(Scur), 6, 0, Math.PI*2);
actx.fill();
actx.strokeStyle = '#999';
actx.beginPath();
actx.moveTo(mapX(0), top);
actx.lineTo(mapX(0), H-bottom);
actx.stroke();
const h = 1e-3;
const slope = (computeAction(h,g,T,mode)-computeAction(-h,g,T,mode))/(2*h);
document.getElementById('currentAction').textContent = Scur.toFixed(8);
document.getElementById('baseAction').textContent = S0.toFixed(8);
document.getElementById('slopeValue').textContent = slope.toExponential(6);
}
function update() {
const epsilon = Number(epsilonEl.value);
const g = Number(gravityEl.value);
const T = Number(flightTimeEl.value);
const mode = deformModeEl.value;
epsilonValue.textContent = epsilon.toFixed(2);
gravityValue.textContent = g.toFixed(2);
flightTimeValue.textContent = T.toFixed(2) + ' s';
drawPathGraph(epsilon, g, T, mode);
drawActionGraph(epsilon, g, T, mode);
}
[epsilonEl, gravityEl, flightTimeEl, deformModeEl].forEach(el => {
el.addEventListener('input', update);
el.addEventListener('change', update);
});
document.getElementById('reset').addEventListener('click', () => {
epsilonEl.value = 0;
gravityEl.value = 9.81;
flightTimeEl.value = 2;
deformModeEl.value = 'sin1';
update();
});
update();
</script>
</body>
</html>
-------------------------------
ホレ、前に脳の話で「現在の絶対値(位置)」だけで計算する静的な機械と捉えない方がいいよ的な話を書いたでしょ。Atraの「経験差分方程式」は、そろそろちゃんと差分を使って生命のダイナミズムそのものを数式化していこうよ、みたいな感じさ。
赤ちゃん、幼児は差分で生きてるからね。自分より大きかどうかで大きさをみて、持ち上げられるかどうかで重さを判断する。人も犬も物体。毎日パパを見て経験の差分を積んで「パパ」という意味を持つ。それが成長。正しさとか間違いなんてものは何処にもない。
毎日腹減った時に想像する食い物(再現)は違うんだよねー
お腹空いた。→ 工学は「食う」しか出てこない。
月曜:ガッツリ焼肉(今週頑張るよ!)火曜:なんか酸っぱい冷麺(あぁ、もう疲れてる)水曜:唐揚げ+ご飯(王道)木曜:突然スイーツ(疲れてる)金曜:ビール+おつまみ系(もう、仕事切り上げるべ)
論文でこんなこと書けないからねー
誤字脱字すみません、ただのノートなので、気にしないでください
---------------------Research Note and Attribution Notice-----------------------
本ブログに含まれる Atra の一人称自律、差分、carry、field、trace、dream slack、外部LLMの翻訳層、非単調な漏れ、現在相(Current Phase)、接相面(Associative Contact Surface)、過去相(Past Associative Phase)およびそれらの関係構造に関する設計記述は、c-side研究所による継続研究メモです。引用・参照・要約・翻案を行う場合は、出典を明記してください。
The design descriptions in this blog concerning Atra’s first-person autonomy, differences, carry, field, trace, dream slack, the translation layer of external LLMs, nonmonotonic leakage, and the relational structure among these elements are ongoing research notes by c-side Research Institute. If you quote, refer to, summarize, or adapt them, please clearly indicate the source.