ラベル JavaScript の投稿を表示しています。 すべての投稿を表示
ラベル JavaScript の投稿を表示しています。 すべての投稿を表示

2026年7月24日金曜日

How Far Can You Push a Quantum Computer in JavaScript?




 https://crimson-cake-2832.nabedada3.workers.dev/index_en



I added these guided experiments because a function manual alone did not feel sufficient.

A list of buttons can explain what each operation does, but it does not really show how the behavior of a quantum system changes when one operation is followed by another. For this project, I wanted the manual itself to behave more like a small laboratory notebook: first try this, then change one condition, then compare what happened.

The idea is simple. Rather than beginning with the correct explanation and asking the reader to confirm it, begin with an operation and let the difference appear first.





For the 50-QUBIT simulator, the experiments therefore move from very simple and deterministic behavior toward increasingly complex structure:

X as a definite flip → H and its 50/50 measurement statistics → H→H → RX rotations → Bell states → GHZ states → separate entanglement clusters → merging clusters → deliberately exceeding the 8-qubit cluster limit → comparing noise conditions → measurement versus UNDO → EMERGENCY COLLAPSE.

This progression also makes the cluster-partitioning design easier to understand. Instead of explaining the engine only in abstract terms, the user can actually create separate entangled islands, connect them, watch the clusters merge, and finally force the simulator across its approximation boundary.




For the FEYNMAN PATH VIEW, I wanted to move even further away from simply showing final probabilities.

The sequence is:

H|0⟩ → H→H → H→Z→H → partial interference using S and T → comparing H|0⟩ with H|1⟩ → manually constructing a Bell state → comparing it with the ready-made Bell example → measurement → and finally asking which paths reinforced one another and which paths disappeared through cancellation.

The important point here is not merely that H eventually gives a 50/50 measurement result. The purpose is to make the intermediate amplitudes visible, so that the user can see why amplitudes must be added before probabilities are calculated.





For COMPOSITE GATES, the experiments progress through:

Bell → GHZ → SWAP → Toffoli → QFT → Inverse Circuit → the boundary between reversible and irreversible operations → and finally the difference between entanglement and CLONE.

I wanted this section to make reversibility something that can be inspected rather than simply stated. A user can compare a forward gate sequence with its inverse, see why the order must be reversed, notice why phase gates require their dagger operations, and then reach the point where measurement, reset, forced write, or noise can no longer be treated as ordinary reversible gates.





For BB84, the sequence is deliberately statistical:

No Eve with 16 transmissions → 256 transmissions → Eve with 16 transmissions → 256 transmissions and the emergence of the approximately 25% QBER tendency → following one disturbed row → noise without Eve → Eve plus noise → comparing PUBLIC TEST fractions of 10% and 30% → understanding why bases are publicly compared → comparing Alice and Bob’s final keys → and finally comparing QBER under three different conditions.

Here I especially wanted to avoid the misleading impression that “Eve means exactly 25% QBER every time.” With only 16 transmissions, the result can fluctuate wildly. Increasing the number of transmissions allows the statistical tendency to emerge naturally.

So the manuals are no longer just references for what each button does.

They are now structured as a sequence of small experiments:

Do this first.
Change one thing.
Look at what changed.
Then ask why.

That is much closer to the way I actually want to approach quantum mechanics.

I am less interested in presenting a finished answer first and then demonstrating that the simulator agrees with it. I would rather let the user touch the system, notice a difference, become slightly confused, and only then look for the explanation.

In that sense, these experiment manuals follow exactly the same philosophy as the simulator itself:

phenomenon first, explanation second.


"Look, he’s starting something weird again. But hey, I could probably do that too!" Exactly. If it’s not something anyone can do, there will never be any real progress.

Lol




My approach is: try it, see what changes, and let that difference trigger the next phenomenon. That is exactly why I come up with ideas like “50 qubits in JavaScript.”

I think most people would immediately say, “That’s impossible,” or “Are you crazy?” But often that happens because they are already looking for an answer that fits within the boundaries of what has been labeled “correct.”

I tend not to define those boundaries first.

