홈으로 돌아가기

Wolfram Language에서의 반딧불 동기화

기사에서는 Wolfram Language에서 반딧불 동기화 모델의 구현을 설명합니다. 에이전트 기반 모델에서 ListConvolve를 사용한 벡터화된 셀룰러 오토마톤으로의 전환. NumericArray를 통한 렌더링 최적화 및 비디오 생성. 2–200 에이전트와 50×50 필드 예시에서 창발 행동을 보여줍니다.

반딧불 동기화: 셀룰러 오토마톤 코드
Advertisement 728x90

불꽃벌레의 동기화: 에이전트 모델에서 세포 자동기로의 전환

불꽃벌레는 지역적 상호작용을 통해 깜빡임을 동기화합니다. 각 에이전트는 [0,1] 범위 내의 내부 타이머를 가지고 있으며, 단계마다 0.01씩 감소합니다. 타이머가 0에 도달하면 플래시(상태 1)가 발생하며, 지정된 반경 내의 이웃들에 영향을 미칩니다.

핵심 메커니즘은 적응형 위상 보정입니다: 이웃이 플래시하면 현재 타이머는 주기 내 위치에 따라 앞으로 또는 뒤로 조정됩니다. 방향은 Sign[2 Round[state] - 1]로 결정되며, 0에 가까운 상태는 음수, 1에 가까운 상태는 양수입니다.

에이전트 모델: 생성과 연결성

먼저 영역에 n개의 에이전트를 배치하고 무작위 초기 상태를 할당합니다:

Google AdInline article slot
generateFireFlies[n_:200, region_:Rectangle[{-10,-10}, {10,10}]] := fireFlies = With[{ 
  pos = RandomPoint[region, n]
},
  Transpose[{pos, Table[RandomReal[{0,1.0}], {Length[pos]}]}]
];

각 불꽃벌레는 {위치, 상태} 쌍으로 표현됩니다. 연결 행렬은 유클리드 거리를 기반으로 계산됩니다:

bakeConnections[r_:3.7] := (
  connectionMatrix = Table[
    If[i == j, Infinity, Power[Norm[i[[1]] - j[[1]]], 2]]
  , {i, fireFlies}, {j, fireFlies}];

  connectionMatrix = MapIndexed[
    Function[{value, index},
      If[value < r, index[[1]], Nothing]
    ],
    #
  ] & /@ connectionMatrix
);

단계별 핵심 연산:

  • 감소: Clip[state - 0.01, {0,1}]
  • 플래시: 상태가 0일 때 → 1
  • 보정: 이웃이 상태 1이면 state + Sign[2 Round[state] - 1] * 0.0001

업데이트: fireFlies = MapIndexed[adjust, decay /@ flash /@ fireFlies];

Google AdInline article slot

소규모 테스트

두 개의 에이전트에서는 동기화가 약 10 사이클 내에 이루어집니다. 상태 그래프는 수렴을 보여줍니다:

generateFireFlies[2, Circle[{0,0},0.5]];
bakeConnections[2.0];

EventHandler[AnimationFrameListener[...]]를 활용한 애니메이션 시각화를 통해 위상 정렬이 명확히 드러납니다.

200개의 에이전트를 사용할 경우 색상 디스크를 활용합니다:

Google AdInline article slot
cf = Blend[{Darker[Red], Yellow}, #] &;
Graphics[{ 
  Table[
    With[{i = i, xy = fireFlies[[i,1]]},
      {RGBColor[colors[[i]]], Disk[xy, 0.3]}
    ], {i, Length[fireFlies]}
  ],
  EventHandler[AnimationFrameListener[colors], update]
}, Background->Black]

복제된 레이어를 흐리게 처리하면 빛나는 효과가 생성됩니다.

세포 자동기로의 전환

논리는 게임 오브 라이프와 유사하지만, 상태가 연속적입니다. 25×25 그리드를 RandomReal[{0,1.01}, {25,25}]로 초기화합니다.

플래시는 Floor[field]로 감지합니다. 이웃 영향은 3×3 컨볼루션 커널을 사용합니다:

ListConvolve[
  {{1.0,1.0,1.0}, {1.0,0.0,1.0}, {1.0,1.0,1.0}},
  Floor[field],
  2, 0
]

보정: (2.0 Round[field] - 1.0) * Clip[convolution, {0, 0.001}]. 감소-플래시: Map[Clip[# - 0.01, {0.0,1.0}, {1.0,1.0}], f, {2}].

30 FPS로 Refresh 내에서 전체 루프 실행:

Module[{f = RandomReal[{0,1.01}, {25,25}]}, Refresh[
  f = Map[Clip[# - 0.01, {0.0,1.0}, {1.0,1.0}]&, f, {2}];

  f = Clip[
    f + (2.0 Round[f] - 1.0)
      Clip[
        ListConvolve[
          {{1.0,1.0,1.0}, {1.0,0.0,1.0}, {1.0,1.0,1.0}},
          Floor[f],
          2, 0
        ], {0, 0.001}
      ],
    {0., 1.0}
  ];

  ArrayPlot[f, Frame->True, ColorFunction->"PlumColors"]
, 1/30.0]]

반복 과정에서 파도 같은 패턴이 나타납니다.

성능 최적화

Refresh 내의 ArrayPlot은 프로토타입에는 잘 작동하지만, 대규모 시스템에서는 NumericArrayImage를 사용하는 것이 좋습니다:

field = RandomReal[{0,1.0}, {50,50}];

render = Function[Null,
  Do[
    field = Map[Clip[# - 0.01, {0.0,1.0}, {1.0,1.0}]&, field, {2}];
    field = Clip[
      field + (2.0 Round[field] - 1.0)
        Clip[ListConvolve[{{1,1,1},{1,0,1},{1,1,1}}, Floor[field], 2, 0], {0,0.001}],
      {0.,1.0}
    ];
  , {2}];

  imageBuffer = NumericArray[255.0 field, "Byte", "ClipAndRound"];
];

Image[imageBuffer, "Byte", Epilog -> EventHandler[AnimationFrameListener[imageBuffer], render], Magnification -> 20]

50×50 그리드에서는 레이더처럼 보이는 구조가 나타납니다.

비디오 생성

내보내기를 위해:

movie = Table[
  render[];
  ImageResize[Colorize[Image[imageBuffer]], Scaled[6], Method->"NearestNeighbor"],
  {600}
];
FrameListVideo[movie, FrameRate->60]

이 모델은 에이전트 기반 시스템에서 GPU 친화적인 컨볼루션으로 확장 가능하며, 자기 조직화된 행동을 보여줍니다.

핵심 요약

  • 지역 규칙(감소 + 적응형 보정)이 글로벌 동기화를 유도합니다.
  • 에이전트 모델 → 세포 자동기: 컨볼루션으로 이웃 루프를 대체합니다.
  • Sign[2 Round[state] - 1]은 양방향 위상 조정을 가능하게 합니다.
  • NumericArray + Image는 대규모 필드 렌더링을 최적화합니다.
  • 직사각형 컨볼루션 커널은 사각형 패턴을 생성하며, 현실감을 높이려면 가우시안 커널이 선호됩니다.

— Editorial Team

Advertisement 728x90

다음 읽기