Ascher Pendant Subsidiarys & Their Neighbors


1. A Pendant & its Subsidiary & its Relation to its Neighbor.

AS029 has a property that relates adjacent pendants to their neighbor and their neighbor’s subsidiary.

In group 1, wherever the pendant value is larger than its subsidiary’s value, the difference is the value of another pendant in the group. That is:

\(P_{i}-P_{i,s1}=P_{j}\;\;for\;(i,j)\;=\;(5,4),\;(7,8),\;(9,10),\;(10,4)\)
By contrast, in group 8, whenever the pendant value is smaller than its subsidiary’ s value, the difference is the value of another pendant in the group. Namely,

\(P_{i,s1}-P_{i}=P_{j}\;\;for\;(i,j)\;=\;(1,2),\;(2,1),\;(4,1)\)
Why this odd type of double book-keeping instead of just 10 cords, or using cords to indicate debt instead? It’s as if the khipukamayoq said “You owe the emperor 100 pieces of silver. Ayllu (Region) 1 paid 20, leaving 90 of which Ayllu 2 paid 10, leaving 80…. etc.

2. Search Criteria:

We can see which khipus have interesting pendant-subsidiary-neighbor relationships. The key routine is excerpted below. Note that unlike Ascher, I only investigate the nearest neighbor, not all neighbors.

Code
def pendant_subsidiary_neighbor_relations(self):
    # Is a valid candidate if group has subsidiaries, and it's a non-zero cord.
    def neighbor_match(anIndex):
        pendant_cord = self.pendant_cords()[anIndex]
        if len(pendant_cord.subsidiary_cords()) == 0: 
            return False

        left_cord = self.pendant_cords()[anIndex - 1] if anIndex > 0 else None
        right_cord = self.pendant_cords() [anIndex + 1] if anIndex < self.num_cords() - 1 else None
        # Ascher assumes only one subsidiary cord. We'll assume sum of all subs...
        # sum_subs = sum([aCord.knotted_value() for aCord in self.subsidiary_cords()[0]])
        sum_subs = pendant_cord.subsidiary_sum()

        # Drop cases where value of something is 0 (i.e p1=5 - p1s1=0 == p2)
        valid_pendant_sub =  (pendant_cord.knotted_value() != 0) and (sum_subs != 0)
        valid_left_cord = valid_pendant_sub and (left_cord is not None) and (left_cord.knotted_value() != 0)
        valid_right_cord = valid_pendant_sub and (right_cord is not None) and (right_cord.knotted_value() != 0)
        
        left_minus_match = valid_left_cord and (left_cord.knotted_value() == abs(pendant_cord.knotted_value() - sum_subs))
        left_sum_match =  valid_left_cord and (left_cord.knotted_value() == pendant_cord.knotted_value() + sum_subs)
        right_minus_match = valid_right_cord and (right_cord.knotted_value() == abs(pendant_cord.knotted_value() - sum_subs))
        right_sum_match =  valid_right_cord and (right_cord.knotted_value() == pendant_cord.knotted_value() + sum_subs)

        if left_minus_match:
            match = (pendant_cord, left_cord, -sum_subs)
        elif right_minus_match:
            match = (pendant_cord, right_cord, -sum_subs)
        elif left_sum_match:
            match = (pendant_cord, left_cord, sum_subs)
        elif right_sum_match:
            match = (pendant_cord, right_cord, sum_subs)
        else:
            match = (None, None, 0)

        return match

    (left_matches, right_matches) = ([], [])
    for anIndex, aCord in enumerate(self.pendant_cords()):
        valid_candidate = (aCord.num_subsidiary_cords()>0) and (aCord.knotted_value() > 0)
        if valid_candidate:
            (pendant_sub_cord, neighbor_cord, sub_sum) = neighbor_match(anIndex)
            if pendant_sub_cord and neighbor_cord:
                handedness = -(pendant_sub_cord.pendant_index()-neighbor_cord.pendant_index())
                if handedness < 0:
                    left_matches.append((pendant_sub_cord, neighbor_cord, sub_sum, handedness))
                else:
                    right_matches.append((pendant_sub_cord, neighbor_cord, sub_sum, handedness))

    return (left_matches, right_matches)
