Skip to content

Instantly share code, notes, and snippets.

@edom18
Last active September 8, 2017 16:01
Show Gist options
  • Save edom18/31eda22dd171e622ea3faa736c1d575a to your computer and use it in GitHub Desktop.
Save edom18/31eda22dd171e622ea3faa736c1d575a to your computer and use it in GitHub Desktop.
[ゲームAI] ファジー理論 ref: http://qiita.com/edo_m18/items/6f66d7510c31e0a57cd7
float temperature = 30.5f;
float cold = Cold(temperature);
float warm = Warm(temperature);
float hot = Hot(temperature);
float FuzzyGrade(float value, float x0, float x1)
{
float x = value;
if (x <= x0)
{
return 0;
}
else if (x >= x1)
{
return 1;
}
else
{
// 分母を計算
float denom = x1 - x0;
return (x / denom) - (x0 / denom);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// ファジー理論のメンバーシップ関数を定義
/// </summary>
static public class Fuzzy
{
/// <summary>
/// 右上がりのグラフのメンバーシップ関数
/// </summary>
/// <param name="value">評価する値</param>
/// <param name="x0">最低位置の値</param>
/// <param name="x1">最大位置の値</param>
/// <returns></returns>
static public float Grade(float value, float x0, float x1)
{
float x = value;
if (x <= x0)
{
return 0;
}
else if (x >= x1)
{
return 1;
}
else
{
// 分母を計算
float denom = x1 - x0;
return (x / denom) - (x0 / denom);
}
}
/// <summary>
/// 右下がりのグラフのメンバーシップ関数
/// </summary>
/// <param name="value">評価する値</param>
/// <param name="x0">最低位置の値</param>
/// <param name="x1">最大位置の値</param>
/// <returns></returns>
static public float ReverseGrade(float value, float x0, float x1)
{
float x = value;
if (x <= x0)
{
return 1;
}
else if (x >= x1)
{
return 0;
}
else
{
float denom = x1 - x0;
return (x1 / denom) - (x / denom);
}
}
/// <summary>
/// 三角形型のグラフのメンバーシップ関数
/// </summary>
/// <param name="value">評価する値</param>
/// <param name="x0">三角形左端の値</param>
/// <param name="x1">中心位置の値</param>
/// <param name="x2">三角形右端の値</param>
/// <returns></returns>
static public float Triangle(float value, float x0, float x1, float x2)
{
float x = value;
if (x <= x0)
{
return 0;
}
else if (x == x1)
{
return 1;
}
else if ((x > x0) && (x < x1))
{
float denom = x1 - x0;
return (x / denom) - (x0 / denom);
}
else
{
float denom = x2 - x1;
return (x2 / denom) - (x / denom);
}
}
/// <summary>
/// 台形のグラフのメンバーシップ関数
/// </summary>
/// <param name="value">評価する値</param>
/// <param name="x0">台形の左端の値</param>
/// <param name="x1">台形上部の左側の値</param>
/// <param name="x2">台形上部の右側の値</param>
/// <param name="x3">台形の右端の値</param>
/// <returns></returns>
static public float Trapezoid(float value, float x0, float x1, float x2, float x3)
{
float x = value;
if (x <= x0)
{
return 0;
}
else if ((x >= x1) && (x <= x2))
{
return 1;
}
else if ((x > x0) && (x < x1))
{
float denom = x1 - x0;
return (x / denom) - (x0 / denom);
}
else
{
float denom = x3 - x2;
return (x3 / denom) - (x / denom);
}
}
/// <summary>
/// ファジー理論AND演算子
/// </summary>
/// <param name="a">評価するファジー値A</param>
/// <param name="b">評価するファジー値B</param>
/// <returns>理論値</returns>
static public float And(float a, float b)
{
return Mathf.Min(a, b);
}
/// <summary>
/// ファジー理論OR演算子
/// </summary>
/// <param name="a">評価するファジー値A</param>
/// <param name="b">評価するファジー値B</param>
/// <returns>理論値</returns>
static public float Or(float a, float b)
{
return Mathf.Max(a, b);
}
/// <summary>
/// ファジー理論NOT演算子
/// </summary>
/// <param name="a">評価するファジー値A</param>
/// <returns>理論値</returns>
static public float Not(float a, float b)
{
return 1.0f - a;
}
}
/// <summary>
/// 現在の方向に応じて、コントローラの位置の補正距離を算出する
/// </summary>
/// <returns>算出された補正距離</returns>
private float CalcDistance()
{
float upCrisp = Vector3.Dot(_projectController.forward, Vector3.up);
float angleCrisp = Vector3.Dot(_camera.forward, _projectController.forward);
float angle = Fuzzy.Grade(angleCrisp, 0f, 1f);
float down = Fuzzy.Triangle(upCrisp, -1f, -0.55f, 0.1f);
float up = Fuzzy.Grade(upCrisp, 0.1f, 1f);
float t = Fuzzy.Or(Fuzzy.Not(angle), Fuzzy.Or(up, down));
return t * _distanceCoeff;
}
float FuzzyReverseGrade(float value, float x0, float x1)
{
float x = value;
if (x <= 0)
{
return 1;
}
else if (x >= x1)
{
return 0;
}
else
{
float denom = x1 - x0;
return (x1 / denom) - (x / denom);
}
}
float FuzzyTriangle(float value, float x0, float x1, float x2)
{
float x = value;
if (x <= x0)
{
return 0;
}
else if (x == x1)
{
return 1;
}
else if ((x > x0) && (x < x1))
{
float denom = x1 - x0;
return (x / denom) - (x0 / denom);
}
else
{
float denom = x2 - x1;
return (x2 / denom) - (x / denom);
}
}
float FuzzyTrapezoid(float value, float x0, float x1, float x2, float x3)
{
float x = value;
if (x <= x0)
{
return 0;
}
else if ((x >= x1) && (x <= x2))
{
return 1;
}
else if ((x > x0) && (x < x1))
{
float denom = x1 - x0;
return (x / denom) - (x0 / denom);
}
else
{
float denom = x3 - x2;
return (x3 / denom) - (x / denom);
}
}
float FuzzyOr(float a, float b)
{
return Mathf.Max(a, b);
}
float FuzzyAnd(float a, float b)
{
return Mathf.Min(a, b);
}
float FuzzyNot(float a, float b)
{
return 1.0f - a;
}
output = \frac{\sum_{i=1}^{n} μ_{i}x_{i}}{\sum_{i=1}^{n} μ_{i}}
[(0.2 * 10) + (0.4 * 1) + (0.7 * -10)] / (0.7 + 0.4 + 0.3) = -2.5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment