<jupyter_start><jupyter_text>Integrating Time Points and Time Intervals<jupyter_code>import qualreas as qr<jupyter_output><empty_output><jupyter_text>References * Allen, <NAME>. (26 November 1983). "Maintaining knowledge about temporal intervals". Communications of the ACM. 26 (11): 832–843.    * [PDF](http://cse.unl.edu/~choueiry/Documents/Allen-CACM1983.pdf)* Reich, <NAME>. (1994). “Intervals, Points, and Branching Time.” 121-133.    * Published in TIME 1994: An International Workshop on Temporal Representation and Reasoning.    * ABSTRACT. This paper extends Allen's interval algebra to include points and either left or right-branching time. The branching time algebras each contain 24 relations: Allen's original 13 relations, 5 more relations resulting from the inclusion of points, and 6 relations because of the inclusion of branching time. The paper also presents: (1) A technique for automatically deriving algebras of relations; (2) a way of representing temporal constraint networks using constraint matrices; and (3) a way of performing constraint propagation using constraint matrix multiplication.    * PDFs are available at the following locations:        * [ResearchGate](https://www.researchgate.net/publication/220810644_Intervals_Points_and_Branching_Time) (Includes a supplementary file containing algebras in structured text form.)        * [SemanticScholar](https://www.semanticscholar.org/paper/Intervals%2C-Points%2C-and-Branching-Time-Reich/a12eca974573c812d696f3d0a58bccb171a8c39d)        * [Time-94](http://www2.cs.uregina.ca/~temporal/time94/reich.pdf)  An Interval & Point Algebra Allen's original algebra of time pertains only to proper intervals.  That is, the domains and ranges of each of his 13 relations are proper time intervals.  Degenerate intervals (i.e., time points) are not permitted.The Interval & Point algebra, described in [Reich 1994] and illustrated in this notebook, extends Allen's algebra by adding 5 new relations and modifying the domains and ranges of the relations to include, not only proper intervals, but also time points (i.e., degenerate intervals).Each of the 5 new relations have something to do with time points and so their abbreviated name starts with the letter 'P'.<jupyter_code>import os
path = os.path.join(os.getenv('PYPROJ'), 'qualreas/Algebras')
allenX = qr.Algebra(os.path.join(path, 'Extended_Linear_Interval_Algebra.json'))
allenX.elements<jupyter_output><empty_output><jupyter_text>Of Allen's original 13 relations, 9 stay the same here with respect to their domains and ranges (that is, they apply to proper intervals only), 4 have their domain, range, or both modified, and 5 are entirely new.  See the last two columns of the table in the next cell, below.<jupyter_code>allenX.summary()<jupyter_output>Algebra Name: Extended_Linear_Interval_Algebra
   Description: Extension of Allen's algebra to include points and intervals
 Equality Rels: E|PE
     Relations:
            NAME (SYMBOL)         CONVERSE (ABBREV)  REFLEXIVE  SYMMETRIC TRANSITIVE   DOMAIN        RANGE
             Before (  B)               After ( BI)    False      False       True    Pt|PInt       Pt|PInt
              After ( BI)              Before (  B)    False      False       True    Pt|PInt       Pt|PInt
             During (  D)            Contains ( DI)    False      False       True    Pt|PInt          PInt
           Contains ( DI)              During (  D)    False      False       True       PInt       Pt|PInt
             Equals (  E)              Equals (  E)     True       True       True       PInt          PInt
           Finishes (  F)         Finished-by ( FI)    False      False       True       PInt          PInt
        Finished-by ( FI)            Finishes (  F)    False      False       True[...]<jupyter_text>Create the singleton relation sets, {Before} and {Met-By} for this algebra and compute their product. Comparing this to the same calculation for Allen's algebra (previous notebook) we see that an additional relation, PS, appears in the resulting relset.<jupyter_code>B = allenX.relset(["B"])
MI = allenX.relset(["MI"])
BxMI = allenX.compose(B, MI)
print(BxMI)<jupyter_output>B|D|M|O|PS|S<jupyter_text>Multiplication is Still Not Commutative<jupyter_code>MIxB = allenX.compose(MI, B)
print(f"MI x B = {MIxB}")

BxMI = allenX.compose(B, MI)
print(f"B x MI = {BxMI}")

print(f"MI x B == B x MI ? {MIxB == BxMI}")
F = allenX.relset(["F"])

MIxF = allenX.compose(MI, F)
print(f"MI x F = {MIxF}")

FxMI = allenX.compose(F, MI)
print(f"F x MI = {FxMI}")

print(f"MI x F == F x MI ? {MIxF == FxMI}")<jupyter_output>MI x F = MI
F x MI = BI
MI x F == F x MI ? False<jupyter_text>Equality Relations Allen's algebra has only one identity element, E, because it deals with only one class of temporal entity, the proper interval.The Interval and Point Algebra, on the other hand, deals with two types of temporal entities, and so it has an equality relation for each one, intervals and points.  Note that intervals here can be degenerate (i.e., equivalent to a point).  This means that the relation E in Allen's algebra is not quite the same as the relation E in the Interval and Point Algebra, since the latter handles degenerate intervals, whereas the former only applies to proper intervalsThe equality relations of an algebra are important when propagating contraints, so there is an Algebra property that returns a list of its equality relations:<jupyter_code>print(f"The Interval & Point Algebra's equality relations: {allenX.all_equality_relations}")<jupyter_output>The Interval & Point Algebra's equality relations: E|PE<jupyter_text>Associativity  Example: {PS} x {B} x {D} Associativity does not hold for this example as shown below:<jupyter_code>PS = allenX.relset(["PS"])
B = allenX.relset(["B"])
D = allenX.relset(["D"])
PSxB = allenX.compose(PS,B)
print(f"({PS} * {B}) * {D}")
print(f"= {PSxB} * {D}")
print(f"= {allenX.compose(PSxB, D)}")

BxD = allenX.compose(B, D)
print(f"\n{PS} * ({B} * {D})")
print(f"= {PS} * {BxD}")
print(f"= {allenX.compose(PS, BxD)}")<jupyter_output>(PS * B) * D
= B * D
= B|D|M|O|PS|S

PS * (B * D)
= PS * B|D|M|O|PS|S
= B|D|PS<jupyter_text>So, What's Going on with Associativity? ...add an explanation about domains & ranges here...<jupyter_code>print(allenX.rel_domain('PS'))<jupyter_output>['Point']<jupyter_text>...finish this thought...  Some Scratch Work... Let's examine associativity for $B*D*OI$ B and D were defined earlier in this notebook:<jupyter_code>OI = allenX.relset(["OI"])
print(OI)
BxD = B * D
DxOI = D * OI<jupyter_output><empty_output><jupyter_text>$(B * D) * OI$ = The 13 Allen-like relation_lookup together with {PF, PS}<jupyter_code>BxD_x_OI = BxD * OI
BxD_x_OI
#print(BxD_x_OI.sorted_list())<jupyter_output><empty_output><jupyter_text>$B * (D * OI)$ = All 18 of the algebra's relation_lookup<jupyter_code>B_x_DxOI = B * DxOI
print B_x_DxOI.sorted_list()<jupyter_output><empty_output><jupyter_text>So, clearly, $(B * D) * OI \ne B * (D * OI).$ Let's examine the domains and ranges involved.<jupyter_code>print alg.relation_lookup['B'].domain
print alg.relation_lookup['B'].range
print alg.relation_lookup['D'].domain
print alg.relation_lookup['D'].range
print alg.relation_lookup['OI'].domain
print alg.relation_lookup['OI'].range<jupyter_output><empty_output><jupyter_text>So, chaining these together in terms of domains and ranges is:$(Int,Int) * (Int,PInt) * (PInt,PInt) = (Int, PInt)$,where $Int = \{PInt, Pt\}$<jupyter_code>B*D<jupyter_output><empty_output><jupyter_text>Now, if W, X, Y, and Z are time intervals, such that W {B} X, X {D} Y, and Y {OI} Z, then...1. In what possible ways does W relate to Y?1. In what possible ways does X relate to Z? To answer these questions, first look at B*D:<jupyter_code>print "%s:\n" % BxD
for rel in B*D:
    print "%s has domain %s" % (rel, list(rel.domain))
print "%s:\n" % BxD
for rel in B*D:
    print "%s has range %s" % (rel, list(rel.range))
W = qr.TemporalObject(['ProperInterval', 'Point'], 'W')
X = qr.TemporalObject(['ProperInterval', 'Point'], 'X')
Y = qr.TemporalObject(['ProperInterval'], 'Y')
Z = qr.TemporalObject(['ProperInterval'], 'Z')
print W
print X
print Y
print Z
net_BxDxOI = qr.Network(alg, "BxDxOI")
print net_BxDxOI<jupyter_output><empty_output><jupyter_text>Assume W, X, Y, and Z are time intervals, such that W {B} X, X {D} Y, and Y {OI} Z<jupyter_code>rel_B  = alg.relation_lookup['B']
rel_D  = alg.relation_lookup['D']
rel_OI = alg.relation_lookup['OI']
net_BxDxOI.constraint(W, X, [rel_B])
net_BxDxOI.constraint(X, Y, [rel_D])
net_BxDxOI.constraint(Y, Z, [rel_OI])
print net_BxDxOI
net_BxDxOI.print_constraints()
net_BxDxOI.propagate()
net_BxDxOI.print_constraints()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1140501545860529, 'fraction_numerical': 0.011679835108210237, 'mean_word_length': 4.2614457831325305, 'pattern_counts': {'":': 0, '<': 57, '<?xml version=': 0, '>': 57, 'https://': 2, 'lorem ipsum': 0, 'www.': 3, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '15', 'dir': 'jupyter-structured-clean-dedup', 'id': '133310', 'license': 'MIT', 'n_tokens_mistral': 3055, 'n_tokens_neox': 2907, 'n_words': 944, 'path': 'Notebooks/Obsolete_Maybe/nb1_Integrating_Points_and_Intervals.ipynb', 'repo_name': 'alreich/qualreas', 'size': '8736'}