<Figure size 6000x3000 with 0 Axes>

3. Significance Criteria:

Significance is defined as the khipu having than 1 occurrence the fieldmark.

4. Summary Results:

Measure Result
Number of Khipus That Match 145 (22%)
Number of Significant Khipus 77 (12%)
Five most Significant Khipu UR016, UR198, UR003, UR093, UR169
Image Quilt Click here
Database View Click here

5. Summary Charts:

Code
# Initialize plotly
plotly.offline.init_notebook_mode(connected = False);

# Read in the Fieldmark and its associated dataframe and match dictionary
from fieldmark_ascher_pendant_sub_neighbor import Fieldmark_Ascher_Pendant_Sub_Neighbor
aFieldmark = Fieldmark_Ascher_Pendant_Sub_Neighbor()
fieldmark_dataframe = aFieldmark.dataframes[0].dataframe
raw_match_dict = aFieldmark.raw_match_dict()
Code
# Plot Matching khipu
matching_khipus = aFieldmark.matching_khipus() 
matching_values = [raw_match_dict[aKhipuName] for aKhipuName in matching_khipus]
matching_df =  pd.DataFrame(list(zip(matching_khipus, matching_values)), columns =['KhipuName', 'Value'])
fig = px.bar(matching_df, x='KhipuName', y='Value', labels={"KhipuName": "Khipu Name", "Value": "Count of Pendant Subsidiary Difference Sums", }, 
            title=f"Matching Khipu ({len(matching_khipus)}) for Pendant Subsidiary Difference",  width=944, height=450).update_layout(showlegend=True).show()
Code
# Plot Significant khipu
significant_khipu_names = aFieldmark.significant_khipus()
significant_values = [raw_match_dict[aKhipuName] for aKhipuName in significant_khipu_names]
significant_df =  pd.DataFrame(list(zip(significant_khipu_names, significant_values)), columns =['KhipuName', 'Value'])
fig = px.bar(significant_df, x='KhipuName', y='Value', labels={"KhipuName": "Khipu Name", "Value": "Pendant Subsidiary Difference", },
             title=f"Significant Khipu ({len(significant_khipu_names)}) for Pendant Subsidiary Difference", width=944, height=450).update_layout(showlegend=True).show()

6. Exploratory Data Analysis

6.1 Review by Size and Handedness

When viewing the dataframe viewer for this relationship, it becomes clear that most of the subsidiary sums are small. Let’s examine that.

Code
from khipu import Khipu
(khipu_dict, all_khipus) = kamayuq.fetch_khipus()

psn_relations_df = aFieldmark.dataframes[1].dataframe
def handed_color(x): return 0.0 if x < 0 else 1.0
psn_relations_df['handed_color'] = [handed_color(x) for x in psn_relations_df.handedness.values]
num_psn_relations = len(psn_relations_df)

fig = px.scatter(psn_relations_df, x="pendant_value", y="pendant_sub_sum", 
                 size=list(abs(psn_relations_df.pendant_sub_sum.values)),
                 color='handed_color', color_continuous_scale=['#3c3fff', '#ff3030'],
                 labels={"pendant_value": "Pendant cord value", 
                         "pendant_sub_sum": "Sum of Pendant's Subsidiaries"},
                 hover_data=['name'], 
                 title="<b>Pendant-Sub Neighbors by Pendant/Sub Value</b> - <i style=\"font-size:10pt;\">Size=Σ(Subsidiaries) Red:Right-handed, Blue:Left-handed</i>",
                 width=944, height=944)\
        .update_layout(showlegend=False).update(layout_coloraxis_showscale=False).show()

Two things become apparent. First there are more subtraction’s than add’s between pendants, their subsidiary sums, and their neighbors. Secondly, most of the deltas (the sum of subsidiaries) appear to be small.

