PageRenderTime 47ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/release 0.1.1/HAB/Expressions/BoolExpression.cs

https://gitlab.com/Tiger66639/neural_network_designer
C# | 340 lines | 234 code | 20 blank | 86 comment | 79 complexity | b9b16834c5c540ff6ae23555651f2b24 MD5 | raw file
  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using System.Text;
  4. namespace NeuralNetworkDesigne.HAB
  5. {
  6. /// <summary>
  7. /// A result expression that can be evaluated to a boolean.
  8. /// </summary>
  9. /// <remarks>
  10. /// If there is only a left part, this evaluates to true if non of the items in the left part are <see cref="PredefinedNeurons.False"/>.
  11. /// </remarks>
  12. [NeuronID((ulong)PredefinedNeurons.BoolExpression, typeof(Neuron))]
  13. [NeuronID((ulong)PredefinedNeurons.And, typeof(Neuron))]
  14. [NeuronID((ulong)PredefinedNeurons.Or, typeof(Neuron))]
  15. [NeuronID((ulong)PredefinedNeurons.Contains, typeof(Neuron))]
  16. [NeuronID((ulong)PredefinedNeurons.Different, typeof(Neuron))]
  17. [NeuronID((ulong)PredefinedNeurons.Equal, typeof(Neuron))]
  18. [NeuronID((ulong)PredefinedNeurons.BiggerOrEqual, typeof(Neuron))]
  19. [NeuronID((ulong)PredefinedNeurons.Smaller, typeof(Neuron))]
  20. [NeuronID((ulong)PredefinedNeurons.SmallerOrEqual, typeof(Neuron))]
  21. [NeuronID((ulong)PredefinedNeurons.Bigger, typeof(Neuron))]
  22. [NeuronID((ulong)PredefinedNeurons.False, typeof(Neuron))]
  23. [NeuronID((ulong)PredefinedNeurons.True, typeof(Neuron))]
  24. [NeuronID((ulong)PredefinedNeurons.Clusters, typeof(Neuron))]
  25. public class BoolExpression : ResultExpression
  26. {
  27. #region ctor
  28. /// <summary>
  29. /// Default constructor.
  30. /// </summary>
  31. public BoolExpression()
  32. {
  33. }
  34. /// <summary>
  35. /// Creates a new bool expression, with the proper links already made.
  36. /// </summary>
  37. /// <param name="left">The left part of the expression.</param>
  38. /// <param name="op">The operator to execute.</param>
  39. /// <param name="right">The right part of the expression.</param>
  40. public BoolExpression(Neuron left, Neuron op, Neuron right)
  41. {
  42. Link iNew = new Link(left, this, (ulong)PredefinedNeurons.LeftPart);
  43. iNew = new Link(op, this, (ulong)PredefinedNeurons.Operator);
  44. iNew = new Link(right, this, (ulong)PredefinedNeurons.RightPart);
  45. }
  46. #endregion ctor
  47. #region Prop
  48. /// <summary>
  49. /// Gets/sets the operator that should be used.
  50. /// </summary>
  51. /// <remarks>
  52. /// This is 'Equal' by defualt. Other values could be 'Bigger', 'Smaller', 'Different, 'BiggerOrEqual', 'SmallerOrEqual' or 'Contains'.
  53. /// <para>
  54. /// If this is an expression, it is first executed before the compare is done (so multiple operators are allowed?).
  55. /// </para>
  56. /// </remarks>
  57. public Neuron Operator
  58. {
  59. get
  60. {
  61. return FindFirstOut((ulong)PredefinedNeurons.Operator);
  62. }
  63. set
  64. {
  65. SetFirstOutgoingLinkTo((ulong)PredefinedNeurons.Operator, value);
  66. }
  67. }
  68. /// <summary>
  69. /// Gets/sets the Neuronlist that should be searched in a 'Contains' expression. This value should only be supplied if this operator
  70. /// is used.
  71. /// </summary>
  72. /// <remarks>
  73. /// If this is an expression, it is first solved, so multiple lists on the same neuron are allowed.
  74. /// </remarks>
  75. public Neuron ListToSearch
  76. {
  77. get
  78. {
  79. return FindFirstOut((ulong)PredefinedNeurons.ListToSearch);
  80. }
  81. set
  82. {
  83. SetFirstOutgoingLinkTo((ulong)PredefinedNeurons.ListToSearch, value);
  84. }
  85. }
  86. /// <summary>
  87. /// Gets/sets the left part of the expression.
  88. /// </summary>
  89. /// <remarks>
  90. /// <para>
  91. /// The left part is compared to the <see cref="BoolExpression.RightPart"/> using the <see cref="BoolExpresssion.Operator"/> (which
  92. /// must be of a known type) to produce a result.
  93. /// </para>
  94. /// <para>
  95. /// If this is an expression, it is first executed before the compare is done.
  96. /// </para>
  97. /// </remarks>
  98. public Neuron LeftPart
  99. {
  100. get
  101. {
  102. return FindFirstOut((ulong)PredefinedNeurons.LeftPart);
  103. }
  104. set
  105. {
  106. SetFirstOutgoingLinkTo((ulong)PredefinedNeurons.LeftPart, value);
  107. }
  108. }
  109. /// <summary>
  110. /// Gets/sets the right part of the expression.
  111. /// </summary>
  112. /// <remarks>
  113. /// The right part is compared to the <see cref="BoolExpression.LeftPart"/> using the <see cref="BoolExpresssion.Operator"/> (which
  114. /// must be of a known type) to produce a result.
  115. /// <para>
  116. /// If this is an expression, it is first executed before the compare is done.
  117. /// </para>
  118. /// </remarks>
  119. public Neuron RightPart
  120. {
  121. get
  122. {
  123. return FindFirstOut((ulong)PredefinedNeurons.RightPart);
  124. }
  125. set
  126. {
  127. SetFirstOutgoingLinkTo((ulong)PredefinedNeurons.RightPart, value);
  128. }
  129. }
  130. #region TypeOfNeuron
  131. /// <summary>
  132. /// Gets the type of this neuron expressed as a Neuron.
  133. /// </summary>
  134. /// <value><see cref="PredefinedNeurons.BoolExpression"/>.</value>
  135. public override Neuron TypeOfNeuron
  136. {
  137. get
  138. {
  139. return Brain.Current[(ulong)PredefinedNeurons.BoolExpression];
  140. }
  141. }
  142. #endregion TypeOfNeuron
  143. #endregion Prop
  144. /// <summary>
  145. /// We push the result of the expression on the stack, this is normally a <see cref="PredefinedNeuron.True"/> or
  146. /// <see cref="PredefinedNeuron.False"/>
  147. /// </summary>
  148. /// <param name="handler"></param>
  149. protected internal override void Execute(Processor handler)
  150. {
  151. if (Evaluate(handler) == true)
  152. handler.Push(Brain.Current[(ulong)PredefinedNeurons.True]);
  153. else
  154. handler.Push(Brain.Current[(ulong)PredefinedNeurons.False]);
  155. }
  156. /// <summary>
  157. /// Returns the value of the compare as a list containing a true or false node.
  158. /// provided to solve general purpose result expressions.
  159. /// </summary>
  160. /// <returns></returns>
  161. public override IEnumerable<Neuron> GetValue(Processor processor)
  162. {
  163. List<Neuron> iRes = new List<Neuron>();
  164. if (Evaluate(processor) == true)
  165. iRes.Add(Brain.Current[(ulong)PredefinedNeurons.True]);
  166. else
  167. iRes.Add(Brain.Current[(ulong)PredefinedNeurons.False]);
  168. return iRes;
  169. }
  170. /// <summary>
  171. /// Evaluates the boolean expression and returns the result. True if the evaluation
  172. /// was true, otherwise false.
  173. /// </summary>
  174. /// <returns>True if the bool expression evaluated to true.</returns>
  175. public bool Evaluate(Processor processor)
  176. {
  177. IEnumerable<Neuron> iRight = null;
  178. IEnumerable<Neuron> iLeft = SolveResultExp(LeftPart, processor);
  179. IEnumerable<Neuron> iOp = SolveResultExp(Operator, processor);
  180. IEnumerable<Neuron> iListsToSearch = SolveResultExp(ListToSearch, processor);
  181. if (iLeft != null) //there were no left parts to evaluate, this is a state of error, so log and return that the condition failed.
  182. {
  183. if (iLeft.Count() == 0)
  184. return iOp.All(i => i.ID == (ulong)PredefinedNeurons.Different) == true; //if we have no result, but are trying to do a '!=' we need to return true.
  185. if (iOp != null)
  186. {
  187. foreach (Neuron iL in iLeft) //check every possible combination, if non is false, it's true.
  188. {
  189. foreach (Neuron iO in iOp) //we need to check the operator in a loop cause an expression can always return multiple items, so also an operator in theory, although this will probably not often be used.
  190. {
  191. if (iO.ID == (ulong)PredefinedNeurons.Contains) //we treat the contains seperatly, cause this needs a different check type.
  192. {
  193. iRight = GetRightPart(iRight, processor);
  194. if (iRight == null || EvaluateContains(iL, iRight, iListsToSearch) == false)
  195. return false;
  196. }
  197. else if (iO.ID == (ulong)PredefinedNeurons.And)
  198. {
  199. if (iL.ID != (ulong)PredefinedNeurons.True)
  200. return false;
  201. iRight = GetRightPart(iRight, processor);
  202. foreach (Neuron iR in iRight)
  203. if (iL.CompareWith(iR, iO) == false)
  204. return false;
  205. }
  206. else if (iO.ID == (ulong)PredefinedNeurons.Or)
  207. {
  208. if (iL.ID != (ulong)PredefinedNeurons.True)
  209. {
  210. iRight = GetRightPart(iRight, processor);
  211. foreach (Neuron iR in iRight)
  212. if (iL.CompareWith(iR, iO) == false)
  213. return false;
  214. }
  215. }
  216. else
  217. {
  218. iRight = GetRightPart(iRight, processor);
  219. foreach (Neuron iR in iRight)
  220. if (iL.CompareWith(iR, iO) == false)
  221. return false;
  222. }
  223. }
  224. }
  225. return true;
  226. }
  227. else
  228. Log.LogError("BoolExpression.Evaluate", string.Format("No valid operator part found during evaluation of: {0}", this));
  229. }
  230. else
  231. Log.LogError("BoolExpression.Evaluate", string.Format("No valid left part to evaluate for: {0}", this));
  232. return false;
  233. }
  234. /// <summary>
  235. /// Small helper function that checks if the right part has already been solved, if not, we try to solve it.
  236. /// </summary>
  237. /// <param name="list">The list.</param>
  238. /// <param name="processor">The processor.</param>
  239. /// <returns></returns>
  240. private IEnumerable<Neuron> GetRightPart(IEnumerable<Neuron> list, Processor processor)
  241. {
  242. if (list == null) //if the right part has not yet been build, do it now.
  243. {
  244. list = SolveResultExp(RightPart, processor);
  245. if (list == null)
  246. Log.LogError("BoolExpression.Evaluate", string.Format("No valid right part found during evaluation of: {0}", this));
  247. }
  248. return list;
  249. }
  250. /// <summary>
  251. /// Performs the evaluation for a contains operator. All lists in left as defined by lists, should contain all the items
  252. /// defined in right
  253. /// </summary>
  254. /// <param name="left">The item who's list(s) to check.</param>
  255. /// <param name="right">The items that need to be found in the list(s)</param>
  256. /// <param name="lists">The list(s) to check, should not be null.</param>
  257. /// <returns>True if all the items were contained in the lists, otherwise false.</returns>
  258. private bool EvaluateContains(Neuron left, IEnumerable<Neuron> right, IEnumerable<Neuron> lists)
  259. {
  260. NeuronCluster iLeft = left as NeuronCluster;
  261. foreach (Neuron iRight in right)
  262. {
  263. foreach (Neuron iList in lists)
  264. {
  265. if (iList.ID == (ulong)PredefinedNeurons.Children)
  266. {
  267. using (ChildrenAccessor iLeftList = iLeft.Children)
  268. if (iLeft == null || iLeftList.Contains(iRight) == false)
  269. return false;
  270. }
  271. else if (iList.ID == (ulong)PredefinedNeurons.Clusters)
  272. {
  273. using (NeuronsAccessor iClusteredBy = left.ClusteredBy)
  274. if (iClusteredBy.Items.Contains(iRight.ID) == false)
  275. return false;
  276. }
  277. }
  278. }
  279. return true;
  280. }
  281. public override string ToString()
  282. {
  283. StringBuilder iStr = new StringBuilder();
  284. Neuron iToWrite = LeftPart;
  285. if (iToWrite != null)
  286. iStr.Append(iToWrite.ToString());
  287. else
  288. iStr.Append("??");
  289. iStr.Append(" ");
  290. iToWrite = Operator;
  291. if (iToWrite == null)
  292. iStr.Append("?");
  293. else if (iToWrite.ID == (ulong)PredefinedNeurons.Equal)
  294. iStr.Append("==");
  295. else if (iToWrite.ID == (ulong)PredefinedNeurons.Smaller)
  296. iStr.Append("<");
  297. else if (iToWrite.ID == (ulong)PredefinedNeurons.Bigger)
  298. iStr.Append(">");
  299. else if (iToWrite.ID == (ulong)PredefinedNeurons.SmallerOrEqual)
  300. iStr.Append("<=");
  301. else if (iToWrite.ID == (ulong)PredefinedNeurons.BiggerOrEqual)
  302. iStr.Append(">=");
  303. else if (iToWrite.ID == (ulong)PredefinedNeurons.Different)
  304. iStr.Append("!=");
  305. else if (iToWrite.ID == (ulong)PredefinedNeurons.Contains)
  306. iStr.Append("contains");
  307. else if (iToWrite != null)
  308. iStr.Append(iToWrite.ToString());
  309. else
  310. iStr.Append("?");
  311. iStr.Append(" ");
  312. iToWrite = RightPart;
  313. if (iToWrite != null)
  314. iStr.Append(iToWrite.ToString());
  315. else
  316. iStr.Append("??");
  317. return iStr.ToString();
  318. }
  319. }
  320. }