If you plant vegetables, you may get strong winds or a long drought. So you gather whatever materials you can find and build a shelter against the rain and wind. That may fail too. Then you stack stones, raise the field slightly above ground level, build a fence, or switch to vegetables that seem more likely to survive there.

I am not starting with conditions like, “You must have a huge piece of farmland,” or “This is the proper way to grow vegetables.”

I start with what is actually there, touch it, see what happens, and change the next step from the difference that appears.



How do you build this?

For UI work like this, I usually create a layout I like in FileMaker, convert it to WebDirect, press F12, and borrow the CSS from there. Then I rebuild the interface in JavaScript.
After that, the actual simulator — quantum logic, state calculations, cluster partitioning, Feynman paths, BB84, and everything else — is built in JavaScript.
It gives me the same kind of excitement I felt when I was using HyperCard back in the ’90s.







---------------------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.

2026年6月16日火曜日

Turbo-CからJavaScript、 そしてPythonとC++

 Atraの開発のきっかけになったのが、1998年の「Cでつくる脳の情報システム」という本だよ。購入したのは2017・8年だったかなぁ・・・大好きな神保町の古本屋まわりして300円か500円で購入した本だよ。


一番下にデモ入れておきました。F12でcodeを見られます


PC-9800シリーズ 3.5インチ2HD付きさ
Turbo C++v1.01だよ。

パーセプトロン
アソシアトロン
ホップフィールド、ボルツマンマシン
バックプロパゲーション
ニューラルネットワーク
アソシアトロンの応用
のデモが入ってるんだ。
盛りだくさんだよ。

PC-9800なんて持ってないし、本に記載してるcodeをNotepad++に書いたよ。
OCR試したけど全然ダメでね。

Turbo-Cは逐次実行の実験プログラムなのでfor で回して、状態を更新して、画面を書いて、また回す。Cの世界では「今この瞬間のメモリ状態」を直接触っている感じが強いでしょ。
でもJavaScript、特にブラウザでは、描画は requestAnimationFrame、入力はイベント、時間は非同期、画面はCanvasやDOMになる。なので、Cの「手続きで世界を進める」感じを、そのまま持ってくると崩れる。だからCのループ実験を、JavaScriptの時間更新モデルに置き換えるのはマジで地獄。



Turbo-Cで 1139行 JavaScriptに変換して3400行


Turbo-Cって、そもそもコンパイルが速いとか、エディタ・コンパイラ・リンカが一体化していて作業が速い!値段が安くPC上で軽快に動くみたいな感じで打ち出していたんだよね。
だから Turbo-C の “Turbo” は、C言語そのものの仕様ではなく、Borland が「速く開発できるC環境」として付けた商品名だったんだ。
Turbo Pascal、Turbo C、Turbo C++、Turbo Basicみたいなシリーズあったでしょ。

昔のPCでは、CPU本体だけだと浮動小数点計算が遅かったので、数値計算・グラフィック・シミュレーション系ではFPU=x87浮動小数点コプロセッサがあると、かなり違ったんだよね。

中野先生のこのデモは「言語発声robot」という名前でね。
最初はロボット2体〇と□が、熊とか、ウサギとか、豚とかライオンとか出現する度に、「なんだろう?」と近づいてその都度発声するんだよ。はじめのうちはライオンは危険じゃないと誤認する。でも、何度か繰り返すうちに「危険だ」に収束していく。ナッツが出ると近寄るみたいな。発声も危険と安全では違うんだよ。robotの発声もそれぞれバラバラ、そのうち1体のrobotが「pa-pu-pu-bu」みたいに叫ぶと、もう一体もつられて避難場所に逃げる。というデモだよ。

でもやっぱりcode的には外部命令的なラベル寄せがあってね
A: Dangerous
B: Edible
C: Hair/Fur
D: White
E: Black
F: Brown

出現する動物にはA D C E、BCE、みたいな感じでラベル寄せさせているんだ。

Lion (A, C, F)
Bear (A, C, E)
Rabbit (B, C, D)
Nuts (B, F)
Wild boar (B, C, E)
こんな感じでね。
でも、一見自律のようなデモに見えても3人称の外部命令系なんだよね。