Code
def trivial_pct(diff_val): 
    return round(float((num_trivial_cords(diff_val))/float(num_psn_relations))*100.0)
def num_trivial_cords(diff_val): 
    return len(psn_relations_df[psn_relations_df['pendant_sub_sum'].abs()<= diff_val])
def print_trivial_cord_info(diff_val): 
    print(f"{num_trivial_cords(diff_val)}/{num_psn_relations}  ({trivial_pct(diff_val)}%) trivial pendant-sub neighbor relations with subsidiary sum <={diff_val}")

print_trivial_cord_info(50)
print_trivial_cord_info(25)
print_trivial_cord_info(10)
print_trivial_cord_info(2)

num_KFG_pendant_cords = sum([aKhipu.num_pendant_cords() for aKhipu in all_khipus])
print(f"There are {num_psn_relations}/{num_KFG_pendant_cords} ({round(float(num_psn_relations)/float(num_KFG_pendant_cords)*100.0,2)}%) pendant_sub neighbors out of all KFG pendant cords")
258/267  (97%) trivial pendant-sub neighbor relations with subsidiary sum <=50
251/267  (94%) trivial pendant-sub neighbor relations with subsidiary sum <=25
227/267  (85%) trivial pendant-sub neighbor relations with subsidiary sum <=10
136/267  (51%) trivial pendant-sub neighbor relations with subsidiary sum <=2
There are 267/41737 (0.64%) pendant_sub neighbors out of all KFG pendant cords

So 51% of these relationships have a delta of 2 or less. Less then 0.64% of all pendant cords in the KFG have this relationship. Not very encouraging…

Code
import math
def sign(x): return -1.0 if x < 0 else 1.0
psn_relations_df['log_pendant_sub_sum'] = [sign(x)*math.log(abs(x)) for x in psn_relations_df.pendant_sub_sum.values.tolist()]
fig = (px.violin(psn_relations_df, 
                y="log_pendant_sub_sum", x="handedness",
                points='all',
                title="Subsidiary Sum Value, by Frequency - <i style=\"font-size:10pt;\">Left-Handed on left, Right-Handed on Right</i>",
                width=944, height=944).show())

6.2 Review by Location

Where do the groups appear on a khipu? We can graph them with a simple text string. Such a simple display shows that these groups frequently group together.

Code
def group_string_val(agroup): return "!"  if agroup.is_pendant_subsidiary_neighbor_relationship() else "."
significant_khipus = [khipu_dict[khipu_name] for khipu_name in aFieldmark.significant_khipus()]
significant_khipus.sort(key=lambda aKhipu: aKhipu.num_cord_groups()*100 + aKhipu.num_pendant_subsidiary_neighbor_relation_groups())
significant_khipus.reverse()
for aKhipu in significant_khipus:
    string_rep = "".join([group_string_val(agroup) for agroup in aKhipu.cord_groups()])
    khipu_name = "{placeholder:<15}".format(placeholder=aKhipu.name())
    cc_description = "{:02d}".format(aKhipu.num_pendant_subsidiary_neighbor_relation_groups()) + "_" + \
                     "{:02d}".format(aKhipu.num_pendant_subsidiary_neighbor_relation_cords())
    print (f"{khipu_name} {cc_description} : {string_rep}")
