/// <summary> /// </summary> /// <param name="before"></param> /// <param name="after"></param> public VRiscuitRule(IBeforePattern before, IAfterPattern after, ScoreCoefficient sce, bool isDebug = false) { BeforePattern = before; AfterPattern = after; _coefficient = sce; _beforeObjectSet = BeforePattern.VRiscuitObjects; _afterObjectSet = AfterPattern.ResultObjectSet; _genDelTable = new Dictionary <string, int>(_afterObjectSet.DistributionTable); IsDebug = isDebug; foreach (var kvp in _beforeObjectSet.DistributionTable) { if (_genDelTable.ContainsKey(kvp.Key)) { _genDelTable[kvp.Key] -= kvp.Value; } else { _genDelTable.Add(kvp.Key, -kvp.Value); } if (_genDelTable[kvp.Key] != 0) { isGenerateOrDeleteObject = true; } } // alphaの値をルールの動き量で決める var afterParam = new VRiscuitObjectSet(_afterObjectSet).ToParameters(); var beforeSet = new VRiscuitObjectSet(_beforeObjectSet); GenerateOrDeleteObject(beforeSet, null); var beforeParam = beforeSet.ToParameters(); _paramLength = TwoArrayDistance(afterParam, beforeParam); }
public Candidate(IRule rule, IVRiscuitObjectSet table, float score) { _rule = rule; _table = table; Score = score; NotNormalizedScore = score; }
public static float[] CalcAppliedFieldScore(IVRiscuitObjectSet currentField, IVRiscuitObjectSet beforeField, IVRiscuitObjectSet afterRuleSet, IVRiscuitObjectSet beforeRuleSet, ScoreCoefficient ef) { var score = 0.0f; var max = 0.0f; var beforeRuleSetArray = beforeRuleSet.ObjectArray; var afterRuleSetArray = afterRuleSet.ObjectArray; var beforeFieldArray = beforeField.ObjectArray; var currentFieldArray = currentField.ObjectArray; var currentSize = currentField.Size; var beforeSize = beforeField.Size; for (int a = 0; a < currentSize; a++) { for (int b = 0; b < beforeSize; b++) { var f = CalcTwoObjectSimilarity(beforeRuleSetArray[b], afterRuleSetArray[a], beforeFieldArray[b], currentFieldArray[a], ef); score += f[0]; max += f[1]; } } var cc = CalcScore(afterRuleSet, currentField, ef); score += cc[0]; max += cc[1]; return(new float[] { score, max }); }
/// <summary> /// オブジェクト集合のコピー /// 実体のないcalculateObjectで構成する /// </summary> /// <param name="source"></param> public VRiscuitObjectSet(IVRiscuitObjectSet source) { _table = new Dictionary <string, List <IVRiscuitObject> >(); foreach (var kvp in source.TypeTable) { _table.Add(kvp.Key, kvp.Value.Select(obj => new CalculateObject(obj) as IVRiscuitObject).ToList()); } }
public Candidate(IRule rule, IVRiscuitObjectSet table, float[] scores) { _rule = rule; _table = table; // オブジェクト個数で優遇する Score = RuleManager.NormalizeScore(scores) * _table.Size; NotNormalizedScore = scores[0]; }
private void GenerateOrDeleteObject(IVRiscuitObjectSet objset, IVRiscuitObjectSet globalTable) { if (isGenerateOrDeleteObject == false) { return; } foreach (var kvp in _genDelTable) { var val = kvp.Value; if (val < 0) { var objs = objset.TypeTable[kvp.Key]; if (objs.Count < -val) { Debug.LogError("Error: 必要な数のオブジェクトがありません。"); if (globalTable != null) { foreach (var obj in objs) { globalTable.Delete(obj); objset.Delete(obj); } } return; } for (int i = 0; i < -val; i++) { if (globalTable != null) { globalTable.Delete(objs[0]); } objset.Delete(objs[0]); } } else if (val > 0) { var first = objset.First(); var generated = new List <CalculateObject>(); for (int i = 0; i < val; i++) { var pos = new Vector3(first.Position.x + 1, first.Position.y, first.Position.z); var rot = Quaternion.Euler(first.Rotation.eulerAngles.x, first.Rotation.eulerAngles.y, first.Rotation.eulerAngles.z); var o = new CalculateObject(pos, rot, kvp.Key); objset.Add(o); generated.Add(o); } _generatedObjects = generated; } } }
protected IEnumerable <List <IVRiscuitObject> > SameNumberObjectGroupsByType(IVRiscuitObjectSet objectSet, IVRiscuitObjectSet ruleBeforeSet) { var typesAndObjs = new List <List <List <IVRiscuitObject> > >(); foreach (var kvp in ruleBeforeSet.TypeTable) { var currentObjs = CurrentObjectSet.GetByType(kvp.Key); if (currentObjs == null || currentObjs.Count < kvp.Value.Count) { return(null); } typesAndObjs.Add(Permutation(currentObjs, kvp.Value.Count()).ToList()); } var choice = Choice(typesAndObjs); var c = choice.ToList(); var result = choice.Select(Flatten); var a = result.ToList(); return(result); }
/// <summary> /// ルールの適用 /// </summary> /// <param name="objectsTable"></param> void IRule.Apply(IVRiscuitObjectSet objectsTable, IVRiscuitObjectSet globalTable) { var beforeTable = new VRiscuitObjectSet(objectsTable); GenerateOrDeleteObject(objectsTable, globalTable); DescentMethod(objectsTable, beforeTable, _afterObjectSet, _beforeObjectSet); // 追加されたオブジェクトをmanagerのobjectSetに追加 if (_generatedObjects == null) { return; } foreach (var obj in _generatedObjects) { if (IsDebug) { globalTable.Add(obj); continue; } } _generatedObjects = null; }
/// <summary> /// Rule上のオブジェクトとフィールドのオブジェクトがどれだけ近い関係にあるかを計算 /// </summary> /// <param name="ruleObjectSet"></param> /// <param name="fieldObjectSet"></param> /// <param name="ef"></param> /// <returns></returns> public static float[] CalcScore(IVRiscuitObjectSet ruleObjectSet, IVRiscuitObjectSet fieldObjectSet, ScoreCoefficient ef) { var score = 0.0f; var max = 0.0f; var ruleObjectList = ruleObjectSet.ObjectArray; var fieldObjectList = fieldObjectSet.ObjectArray; var len = fieldObjectList.Length; if (len == 1) { return(new float[] { 10, 10 }); } for (int i = 0; i < len - 1; i++) { for (int j = i + 1; j < len; j++) { var fs = CalcTwoObjectSimilarity(ruleObjectList[i], ruleObjectList[j], fieldObjectList[i], fieldObjectList[j], ef); score += fs[0]; max += fs[1]; } } return(new float[] { score, max }); }
public BeforePattern(IVRiscuitObjectSet objects) { _vriscuitObjects = objects; }
/// <summary> /// 最急降下法で最適な位置を計算する /// </summary> /// <param name="currentTable"></param> /// <param name="beforeRuleTable"></param> /// <param name="afterRuleTable"></param> /// <param name="changes"></param> private void DescentMethod(IVRiscuitObjectSet currentTable, IVRiscuitObjectSet beforeTable, IVRiscuitObjectSet afterRuleTable, IVRiscuitObjectSet beforeRuleTable) { var limit = 100; var beforeScore = 0.0f; var beforec = new VRiscuitObjectSet(beforeTable); var currentc = new VRiscuitObjectSet(currentTable); var parameters = currentc.ToParameters(); var firstParam = currentc.ToParameters(); var beforeDelta = new float[parameters.Length]; Func <float[], float> func = delegate(float[] param) { (currentc as IVRiscuitObjectSet).SetParameter(param); var scores = RuleManager.CalcAppliedFieldScore(currentc, beforec, afterRuleTable, beforeRuleTable, (this as IRule).RuleScoreCoefficient); return(scores[0] / scores[1]); }; var alpha = _paramLength; var f = 0.001; // scoreの変動がこの値以下になったら終わり for (int i = 0; i < limit; i++) { var score = func(parameters); // var message = String.Format("{0}: {1}, {2}, {3}, {5}, {6}, {7} => {4} points", i, parameters[0], parameters[1], parameters[2], score, parameters[3], parameters[4], parameters[5]); //Debug.Log(message); // Debug.Log("alpha = " + alpha); if (Mathf.Abs(beforeScore - score) <= f && i != 0) { // 終了 break; } beforeScore = score; var delta = Differential(func, parameters); delta = NormalizeArray(delta); // deltaの中に0の要素があったら、beforeDeltaをもとに前回の変更を半分もとに戻す // その場合次のbeforeDeltaは // 同時にbeforeDeltaの更新 for (int di = 0; di < delta.Length; di++) { if (delta[di] == 0) { delta[di] = -(beforeDelta[di] / 2); beforeDelta[di] /= 2; } else { beforeDelta[di] = delta[di]; } } // Debug.Log("delta = " + delta.Skip(1).Aggregate(delta[0].ToString(), (acc, next) => acc + ", " + next.ToString())); for (int j = 0; j < parameters.Length; j++) { parameters[j] += delta[j] * alpha; } // Debug.Log("parameter = " + parameters.Skip(1).Aggregate(parameters[0].ToString(), (acc, next) => acc + ", " + next.ToString())); alpha *= Mathf.Max((float)Math.Exp(-alpha), 0.1f); } // オブジェクトの生成、削除がある場合には、1fで動かす // そうでない場合には、1秒かけて動かすように調整する if (!isGenerateOrDeleteObject) { var len = firstParam.Length; var d = new float[len]; for (int i = 0; i < len; i++) { var di = parameters[i] - firstParam[i]; // 細かい部分を四捨五入, 秒間スピードに変更 di = ((float)Math.Round(di, 1)) * Time.deltaTime; parameters[i] = firstParam[i] + di; } } currentTable.SetParameter(parameters); }
public void RuleApply(IVRiscuitObjectSet globalTable) { _rule.Apply(_table, globalTable); }
public RuleManagerTest(IVRiscuitObjectSet objset, IEnumerable <IRule> rules) : base(objset, rules) { }
public RuleManager(IVRiscuitObjectSet objects, IEnumerable <IRule> rules) { VRiscuitPrefavTable = new Dictionary <string, GameObject>(); CurrentObjectSet = objects; _rules = rules.ToList(); }
public AfterPattern(IVRiscuitObjectSet objects) { _objects = objects; }