/// <summary> /// Divides one Tnum by another. /// </summary> public static Tnum operator /(Tnum tn1, Tnum tn2) { Tnum result = new Tnum(); foreach (KeyValuePair <DateTime, List <Hval> > slice in TimePointValues(tn1, tn2)) { Hstate top = PrecedingState(slice.Value); decimal denominator = Convert.ToDecimal(slice.Value[1].Val); if (denominator == 0) // Short circuit 1: Div-by-zero { result.AddState(slice.Key, new Hval(null)); } else if (top != Hstate.Known) // Short circuit 2: Hstates { result.AddState(slice.Key, new Hval(null, top)); } else // Do the math { decimal r = Convert.ToDecimal(slice.Value[0].Val) / denominator; result.AddState(slice.Key, new Hval(r)); } } return(result.Lean); }
public static Tnum IntervalsUntil(Tdate startDate, Tdate endDate, IntervalType interval, int startAt) { // Handle unknowns Hstate top = PrecedingState(startDate.FirstValue, endDate.FirstValue); if (top != Hstate.Known) { return(new Tnum(new Hval(null, top))); } DateTime start = startDate.ToDateTime; DateTime end = endDate.ToDateTime; Tnum result = new Tnum(); DateTime indexDate = end; int indexNumber = startAt - 1; while (indexDate > start) { if (indexNumber != startAt - 1) { result.AddState(indexDate, Convert.ToString(indexNumber)); } indexNumber++; indexDate = indexDate.SubtractInterval(interval); } result.AddState(Time.DawnOf, 0); result.AddState(start, Convert.ToString(indexNumber)); result.AddState(end, 0); return(result); }
/// <summary> /// Multiplies two Tnums together. /// </summary> public static Tnum operator *(Tnum tn1, Tnum tn2) { Tnum result = new Tnum(); foreach (KeyValuePair <DateTime, List <Hval> > slice in TimePointValues(tn1, tn2)) { Hstate top = PrecedingState(slice.Value); decimal val1 = Convert.ToDecimal(slice.Value [0].Val); decimal val2 = Convert.ToDecimal(slice.Value [1].Val); // Short circuit 1 if (val1 == 0 || val2 == 0) { result.AddState(slice.Key, new Hval(0)); } else if (top != Hstate.Known) // Short circuit 2 { result.AddState(slice.Key, new Hval(null, top)); } else // Do the math { decimal prod = val1 * val2; result.AddState(slice.Key, new Hval(prod)); } } return(result.Lean); }
/// <summary> /// Multiplies two Tnums together. /// </summary> public static Tnum operator * (Tnum tn1, Tnum tn2) { Tnum result = new Tnum(); foreach(KeyValuePair<DateTime,List<Hval>> slice in TimePointValues(tn1,tn2)) { Hstate top = PrecedingState(slice.Value); decimal val1 = Convert.ToDecimal(slice.Value [0].Val); decimal val2 = Convert.ToDecimal(slice.Value [1].Val); // Short circuit 1 if (val1 == 0 || val2 == 0) { result.AddState(slice.Key, new Hval(0)); } else if (top != Hstate.Known) // Short circuit 2 { result.AddState(slice.Key, new Hval(null,top)); } else // Do the math { decimal prod = val1 * val2; result.AddState(slice.Key, new Hval(prod)); } } return result.Lean; }
/// <summary> /// Returns the total elapsed days that a Tvar has a given value, /// for each of a given set of intervals. /// Example: meetsAnnualTest = var.ElapsedDaysPerInterval(theYear) > 183; /// </summary> public Tnum TotalElapsedDaysPer(Tnum period) { // If base Tnum is ever unknown during the time period, return // the state with the proper precedence Hstate baseState = PrecedenceForMissingTimePeriods(this); Hstate periodState = PrecedenceForMissingTimePeriods(period); Hstate top = PrecedingState(baseState, periodState); if (top != Hstate.Known) return new Tnum(top); Tnum result = new Tnum(); int count = period.IntervalValues.Count; for (int i=0; i < count; i++) { DateTime spanEnd = Time.EndOf; if (i < count-1) { spanEnd = period.IntervalValues.Keys[i+1]; } TimeSpan time = this.TotalElapsedTime(period.IntervalValues.Keys[i], spanEnd); // Add the state, but not if it's at the end of time if (period.IntervalValues.Keys[i] < Time.EndOf) { result.AddState(period.IntervalValues.Keys[i], time.TotalDays); } } return result.Lean; }
/// <summary> /// Returns a total count of the number of complete subintervals /// within each interval in which the Tvar (this) is true. /// </summary> /// <remarks> /// This function should be used as an extension method to EverPer() /// or AlwaysPer(). /// Example: Count the number of weeks each year during which /// a person was employed. /// </remarks> // TODO: Add support for counting partial subintervals public Tnum CountPer(Tnum intervals) { // TODO: Handle unknowns... Tnum result = new Tnum(); SortedList <DateTime, Hval> big = intervals.IntervalValues; SortedList <DateTime, Hval> small = this.IntervalValues; for (int b = 0; b < big.Count - 1; b++) { int count = 0; DateTime bStart = big.Keys[b]; DateTime bEnd = big.Keys[b + 1]; for (int s = 0; s < small.Count - 1; s++) { DateTime sStart = small.Keys[s]; DateTime sEnd = small.Keys[s + 1]; if (sStart >= bStart && sEnd <= bEnd && this.AsOf(sStart).ToBool == true) { count++; } } result.AddState(bStart, count); count = 0; } return(result.Lean); }
public static Tnum IntervalsSince(Tdate startDate, Tdate endDate, IntervalType interval, int? startAt) { // Handle unknowns Hstate top = PrecedingState(startDate.FirstValue, endDate.FirstValue); if (top != Hstate.Known) return new Tnum(new Hval(null,top)); DateTime start = startDate.ToDateTime; DateTime end = endDate.ToDateTime; Tnum result = new Tnum(); if (start != Time.DawnOf) { result.AddState(Time.DawnOf,0); } DateTime indexDate = start; int? indexNumber = startAt; while (indexDate < end) { result.AddState(indexDate,Convert.ToDecimal(indexNumber)); indexNumber++; indexDate = indexDate.AddInterval(interval, 1); } if (end < Time.EndOf) result.AddState(end, 0); return result; }
/// <summary> /// Takes a Tnum representing some value per unit time, and sums or /// accumulates it over a given type of time interval to obtain a /// running total. /// </summary> /// <example> /// Calculate lifetime accrued income, given a person's annual income: /// /// AccruedIncome = AnnualIncome.RunningSummedIntervals(TheYear) /// /// The time units cancel: [$/year] * [year] yields [$]. /// </example> public Tnum RunningSummedIntervals(Tnum interval) { // TODO: Review how uncertainty is handled here: // Handle unknowns Hstate top = PrecedingState(this.FirstValue, interval.FirstValue); if (top != Hstate.Known) return new Tnum(new Hval(null,top)); // If base Tnum is ever unknown during the time period, return // the state with the proper precedence Hstate baseState = PrecedenceForMissingTimePeriods(this); if (baseState != Hstate.Known) return new Tnum(baseState); // Start accumulating... Tnum result = new Tnum(0); decimal total = 0; decimal previousVal = 0; // Iterate through the intervals, totaling for (int i=1; i < interval.TimeLine.Count-1; i++) { total += Convert.ToDecimal(this.ObjectAsOf(interval.TimeLine.Keys[i]).Val); // Only add changepoint if value actually changes if (total != previousVal) { result.AddState(interval.TimeLine.Keys[i+1], total); } // Set for next iteration previousVal = total; } return result; }
/// <summary> /// Provides a running count of how many whole intervals a Tbool /// has been continuously true. /// </summary> /// <remarks> /// Example: /// tb = <--FTFTTF--> /// tb.ICT = <--010120--> /// /// Use judiciously with TheDay and TheCalendarWeek, as they have thousands of time intervals. /// </remarks> public Tnum ContinuousElapsedIntervals(Tnum interval) { // If base Tnum is ever unknown during the time period, return // the state with the proper precedence Hstate baseState = PrecedenceForMissingTimePeriods(this); if (baseState != Hstate.Known) { return(new Tnum(baseState)); } int intervalCount = 0; DateTime dateNextTrue = this.DateNextTrue(Time.DawnOf); DateTime dateNextTrueIntervalEnds = this.NextChangeDate(dateNextTrue.AddTicks(1)); Tnum result = new Tnum(0); // Iterate through the time intervals in the input Tnum for (int i = 0; i < interval.IntervalValues.Count - 1; i++) { DateTime start = interval.IntervalValues.Keys[i]; DateTime end = interval.IntervalValues.Keys[i + 1]; // If base Tbool is always true during the interval, increment the count if (end <= dateNextTrueIntervalEnds) { if (start >= dateNextTrue) { intervalCount++; result.AddState(end, intervalCount); continue; } } else { // Otherwise, skip to next true interval intervalCount = 0; result.AddState(end, intervalCount); dateNextTrue = this.DateNextTrue(end); dateNextTrueIntervalEnds = this.NextChangeDate(dateNextTrue.AddTicks(1)); } } return(result); }
/// <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> /// Provides a running count of how many whole intervals a Tbool /// has been continuously true. /// </summary> /// <remarks> /// Example: /// tb = <--FTFTTF--> /// tb.ICT = <--010120--> /// /// Use judiciously with TheDay and TheCalendarWeek, as they have thousands of time intervals. /// </remarks> public Tnum ContinuousElapsedIntervals(Tnum interval) { // If base Tnum is ever unknown during the time period, return // the state with the proper precedence Hstate baseState = PrecedenceForMissingTimePeriods(this); if (baseState != Hstate.Known) return new Tnum(baseState); int intervalCount = 0; DateTime dateNextTrue = this.DateNextTrue(Time.DawnOf); DateTime dateNextTrueIntervalEnds = this.NextChangeDate(dateNextTrue.AddTicks(1)); Tnum result = new Tnum(0); // Iterate through the time intervals in the input Tnum for (int i=0; i < interval.IntervalValues.Count-1; i++) { DateTime start = interval.IntervalValues.Keys[i]; DateTime end = interval.IntervalValues.Keys[i+1]; // If base Tbool is always true during the interval, increment the count if (end <= dateNextTrueIntervalEnds) { if (start >= dateNextTrue) { intervalCount++; result.AddState(end, intervalCount); continue; } } else { // Otherwise, skip to next true interval intervalCount = 0; result.AddState(end, intervalCount); dateNextTrue = this.DateNextTrue(end); dateNextTrueIntervalEnds = this.NextChangeDate(dateNextTrue.AddTicks(1)); } } return result; }
//********************************************************************* // TEMPORAL "RECURRENCE" FUNCTIONS //********************************************************************* /// <summary> /// Loops (cycles) through numbers over time (e.g. 1 2 3 4 1 2 3 4 ...) /// </summary> public static Tnum Recurrence(Tdate startDate, Tdate endDate, IntervalType interval, int min, int max) { // Handle unknowns Hstate top = PrecedingState(startDate.FirstValue, endDate.FirstValue); if (top != Hstate.Known) { return(new Tnum(new Hval(null, top))); } DateTime start = startDate.ToDateTime; DateTime end = endDate.ToDateTime; Tnum result = new Tnum(); if (start != Time.DawnOf) { result.AddState(Time.DawnOf, 0); } DateTime indexDate = start; int indexNumber = min; while (indexDate < end) { result.AddState(indexDate, Convert.ToString(indexNumber)); indexDate = indexDate.AddInterval(interval, 1); // Reset sequence indexNumber++; if (indexNumber > max) { indexNumber = min; } } result.AddState(end, 0); return(result); }
/// <summary> /// Returns a running count (over time) of the number of subintervals /// within each interval in which the Tvar (this) is true. /// </summary> /// <remarks> /// This function should be used as an extension method to EverPer() /// or AlwaysPer(). /// Example: Count the number of weeks each year during which /// a person was employed. The first week of employment would be /// numbered 0, the second 1, etc. /// </remarks> // TODO: Fix broken test case for this function. public Tnum RunningCountPer(Tnum intervals) { // TODO: Implement unknowns Tnum result = new Tnum(); result.AddState(Time.DawnOf, 0); int count = 0; decimal?prevBig = 0; SortedList <DateTime, Hval> sub = this.IntervalValues; // Iterate through the sub-intervals for (int i = 0; i < sub.Count - 1; i++) { DateTime dt = sub.Keys[i]; // Reset count for each new (big, not sub-) interval decimal?big = intervals.AsOf(dt).ToDecimal; if (big != prevBig) { count = 0; } prevBig = big; // If the Tbool is true during the subinterval, increment // the subsequent subinterval if (this.AsOf(dt).ToBool == true) { count++; } result.AddState(sub.Keys[i + 1], count); } return(result.Lean); }
/// <summary> /// Returns a Tnum representing the calendar week (by default, a /// 10-year span centered on the start of the current year). /// </summary> /// <remarks> /// See remarks in the CalendarWeek method in the H class. /// </remarks> public static Tnum CalendarWeek(int halfSpanInYears) { Tnum result = new Tnum(); result.AddState(Time.DawnOf, 0); // Get the start date for week 1, n years in the past DateTime d = NthDayOfWeekMonthYear(1, DayOfWeek.Saturday, 1, DateTime.Now.Year - halfSpanInYears); if (d.Day != 1) { d = d.AddDays(-7); } // Mark off each week for (int i = 0; i < (halfSpanInYears * 106); i++) { result.AddState(d, 0); d = d.AddDays(7); } // Don't apply .Lean because it would defeat the purpose of this object. return(result); }
public static Tnum IntervalsSince(Tdate startDate, Tdate endDate, IntervalType interval, int?startAt) { // Handle unknowns Hstate top = PrecedingState(startDate.FirstValue, endDate.FirstValue); if (top != Hstate.Known) { return(new Tnum(new Hval(null, top))); } DateTime start = startDate.ToDateTime; DateTime end = endDate.ToDateTime; Tnum result = new Tnum(); if (start != Time.DawnOf) { result.AddState(Time.DawnOf, 0); } DateTime indexDate = start; int? indexNumber = startAt; while (indexDate < end) { result.AddState(indexDate, Convert.ToDecimal(indexNumber)); indexNumber++; indexDate = indexDate.AddInterval(interval, 1); } if (end < Time.EndOf) { result.AddState(end, 0); } return(result); }
/// <summary> /// Takes a Tnum representing some value per unit time, and sums or /// accumulates it over a given type of time interval to obtain a /// running total. /// </summary> /// <example> /// Calculate lifetime accrued income, given a person's annual income: /// /// AccruedIncome = AnnualIncome.RunningSummedIntervals(TheYear) /// /// The time units cancel: [$/year] * [year] yields [$]. /// </example> public Tnum RunningSummedIntervals(Tnum interval) { // TODO: Review how uncertainty is handled here: // Handle unknowns Hstate top = PrecedingState(this.FirstValue, interval.FirstValue); if (top != Hstate.Known) { return(new Tnum(new Hval(null, top))); } // If base Tnum is ever unknown during the time period, return // the state with the proper precedence Hstate baseState = PrecedenceForMissingTimePeriods(this); if (baseState != Hstate.Known) { return(new Tnum(baseState)); } // Start accumulating... Tnum result = new Tnum(0); decimal total = 0; decimal previousVal = 0; // Iterate through the intervals, totaling for (int i = 1; i < interval.TimeLine.Count - 1; i++) { total += Convert.ToDecimal(this.ObjectAsOf(interval.TimeLine.Keys[i]).Val); // Only add changepoint if value actually changes if (total != previousVal) { result.AddState(interval.TimeLine.Keys[i + 1], total); } // Set for next iteration previousVal = total; } return(result); }
/// <summary> /// Returns the total elapsed days that a Tvar has a given value, /// for each of a given set of intervals. /// Example: meetsAnnualTest = var.ElapsedDaysPerInterval(theYear) > 183; /// </summary> public Tnum TotalElapsedDaysPer(Tnum period) { // If base Tnum is ever unknown during the time period, return // the state with the proper precedence Hstate baseState = PrecedenceForMissingTimePeriods(this); Hstate periodState = PrecedenceForMissingTimePeriods(period); Hstate top = PrecedingState(baseState, periodState); if (top != Hstate.Known) { return(new Tnum(top)); } Tnum result = new Tnum(); int count = period.IntervalValues.Count; for (int i = 0; i < count; i++) { DateTime spanEnd = Time.EndOf; if (i < count - 1) { spanEnd = period.IntervalValues.Keys[i + 1]; } TimeSpan time = this.TotalElapsedTime(period.IntervalValues.Keys[i], spanEnd); // Add the state, but not if it's at the end of time if (period.IntervalValues.Keys[i] < Time.EndOf) { result.AddState(period.IntervalValues.Keys[i], time.TotalDays); } } return(result.Lean); }
/// <summary> /// Takes a Tnum representing some value per unit time, and accumulates it /// over a given number of successive time intervals. /// </summary> /// <example> /// Calculate income accumulated over a three month period, where the /// person earned $3,000/month: /// /// Income = MonthlyIncome.SlidingSummedIntervals(TheMonth, 3) /// /// The time units cancel: [$/mo.] * [mo.] yields [$]. /// </example> public Tnum SlidingSummedIntervals(Tnum interval, Tnum windowSize) { // TODO: Review how uncertainty is handled here: // Handle unknowns Hstate top = PrecedingState(this.FirstValue, interval.FirstValue, windowSize.FirstValue); if (top != Hstate.Known) { return(new Tnum(new Hval(null, top))); } // If base Tnum is ever unknown during the time period, return // the state with the proper precedence Hstate baseState = PrecedenceForMissingTimePeriods(this); if (baseState != Hstate.Known) { return(new Tnum(baseState)); } // Handle eternal values if (this.IsEternal) { return(this * windowSize); } // Start accumulating... int num = windowSize.ToHardInt; // Get first accumulated value decimal firstVal = 0; for (int j = 0; j < num; j++) { // Don't walk off the end of the timeline if (j < interval.TimeLine.Count) { firstVal += this.AsOf(interval.TimeLine.Keys [j]).ToHardDecimal; } } Tnum result = new Tnum(firstVal); // Iterate through the subsequent intervals decimal previousVal = firstVal; for (int i = 1; i < interval.TimeLine.Count - num; i++) { // Take the value from the last iteration, and slide it the time window to the right, // subtracting the left interval and adding the new right one. decimal lastOldInterval = Convert.ToDecimal(this.ObjectAsOf(interval.TimeLine.Keys[i - 1]).Val); decimal nextNewInterval = Convert.ToDecimal(this.ObjectAsOf(interval.TimeLine.Keys[i + num - 1]).Val); decimal newVal = previousVal - lastOldInterval + nextNewInterval; // Only add changepoint if value actually changes if (newVal != previousVal) { // The value of an interval is counted after it has elapsed result.AddState(interval.TimeLine.Keys[i + num], newVal); } // Set for next iteration previousVal = newVal; } return(result); }
/// <summary> /// Takes a Tnum representing some value per unit time, and accumulates it /// over a given number of successive time intervals. /// </summary> /// <example> /// Calculate income accumulated over a three month period, where the /// person earned $3,000/month: /// /// Income = MonthlyIncome.SlidingSummedIntervals(TheMonth, 3) /// /// The time units cancel: [$/mo.] * [mo.] yields [$]. /// </example> public Tnum SlidingSummedIntervals(Tnum interval, Tnum windowSize) { // TODO: Review how uncertainty is handled here: // Handle unknowns Hstate top = PrecedingState(this.FirstValue, interval.FirstValue, windowSize.FirstValue); if (top != Hstate.Known) return new Tnum(new Hval(null,top)); // If base Tnum is ever unknown during the time period, return // the state with the proper precedence Hstate baseState = PrecedenceForMissingTimePeriods(this); if (baseState != Hstate.Known) return new Tnum(baseState); // Handle eternal values if (this.IsEternal) { return this * windowSize; } // Start accumulating... int num = windowSize.ToHardInt; // Get first accumulated value decimal firstVal = 0; for (int j=0; j<num; j++) { // Don't walk off the end of the timeline if (j < interval.TimeLine.Count) { firstVal += this.AsOf(interval.TimeLine.Keys [j]).ToHardDecimal; } } Tnum result = new Tnum(firstVal); // Iterate through the subsequent intervals decimal previousVal = firstVal; for (int i=1; i < interval.TimeLine.Count-num; i++) { // Take the value from the last iteration, and slide it the time window to the right, // subtracting the left interval and adding the new right one. decimal lastOldInterval = Convert.ToDecimal(this.ObjectAsOf(interval.TimeLine.Keys[i-1]).Val); decimal nextNewInterval = Convert.ToDecimal(this.ObjectAsOf(interval.TimeLine.Keys[i+num-1]).Val); decimal newVal = previousVal - lastOldInterval + nextNewInterval; // Only add changepoint if value actually changes if (newVal != previousVal) { // The value of an interval is counted after it has elapsed result.AddState(interval.TimeLine.Keys[i+num], newVal); } // Set for next iteration previousVal = newVal; } return result; }
/// <summary> /// Returns a Tnum representing the calendar week (by default, a /// 10-year span centered on the start of the current year). /// </summary> /// <remarks> /// See remarks in the CalendarWeek method in the H class. /// </remarks> public static Tnum CalendarWeek(int halfSpanInYears) { Tnum result = new Tnum(); result.AddState(Time.DawnOf, 0); // Get the start date for week 1, n years in the past DateTime d = NthDayOfWeekMonthYear(1, DayOfWeek.Saturday, 1, DateTime.Now.Year-halfSpanInYears); if (d.Day != 1) { d = d.AddDays(-7); } // Mark off each week for (int i=0; i < (halfSpanInYears*106); i++) { result.AddState(d, 0); d = d.AddDays(7); } // Don't apply .Lean because it would defeat the purpose of this object. return result; }
//********************************************************************* // TEMPORAL "RECURRENCE" FUNCTIONS //********************************************************************* /// <summary> /// Loops (cycles) through numbers over time (e.g. 1 2 3 4 1 2 3 4 ...) /// </summary> public static Tnum Recurrence(Tdate startDate, Tdate endDate, IntervalType interval, int min, int max) { // Handle unknowns Hstate top = PrecedingState(startDate.FirstValue, endDate.FirstValue); if (top != Hstate.Known) return new Tnum(new Hval(null,top)); DateTime start = startDate.ToDateTime; DateTime end = endDate.ToDateTime; Tnum result = new Tnum(); if (start != Time.DawnOf) { result.AddState(Time.DawnOf, 0); } DateTime indexDate = start; int indexNumber = min; while (indexDate < end) { result.AddState(indexDate,Convert.ToString(indexNumber)); indexDate = indexDate.AddInterval(interval, 1); // Reset sequence indexNumber++; if (indexNumber > max) { indexNumber = min; } } result.AddState(end, 0); return result; }
public static Tnum IntervalsUntil(Tdate startDate, Tdate endDate, IntervalType interval, int startAt) { // Handle unknowns Hstate top = PrecedingState(startDate.FirstValue, endDate.FirstValue); if (top != Hstate.Known) return new Tnum(new Hval(null,top)); DateTime start = startDate.ToDateTime; DateTime end = endDate.ToDateTime; Tnum result = new Tnum(); DateTime indexDate = end; int indexNumber = startAt-1; while (indexDate > start) { if (indexNumber != startAt-1) { result.AddState(indexDate,Convert.ToString(indexNumber)); } indexNumber++; indexDate = indexDate.SubtractInterval(interval); } result.AddState(Time.DawnOf, 0); result.AddState(start,Convert.ToString(indexNumber)); result.AddState(end, 0); return result; }
/// <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> /// Asserts a given fact (of the proper Tvar type) /// </summary> private static void AssertFact(Factoid f) { // Instantiate relevant Things Thing t1 = f.Arg1.ToString() != "" ? Facts.AddThing(f.Arg1.ToString()) : null; Thing t2 = f.Arg2.ToString() != "" ? Facts.AddThing(f.Arg2.ToString()) : null; Thing t3 = f.Arg3.ToString() != "" ? Facts.AddThing(f.Arg3.ToString()) : null; // Sometimes I have my doubts about static typing... if (f.FactType == "Tbool") { Tbool val = new Tbool(); foreach (TemporalValue v in f.Timeline) { val.AddState(v.Date, new Hval(v.Value)); } Facts.Assert(t1, f.Relationship, t2, t3, val); } else if (f.FactType == "Tnum") { Tnum val = new Tnum(); foreach (TemporalValue v in f.Timeline) { val.AddState(v.Date, new Hval(v.Value)); } Facts.Assert(t1, f.Relationship, t2, t3, val); } else if (f.FactType == "Tstr") { Tstr val = new Tstr(); foreach (TemporalValue v in f.Timeline) { val.AddState(v.Date, new Hval(v.Value)); } Facts.Assert(t1, f.Relationship, t2, t3, val); } else if (f.FactType == "Tdate") { Tdate val = new Tdate(); foreach (TemporalValue v in f.Timeline) { val.AddState(v.Date, new Hval(v.Value)); } Facts.Assert(t1, f.Relationship, t2, t3, val); } else if (f.FactType == "Tset") { Tset val = new Tset(); foreach (TemporalValue v in f.Timeline) { val.AddState(v.Date, new Hval(v.Value)); } Facts.Assert(t1, f.Relationship, t2, t3, val); } }
/// <summary> /// Divides one Tnum by another. /// </summary> public static Tnum operator / (Tnum tn1, Tnum tn2) { Tnum result = new Tnum(); foreach(KeyValuePair<DateTime,List<Hval>> slice in TimePointValues(tn1,tn2)) { Hstate top = PrecedingState(slice.Value); decimal denominator = Convert.ToDecimal(slice.Value[1].Val); if (denominator == 0) // Short circuit 1: Div-by-zero { result.AddState(slice.Key, new Hval(null)); } else if (top != Hstate.Known) // Short circuit 2: Hstates { result.AddState(slice.Key, new Hval(null,top)); } else // Do the math { decimal r = Convert.ToDecimal(slice.Value[0].Val) / denominator; result.AddState(slice.Key, new Hval(r)); } } return result.Lean; }