Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
FunctionMultiVariate.cs
1using System;
2using System.Collections.Generic;
3using System.Threading.Tasks;
8
9namespace Waher.Script.Model
10{
14 public abstract class FunctionMultiVariate : Function
15 {
19 protected static readonly ArgumentType[] argumentTypes0 = new ArgumentType[0];
20
24 protected static readonly ArgumentType[] argumentTypes1Normal = new ArgumentType[] { ArgumentType.Normal };
25
29 protected static readonly ArgumentType[] argumentTypes1Vector = new ArgumentType[] { ArgumentType.Vector };
30
34 protected static readonly ArgumentType[] argumentTypes1Matrix = new ArgumentType[] { ArgumentType.Matrix };
35
39 protected static readonly ArgumentType[] argumentTypes1Set = new ArgumentType[] { ArgumentType.Set };
40
44 protected static readonly ArgumentType[] argumentTypes2Normal = new ArgumentType[] { ArgumentType.Normal, ArgumentType.Normal };
45
49 protected static readonly ArgumentType[] argumentTypes3Normal = new ArgumentType[] { ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal };
50
54 protected static readonly ArgumentType[] argumentTypes4Normal = new ArgumentType[] { ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal };
55
59 protected static readonly ArgumentType[] argumentTypes5Normal = new ArgumentType[] { ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal };
60
64 protected static readonly ArgumentType[] argumentTypes6Normal = new ArgumentType[] { ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal };
65
69 protected static readonly ArgumentType[] argumentTypes7Normal = new ArgumentType[] { ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal };
70
74 protected static readonly ArgumentType[] argumentTypes8Normal = new ArgumentType[] { ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal };
75
79 protected static readonly ArgumentType[] argumentTypes9Normal = new ArgumentType[] { ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal, ArgumentType.Normal };
80
84 protected static readonly ArgumentType[] argumentTypes1Scalar = new ArgumentType[] { ArgumentType.Scalar };
85
89 protected static readonly ArgumentType[] argumentTypes2Scalar = new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar };
90
94 protected static readonly ArgumentType[] argumentTypes3Scalar = new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar };
95
99 protected static readonly ArgumentType[] argumentTypes4Scalar = new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar };
100
104 protected static readonly ArgumentType[] argumentTypes5Scalar = new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar };
105
109 protected static readonly ArgumentType[] argumentTypes6Scalar = new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar };
110
114 protected static readonly ArgumentType[] argumentTypes7Scalar = new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar };
115
119 protected static readonly ArgumentType[] argumentTypes8Scalar = new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar };
120
124 protected static readonly ArgumentType[] argumentTypes9Scalar = new ArgumentType[] { ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar, ArgumentType.Scalar };
125
126
127 private readonly ScriptNode[] arguments;
128 private readonly ArgumentType[] argumentTypes;
129 private readonly bool allNormal;
130 private readonly int nrArguments;
131 private bool isAsync;
132
142 : base(Start, Length, Expression)
143 {
144 if (Arguments.Length != ArgumentTypes.Length)
145 throw new ArgumentException("Size of ArgumentTypes must match the size of Arguments.", nameof(ArgumentTypes));
146
147 this.arguments = Arguments;
148 this.arguments?.SetParent(this);
149
150 this.argumentTypes = ArgumentTypes;
151 this.nrArguments = this.arguments.Length;
152
153 this.allNormal = true;
154 foreach (ArgumentType Type in this.argumentTypes)
155 {
156 if (Type != ArgumentType.Normal)
157 {
158 this.allNormal = false;
159 break;
160 }
161 }
162
163 this.CalcIsAsync();
164 }
165
166 private void CalcIsAsync()
167 {
168 this.isAsync = false;
169
170 for (int i = 0; i < this.nrArguments; i++)
171 {
172 if (this.arguments[i]?.IsAsynchronous ?? false)
173 {
174 this.isAsync = true;
175 break;
176 }
177 }
178 }
179
183 public ScriptNode[] Arguments => this.arguments;
184
188 public ArgumentType[] ArgumentTypes => this.argumentTypes;
189
194 public override bool IsAsynchronous => this.isAsync;
195
202 {
203 IElement[] Arg = new IElement[this.nrArguments];
204 ScriptNode Node;
205 int i;
206
207 for (i = 0; i < this.nrArguments; i++)
208 {
209 Node = this.arguments[i];
210 if (Node is null)
211 Arg[i] = ObjectValue.Null;
212 else
213 Arg[i] = Node.Evaluate(Variables);
214 }
215
216 if (this.allNormal)
217 return this.Evaluate(Arg, Variables);
218 else
219 return this.EvaluateCanonicalExtension(Arg, Variables);
220 }
221
227 public override async Task<IElement> EvaluateAsync(Variables Variables)
228 {
229 if (!this.IsAsynchronous)
230 return this.Evaluate(Variables);
231
232 IElement[] Arg = new IElement[this.nrArguments];
233 ScriptNode Node;
234 int i;
235
236 for (i = 0; i < this.nrArguments; i++)
237 {
238 Node = this.arguments[i];
239 if (Node is null)
240 Arg[i] = ObjectValue.Null;
241 else
242 Arg[i] = await Node.EvaluateAsync(Variables);
243 }
244
245 if (this.allNormal)
246 return await this.EvaluateAsync(Arg, Variables);
247 else
248 return await this.EvaluateCanonicalExtensionAsync(Arg, Variables);
249 }
250
251 private IElement EvaluateCanonicalExtension(IElement[] Arguments, Variables Variables)
252 {
253 int i, j;
254
255 this.Prepare(Arguments, out Encapsulation Encapsulation, out int Dimension, out IEnumerator<IElement>[] e);
256
257 if (!(Encapsulation is null))
258 {
259 LinkedList<IElement> Result = new LinkedList<IElement>();
260 IElement[] Arguments2 = new IElement[this.nrArguments];
261
262 for (j = 0; j < Dimension; j++)
263 {
264 for (i = 0; i < this.nrArguments; i++)
265 {
266 if (e[i] is null || !e[i].MoveNext())
267 Arguments2[i] = Arguments[i];
268 else
269 Arguments2[i] = e[i].Current;
270 }
271
272 Result.AddLast(this.EvaluateCanonicalExtension(Arguments2, Variables));
273 }
274
275 return Encapsulation(Result, this);
276 }
277 else
278 return this.Evaluate(Arguments, Variables);
279 }
280
281 private void Prepare(IElement[] Arguments, out Encapsulation Encapsulation, out int Dimension, out IEnumerator<IElement>[] e)
282 {
283 ICollection<IElement> ChildElements;
284 IElement Argument;
285 IMatrix M;
286 ISet S;
288 int i, j;
289
290 e = new IEnumerator<IElement>[this.nrArguments];
291 Encapsulation = null;
292 Dimension = -1;
293
294 for (i = 0; i < this.nrArguments; i++)
295 {
296 Argument = Arguments[i];
297
298 switch (this.argumentTypes[i])
299 {
300 case ArgumentType.Normal:
301 e[i] = null;
302 break;
303
304 case ArgumentType.Scalar:
305 if (Argument.IsScalar)
306 e[i] = null;
307 else
308 {
309 ChildElements = Argument.ChildElements;
310
311 if (Dimension < 0)
312 Dimension = ChildElements.Count;
313 else if (ChildElements.Count != Dimension)
314 throw new ScriptRuntimeException("Argument dimensions not consistent.", this);
315
316 e[i] = ChildElements.GetEnumerator();
317 if (Encapsulation is null)
318 Encapsulation = Argument.Encapsulate;
319 }
320 break;
321
322 case ArgumentType.Vector:
323 if (Argument is IVector)
324 e[i] = null;
325 else if (!((M = Argument as IMatrix) is null))
326 {
327 if (Dimension < 0)
328 Dimension = M.Rows;
329 else if (M.Rows != Dimension)
330 throw new ScriptRuntimeException("Argument dimensions not consistent.", this);
331
332 LinkedList<IElement> Vectors = new LinkedList<IElement>();
333
334 for (j = 0; j < Dimension; j++)
335 Vectors.AddLast(M.GetRow(j));
336
337 e[i] = Vectors.GetEnumerator();
338 if (Encapsulation is null)
339 Encapsulation = Operators.LambdaDefinition.EncapsulateToVector;
340 }
341 else if (!((S = Argument as ISet) is null))
342 {
343 int? Size = S.Size;
344 if (!Size.HasValue)
345 throw new ScriptRuntimeException("Argument dimensions not consistent.", this);
346
347 if (Dimension < 0)
348 Dimension = Size.Value;
349 else if (Size.Value != Dimension)
350 throw new ScriptRuntimeException("Argument dimensions not consistent.", this);
351
352 e[i] = S.ChildElements.GetEnumerator();
353 if (Encapsulation is null)
354 Encapsulation = Argument.Encapsulate;
355 }
356 else
357 {
358 Arguments[i] = Operators.Vectors.VectorDefinition.Encapsulate(new IElement[] { Argument }, false, this);
359 e[i] = null;
360 }
361 break;
362
363 case ArgumentType.Set:
364 if (Argument is ISet)
365 e[i] = null;
366 else if (!((V = Argument as IVectorSpaceElement) is null))
367 {
368 Arguments[i] = Operators.Sets.SetDefinition.Encapsulate(V.ChildElements);
369 e[i] = null;
370 }
371 else if (!((M = Argument as IMatrix) is null))
372 {
373 if (Dimension < 0)
374 Dimension = M.Rows;
375 else if (M.Rows != Dimension)
376 throw new ScriptRuntimeException("Argument dimensions not consistent.", this);
377
378 LinkedList<IElement> Vectors = new LinkedList<IElement>();
379
380 for (j = 0; j < Dimension; j++)
381 Vectors.AddLast(M.GetRow(j));
382
383 Arguments[i] = Argument = Operators.Sets.SetDefinition.Encapsulate(Vectors);
384 ChildElements = Argument.ChildElements;
385
386 e[i] = ChildElements.GetEnumerator();
387 if (Encapsulation is null)
388 Encapsulation = Operators.LambdaDefinition.EncapsulateToVector;
389 }
390 else
391 {
392 Arguments[i] = Operators.Sets.SetDefinition.Encapsulate(new IElement[] { Argument });
393 e[i] = null;
394 }
395 break;
396
397 case ArgumentType.Matrix:
398 if (Argument is IMatrix)
399 e[i] = null;
400 else if (!((V = Argument as IVectorSpaceElement) is null))
401 {
402 Arguments[i] = Operators.Matrices.MatrixDefinition.Encapsulate(V.ChildElements, 1, V.Dimension, this);
403 e[i] = null;
404 }
405 else if (!((S = Argument as ISet) is null))
406 {
407 int? Size = S.Size;
408 if (!Size.HasValue)
409 throw new ScriptRuntimeException("Argument dimensions not consistent.", this);
410
411 if (Dimension < 0)
412 Dimension = Size.Value;
413 else if (Size.Value != Dimension)
414 throw new ScriptRuntimeException("Argument dimensions not consistent.", this);
415
416 e[i] = S.ChildElements.GetEnumerator();
417 if (Encapsulation is null)
418 Encapsulation = Argument.Encapsulate;
419 }
420 else
421 {
422 Arguments[i] = Operators.Matrices.MatrixDefinition.Encapsulate(new IElement[] { Argument }, 1, 1, this);
423 e[i] = null;
424 }
425 break;
426
427 default:
428 throw new ScriptRuntimeException("Unhandled argument type.", this);
429 }
430 }
431 }
432
433 private async Task<IElement> EvaluateCanonicalExtensionAsync(IElement[] Arguments, Variables Variables)
434 {
435 int i, j;
436
437 this.Prepare(Arguments, out Encapsulation Encapsulation, out int Dimension, out IEnumerator<IElement>[] e);
438
439 if (!(Encapsulation is null))
440 {
441 LinkedList<IElement> Result = new LinkedList<IElement>();
442 IElement[] Arguments2 = new IElement[this.nrArguments];
443
444 for (j = 0; j < Dimension; j++)
445 {
446 for (i = 0; i < this.nrArguments; i++)
447 {
448 if (e[i] is null || !e[i].MoveNext())
449 Arguments2[i] = Arguments[i];
450 else
451 Arguments2[i] = e[i].Current;
452 }
453
454 Result.AddLast(await this.EvaluateCanonicalExtensionAsync(Arguments2, Variables));
455 }
456
457 return Encapsulation(Result, this);
458 }
459 else
460 return await this.EvaluateAsync(Arguments, Variables);
461 }
462
470
477 public virtual Task<IElement> EvaluateAsync(IElement[] Arguments, Variables Variables)
478 {
479 return Task.FromResult(this.Evaluate(Arguments, Variables));
480 }
481
489 public override bool ForAllChildNodes(ScriptNodeEventHandler Callback, object State, SearchMethod Order)
490 {
491 int i;
492
493 if (Order == SearchMethod.DepthFirst)
494 {
495 if (!this.arguments.ForAllChildNodes(Callback, State, Order))
496 return false;
497 }
498
499 ScriptNode Node;
500 bool RecalcIsAsync = false;
501
502 for (i = 0; i < this.nrArguments; i++)
503 {
504 Node = this.arguments[i];
505 if (!(Node is null))
506 {
507 bool b = !Callback(Node, out ScriptNode NewNode, State);
508 if (!(NewNode is null))
509 {
510 this.arguments[i] = NewNode;
511 NewNode.SetParent(this);
512 Node = NewNode;
513
514 RecalcIsAsync = true;
515 }
516
517 if (b || (Order == SearchMethod.TreeOrder && !Node.ForAllChildNodes(Callback, State, Order)))
518 {
519 if (RecalcIsAsync)
520 this.CalcIsAsync();
521
522 return false;
523 }
524 }
525 }
526
527 if (RecalcIsAsync)
528 this.CalcIsAsync();
529
530 if (Order == SearchMethod.BreadthFirst)
531 {
532 if (!this.arguments.ForAllChildNodes(Callback, State, Order))
533 return false;
534 }
535
536 return true;
537 }
538
540 public override bool Equals(object obj)
541 {
542 return obj is FunctionMultiVariate O &&
543 AreEqual(this.arguments, O.arguments) &&
544 AreEqual(this.argumentTypes, O.argumentTypes) &&
545 base.Equals(obj);
546 }
547
549 public override int GetHashCode()
550 {
551 int Result = base.GetHashCode();
552 Result ^= Result << 5 ^ GetHashCode(this.arguments);
553 Result ^= Result << 5 ^ GetHashCode(this.argumentTypes);
554 return Result;
555 }
556
557 }
558}
Class managing a script expression.
Definition: Expression.cs:39
Base class for all funcions.
Definition: Function.cs:9
Base class for multivariate funcions.
static readonly ArgumentType[] argumentTypes3Normal
Three normal parameters.
static readonly ArgumentType[] argumentTypes5Scalar
Five scalar parameters.
override IElement Evaluate(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection.
static readonly ArgumentType[] argumentTypes4Normal
Four normal parameters.
static readonly ArgumentType[] argumentTypes1Matrix
One matrix parameter.
static readonly ArgumentType[] argumentTypes8Normal
Eight normal parameters.
static readonly ArgumentType[] argumentTypes2Normal
Two normal parameters.
ScriptNode[] Arguments
Function arguments.
FunctionMultiVariate(ScriptNode[] Arguments, ArgumentType[] ArgumentTypes, int Start, int Length, Expression Expression)
Base class for funcions of one variable.
static readonly ArgumentType[] argumentTypes2Scalar
Two scalar parameters.
static readonly ArgumentType[] argumentTypes0
Zero parameters.
static readonly ArgumentType[] argumentTypes7Normal
Seven normal parameters.
abstract IElement Evaluate(IElement[] Arguments, Variables Variables)
Evaluates the function.
static readonly ArgumentType[] argumentTypes1Normal
One scalar parameter.
static readonly ArgumentType[] argumentTypes9Normal
Nine normal parameters.
override bool IsAsynchronous
If the node (or its decendants) include asynchronous evaluation. Asynchronous nodes should be evaluat...
static readonly ArgumentType[] argumentTypes1Vector
One vector parameter.
static readonly ArgumentType[] argumentTypes3Scalar
Three scalar parameters.
static readonly ArgumentType[] argumentTypes7Scalar
Seven scalar parameters.
static readonly ArgumentType[] argumentTypes9Scalar
Nine scalar parameters.
static readonly ArgumentType[] argumentTypes8Scalar
Eight scalar parameters.
static readonly ArgumentType[] argumentTypes6Normal
Six normal parameters.
ArgumentType[] ArgumentTypes
Function argument types.
static readonly ArgumentType[] argumentTypes5Normal
Five normal parameters.
virtual Task< IElement > EvaluateAsync(IElement[] Arguments, Variables Variables)
Evaluates the function.
override bool ForAllChildNodes(ScriptNodeEventHandler Callback, object State, SearchMethod Order)
Calls the callback method for all child nodes.
override async Task< IElement > EvaluateAsync(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection.
static readonly ArgumentType[] argumentTypes1Scalar
One scalar parameter.
static readonly ArgumentType[] argumentTypes1Set
One set parameter.
static readonly ArgumentType[] argumentTypes6Scalar
Six scalar parameters.
static readonly ArgumentType[] argumentTypes4Scalar
Four scalar parameters.
Base class for all nodes in a parsed script tree.
Definition: ScriptNode.cs:69
bool ForAllChildNodes(ScriptNodeEventHandler Callback, object State, bool DepthFirst)
Calls the callback method for all child nodes.
Definition: ScriptNode.cs:243
int Length
Length of expression covered by node.
Definition: ScriptNode.cs:101
static bool AreEqual(ScriptNode S1, ScriptNode S2)
Compares if two script nodes are equal.
Definition: ScriptNode.cs:275
int Start
Start position in script expression.
Definition: ScriptNode.cs:92
void SetParent(ScriptNode Parent)
Sets the parent node. Can only be used when expression is being parsed.
Definition: ScriptNode.cs:132
abstract IElement Evaluate(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection. This method should be ...
virtual Task< IElement > EvaluateAsync(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection. This method should be ...
Definition: ScriptNode.cs:158
static readonly ObjectValue Null
Null value.
Definition: ObjectValue.cs:86
Collection of variables.
Definition: Variables.cs:25
Basic interface for all types of elements.
Definition: IElement.cs:20
ICollection< IElement > ChildElements
An enumeration of child elements. If the element is a scalar, this property will return null.
Definition: IElement.cs:49
IElement Encapsulate(ICollection< IElement > Elements, ScriptNode Node)
Encapsulates a set of elements into a similar structure as that provided by the current element.
bool IsScalar
If the element represents a scalar value.
Definition: IElement.cs:41
Basic interface for matrices.
Definition: IMatrix.cs:9
IVector GetRow(int Row)
Gets a row vector from the matrix.
Basic interface for vectors.
Definition: IVector.cs:9
int Dimension
Dimension of vector.
Definition: IVector.cs:14
Basic interface for all types of module elements.
Basic interface for all types of sets.
Definition: ISet.cs:10
int? Size
Size of set, if finite and known, otherwise null is returned.
Definition: ISet.cs:22
delegate IElement Encapsulation(ICollection< IElement > Elements, ScriptNode Node)
Delegate for encapsulation methods.
delegate bool ScriptNodeEventHandler(ScriptNode Node, out ScriptNode NewNode, object State)
Delegate for ScriptNode callback methods.
ArgumentType
Type of parameter used in a function definition or a lambda definition.
Definition: IFunction.cs:9
SearchMethod
Method to traverse the expression structure
Definition: ScriptNode.cs:38