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;
2using System.Collections.Generic;
3using System.Reflection;
4using System.Text;
13using System.Threading.Tasks;
14
16{
21 {
22 private readonly string[] argumentNames;
23 private readonly ArgumentType[] argumentTypes;
24 private readonly int nrArguments;
25 private readonly bool allNormal;
26
38 {
39 this.argumentNames = ArgumentNames;
40 this.argumentTypes = ArgumentTypes;
41 this.nrArguments = ArgumentNames.Length;
42
43 this.allNormal = true;
44 foreach (ArgumentType Type in this.argumentTypes)
45 {
46 if (Type != ArgumentType.Normal)
47 {
48 this.allNormal = false;
49 break;
50 }
51 }
52 }
53
57 public int NrArguments => this.nrArguments;
58
62 public string[] ArgumentNames => this.argumentNames;
63
67 public ArgumentType[] ArgumentTypes => this.argumentTypes;
68
72 public object AssociatedObjectValue => this;
73
78
82 public ICollection<IElement> ChildElements => null;
83
87 public bool IsScalar => true;
88
95 public IElement Encapsulate(ICollection<IElement> Elements, ScriptNode Node)
96 {
97 return null;
98 }
99
106 {
107 return this;
108 }
109
115 public override Task<IElement> EvaluateAsync(Variables Variables)
116 {
117 return Task.FromResult<IElement>(this);
118 }
119
127 {
128 return this;
129 }
130
137 public override Task<IElement> EvaluateAsync(IElement Operand, Variables Variables)
138 {
139 return Task.FromResult<IElement>(this);
140 }
141
149 {
150 if (Arguments.Length != this.nrArguments)
151 throw new ScriptRuntimeException("Expected " + this.nrArguments.ToString() + " arguments.", this);
152
153 Variables.Push();
154 try
155 {
156 if (this.allNormal)
157 {
158 int i;
159
160 for (i = 0; i < this.nrArguments; i++)
161 Variables[this.argumentNames[i]] = Arguments[i];
162
163 try
164 {
165 return this.op.Evaluate(Variables);
166 }
168 {
169 return ex.ReturnValue;
170 }
171 }
172 else
173 return this.EvaluateCanonicalExtension(Arguments, Variables);
174 }
175 finally
176 {
177 Variables.Pop();
178 }
179 }
180
187 public async Task<IElement> EvaluateAsync(IElement[] Arguments, Variables Variables)
188 {
189 if (!this.IsAsynchronous)
190 return this.Evaluate(Arguments, Variables);
191
192 if (Arguments.Length != this.nrArguments)
193 throw new ScriptRuntimeException("Expected " + this.nrArguments.ToString() + " arguments.", this);
194
195 Variables.Push();
196 try
197 {
198 if (this.allNormal)
199 {
200 int i;
201
202 for (i = 0; i < this.nrArguments; i++)
203 Variables[this.argumentNames[i]] = Arguments[i];
204
205 try
206 {
207 return await this.op.EvaluateAsync(Variables);
208 }
210 {
211 return ex.ReturnValue;
212 }
213 }
214 else
215 return await this.EvaluateCanonicalExtensionAsync(Arguments, Variables);
216 }
217 finally
218 {
219 Variables.Pop();
220 }
221 }
222
223 private IElement EvaluateCanonicalExtension(IElement[] Arguments, Variables Variables)
224 {
225 int i, j;
226
227 this.Prepare(Arguments, out Encapsulation Encapsulation, out int Dimension, out IEnumerator<IElement>[] e);
228
229 if (!(Encapsulation is null))
230 {
231 LinkedList<IElement> Result = new LinkedList<IElement>();
232 IElement[] Arguments2 = new IElement[this.nrArguments];
233
234 for (j = 0; j < Dimension; j++)
235 {
236 for (i = 0; i < this.nrArguments; i++)
237 {
238 if (e[i] is null || !e[i].MoveNext())
239 Arguments2[i] = Arguments[i];
240 else
241 Arguments2[i] = e[i].Current;
242 }
243
244 Result.AddLast(this.EvaluateCanonicalExtension(Arguments2, Variables));
245 }
246
247 return Encapsulation(Result, this);
248 }
249 else
250 {
251 for (i = 0; i < this.nrArguments; i++)
252 Variables[this.argumentNames[i]] = Arguments[i];
253
254 try
255 {
256 return this.op.Evaluate(Variables);
257 }
259 {
260 return ex.ReturnValue;
261 }
262 }
263 }
264
265 private async Task<IElement> EvaluateCanonicalExtensionAsync(IElement[] Arguments, Variables Variables)
266 {
267 int i, j;
268
269 this.Prepare(Arguments, out Encapsulation Encapsulation, out int Dimension, out IEnumerator<IElement>[] e);
270
271 if (!(Encapsulation is null))
272 {
273 LinkedList<IElement> Result = new LinkedList<IElement>();
274 IElement[] Arguments2 = new IElement[this.nrArguments];
275
276 for (j = 0; j < Dimension; j++)
277 {
278 for (i = 0; i < this.nrArguments; i++)
279 {
280 if (e[i] is null || !e[i].MoveNext())
281 Arguments2[i] = Arguments[i];
282 else
283 Arguments2[i] = e[i].Current;
284 }
285
286 Result.AddLast(await this.EvaluateCanonicalExtensionAsync(Arguments2, Variables));
287 }
288
289 return Encapsulation(Result, this);
290 }
291 else
292 {
293 for (i = 0; i < this.nrArguments; i++)
294 Variables[this.argumentNames[i]] = Arguments[i];
295
296 try
297 {
298 return await this.op.EvaluateAsync(Variables);
299 }
301 {
302 return ex.ReturnValue;
303 }
304 }
305 }
306
307 private void Prepare(IElement[] Arguments, out Encapsulation Encapsulation, out int Dimension, out IEnumerator<IElement>[] e)
308 {
309 ICollection<IElement> ChildElements;
310 IElement Argument;
311 IMatrix M;
312 ISet S;
314 int i, j;
315
316 e = new IEnumerator<IElement>[this.nrArguments];
317 Encapsulation = null;
318 Dimension = -1;
319
320 for (i = 0; i < this.nrArguments; i++)
321 {
322 Argument = Arguments[i];
323
324 switch (this.argumentTypes[i])
325 {
326 case ArgumentType.Normal:
327 e[i] = null;
328 break;
329
330 case ArgumentType.Scalar:
331 if (Argument.IsScalar)
332 e[i] = null;
333 else
334 {
335 ChildElements = Argument.ChildElements;
336
337 if (Dimension < 0)
338 Dimension = ChildElements.Count;
339 else if (ChildElements.Count != Dimension)
340 throw new ScriptRuntimeException("Argument dimensions not consistent.", this);
341
342 e[i] = ChildElements.GetEnumerator();
343 if (Encapsulation is null)
344 Encapsulation = Argument.Encapsulate;
345 }
346 break;
347
348 case ArgumentType.Vector:
349 if (Argument is IVectorSpaceElement)
350 e[i] = null;
351 else if (!((M = Argument as IMatrix) is null))
352 {
353 if (Dimension < 0)
354 Dimension = M.Rows;
355 else if (M.Rows != Dimension)
356 throw new ScriptRuntimeException("Argument dimensions not consistent.", this);
357
358 LinkedList<IElement> Vectors = new LinkedList<IElement>();
359
360 for (j = 0; j < Dimension; j++)
361 Vectors.AddLast(M.GetRow(j));
362
363 e[i] = Vectors.GetEnumerator();
364 if (Encapsulation is null)
365 Encapsulation = EncapsulateToVector;
366 }
367 else if (!((S = Argument as ISet) is null))
368 {
369 int? Size = S.Size;
370 if (!Size.HasValue)
371 throw new ScriptRuntimeException("Argument dimensions not consistent.", this);
372
373 if (Dimension < 0)
374 Dimension = Size.Value;
375 else if (Size.Value != Dimension)
376 throw new ScriptRuntimeException("Argument dimensions not consistent.", this);
377
378 e[i] = S.ChildElements.GetEnumerator();
379 if (Encapsulation is null)
380 Encapsulation = Argument.Encapsulate;
381 }
382 else
383 {
384 Arguments[i] = VectorDefinition.Encapsulate(new IElement[] { Argument }, false, this);
385 e[i] = null;
386 }
387 break;
388
389 case ArgumentType.Set:
390 if (Argument is ISet)
391 e[i] = null;
392 else if (!((V = Argument as IVectorSpaceElement) is null))
393 {
394 Arguments[i] = SetDefinition.Encapsulate(V.ChildElements);
395 e[i] = null;
396 }
397 else if (!((M = Argument as IMatrix) is null))
398 {
399 if (Dimension < 0)
400 Dimension = M.Rows;
401 else if (M.Rows != Dimension)
402 throw new ScriptRuntimeException("Argument dimensions not consistent.", this);
403
404 LinkedList<IElement> Vectors = new LinkedList<IElement>();
405
406 for (j = 0; j < Dimension; j++)
407 Vectors.AddLast(M.GetRow(j));
408
409 Arguments[i] = Argument = SetDefinition.Encapsulate(Vectors);
410 ChildElements = Argument.ChildElements;
411
412 e[i] = ChildElements.GetEnumerator();
413 if (Encapsulation is null)
414 Encapsulation = EncapsulateToVector;
415 }
416 else
417 {
418 Arguments[i] = SetDefinition.Encapsulate(new IElement[] { Argument });
419 e[i] = null;
420 }
421 break;
422
423 case ArgumentType.Matrix:
424 if (Argument is IMatrix)
425 e[i] = null;
426 else if (!((V = Argument as IVectorSpaceElement) is null))
427 {
428 Arguments[i] = MatrixDefinition.Encapsulate(V.ChildElements, 1, V.Dimension, this);
429 e[i] = null;
430 }
431 else if (!((S = Argument as ISet) is null))
432 {
433 int? Size = S.Size;
434 if (!Size.HasValue)
435 throw new ScriptRuntimeException("Argument dimensions not consistent.", this);
436
437 if (Dimension < 0)
438 Dimension = Size.Value;
439 else if (Size.Value != Dimension)
440 throw new ScriptRuntimeException("Argument dimensions not consistent.", this);
441
442 e[i] = S.ChildElements.GetEnumerator();
443 if (Encapsulation is null)
444 Encapsulation = Argument.Encapsulate;
445 }
446 else
447 {
448 Arguments[i] = MatrixDefinition.Encapsulate(new IElement[] { Argument }, 1, 1, this);
449 e[i] = null;
450 }
451 break;
452
453 default:
454 throw new ScriptRuntimeException("Unhandled argument type.", this);
455 }
456 }
457 }
458
459 internal static IElement EncapsulateToVector(ICollection<IElement> Elements, ScriptNode Node)
460 {
461 return VectorDefinition.Encapsulate(Elements, true, Node);
462 }
463
470 public bool TryConvertTo(Type DesiredType, out object Value)
471 {
472 if (DesiredType.GetTypeInfo().IsAssignableFrom(this.GetType().GetTypeInfo()))
473 {
474 Value = this;
475 return true;
476 }
477
478 Value = null;
479 return false;
480 }
481
488 public ScriptNode Differentiate(string VariableName, Variables Variables)
489 {
490 if (Array.IndexOf(this.argumentNames, VariableName) < 0)
491 return new ConstantElement(Objects.DoubleNumber.ZeroElement, this.Start, this.Length, this.Expression);
492 else if (this.op is IDifferentiable Differentiable)
493 return new LambdaDefinition(this.argumentNames, this.argumentTypes, Differentiable.Differentiate(VariableName, Variables), this.Start, this.Length, this.Expression);
494 else
495 throw new ScriptRuntimeException("Lambda expression not differentiable.", this);
496 }
497
501 public override string DefaultVariableName
502 {
503 get
504 {
505 if (this.argumentNames.Length == 1)
506 return this.argumentNames[0];
507 else
508 return null;
509 }
510 }
511
513 public override string ToString()
514 {
515 return ToString(this);
516 }
517
524 {
525 string[] ArgumentNames = Expression.ArgumentNames;
526 ArgumentType[] ArgumentTypes = Expression.ArgumentTypes;
527 StringBuilder Result = new StringBuilder();
528 int i;
529
530 Result.Append("λ(");
531
532 for (i = 0; i < Expression.NrArguments; i++)
533 {
534 if (i > 0)
535 Result.Append(',');
536
537 switch (ArgumentTypes[i])
538 {
539 case ArgumentType.Matrix:
540 Result.Append(ArgumentNames[i]);
541 Result.Append("[[]]");
542 break;
543
544 case ArgumentType.Normal:
545 default:
546 Result.Append(ArgumentNames[i]);
547 break;
548
549 case ArgumentType.Scalar:
550 Result.Append('[');
551 Result.Append(ArgumentNames[i]);
552 Result.Append(']');
553 break;
554
555 case ArgumentType.Set:
556 Result.Append(ArgumentNames[i]);
557 Result.Append("{}");
558 break;
559
560 case ArgumentType.Vector:
561 Result.Append(ArgumentNames[i]);
562 Result.Append("[]");
563 break;
564 }
565 }
566
567 Result.Append(')');
568
569 return Result.ToString();
570 }
571 }
572}
Class managing a script expression.
Definition: Expression.cs:39
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.
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(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:180
virtual void Pop()
Pops a previously stored set of variables from the stack. Variables are stored on the stack by callin...
Definition: Variables.cs:202
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.
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