PSO : Particle Swarm Optimization(입자 군집 최적화)
PSO는 Particle Swarm Optimization(입자 군집 최적화)이라는 최적화 알고리즘을 말한다.
1995년에 James Kennedy와 Russell Eberhart가 자연에서의 새 떼나 물고기 떼의 움직임에서 영감을 받아 만든 진화 계산 기법으로 많으면 군체의 움직임이 보여진다.
반응형
< 동작 원리 >
입자(Particle): 가능한 해(solution) 오브젝트
군집(Swarm): 여러 개의 입자로 구성된 집단
입자들은 공간 내에서 이동하면서 최적 해를 찾아 간다.
각 입자는 자신이 찾은 최적 해와, 전체 군집 중 가장 좋은 해를 참고하여 방향을 조정해서 이동하게 된다.
< 예시 코드 >
using System.Collections.Generic;
using UnityEngine;
public class PSOManager : MonoBehaviour
{
[Header("PSO Settings")]
public int swarmSize = 30;
public float inertiaWeight = 0.5f;
public float cognitiveWeight = 1.5f;
public float socialWeight = 1.5f;
public float maxSpeed = 0.3f;
[Header("References")]
public GameObject particlePrefab;
public Vector2 targetPosition = new Vector2(-2f, 3f);
public Transform[] obstacles; // optional: 장애물 회피 추가 가능
private List<Particle> swarm;
private Vector2 globalBestPos;
private float globalBestFitness;
void Start()
{
swarm = new List<Particle>();
globalBestFitness = float.MaxValue;
for (int i = 0; i < swarmSize; i++)
{
Vector2 startPos = new Vector2(Random.Range(-5f, 5f), Random.Range(-5f, 5f));
GameObject go = Instantiate(particlePrefab, new Vector3(startPos.x, startPos.y, 0f), Quaternion.identity);
var p = new Particle(startPos, go, targetPosition);
swarm.Add(p);
if (p.bestFitness < globalBestFitness)
{
globalBestFitness = p.bestFitness;
globalBestPos = p.bestPosition;
}
}
}
void Update()
{
foreach (Particle p in swarm)
{
// 기본 PSO 계산
Vector2 inertia = inertiaWeight * p.velocity;
Vector2 cognitive = cognitiveWeight * Random.value * (p.bestPosition - p.position);
Vector2 social = socialWeight * Random.value * (globalBestPos - p.position);
Vector2 newVelocity = inertia + cognitive + social;
// 장애물 회피 계산
foreach (var obs in obstacles)
{
float dist = Vector2.Distance(p.position, obs.position);
if (dist < 1.0f)
{
Vector2 away = (p.position - (Vector2)obs.position).normalized;
newVelocity += away * 0.5f; // 회피 강도 증가 가능
}
}
// 속도 제한
newVelocity = Vector2.ClampMagnitude(newVelocity, maxSpeed);
// 타겟 도달 시 정지
if ((p.position - targetPosition).magnitude < 0.01f)
{
p.velocity = Vector2.zero;
}
else
{
p.velocity = newVelocity;
p.position += newVelocity;
}
// 최적값, 시각 업데이트
p.UpdatePersonalBest();
if (p.bestFitness < globalBestFitness)
{
globalBestFitness = p.bestFitness;
globalBestPos = p.bestPosition;
}
p.UpdateVisual();
}
Debug.Log("Best: " + globalBestFitness.ToString("F6") + " at " + globalBestPos);
}
}using UnityEngine;
public class Particle
{
public Vector2 position;
public Vector2 velocity;
public Vector2 bestPosition;
public float bestFitness;
public GameObject visual;
private Vector2 target;
public Particle(Vector2 startPos, GameObject go, Vector2 targetPos)
{
position = startPos;
velocity = Random.insideUnitCircle * 0.1f;
bestPosition = position;
target = targetPos;
bestFitness = Fitness(position);
visual = go;
}
public float Fitness(Vector2 pos)
{
return (pos - target).sqrMagnitude; // (x−tx)² + (y−ty)²
}
public void UpdatePersonalBest()
{
float currentFitness = Fitness(position);
if (currentFitness < bestFitness)
{
bestFitness = currentFitness;
bestPosition = position;
}
}
public void UpdateVisual()
{
visual.transform.position = new Vector3(position.x, position.y, visual.transform.position.z);
if (Fitness(position) < 0.001f)
{
Renderer rend = visual.GetComponent<Renderer>();
if (rend != null)
rend.material.color = Color.green;
var ps = visual.GetComponent<ParticleSystem>();
if (ps && !ps.isPlaying)
ps.Play();
}
}
}
★☆☆☆☆
반응형
'개발 > 기본) 알고리즘' 카테고리의 다른 글
알고리즘) Fisher-Yates 알고리즘 (0) | 2025.01.04 |
---|---|
알고리즘)그로버 알고리즘(Grover Algorithm) (0) | 2024.05.09 |
알고리즘) Force-Directed Drawing Algorithms (시각화 알고리즘) (0) | 2024.04.30 |
알고리즘)Decision Trees Algorithm(의사 결정 알고리즘) (0) | 2024.03.08 |
알고리즘) Given When Then Pattern ( 테스트 케이스 작성 기법 ) (0) | 2024.01.31 |
댓글