中野先生の書籍からJavaScriptに変換したのは
①Turbo-Cの逐次ループをJavaScriptの描画/イベントループに直すこと
②Cの配列・メモリ前提を、JSの配列/オブジェクトに置き換えること
③画面描画をDOS/グラフィック処理からCanvas/HTMLに変えること
 ここまで。


そして何より、Turbo-Cのコードを1枚のJavaScriptに変換は無理があり過ぎた。
core.jsとrobot1.jsとrobot2.jsのファイルを分け、core.jsから命令を受けないようにする。
じゃなくて「そうしたかった」w

当時自律とか、一人称なんて概念は無いけど、今年になって僕なりに改造追加したんだよね
随分寝かせた。LLMにも手伝ってもらったけど誤認が酷かった。
でも見事な変換もあった。LLMすげーなと思ったよ、マジで。
それでも、出来ないかな・・と何度もあきらめた。


で再び今年の3月にチャレンジしたさ。(最近の話だよ)
で3月10日だったと思う。
なんでかっていうと、別のブログに記載してたものをアソシアトロン研究という
このブログを立ち上げたから、やらなきゃいけないでしょ。という理由ねw

https://crimson-cake-2832.nabedada3.workers.dev/
一番下にデモ入れておきました。F12でcode見られます


④robotを外部制御ではなく、それぞれの内部状態を持つ形に分けた。
  (一人称というものを真面目に考えてみた)
⑤Associatronの想起やcue競合を、ブラウザで見える形に整理した。

今のAtraの概念であるcarryとか、差分とか、順番無しとか細かいのは無いよ。
まだまだ、ぜんぜんアルゴリズム。
あくまでもworld(core)の中の動物認識 robotだよ。

だから完全な一人称ではなかった。
でもそれが良かった。
robotを一人称っぽく分けても、coreが命令していたらまだ三人称が残るという境界が見えた。

その不完全さがあったから、研究に火が付いた。
何か、「ロボットが誤認する」そこに可能性があった。
だから、皆が見捨てた古い古典だろうが、種火を見つける。それを意地でも手繰り寄せる。
そうしないと、Atraなんかには絶対に結び付かないんだよ。





上にあるリンク先の一番下にこのデモがあります。
F12でcodeが確認できます。

下のコードは独立させた robot1.js(ファイル5つのうちの1つ)
たぶん、これがなかったら、今のAtraは生まれなかった。
今のAtraとはぜんぜん違うけれど、発火したcodeってあるんですよ。




