/// <summary> /// Indicates, for each time interval in a given Tnum, whether the Tbool /// is ever true during that interval. /// </summary> public Tbool EverPer(Tnum intervals) { // If the interval Tnum is eternally unknown, return unknown if (intervals.IntervalValues.Count == 1 && !intervals.FirstValue.IsKnown) { return(new Tbool(intervals.FirstValue)); } Tbool result = new Tbool(); IList <DateTime> tPoints = intervals.TimePoints(); // Check each time interval to see if condition is true for (int i = 0; i < tPoints.Count - 1; i++) { Hval isEverTrue = this.IsEverTrue(tPoints[i], tPoints[i + 1]).FirstValue; result.AddState(tPoints[i], isEverTrue); } // This doesn't use .Lean because the output of EverPer() is often // the input to a function that counts the number of discrete // intervals. If you want a "lean" result, append .Lean when using // this function. return(result); }
private static Hval CoreReverse(Hval h) { List <Thing> list = (List <Thing>)h.Val; list.Reverse(); return(new Hval(list)); }
public static object ReturnProperTvar <T>(Hval val) { if (typeof(T) == new Tbool().GetType()) { return(new Tbool(val)); } if (typeof(T) == new Tnum().GetType()) { return(new Tnum(val)); } if (typeof(T) == new Tstr().GetType()) { return(new Tstr(val)); } if (typeof(T) == new Tdate().GetType()) { return(new Tdate(val)); } if (typeof(T) == new Tset().GetType()) { return(new Tset(val)); } // If all else fails return default... return(default(T)); }
/// <summary> /// Finds the Tset associated with a given Tnum value on a given date. /// </summary> private static Hval AssociatedTset(List <Tuple <Tset, Tnum> > setFcnVals, Tnum val, DateTime asOfDate) { foreach (Tuple <Tset, Tnum> t in setFcnVals) { // Handle uncertainty Hval s = t.Item2.AsOf(asOfDate).FirstValue; Hval v = val.AsOf(asOfDate).FirstValue; if (s.IsUncertain && v.IsUncertain) { return(new Hval(null)); // Not hitting this for some reason... } if (s.IsUnstated && v.IsUnstated) { return(new Hval(null, Hstate.Unstated)); } if (s.IsStub && v.IsStub) { return(new Hval(null, Hstate.Stub)); } // Compare numeric values if (t.Item2.AsOf(asOfDate) == val.AsOf(asOfDate)) { // Tsets created in Combos() are eternal, so FirstValue is ok here return(t.Item1.FirstValue); } } return(new Hval(null, Hstate.Stub)); }
/// <summary> /// Applies an aggregation function to a Tset and an argument function. /// </summary> private static T ApplyFcnToTset <T>(Tset theSet, Func <Thing, Tvar> argumentFcn, Func <List <Tuple <Thing, Hval> >, Hval> aggregationFcn) where T : Tvar { Dictionary <Thing, Tvar> fcnValues = new Dictionary <Thing, Tvar>(); List <Tvar> listOfTvars = new List <Tvar>(); // Get the temporal value of each distinct entity in the set foreach (Thing le in DistinctEntities(theSet)) { Tvar val = argumentFcn(le); fcnValues.Add(le, val); listOfTvars.Add(val); } // At each breakpoint, for each member of the set, // aggregate and analyze the values of the functions T result = (T)Util.ReturnProperTvar <T>(); foreach (DateTime dt in AggregatedTimePoints(theSet, listOfTvars)) { Hval membersOfSet = theSet.ObjectAsOf(dt); // If theSet is unknown... if (!membersOfSet.IsKnown) { result.AddState(dt, membersOfSet); } else { // Cube that gets sent to the aggregation function List <Tuple <Thing, Hval> > thingValPairs = new List <Tuple <Thing, Hval> >(); // Values to check for uncertainty List <Hval> values = new List <Hval>(); foreach (Thing le in (List <Thing>)membersOfSet.Val) { Tvar funcVal = (Tvar)fcnValues[le]; Hval funcValAt = funcVal.ObjectAsOf(dt); values.Add(funcValAt); thingValPairs.Add(new Tuple <Thing, Hval>(le, funcValAt)); } Hstate top = PrecedingState(values); if (top != Hstate.Known) { result.AddState(dt, new Hval(null, top)); } else { result.AddState(dt, aggregationFcn(thingValPairs)); } } } return(result.LeanTvar <T>()); }
/// <summary> /// Implements Tset.OptimalSubset(Tnum fcn). /// </summary> private static Tset OptimalSubsetCore(Tset theSet, Func <Tset, Tnum> fcn) { Tset result = new Tset(); // For each time period in the Tset for (int i = 0; i < theSet.IntervalValues.Count; i++) { // Get some useful values Hval thisSetVal = theSet.IntervalValues.Values[i]; DateTime start = theSet.IntervalValues.Keys[i]; // Handle uncertainty of theSet if (!thisSetVal.IsKnown) { result.AddState(start, thisSetVal); } else { // Date parameters and set members of that time interval List <Thing> mems = (List <Thing>)thisSetVal.Val; DateTime end = Time.EndOf; try { end = theSet.IntervalValues.Keys[i + 1]; } catch {} // For each combination of set members, get the associated fcn val List <Tuple <Tset, Tnum> > setFcnVals = new List <Tuple <Tset, Tnum> >(); Tnum maxVal = new Tnum(Decimal.MinValue); foreach (Tset s in Combos(mems)) { // Invoke the fcn for that subset Tnum val = fcn(s); // Save the result of the fcn and the associated Tset setFcnVals.Add(Tuple.Create(s, val)); // Update the running maximum value maxVal = Max(maxVal, val); } // Foreach changepoint in maxVal, find the associated Tset for (int j = 0; j < maxVal.IntervalValues.Count; j++) { DateTime mDate = maxVal.IntervalValues.Keys[j]; if (mDate >= start && mDate < end) { // Get the associated Tset Hval outSet = AssociatedTset(setFcnVals, maxVal, mDate); // Add the change point result.AddState(mDate, outSet); } } } } return(result); }
/// <summary> /// Returns a Tvar in which the values are shifted in time relative to /// the dates. A negative offset gets values from the past; a positive one /// gets them from the future. /// </summary> /// <remarks> /// Used, for example, to get the value of a Tvar during a prior or future /// time period. /// Note: Time points on both the base Tvar and the temporalPeriod Tnum /// must line up in order for the method to work properly. /// </remarks> /// <example> /// N = <--33--|--44--|--55--|--66--|--77--> /// Year = <-2010-|-2011-|-2012-|-2013-|-2014-> /// N.Shift(-2,Year) = <---------33---------|--44--|--55--|--66--|--77--> /// </example> public T Shift <T>(int offset, Tnum temporalPeriod) where T : Tvar { // TODO: Make "offset" a Tnum instead of an int T result = (T)Util.ReturnProperTvar <T>(); result.AddState(this.TimeLine.Keys[0], this.TimeLine.Values[0]); // No need to handle uncertainty b/c this method just reuses the values in // the base Tvar. // Iterate through pairs in the base Tvar foreach (KeyValuePair <DateTime, Hval> de in this.TimeLine) { // Extract parts of the date-value pair DateTime origDate = Convert.ToDateTime(de.Key); Hval val = de.Value; DateTime offsetDate = Time.EndOf; // Leave the value at Time.DawnOf alone if (origDate != Time.DawnOf) { // Get the time point with the appropriate offset from the current time point // First, look up the original date in temporalPeriod for (int i = 0; i < temporalPeriod.TimeLine.Values.Count; i++) { DateTime testDate = Convert.ToDateTime(temporalPeriod.TimeLine.Keys[i]); if (testDate == origDate) { // Then get the date offset from the original date int offsetIndex = i + (offset * -1); // Don't overrun the temporalPeriod list if (offsetIndex < temporalPeriod.TimeLine.Count && offsetIndex >= 0) { offsetDate = temporalPeriod.TimeLine.Keys[offsetIndex]; // Prevent overflowing the bounds of Time if (offsetDate < Time.EndOf) { result.AddState(offsetDate, val); } break; } } } } } return(result); }
/// <summary> /// I'm not thrilled about this. /// </summary> public bool IsEqualTo(Hval h2) { if (this.IsKnown && h2.IsKnown) { // Note: Won't work for List<LegalEntity> if (object.Equals(this.Obj, h2.Obj)) { return(true); } } return(false); }
/// <summary> /// Returns a Tvar when its associated Tbool is true. /// </summary> /// <remarks> /// Similar in principle to a C# switch statement, just temporal. /// Sample usage: Switch(Tbool1, Tvar1, Tbool2, Tvar2, ..., defaultTvar). /// Returns Tvar1 if Tbool2 is true, else Tvar2 if Tbool2 is true, etc., else defaultTvar. /// </remarks> public static T Switch <T>(params Func <Tvar>[] arguments) where T : Tvar { // Default result Hval h = new Hval(null, Hstate.Null); T result = (T)Util.ReturnProperTvar <T>(h); // Analyze each condition-value pair...and keep going // until all intervals of the result Tvar are defined... int len = (int)arguments.Length; for (int arg = 0; arg < len - 1; arg += 2) { // Get value of the condition Tbool newCondition = Util.ConvertToTvar <Tbool>(arguments[arg].Invoke()); // Identify the intervals when the new condition is neither false nor true // Falsehood causes it to fall through to next condition. Truth causes the // result to assume the value during that interval. Tbool newConditionIsUnknown = Util.HasUnknownState(newCondition); // Merge these 'unknown' intervals in new condition into the result. result = Util.MergeTvars <T>(result, Util.ConditionalAssignment <T>(newConditionIsUnknown, newCondition)); // Identify the intervals when the new condition is true. // Ignore irrelevant periods when result is already determined. // During these intervals, "result" takes on the value of its conclusion. Tbool newConditionIsTrueAndResultIsNull = newCondition && Util.IsNull(result); // If new true segments are found, accumulate the values during those intervals if (newConditionIsTrueAndResultIsNull.IsEverTrue()) { T val = (T)Util.ConvertToTvar <T>(arguments[arg + 1].Invoke()); result = Util.MergeTvars <T>(result, Util.ConditionalAssignment <T>(newConditionIsTrueAndResultIsNull, val)); } if (!Util.HasUndefinedIntervals(result)) { return(result.LeanTvar <T>()); } } T defaultVal = (T)Util.ConvertToTvar <T>(arguments[len - 1].Invoke()); result = Util.MergeTvars <T>(result, defaultVal); return(result.LeanTvar <T>()); }
/// <summary> /// Converts Uncertain and Stub time periods to a given value. /// </summary> /// <remarks> /// Used to rid a Tnum of uncertainty. Note that it does not convert Unstated /// periods because doing so would break the backward chaining interview. /// </remarks> public Tnum NormalizedTo(decimal val) { Tnum result = new Tnum(); foreach (KeyValuePair <DateTime, Hval> slice in this.IntervalValues) { Hval theVal = slice.Value; if (theVal.IsUncertain || theVal.IsStub) { result.AddState(slice.Key, val); } else { result.AddState(slice.Key, slice.Value); } } return(result.Lean); }
/// <summary> /// Determines whether the Tvar is ever the specified boolean val. /// </summary> private Tbool IsEver(Hval val) { // If val is unknown and base Tvar is eternally unknown, // return the typical precedence state if (!val.IsKnown && this.TimeLine.Count == 1) { if (!this.FirstValue.IsKnown) { Hstate s = PrecedingState(this.FirstValue, val); return(new Tbool(s)); } } // If val is unknown, return its state if (!val.IsKnown) { return(new Tbool(val)); } // If the base Tvar is ever val, return true foreach (Hval h in this.TimeLine.Values) { if (h.IsEqualTo(val)) { return(true); } } // If base Tvar has a time period of unknownness, return // the state with the proper precedence Hstate returnState = PrecedenceForMissingTimePeriods(this); if (returnState != Hstate.Known) { return(new Tbool(returnState)); } return(false); }
/// <summary> /// Returns the value of a Tvar at a specified point in time. /// </summary> /// <remarks> /// If the Tdate varies over time, only the first value is used. /// </remarks> public T AsOf <T>(Tdate date) where T : Tvar { Hval result; // If base Tvar has eternal, known value, return that. // (In these cases, the Tdate is irrelevant.) if (this.IsEternal && !this.IsEternallyUnknown) { result = this.FirstValue; } // If either the base Tvar or Tdate are unknown... else if (!date.FirstValue.IsKnown || this.IsEternallyUnknown) { Hstate top = PrecedingState(this.FirstValue, date.FirstValue); result = new Hval(null, top); } else { result = this.ObjectAsOf(date.ToDateTime); } return((T)Util.ReturnProperTvar <T>(result)); }
/// <summary> /// Indicates, for each time interval in a given Tnum, whether the Tbool /// is always true during that interval. /// </summary> public Tbool AlwaysPer(Tnum intervals) { // If the interval Tnum is eternally unknown, return unknown if (intervals.IntervalValues.Count == 1 && !intervals.FirstValue.IsKnown) { return(new Tbool(intervals.FirstValue)); } Tbool result = new Tbool(); IList <DateTime> tPoints = intervals.TimePoints(); // Foreach interval in intervals for (int i = 0; i < tPoints.Count - 1; i++) { Hval isAlwaysTrue = this.IsAlwaysTrue(tPoints[i], tPoints[i + 1]).FirstValue; result.AddState(tPoints[i], isAlwaysTrue); } // Doesn't use .Lean. See explanation in EverPer() above. return(result); }
private static Hval CoreSin(Hval h) { return Math.Sin(Convert.ToDouble(h.Val)); }
private static Hval CoreReverse(Hval h) { List<Thing> list = (List<Thing>)h.Val; list.Reverse(); return new Hval(list); }
private static Hval CoreNatLog(Hval h) { return(Math.Log(Convert.ToDouble(h.Val))); }
public void HvalEquality2() { Hval h1 = new Hval(22); Hval h2 = new Hval(23); Assert.AreEqual(false, h1.IsEqualTo(h2)); }
private static Hval CoreSin(Hval h) { return(Math.Sin(Convert.ToDouble(h.Val))); }
/// <summary> /// Adds an time-value state to the TimeLine. /// </summary> public void AddState(DateTime dt, Hval hval) { TimeLine.Add(dt, hval); }
public void TestHval16() { Hval h = new Hval(null,Hstate.Uncertain); Assert.AreEqual("Uncertain", h.ToString); }
private static Hval GetMonth(Hval h) { return Convert.ToDateTime(h.Val).Month; }
private static Hval GetDay(Hval h) { return Convert.ToDateTime(h.Val).Day; }
private static Hval GetMonth(Hval h) { return(Convert.ToDateTime(h.Val).Month); }
private static Hval GetYear(Hval h) { return Convert.ToDateTime(h.Val).Year; }
public Tnum(Hval val) { this.SetEternally(val); }
private static Hval GetDay(Hval h) { return(Convert.ToDateTime(h.Val).Day); }
private static Hval CoreToUSD(Hval h) { return(String.Format("{0:C}", Convert.ToDecimal(h.Val))); }
private static Hval CoreArcTan(Hval h) { return Math.Atan(Convert.ToDouble(h.Val)); }
public Tdate(Hval val) { this.SetEternally(val); }
public Tbool(Hval v) { this.SetEternally(v); }
private static Hval CoreTsetCount(Hval h) { return(((List <Thing>)h.Val).Count); }
/// <summary> /// I'm not thrilled about this. /// </summary> public bool IsEqualTo(Hval h2) { if (this.IsKnown && h2.IsKnown) { // Note: Won't work for List<LegalEntity> if (object.Equals(this.Obj, h2.Obj)) return true; } return false; }
private static Hval GetYear(Hval h) { return(Convert.ToDateTime(h.Val).Year); }
public void TestHval6() { Hval HnumKnown2 = new Hval(42); Assert.AreEqual(HnumKnown.Val, HnumKnown2.Val); }
private static Hval Not(Hval h) { return !Convert.ToBoolean(h.Val); }
public void HvalEquality4() { Hval h1 = new Hval(true); Hval h2 = new Hval(true); Assert.AreEqual(true, h1.IsEqualTo(h2)); }
private static Hval CoreArcTan(Hval h) { return(Math.Atan(Convert.ToDouble(h.Val))); }
private static Hval CoreTsetCount(Hval h) { return ((List<Thing>)h.Val).Count; }
public Tset(Hval val) { this.SetEternally(val); }
private static Hval CoreArcCos(Hval h) { return(Math.Acos(Convert.ToDouble(h.Val))); }
private static Hval CoreNatLog(Hval h) { return Math.Log(Convert.ToDouble(h.Val)); }
public void TestHval11() { Hval HboolF = new Hval(false); bool r = HboolF.IsTrue; Assert.AreEqual(false, r); }
private static Hval CoreArcCos(Hval h) { return Math.Acos(Convert.ToDouble(h.Val)); }
public void TestHval13() { Hval h = new Hval(null,Hstate.Uncertain); Assert.AreEqual(false, h.IsKnown); }
/// <summary> /// Determines whether the Tvar is ever the specified boolean val. /// </summary> private Tbool IsEver(Hval val) { // If val is unknown and base Tvar is eternally unknown, // return the typical precedence state if (!val.IsKnown && this.TimeLine.Count == 1) { if (!this.FirstValue.IsKnown) { Hstate s = PrecedingState(this.FirstValue, val); return new Tbool(s); } } // If val is unknown, return its state if (!val.IsKnown) return new Tbool(val); // If the base Tvar is ever val, return true foreach (Hval h in this.TimeLine.Values) { if (h.IsEqualTo(val)) return true; } // If base Tvar has a time period of unknownness, return // the state with the proper precedence Hstate returnState = PrecedenceForMissingTimePeriods(this); if (returnState != Hstate.Known) return new Tbool(returnState); return false; }
public void TestHval14() { Hval h = new Hval(44); Assert.AreEqual(true, h.IsKnown); }
/// <summary> /// Sets a Tvar to an "eternal" value (the same at all points in time). /// </summary> public void SetEternally(Hval hval) { AddState(Time.DawnOf, hval); }
public void TestHval15() { Hval h = new Hval(44); Assert.AreEqual("44", h.ToString); }
/// <summary> /// Gets all time points and assocated values from the input Tvar objects, by merging them /// together like a zipper. /// </summary> /// <remarks> /// This method is ~590 times faster than TimePointValuesForMultipleTvars in a worst-case /// scenario like computing Time.TheDay > 12. For Tvars with very few time points, it's /// about 10-20% faster. /// </remarks> public static SortedList <DateTime, List <Hval> > TimePointValues(params Tvar[] list) { // Handle cases with more than two input Tvars, and BoolCount with one input argument if (list.Length != 2) { return(TimePointValuesForMultipleTvars(list)); } SortedList <DateTime, List <Hval> > result = new SortedList <DateTime, List <Hval> >(); SortedList <DateTime, Hval> t1 = list[0].IntervalValues; SortedList <DateTime, Hval> t2 = list[1].IntervalValues; int idx1 = 0; int idx2 = 0; Hval val1 = t1.Values[0]; Hval val2 = t2.Values[0]; int t1Count = t1.Count; int t2Count = t2.Count; // Add the first state - assumes all Tvars start at Time.DawnOf result.Add(Time.DawnOf, new List <Hval>() { val1, val2 }); // Walk along the two Tvars, index by index, until you get to the end of both while (!(idx1 + 1 >= t1Count && idx2 + 1 >= t2Count)) { // Don't exceed the length of an array int nextIdx1 = Math.Min(idx1 + 1, t1Count - 1); int nextIdx2 = Math.Min(idx2 + 1, t2Count - 1); DateTime nextDate1 = t1.Keys[nextIdx1]; DateTime nextDate2 = t2.Keys[nextIdx2]; // If the next dates on T1 and T2 are the same, advance along both Tvars if (nextDate1 == nextDate2) { idx1 = nextIdx1; val1 = t1.Values[idx1]; idx2 = nextIdx2; val2 = t2.Values[idx2]; result.Add(nextDate1, new List <Hval>() { val1, val2 }); } // Advance along Tvar that is farther behind, except when the one that's behind is at its end else if (idx2 == t2Count - 1 || (idx1 != t1Count - 1 && nextDate2 > nextDate1)) { // Advance along T1 idx1 = nextIdx1; val1 = t1.Values[idx1]; result.Add(nextDate1, new List <Hval>() { val1, val2 }); } else { // Advance along T2 idx2 = nextIdx2; val2 = t2.Values[idx2]; result.Add(nextDate2, new List <Hval>() { val1, val2 }); } } return(result); }
private static Hval Not(Hval h) { return(!Convert.ToBoolean(h.Val)); }
private static Hval CoreToUSD(Hval h) { return String.Format("{0:C}" ,Convert.ToDecimal(h.Val)); }