Skip to content
Snippets Groups Projects
Select Git revision
  • 6748b406d1af107b78b94772cfa4a95799bd3bf0
  • master default
  • JS-based-scroll-rendering
  • Paul_Marius_Level
  • Paul_Marius_2
  • Paul_Marius
  • Andi_Mark
  • be-UnityWebView
  • gitignoreFrameitServer
  • ZimmerBSc
  • Bugfix_StageLoading
  • stages
  • MAZIFAU_Experimental
  • tsc/coneworld
  • tsc/fact-interaction
  • marcel
  • MaZiFAU_TopSort
  • mergeHelper
  • zwischenSpeichern
  • tempAndrToMaster
  • SebBranch
  • 3.0
  • v2.1
  • v2.0
  • v1.0
25 results

FunctionFact.cs

Blame
  • user avatar
    MaZiFAU authored
    Bug Fixes:
    + invalid casting for List<dynamic>
    + slightly wrong validation for FunctionCallFacts
    + force enable studio stages for validation (not local)
    + Singelton in ScrollStatic wont be recycled due to infinite asyncs
    + SomDoc.Var: parameter binding priority reversed
    148d327c
    History
    FunctionFact.cs 10.26 KiB
    using Newtonsoft.Json;
    using REST_JSON_API;
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Expressions;
    using UnityEngine;
    
    /// <summary>
    /// Binds a domain mapper (<see cref="FunctionFact"/>) opperating on time t in seconds to a <see cref="FunctionFact"/>.
    /// Uses <see cref="FunctionFact"/> Function_args to map from a linear scale to the domain of <see cref="FunctionFact"/> Function to execute it.
    /// </summary>
    public class FunctionCallFact : FactWrappedCRTP<FunctionCallFact>
    {
        protected override object GetCompiledValue()
            => Tuple.Create(Domain, Function_args.CompiledValue, Function.CompiledValue);
    
        /// <summary>
        /// <see cref="Fact.Id"/> of <see cref="Function"/>
        /// </summary>
        public string func_id
        {
            get => Function?.Id ?? _func_id;
            private set
            {
                _func_id = value;
                FactRecorder.AllFacts.TryGetValue(value, out Fact func);
                Function = (FunctionFact)func;
            }
        }
        private string _func_id;
    
        /// <summary>
        /// <see cref="Fact.Id"/> of <see cref="Function_args"/>
        /// </summary>
        public string arg_func_id
        {
            get => Function_args?.Id ?? _arg_func_id;
            private set
            {
                _arg_func_id = value;
                FactRecorder.AllFacts.TryGetValue(value, out Fact func);
                Function_args = (FunctionFact)func;
            }
        }
        private string _arg_func_id;
    
        /// <summary>
        /// Linear domain on R this Fact is valid on;
        /// Intervall is defined as [t_0, t_n]
        /// </summary>
        public (float t_0, float t_n) Domain;
    
        /// <summary>
        /// The function to be called with <see cref="Call(float)"/>
        /// </summary>
        [JsonIgnore]
        public FunctionFact Function;
    
        /// <summary>
        /// Mapps from linear <see cref="Domain"/> to arguments from <see cref="Function"/>. (may be multidimensional)
        /// </summary>
        [JsonIgnore]
        public FunctionFact Function_args;
    
        [JsonConstructor]
        public FunctionCallFact(string func_id, string arg_func_id, (float t_0, float t_n) Domain) : base()
        {
            this.func_id = func_id;
            this.arg_func_id = arg_func_id;
            this.Domain = Domain;
    
            if (Function_args != null // is case when reading in Json
             && (Function_args.Signature[0] != typeof(float) // takes in |R
              || (Function_args.Signature[1..].SequenceEqual(Function.Signature[..^0]) // output equals input
               && Function_args.Signature[^1] != typeof(object[])))) // if output is object array => types are concieled
                throw new ArgumentException(
                    $"Signatures must match: Func<float, D> {nameof(arg_func_id)} and Func<D,R> {nameof(func_id)}!\n" +
                    $"But where {Function_args.Signature} and {Function.Signature}.");
        }
    
        public FunctionCallFact(FunctionFact Function, FunctionFact Function_args, (float t_0, float t_n) Domain) : base()
        {
            this.Function = Function;
            this.Function_args = Function_args;
            this.Domain = Domain;
    
            if (Function_args.Signature[0] != typeof(float) // takes in |R
              || (Function_args.Signature[1..].SequenceEqual(Function.Signature[..^0]) // output equals input
               && Function_args.Signature[^1] != typeof(object[]))) // if output is object array => types are concieled
                throw new ArgumentException(
                    $"Signatures must match: Func<float, D> {nameof(arg_func_id)} and Func<D,R> {nameof(func_id)}!\n" +
                    $"But where {Function_args.Signature} and {Function.Signature}.");
        }
    
        /// <summary>
        /// Mapps <paramref name="t"/> with <see cref="Function_args"/> to domain of <see cref="Function"/> and calls it.
        /// </summary>
        /// <param name="t">to be used as argument for <see cref="Function_args"/>. Semantical use is time in seconds.</param>
        /// <returns><see cref="Function"/>(<see cref="Function_args"/>(<paramref name="t"/>)) iff <paramref name="t"/> is within <see cref="Domain"/></returns>
        public object[] Call(float t)
        {
            if (t < Domain.t_0 || t > Domain.t_n)
                return null;
    
            object[] path = Function_args.Function(new object[] { t });
            return Function.Function(path);
        }
    
        public override bool HasDependentFacts
            => true;
    
        protected override string[] GetDependentFactIds()
            => new[] { func_id, arg_func_id };
    
        protected override bool EquivalentWrapped(FunctionCallFact f1, FunctionCallFact f2)
        {
            if (Mathf.Approximately(f1.Domain.t_0, f2.Domain.t_0)
                && Mathf.Approximately(f1.Domain.t_n, f2.Domain.t_n)
                && DependentFactsEquivalent(f1, f2)
            )
                return true;
    
            if (f1.Function.Signature[^1] != f2.Function.Signature[^1])
                return false;
            return false;
            int samplenumber = 3;
            float stepsizef1 = (f1.Domain.t_n - f1.Domain.t_0) / (samplenumber - 1);
            float stepsizef2 = (f2.Domain.t_n - f2.Domain.t_0) / (samplenumber - 1);
            for ((int i, float f1step, float f2step) = (0, f1.Domain.t_0, f2.Domain.t_0);
                i < samplenumber;
                i++, f1step += stepsizef1, f2step += stepsizef2)
            {
                object[] c1 = f1.Call(f1step);
                object[] c2 = f2.Call(f2step);
                if (c1 == null || c2 == null
                || !c1.SequenceEqual(c2, new ApproximationComparer(1e-3d)))
                    return false;
            }
            return true;
        }
    
        public override MMTFact MakeMMTDeclaration()
        {
            MMTGeneralFact mmt_arg = (MMTGeneralFact)Function_args.MakeMMTDeclaration();
            MMTGeneralFact mmt_in = (MMTGeneralFact)Function.MakeMMTDeclaration();
    
            SOMDoc type = new OMA(
                new OMS(MMTConstants.Product),
                new[]{
                    new OMA(
                        new OMS(MMTConstants.Product),
                        new []{
                            new OMS(MMTConstants.RealLit),
                            new OMS(MMTConstants.RealLit)
                    }),
                    mmt_arg.type,
                    mmt_in.type,
                });
    
            return new MMTGeneralFact(_LastLabel, type, Defines());
        }
    
        public override SOMDoc Defines()
            => new OMA(
                new OMS(MMTConstants.Tuple),
                new[] {
                    new OMA(
                        new OMS(MMTConstants.Tuple),
                        new[]{
                            new OMLIT<float>(Domain.t_0),
                            new OMLIT<float>(Domain.t_n)
                    }),
                    Function_args?.ServerDefinition ?? OMNONE.Instance,
                    Function?.ServerDefinition ?? OMNONE.Instance,
            });
    
        protected override void RecalculateTransform()
        {
            Position = Function.Position;
            Rotation = Function.Rotation;
            LocalScale = Function.LocalScale;
        }
    
        protected override Fact _ReInitializeMe(Dictionary<string, string> old_to_new)
            => new FunctionCallFact(old_to_new[this.func_id], old_to_new[this.arg_func_id], this.Domain);
    }
    
    /// <summary>
    /// A function <c>Func<object[], object[]></c> as Fact.
    /// </summary>
    public class FunctionFact : FactWrappedCRTP<FunctionFact>
    {
        protected override object GetCompiledValue()
            => Expression.Lambda(CompileBase).Compile().DynamicInvoke();
    
        /// <summary>
        /// MMT AST representing the function
        /// </summary>
        public SOMDoc Function_SOMDoc;
    
        /// <summary>
        /// The signature of this function.
        /// </summary>
        [JsonIgnore]
        public Type[] Signature;
    
        /// <summary>
        /// Encapsulated function.
        /// </summary>
        [JsonIgnore]
        public Func<object[], object[]> Function;
    
        /// <summary> \copydoc Fact.Fact </summary>
        public FunctionFact() : base() { }
    
        /// <summary>
        /// Standard Constructor:
        /// Initiates members and creates MMT %Fact Server-Side
        /// </summary>
        /// <param name="Function_SOMDoc">sets <see cref="Function_SOMDoc"/> and contains the Abstract Syntax Tree</param>
        public FunctionFact(SOMDoc Function_SOMDoc) : base()
        {
            this.Function_SOMDoc = Function_SOMDoc;
            this.Function = this.Function_SOMDoc.PartialInvokeCastingLambdaExpression(out Expression CompileBase, out Signature);
            this.CompileBase = CompileBase;
        }
    
        /// <summary>
        /// Bypasses initialization of new MMT %Fact by using existend URI, _which is not checked for existence_.
        /// </summary>
        /// <param name="function_expression">sets <see cref="Function_expression"/> and contains the Abstract Syntax Tree</param>
        /// <param name="uri">MMT URI</param>
        public FunctionFact(SOMDoc Function_SOMDoc, SOMDoc _ServerDefinition) : base()
        {
            this.Function_SOMDoc = Function_SOMDoc;
            this.Function = Function_SOMDoc.PartialInvokeCastingLambdaExpression(out Expression CompileBase, out Signature);
            this.CompileBase = CompileBase;
            this.ServerDefinition = _ServerDefinition;
        }
    
        protected override void RecalculateTransform() { }
    
        /// \copydoc Fact.parseFact(ScrollFact)
        public new static IEnumerator parseFact(List<Fact> ret, MMTFact fact)
        {// TODO Correctness
    
            if (((MMTGeneralFact)fact).defines is not FUN fun
                && (((MMTGeneralFact)fact).defines is not FallbackWrapper SFW
                || (fun = SFW.Wrapper as FUN) == null)
            )
                yield break;
    
            ParsingDictionary.parseTermsToId.TryAdd(fun.ToString(), fact.@ref.uri);
    
            ret.Add(new FunctionFact(fun, fact.@ref));
        }
    
        /// \copydoc Fact.hasDependentFacts
        public override bool HasDependentFacts
            => false;
    
        /// \copydoc Fact.getDependentFactIds
        protected override string[] GetDependentFactIds()
            => new string[] { };
    
        /// \copydoc Fact.GetHashCode
        public override int GetHashCode()
            => Function.GetHashCode();
    
        /// \copydoc Fact.EquivalentWrapped
        protected override bool EquivalentWrapped(FunctionFact f1, FunctionFact f2)
            => f1.Function_SOMDoc.Equivalent(f2.Function_SOMDoc);
    
        protected override Fact _ReInitializeMe(Dictionary<string, string> old_to_new)
            => new FunctionFact(this.Function_SOMDoc.MapURIs(old_to_new));
    
        public override MMTFact MakeMMTDeclaration()
            => new MMTGeneralFact(
                _LastLabel,
                SOMDoc.SOMDocType(FuncExtensions.CreateFuncType(Signature)),
                Defines());
    
        public override SOMDoc Defines()
            => Function_SOMDoc;
    }