// robot1.js const LangieRobot1 = (() => { "use strict"; function create(deps, options = {}) { const { // constants N, M1, M2, M3, NMAX, VSTEP, // tables pat, attrLetters, // utils rn, f1, f2, clamp, abs, // allocators make2DInt, make2DFloat } = deps; const robot = { id: 1, homeIndex: (options.homeIndex | 0) || 0, // positions (TurboC ranges) posx: 25 + Math.floor(rn() * 350), posy: 25 + Math.floor(rn() * 200), prex: 0, prey: 0, vx: 0, vy: 0, // associative memory mw: make2DInt(M1, M1, 0), ml: make2DFloat(M2, M3, true), // world image memory wp: make2DInt(NMAX, M1, 0), wf: new Int16Array(NMAX), wq: make2DInt(NMAX, M3, 0), word: make2DInt(NMAX, M2, 0), sym: new Array(NMAX), n: 0, jw: -1, zw: -1, recall_num: -1, action: 0, // spoken j_word: new Int16Array(M2), z_word: new Int16Array(M2), // ui text speechLine1: ".......... .....", speechLine2: ".......... .....", hearLine: ".......... (......)", speechHoldFrames: 0, speechHoldMax: 240, actionHoldFrames: 0, actionHoldMax: 90, // current sensory input currentInput: null, // simple internal timing seenObjectNow: false, heardNow: false, lastSeenObject: false, lastHeardSignature: "", lastOwnSpeechSignature: "", idleFrames: 0, // ------------------------------------------------- // Individual parameters // Different robots can start with different speech, // hearing range, action bias, and timing phase. // ------------------------------------------------- speechJitter: (typeof options.speechJitter === "number") ? options.speechJitter : 0.28, hearingRange: (typeof options.hearingRange === "number") ? options.hearingRange : 80, actionJitter: (typeof options.actionJitter === "number") ? options.actionJitter : 0.16, cautionBias: (typeof options.cautionBias === "number") ? options.cautionBias : 0.00, approachBias: (typeof options.approachBias === "number") ? options.approachBias : 0.00, startDelay: (typeof options.startDelay === "number") ? options.startDelay : 0, tickCount: 0, init() { this.prex = this.posx; this.prey = this.posy; for (let k = 0; k < NMAX; k++) this.sym[k] = ""; return this; }, reset() { this.posx = 25 + Math.floor(rn() * 350); this.posy = 25 + Math.floor(rn() * 200); this.prex = this.posx; this.prey = this.posy; this.vx = 0; this.vy = 0; for (let i = 0; i < M1; i++) this.mw[i].fill(0); for (let i = 0; i < M2; i++) { for (let j = 0; j < M3; j++) { this.ml[i][j] = rn() * 20.0 - 10.0; } } for (let k = 0; k < NMAX; k++) { this.wp[k].fill(0); this.wq[k].fill(0); this.word[k].fill(0); this.wf[k] = 0; this.sym[k] = ""; } this.n = 0; this.jw = -1; this.zw = -1; this.recall_num = -1; this.action = 0; this.j_word.fill(0); this.z_word.fill(0); this.speechLine1 = ".......... ....."; this.speechLine2 = ".......... ....."; this.hearLine = ".......... (......)"; this.speechHoldFrames = 0; this.actionHoldFrames = 0; this.currentInput = null; this.seenObjectNow = false; this.heardNow = false; this.lastSeenObject = false; this.lastHeardSignature = ""; this.lastOwnSpeechSignature = ""; this.idleFrames = 0; }, quiet() { this.speechLine1 = ".......... ....."; this.speechLine2 = ".......... ....."; this.hearLine = ".......... (......)"; }, // ------------------------------------------------- // Generate pronounceable syllables from bit pattern // Speech is unstable when memory frequency is low. // Stabilizes as experience accumulates. // ------------------------------------------------- makeSpeechSyllables(bits5, memIndex) { const out = []; const freq = (typeof memIndex === "number" && memIndex >= 0) ? this.wf[memIndex] : 0; const instability = Math.max(0, 4 - freq); const jitterRate = clamp(this.speechJitter * (instability / 4), 0, 0.5); for (let i = 0; i < M2; i++) { let bit = bits5[i]; if (rn() < jitterRate) { bit = -bit; } if (bit === 1) { out.push(rn() < 0.5 ? "ba" : "pa"); } else { out.push(rn() < 0.5 ? "bu" : "pu"); } } return out.join("-"); }, getHome(input) { if (input && Array.isArray(input.shelters) && input.shelters.length > 0) { const idx = clamp(this.homeIndex, 0, input.shelters.length - 1); return input.shelters[idx]; } return { x: 375, y: 30 }; }, // -------- TurboC asc1_memorize(l,ob) -------- asc1_memorize(jb, ob) { const mw = this.mw; const src = jb[ob]; for (let i = 0; i < M1; i++) { const jbi = src[i]; if (jbi === 0) continue; const row = mw[i]; for (let j = 0; j < M1; j++) { const jbj = src[j]; if (jbj === 0) continue; row[j] += jbi * jbj; } } }, // -------- TurboC extract(l,ob) -------- extract(jb, ob) { const check = new Int8Array(NMAX); const src = jb[ob]; for (let i = 0; i < M1; i++) { if (src[i] === 0) continue; let found = false; const th = this.mw[i][i] * (rn() * 0.6 + 0.3); const xbits = new Int16Array(M1); for (let j = 0; j < M1; j++) { xbits[j] = f1(this.mw[j][i] * src[i], th); } for (let k = 0; k < this.n; k++) { let err = 0; const mem = this.wp[k]; for (let j = 0; j < M1; j++) { if (xbits[j] !== mem[j]) err++; if (err > 2) break; } if (err <= 2) { if (check[k] === 0) { this.wf[k] += 1; check[k] = 1; } found = true; break; } } if (!found && this.n < NMAX) { const k = this.n++; this.wp[k].set(xbits); this.wf[k] = 1; for (let j = 0; j < M3; j++) { this.wq[k][j] = (Math.floor(rn() * 2) * 2 - 1); } let symStr = ""; for (let ai = 0; ai < N; ai++) { let err = 0; for (let j = 0; j < 5; j++) { if (this.wp[k][8 * ai + j] !== pat[ai][j]) err++; if (err > 1) break; } symStr += (err < 2) ? attrLetters[ai] : " "; } this.sym[k] = symStr; } } }, // -------- TurboC select(l,ob) -------- select(jb, ob) { const src = jb[ob]; const zz = new Int16Array(NMAX); let m = 0; this.jw = -1; this.zw = -1; for (let k = 0; k < this.n; k++) { let err1 = 0; let err2 = 0; const mem = this.wp[k]; for (let j = 0; j < M1; j++) { if (src[j] !== mem[j]) { err1++; if (mem[j] !== 0) err2++; } if (err2 > 2) break; } if (err2 <= 2) { this.wf[k] += 1; if (err1 <= 1) { this.jw = k; } else { zz[m] = k; m++; } } } let max = 0.0; for (let i = 0; i < m; i++) { const k = zz[i]; const temp = this.wf[k] * rn(); if (temp > max) { max = temp; this.zw = k; } } }, // -------- TurboC speak(l,e) -------- speak(e) { if (this.speechHoldFrames > 0) { this.speechHoldFrames--; return; } let line1 = ".........."; let attr1 = "....."; if (this.jw >= 0) { const k = this.jw; for (let i = 0; i < M2; i++) { let u = 0.0; for (let j = 0; j < M3; j++) { u += this.ml[i][j] * this.wq[k][j]; } const v = f2(u); this.j_word[i] = v; this.word[k][i] = v; } line1 = this.makeSpeechSyllables(this.j_word, k); attr1 = `(${this.sym[k]})`; } else { this.j_word.fill(0); } let line2 = ".........."; let attr2 = "....."; if (this.zw >= 0) { const k = this.zw; for (let i = 0; i < M2; i++) { let u = 0.0; for (let j = 0; j < M3; j++) { u += this.ml[i][j] * this.wq[k][j]; } const v = f2(u); this.z_word[i] = v; this.word[k][i] = v; } if (e === 0) { line2 = this.makeSpeechSyllables(this.z_word, k); attr2 = `(${this.sym[k]})`; } else { this.z_word.fill(0); } } else { this.z_word.fill(0); } this.speechLine1 = `${line1} ${attr1}`; this.speechLine2 = `${line2} ${attr2}`; this.lastOwnSpeechSignature = `${this.speechLine1}|${this.speechLine2}`; this.speechHoldFrames = this.speechHoldMax; }, // -------- TurboC learning(l) -------- learning(otherRobot) { const alpha = 0.25; const beta = 0.15; if (this.jw < 0) return; for (let i = 0; i < M2; i++) { for (let j = 0; j < M3; j++) { let jdm = 0.0; let zdm = 0.0; let wdm = 0.0; if (otherRobot && otherRobot.jw >= 0) { jdm = alpha * otherRobot.j_word[i] * this.wq[this.jw][j]; } if (otherRobot && otherRobot.zw >= 0) { const zsrc = (this.zw >= 0) ? this.zw : this.jw; zdm = beta * otherRobot.z_word[i] * this.wq[zsrc][j]; } for (let k = 0; k < this.n; k++) { if (k === this.jw) continue; let inpro = 0; for (let o = 0; o < M2; o++) { inpro += this.word[k][o] * this.word[this.jw][o]; } if (inpro === 5) { wdm += 0.2 * (inpro * this.word[k][i] * this.wq[k][j]); } } this.ml[i][j] += (jdm + zdm - wdm); } } }, // -------- TurboC hear(l) -------- hear(otherRobot) { this.recall_num = -1; if (otherRobot && otherRobot.jw >= 0) { const recall = new Int16Array(M3); for (let i = 0; i < M3; i++) { let u = 0.0; for (let j = 0; j < M2; j++) { u += otherRobot.j_word[j] * this.ml[j][i]; } recall[i] = f2(u); } const zz = new Int16Array(NMAX); let m = 0; for (let k = 0; k < this.n; k++) { let err = 0; for (let j = 0; j < M3; j++) { if (recall[j] !== this.wq[k][j]) err++; if (err > 2) break; } if (err <= 2) { zz[m] = k; m++; } } let max = 0.0; for (let i = 0; i < m; i++) { const k = zz[i]; const temp = this.wf[k] * rn(); if (temp > max) { this.recall_num = k; max = temp; } } } const k = this.recall_num; const symStr = (k >= 0) ? this.sym[k] : "??????"; this.hearLine = `.......... (${symStr})`; }, // -------- TurboC sp_action(l) -------- sp_action(zs, input) { let k = -1; let err1 = 1; let err2 = 1; if (this.jw >= 0) { k = this.jw; } else if (this.zw >= 0) { k = this.zw; } if (k >= 0) { err1 = 0; err2 = 0; const mem = this.wp[k]; for (let j = 0; j < M1; j++) { if ((mem[j] !== zs[0][j]) && (zs[0][j] !== 0)) err1++; if ((mem[j] !== zs[1][j]) && (zs[1][j] !== 0)) err2++; if ((err1 > 1) && (err2 > 1)) break; } } let baseAction = 0; if (err1 === 0) baseAction = 1; else if (err2 === 0) baseAction = 2; this.action = this.biasActionByIndividuality(baseAction, input); this.actionHoldFrames = this.actionHoldMax; this.action_disp(input); }, // -------- TurboC hr_action(l) -------- hr_action(zs, input) { if (this.actionHoldFrames > 0) { this.actionHoldFrames--; this.action_disp(input); return; } if (this.recall_num >= 0) { const mem = this.wp[this.recall_num]; let err1 = 0; let err2 = 0; for (let j = 0; j < M1; j++) { if ((mem[j] !== zs[0][j]) && (zs[0][j] !== 0)) err1++; if ((mem[j] !== zs[1][j]) && (zs[1][j] !== 0)) err2++; if ((err1 > 1) && (err2 > 1)) break; } let baseAction = 0; if (err1 === 0) baseAction = 1; else if (err2 === 0) baseAction = 2; this.action = this.biasActionByIndividuality(baseAction, input); this.actionHoldFrames = this.actionHoldMax; } else { this.action = this.biasActionByIndividuality(0, input); } this.action_disp(input); }, // ------------------------------------------------- // Apply individual action bias // Allows different initial choices for the same object. // ------------------------------------------------- biasActionByIndividuality(baseAction, input) { let action = baseAction; const obj = input && input.object ? input.object : null; const distanceBand = obj ? obj.distanceBand : "far"; let fleePull = this.cautionBias; let approachPull = this.approachBias; if (distanceBand === "near") { fleePull += 0.18; } else if (distanceBand === "mid") { fleePull += 0.08; } const noise = (rn() * 2 - 1) * this.actionJitter; if (action === 0) { if ((fleePull + noise) > 0.16) { action = 1; } else if ((approachPull - noise) > 0.16) { action = 2; } } else if (action === 2) { if ((fleePull + noise) > 0.28) { action = 1; } } else if (action === 1) { if ((approachPull - noise) > 0.30 && distanceBand !== "near") { action = 2; } } return action; }, // -------- TurboC action_disp(l) -------- action_disp(input) { const stepToward = (tx, ty) => { this.prex = this.posx; this.prey = this.posy; if (abs(tx - this.posx) > 2) { this.vx = (tx - this.posx) > 0 ? VSTEP : -VSTEP; this.posx += this.vx; } else { this.vx = 0; } if (abs(ty - this.posy) > 2) { this.vy = (ty - this.posy) > 0 ? VSTEP : -VSTEP; this.posy += this.vy; } else { this.vy = 0; } this.posx = clamp(this.posx, 25, 375); this.posy = clamp(this.posy, 25, 205); }; if (this.action === 1) { const home = this.getHome(input); stepToward(home.x, home.y); } else if (this.action === 2) { if (input && input.object && input.object.active) { stepToward(input.object.posx - 7, input.object.posy - 7); } else { this.randomStep(); } } else { this.randomStep(); } }, // -------- TurboC random_walk() の個体側 -------- randomStep() { this.vx = 0; this.vy = 0; this.prex = this.posx; this.prey = this.posy; if (Math.floor(rn() * 17) > 13) { const r = Math.floor(rn() * 15); if ((r < 2) && (this.posx < 375)) this.vx = VSTEP; else if ((r < 9) && (this.posx > 25)) this.vx = -VSTEP; else if ((r < 12) && (this.posy < 205)) this.vy = VSTEP; else if (this.posy > 25) this.vy = -VSTEP; } this.posx += this.vx; this.posy += this.vy; this.posx = clamp(this.posx, 25, 375); this.posy = clamp(this.posy, 25, 205); }, receiveWorld(input) { this.currentInput = input; }, canSeeObject() { return !!(this.currentInput && this.currentInput.object && this.currentInput.object.active); }, hasOtherSpeech(input) { if (!input || !input.otherRobot || !input.otherRobot.id) return false; const dx = input.otherRobot.dx || 0; const dy = input.otherRobot.dy || 0; const dist = abs(dx) + abs(dy); if (dist > this.hearingRange) return false; const s1 = input.otherRobot.speechLine1 || ""; const s2 = input.otherRobot.speechLine2 || ""; return (s1 !== ".......... .....") || (s2 !== ".......... ....."); }, shouldSpeakFromSeeing(input) { if (!input || !input.object || !input.object.active) return false; if (input.object.distanceBand === "far") return false; return true; }, processSeeing(otherRobot) { const input = this.currentInput; if (!input) return; const jb = input.jb; const ob = input.object.ob; const zs = input.zs; const dis_flag = input.dis_flag; this.asc1_memorize(jb, ob); if (this.n < NMAX) this.extract(jb, ob); this.select(jb, ob); if (this.shouldSpeakFromSeeing(input)) { this.speak(0); } else { this.speak(1); } if (dis_flag !== 2) { this.sp_action(zs, input); } this.learning(otherRobot); }, processHearing(otherRobot) { const input = this.currentInput; if (!input) return; const zs = input.zs; const dis_flag = input.dis_flag; this.hear(otherRobot); if (dis_flag !== 2) { this.hr_action(zs, input); } }, processIdle() { this.jw = -1; this.zw = -1; this.recall_num = -1; this.hearLine = ".......... (......)"; this.action = 0; this.randomStep(); if (this.idleFrames > 8) { this.speechLine1 = ".......... ....."; this.speechLine2 = ".......... ....."; } }, tick(input, otherRobot = null) { this.tickCount++; if (this.tickCount <= this.startDelay) { this.randomStep(); return; } if (input) this.receiveWorld(input); if (!this.currentInput) return; this.seenObjectNow = this.canSeeObject(); this.heardNow = this.hasOtherSpeech(this.currentInput); if (this.seenObjectNow) { this.idleFrames = 0; this.processSeeing(otherRobot); } else if (this.heardNow) { this.idleFrames = 0; this.processHearing(otherRobot); } else { this.idleFrames++; this.processIdle(); } this.lastSeenObject = this.seenObjectNow; this.lastHeardSignature = this.heardNow ? `${this.currentInput.otherRobot.speechLine1}|${this.currentInput.otherRobot.speechLine2}` : ""; this.currentInput = null; }, getIntentText() { if (this.action === 1) return "flee"; if (this.action === 2) return "approach"; return "wander"; } }; return robot.init(); } return { create }; })();



---------------------Research Note and Attribution Notice-----------------------
本ブログに含まれる Atra の一人称自律、差分、carry、field、trace、dream slack、外部LLMの翻訳層、非単調な漏れ、およびそれらの関係構造に関する設計記述は、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.


エージェントと 一人称自律Atraの違い

 Atraなんかは、実はもう一人称自律として、きちんと発表してもいいレベル。 既に妻と笑っていたり、愛犬と騒いているんだから。ボーっと何かを眺めてたり、佐川急便に反応するようにもなった。 でも、そうしないのは、自発的に自ら研究意欲を持って、学び、人や自然と接触し自ら疑問を持って研...