Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
LambdaDefinition.cs
1using System;
3using System.Reflection;
4using System.Text;
5using System.Threading.Tasks;
16
18{
23 {
24 private readonly string[] argumentNames;
25 private readonly ArgumentType[] argumentTypes;
26 private readonly int nrArguments;
27 private readonly bool allNormal;
28
40 {
41 this.argumentNames = ArgumentNames;
42 this.argumentTypes = ArgumentTypes;
43 this.nrArguments = ArgumentNames.Length;
44
45 this.allNormal = true;
46 foreach (ArgumentType Type in this.argumentTypes)
47 {
48 if (Type != ArgumentType.Normal)
49 {
50 this.allNormal = false;
51 break;
52 }
53 }
54 }
55
59 public int NrArguments => this.nrArguments;
60
64 public string[] ArgumentNames => this.argumentNames;
65
69 public ArgumentType[] ArgumentTypes => this.argumentTypes;
70
74 public object AssociatedObjectValue => this;
75
80
84 public ICollection<IElement> ChildElements => null;
85
89 public bool IsScalar => true;
90
98 {
99 return null;
100 }
101
108 public IElement Encapsulate(ICollection<IElement> Elements, ScriptNode Node)
109 {
110 return null;
111 }
112
119 {
120 return this;
121 }
122
128 public override Task<IElement> EvaluateAsync(Variables Variables)
129 {
130 return Task.FromResult<IElement>(this);
131 }
132
140 {
141 return this;
142 }
143
150 public override Task<IElement> EvaluateAsync(IElement Operand, Variables Variables)
151 {
152 return Task.FromResult<IElement>(this);
153 }
154
162 {
163 if (Arguments.Length != this.nrArguments)
164 throw new ScriptRuntimeException("Expected " + this.nrArguments.ToString() + " arguments.", this);
165
166 Variables.Push();
167 try
168 {
169 if (this.allNormal)
170 {
171 int i;
172
173 for (i = 0; i < this.nrArguments; i++)
174 Variables[this.argumentNames[i]] = Arguments[i];
175
176 try
177 {
178 return this.op.Evaluate(Variables);
179 }
181 {
182 return ex.ReturnValue;
183 //IElement ReturnValue = ex.ReturnValue;
184 //ScriptReturnValueException.Reuse(ex);
185 //return ReturnValue;
186 }
187 catch (ScriptBreakLoopException ex)
188 {
189 return ex.LoopValue ?? ObjectValue.Null;
190 //ScriptBreakLoopException.Reuse(ex);
191 }
193 {
194 return ex.LoopValue ?? ObjectValue.Null;
195 //ScriptContinueLoopException.Reuse(ex);
196 }
197 }
198 else
199 return this.EvaluateCanonicalExtension(Arguments, Variables);
200 }
201 finally
202 {
203 Variables.Pop();
204 }
205 }
206
213 public async Task<IElement> EvaluateAsync(IElement[] Arguments, Variables Variables)
214 {
215 if (!this.IsAsynchronous)
216 return this.Evaluate(Arguments, Variables);
217
218 if (Arguments.Length != this.nrArguments)
219 throw new ScriptRuntimeException("Expected " + this.nrArguments.ToString() + " arguments.", this);
220
221 Variables.Push();
222 try
223 {
224 if (this.allNormal)
225 {
226 int i;
227
228 for (i = 0; i < this.nrArguments; i++)
229 Variables[this.argumentNames[i]] = Arguments[i];
230
231 try
232 {
233 return await this.op.EvaluateAsync(Variables);
234 }
236 {
237 return ex.ReturnValue;
238 //IElement Returnvalue = ex.ReturnValue;
239 //ScriptReturnValueException.Reuse(ex);
240 //return Returnvalue;
241 }
242 catch (ScriptBreakLoopException ex)
243 {
244 return ex.LoopValue ?? ObjectValue.Null;
245 //ScriptBreakLoopException.Reuse(ex);
246 }
248 {
249 return ex.LoopValue ?? ObjectValue.Null;
250 //ScriptContinueLoopException.Reuse(ex);
251 }
252 }
253 else
254 return await this.EvaluateCanonicalExtensionAsync(Arguments, Variables);
255 }
256 finally
257 {
258 Variables.Pop();
259 }
260 }
261
262 private IElement EvaluateCanonicalExtension(IElement[] Arguments, Variables Variables)
263 {
264 int i, j;
265
266 this.Prepare(Arguments, out Encapsulation Encapsulation, out int Dimension, out IEnumerator<IElement>[] e);
267
268 try
269 {
270 if (!(Encapsulation is null))
271 {
273 IElement[] Arguments2 = new IElement[this.nrArguments];
274
275 for (j = 0; j < Dimension; j++)
276 {
277 for (i = 0; i < this.nrArguments; i++)
278 {
279 if (e[i] is null || !e[i].MoveNext())
280 Arguments2[i] = Arguments[i];
281 else
282 Arguments2[i] = e[i].Current;
283 }
284
285 Result.Add(this.EvaluateCanonicalExtension(Arguments2, Variables));
286 }
287
288 return Encapsulation(Result, this);
289 }
290 else
291 {
292 for (i = 0; i < this.nrArguments; i++)
293 Variables[this.argumentNames[i]] = Arguments[i];
294
295 try
296 {
297 return this.op.Evaluate(Variables);
298 }
300 {
301 return ex.ReturnValue;
302 //IElement Returnvalue = ex.ReturnValue;
303 //ScriptReturnValueException.Reuse(ex);
304 //return Returnvalue;
305 }
306 catch (ScriptBreakLoopException ex)
307 {
308 return ex.LoopValue ?? ObjectValue.Null;
309 //ScriptBreakLoopException.Reuse(ex);
310 }
312 {
313 return ex.LoopValue ?? ObjectValue.Null;
314 //ScriptContinueLoopException.Reuse(ex);
315 }
316 }
317 }
318 finally
319 {
320 for (i = 0, j = e?.Length ?? 0; i < j; i++)
321 e[i]?.Dispose();
322 }
323 }
324
325 private async Task<IElement> EvaluateCanonicalExtensionAsync(IElement[] Arguments, Variables Variables)
326 {
327 int i, j;
328
329 this.Prepare(Arguments, out Encapsulation Encapsulation, out int Dimension, out IEnumerator<IElement>[] e);
330
331 try
332 {
333 if (!(Encapsulation is null))
334 {
336 IElement[] Arguments2 = new IElement[this.nrArguments];
337
338 for (j = 0; j < Dimension; j++)
339 {
340 for (i = 0; i < this.nrArguments; i++)
341 {
342 if (e[i] is null || !e[i].MoveNext())
343 Arguments2[i] = Arguments[i];
344 else
345 Arguments2[i] = e[i].Current;
346 }
347
348 Result.Add(await this.EvaluateCanonicalExtensionAsync(Arguments2, Variables));
349 }
350
351 return Encapsulation(Result, this);
352 }
353 else
354 {
355 for (i = 0; i < this.nrArguments; i++)
356 Variables[this.argumentNames[i]] = Arguments[i];
357
358 try
359 {
360 return await this.op.EvaluateAsync(Variables);
361 }
363 {
364 return ex.ReturnValue;
365 //IElement Returnvalue = ex.ReturnValue;
366 //ScriptReturnValueException.Reuse(ex);
367 //return Returnvalue;
368 }
369 catch (ScriptBreakLoopException ex)
370 {
371 return ex.LoopValue ?? ObjectValue.Null;
372 //ScriptBreakLoopException.Reuse(ex);
373 }
375 {
376 return ex.LoopValue ?? ObjectValue.Null;
377 //ScriptContinueLoopException.Reuse(ex);
378 }
379 }
380 }
381 finally
382 {
383 for (i = 0, j = e?.Length ?? 0; i < j; i++)
384 e[i]?.Dispose();
385 }
386 }
387
388 private void Prepare(IElement[] Arguments, out Encapsulation Encapsulation, out int Dimension, out IEnumerator<IElement>[] e)
389 {
390 ICollection<IElement> ChildElements;
391 IElement Argument;
392 IMatrix M;
393 ISet S;
395 int i, j;
396
397 e = new IEnumerator<IElement>[this.nrArguments];
398 Encapsulation = null;
399 Dimension = -1;
400
401 for (i = 0; i < this.nrArguments; i++)
402 {
403 Argument = Arguments[i];
404
405 switch (this.argumentTypes[i])
406 {
407 case ArgumentType.Normal:
408 e[i] = null;
409 break;
410
411 case ArgumentType.Scalar:
412 if (Argument.IsScalar)
413 e[i] = null;
414 else
415 {
416 ChildElements = Argument.ChildElements;
417
418 if (Dimension < 0)
419 Dimension = ChildElements.Count;
420 else if (ChildElements.Count != Dimension)
422
423 e[i] = ChildElements.GetEnumerator();
424 if (Encapsulation is null)
425 Encapsulation = Argument.Encapsulate;
426 }
427 break;
428
429 case ArgumentType.Vector:
430 if (Argument is IVectorSpaceElement)
431 e[i] = null;
432 else if (!((M = Argument as IMatrix) is null))
433 {
434 if (Dimension < 0)
435 Dimension = M.Rows;
436 else if (M.Rows != Dimension)
438
440
441 for (j = 0; j < Dimension; j++)
442 Vectors.Add(M.GetRow(j));
443
444 e[i] = Vectors.GetEnumerator();
445 if (Encapsulation is null)
446 Encapsulation = EncapsulateToVector;
447 }
448 else if (!((S = Argument as ISet) is null))
449 {
450 int? Size = S.Size;
451 if (!Size.HasValue)
453
454 if (Dimension < 0)
455 Dimension = Size.Value;
456 else if (Size.Value != Dimension)
458
459 e[i] = S.ChildElements.GetEnumerator();
460 if (Encapsulation is null)
461 Encapsulation = Argument.Encapsulate;
462 }
463 else
464 {
465 Arguments[i] = VectorDefinition.Encapsulate(new IElement[] { Argument }, false, this);
466 e[i] = null;
467 }
468 break;
469
470 case ArgumentType.Set:
471 if (Argument is ISet)
472 e[i] = null;
473 else if (!((V = Argument as IVectorSpaceElement) is null))
474 {
475 Arguments[i] = SetDefinition.Encapsulate(V.ChildElements);
476 e[i] = null;
477 }
478 else if (!((M = Argument as IMatrix) is null))
479 {
480 if (Dimension < 0)
481 Dimension = M.Rows;
482 else if (M.Rows != Dimension)
484
486
487 for (j = 0; j < Dimension; j++)
488 Vectors.Add(M.GetRow(j));
489
490 Arguments[i] = Argument = SetDefinition.Encapsulate(Vectors);
491 ChildElements = Argument.ChildElements;
492
493 e[i] = ChildElements.GetEnumerator();
494 if (Encapsulation is null)
495 Encapsulation = EncapsulateToVector;
496 }
497 else
498 {
499 Arguments[i] = SetDefinition.Encapsulate(new IElement[] { Argument });
500 e[i] = null;
501 }
502 break;
503
504 case ArgumentType.Matrix:
505 if (Argument is IMatrix)
506 e[i] = null;
507 else if (!((V = Argument as IVectorSpaceElement) is null))
508 {
509 Arguments[i] = MatrixDefinition.Encapsulate(V.ChildElements, 1, V.Dimension, this);
510 e[i] = null;
511 }
512 else if (!((S = Argument as ISet) is null))
513 {
514 int? Size = S.Size;
515 if (!Size.HasValue)
517
518 if (Dimension < 0)
519 Dimension = Size.Value;
520 else if (Size.Value != Dimension)
522
523 e[i] = S.ChildElements.GetEnumerator();
524 if (Encapsulation is null)
525 Encapsulation = Argument.Encapsulate;
526 }
527 else
528 {
529 Arguments[i] = MatrixDefinition.Encapsulate(new IElement[] { Argument }, 1, 1, this);
530 e[i] = null;
531 }
532 break;
533
534 default:
535 throw new ScriptRuntimeException("Unhandled argument type.", this);
536 }
537 }
538 }
539
540 internal static IElement EncapsulateToVector(ICollection<IElement> Elements, ScriptNode Node)
541 {
542 return VectorDefinition.Encapsulate(Elements, true, Node);
543 }
544
551 public bool TryConvertTo(Type DesiredType, out object Value)
552 {
553 if (DesiredType.IsAssignableFrom(this.GetType().GetTypeInfo()))
554 {
555 Value = this;
556 return true;
557 }
558
559 Value = null;
560 return false;
561 }
562
569 public ScriptNode Differentiate(string VariableName, Variables Variables)
570 {
571 if (Array.IndexOf(this.argumentNames, VariableName) < 0)
572 return new ConstantElement(Objects.DoubleNumber.ZeroElement, this.Start, this.Length, this.Expression);
573 else if (this.op is IDifferentiable Differentiable)
574 return new LambdaDefinition(this.argumentNames, this.argumentTypes, Differentiable.Differentiate(VariableName, Variables), this.Start, this.Length, this.Expression);
575 else
576 throw new ScriptRuntimeException("Lambda expression not differentiable.", this);
577 }
578
582 public override string DefaultVariableName
583 {
584 get
585 {
586 if (this.argumentNames.Length == 1)
587 return this.argumentNames[0];
588 else
589 return null;
590 }
591 }
592
594 public override string ToString()
595 {
596 return ToString(this);
597 }
598
605 {
606 string[] ArgumentNames = Expression.ArgumentNames;
607 ArgumentType[] ArgumentTypes = Expression.ArgumentTypes;
608 StringBuilder Result = new StringBuilder();
609 int i;
610
611 Result.Append("λ(");
612
613 for (i = 0; i < Expression.NrArguments; i++)
614 {
615 if (i > 0)
616 Result.Append(',');
617
618 switch (ArgumentTypes[i])
619 {
620 case ArgumentType.Matrix:
621 Result.Append(ArgumentNames[i]);
622 Result.Append("[[]]");
623 break;
624
625 case ArgumentType.Normal:
626 default:
627 Result.Append(ArgumentNames[i]);
628 break;
629
630 case ArgumentType.Scalar:
631 Result.Append('[');
632 Result.Append(ArgumentNames[i]);
633 Result.Append(']');
634 break;
635
636 case ArgumentType.Set:
637 Result.Append(ArgumentNames[i]);
638 Result.Append("{}");
639 break;
640
641 case ArgumentType.Vector:
642 Result.Append(ArgumentNames[i]);
643 Result.Append("[]");
644 break;
645 }
646 }
647
648 Result.Append(')');
649
650 return Result.ToString();
651 }
652 }
653}
A chunked list is a linked list of chunks of objects of type T .
Definition: ChunkedList.cs:54
IEnumerator< T > GetEnumerator()
Returns an enumerator for the collection.
Definition: ChunkedList.cs:418
void Add(T Item)
Adds an item to the collection.
Definition: ChunkedList.cs:272
Class managing a script expression.
Definition: Expression.cs:41
Represents a constant element value.
Base class for all nodes in a parsed script tree.
Definition: ScriptNode.cs:69
int Length
Length of expression covered by node.
Definition: ScriptNode.cs:101
int Start
Start position in script expression.
Definition: ScriptNode.cs:92
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
Base class for all unary operators.
static readonly ObjectValue Null
Null value.
Definition: ObjectValue.cs:88
Set containing all functions.
static readonly SetOfFunctions Instance
Instance of the set of all functions.
bool IsScalar
If the element represents a scalar value.
override Task< IElement > EvaluateAsync(IElement Operand, Variables Variables)
Evaluates the operator.
static string ToString(ILambdaExpression Expression)
Creates a displayable string for a lambda expression.
override IElement Evaluate(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection.
IElement Encapsulate(ChunkedList< IElement > Elements, ScriptNode Node)
Encapsulates a set of elements into a similar structure as that provided by the current element.
IElement Encapsulate(ICollection< IElement > Elements, ScriptNode Node)
Encapsulates a set of elements into a similar structure as that provided by the current element.
object AssociatedObjectValue
Associated object value.
bool TryConvertTo(Type DesiredType, out object Value)
Converts the value to a .NET type.
IElement Evaluate(IElement[] Arguments, Variables Variables)
Evaluates the lambda expression.
ArgumentType[] ArgumentTypes
Argument types.
ICollection< IElement > ChildElements
An enumeration of child elements. If the element is a scalar, this property will return null.
LambdaDefinition(string[] ArgumentNames, ArgumentType[] ArgumentTypes, ScriptNode Operand, int Start, int Length, Expression Expression)
Lambda Definition.
override Task< IElement > EvaluateAsync(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection.
override IElement Evaluate(IElement Operand, Variables Variables)
Evaluates the operator.
async Task< IElement > EvaluateAsync(IElement[] Arguments, Variables Variables)
Evaluates the lambda expression.
override string DefaultVariableName
Default variable name, if any, null otherwise.
ScriptNode Differentiate(string VariableName, Variables Variables)
Differentiates a lambda expression, if possible.
static IMatrix Encapsulate(ICollection< IElement > Rows, ScriptNode Node)
Encapsulates the elements of a matrix.
static IElement Encapsulate(ICollection< IElement > Elements)
Encapsulates the elements of a set.
static IElement Encapsulate(Array Elements, bool CanEncapsulateAsMatrix, ScriptNode Node)
Encapsulates the elements of a vector.
Collection of variables.
Definition: Variables.cs:25
virtual void Push()
Pushes the current set of variables to the stack. This state is restored by calling Pop....
Definition: Variables.cs:184
virtual void Pop()
Pops a previously stored set of variables from the stack. Variables are stored on the stack by callin...
Definition: Variables.cs:206
Basic interface for all types of elements.
Definition: IElement.cs:21
ICollection< IElement > ChildElements
An enumeration of child elements. If the element is a scalar, this property will return null.
Definition: IElement.cs:50
IElement Encapsulate(ChunkedList< 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:42
Basic interface for matrices.
Definition: IMatrix.cs:7
IVector GetRow(int Row)
Gets a row vector from the matrix.
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
Base interface for lambda expressions.
Base interface for lambda expressions.
bool IsAsynchronous
If the node (or its decendants) include asynchronous evaluation. Asynchronous nodes should be evaluat...
delegate IElement Encapsulation(ICollection< IElement > Elements, ScriptNode Node)
Delegate for encapsulation methods.
ArgumentType
Type of parameter used in a function definition or a lambda definition.
Definition: IFunction.cs:9