UR1032          02_02 : .............!..........................................................................!...................
UR006           04_05 : ..!..!................!.........!..............................
UR087           06_07 : !.........!.......!......!...!.!........................
UR001           02_02 : ..!!............................................
UR1175          02_02 : ..!.......................................!..
UR195           02_07 : .......................!!...................
UR198           12_13 : ....!..!..!.......!..!.!!!!!........!!..
MM019           02_02 : .!.....!...............................
UR034           03_03 : .............!...................!!...
UR045           02_02 : ......!.............!.................
UR113           05_05 : .!..!.!!..!....................
UR022           03_03 : .!!...................!........
QU015           03_03 : ...........!......!!..........
QU019           02_06 : ............!.......!.........
AS044           03_03 : ................!.!...!.....
UR1176          02_02 : ........!......!..........
UR1126          03_05 : !.............!.......!..
UR1088          03_05 : ...!..!.....!............
QU007           03_03 : ....!........!...!.....
AS128           01_02 : ......!................
UR190           05_09 : .....!........!.!!!...
UR1136          06_07 : .!!.!....!.!........!
QU021           04_04 : ..........!...!!!....
UR1166          02_02 : .!...........!.......
UR009           02_03 : ...!..........!......
UR235           05_07 : ....!..!....!..!.!
UR1131          04_04 : !...........!!!...
MM021           02_02 : ..........!!......
UR1034          01_02 : ............!.....
QU009           04_05 : ....!....!...!.!
KH0227          03_04 : !..!...!........
UR114           03_05 : ...!!........!..
UR007           02_02 : ...........!!...
UR003           06_11 : ..!.!!!.!...!..
AS029           02_05 : !......!......
AS212           06_07 : ...!!!.!.!.!.
AS026B          04_09 : ...!.!.....!!
QU012           02_08 : ......!.....!
UR093           06_10 : ..!..!!.!!!.
AS048           03_05 : !.....!....!
UR131B          02_02 : .........!!.
AS005           04_04 : ....!.!!.!.
KH0058          04_06 : !!..!!....
UR1095          02_02 : ..!.!.....
UR002           02_03 : ....!.!...
UR222           01_03 : ...!......
UR089           02_06 : ....!...!
UR196           01_06 : ......!..
UR169           07_10 : !!!!!!!.
UR116A          04_09 : .!!!!...
UR028           02_03 : ..!....!
AS159           02_04 : ..!..!..
UR029           06_09 : .!!!!!!
AS186           05_07 : !!.!.!!
UR016           03_25 : ..!!.!.
UR238           03_06 : ..!!!.
UR189           03_08 : ..!!!.
UR193           01_02 : ...!..
UR053E          04_06 : !!!!
UR1151          02_03 : .!!.
UR057           02_05 : ..!!
UR194           01_02 : !...
UR1052          01_02 : .!..
UR1049          03_08 : !!!
AS201           02_02 : .!!
UR091           02_06 : !!.
QU004           01_02 : .!.
UR137           01_02 : !..
AS153           01_02 : ..!
AS111           01_02 : .!.
AS061/MA036     01_03 : ..!
UR215           01_07 : !..
UR023           02_03 : !!
AS017           02_04 : !!
AS011           01_03 : !.
UR1130          01_05 : .!
UR177           01_03 : !

Interesting. This distribution is not at all like the decreasing cord group distribution. Grouping groups are the exception, not the rule…the outlier exceptions being our two previously mentioned friends UR169 and UR029.

6.3 Are these relationships accidental?

A view of the actual pendant-sub neighbor cords is helpful when examing this relationship.

51% of pendant-sub neighbor relationships have a delta of 2 or less. Less then 0.64% of all pendant cords in the KFG have this relationship. On the other hand an examination of the outlier, UR142 is interesting. Here cord p3:352 = p2:34 + it’s subsidiaries. This is clearly not accidental. The next outlier UR131B seems intentional, but only vaguely. Similarly for AS101-Part 1. As an alternative argument, let’s look at UR016, with 25 sums. A review of the actual sums, shows that most of them are 1, or -1. While these pendant-sum neighbor relationships do appear, and they do appear to be intentional, they seem quite rare, and localized.

7. Conclusion

The pendant_subsidiary_neighbor relationship seems likely to be a fluke. Occuring 0.64% of the time, and even less, when the pendant-subsidiary difference is >= 3 (0.3%), I’m inclined to write off this relationship as a statistical fluke, masquerading as a relationship, and not an intentional writing/recitation design strategy. A good decipherer never says “never.” They say “maybe.” Maybe there’s something here, but I can’t see it.