<jupyter_start><jupyter_text>Bifurcation DiagramIn this notebook, we generate the bifurcation diagram.<jupyter_code>%matplotlib qt
import numpy as np
from TriangleFunctions import *
import math
import matplotlib.pyplot as plt<jupyter_output><empty_output><jupyter_text>Start by looking at triangle code, and determining method to go about it.  I will need to come up with a way to keep iterating until get a point that matches, and then graph all the previous points until the last one that matches.  That is, take all the previous points up until the last one that matches, and compute over them to determine their y value on the graph.  The given set of points will then be paired with an alpha value.  Can geometrically find their y value useing the method in my notebook.  Will also need to start each one on both sides to ensure get all possible points. Data Setup<jupyter_code>def return_iso_points(angle1, right_point):
    """anlge1 is top angle, angle2 is right angle.
    The left point is on origin, the right point is defined by you, the top point is found computationally"""
    
    #find left angle
    angle2 = ((180 - angle1) / 2)
    angle3 = angle2
    
    #define left line, slope and intersection.  Use tan to define slope
    m1 = math.tan(math.radians(angle3))
    b1 = 0
    mb1 = [m1, b1]
    
    #define right line
    m2 = -(math.tan(math.radians(angle2)))
    b2 = newB(m2, right_point)
    mb2 = [m2, b2]
    
    # find out when the line defined by left and right side intersect to get your final point.
    pointT = inter(mb2, mb1)
    
    return (0, 0), pointT, right_point
## want to edit this function.  Add into method the while loop, and iteration step value of the angle.
# need to use return point and feed as input into triangle so as to get initial conditions of the triangle
def orbit_points(startPoint, points):
    """
    startPoint: the point to start the process from within the triangle
    points: the set of points that define the outer triangle
    """
    
    # current point to draw from
    current_point = startPoint
    # track visited points for graphing
    visited_points = []
    indx = 0
    
    # define lines of triangle.  Of form [m, b]
    # bottom line is on x axis so don't have to draw it.
    l1 = findFunc(points[0], points[1])
    l2 = findFunc(points[1], points[2])
    
    # define perpindicular functions.  Returns m'
    lp1 = pFunc(l1[0])
    lp2 = pFunc(l2[0])
    
    # iterate until point is in loop.  When point is in set, get its index
    while True:
        
        if(current_point in visited_points):
            # get indx
            indx = visited_points.index(current_point)
            break
          
        
        visited_points.append(current_point)
        
        # for each perpendicular line, define the exact function that passes through the current point to find next step
        lOne = [lp1, newB(lp1, current_point)]
        inter1 = inter(l1, lOne)
        
        lTwo = [lp2, newB(lp2, current_point)]
        inter2 = inter(l2, lTwo)
        
        # this corresponds to the botton line which lies along the x axis so need a different function rule for it.  
        inter3 = [current_point[0], 0]
        
        dist1 = dist(current_point, inter1)
        dist2 = dist(current_point, inter2)
        #dist3 = dist(current_point, inter3)
        ## NEW CODE
        dist3 = current_point[1]
        
        # use largest to pick the longest distance to travel within triangle
        largest = heapq.nlargest(3, [dist1, dist2, dist3])
        cur_largest = largest[0]
        next_indx = largest.index(cur_largest) + 1
        next_largest = largest[next_indx]
        
        """### NEW CODE UPDATE, AFTER BIF 2, OLD IN RED COMMENTS
        if(cur_largest == dist1):
            current_point = inter1
            
        if(cur_largest == dist2):
            current_point = inter2
            
        if(cur_largest == dist3):
            current_point = inter3"""
        
        
        # prevent program from drawing outside of triangle
        
        while(True):
            if((cur_largest == dist1) and (inter1[1] >= points[1][1])):
                cur_largest = largest[next_indx]
            if((cur_largest == dist2) and (inter2[1] >= points[1][1])):
                cur_largest = largest[next_indx]
            if((cur_largest == dist3) and (inter3[1] >= points[1][1])):
                cur_largest = largest[next_indx]
            else:
                break
        
        # if two distances are the same pick a random one to follow
        if(cur_largest == next_largest):
            # make a random choice between the two
            largest_pick = random.choice([cur_largest, next_largest])

            if(largest_pick == dist1):
                current_point = inter1
                #visited_points.append(current_point)

            if(largest_pick == dist2):
                current_point = inter2
                #visited_points.append(current_point)

            if(largest_pick == dist3):
                current_point = inter3
                #visited_points.append(current_point)
         
        # if all different distances and within rules, move to the new point
        if(cur_largest != next_largest):   
            
            if(cur_largest == dist1):
                current_point = inter1
                #visited_points.append(current_point)
            if(cur_largest == dist2):
                current_point = inter2
                #visited_points.append(current_point)
            if(cur_largest == dist3):
                current_point = inter3
                #visited_points.append(current_point)
                
        
    
    return visited_points, indx
%%time
# test
triangle = return_iso_points(2, [1, 0])
pnts, indx = orbit_points([0, 0], triangle)
#print(pnts), print(indx)<jupyter_output><empty_output><jupyter_text>Generate Data<jupyter_code>np.random.uniform(low=0, high=(1/3))
# setup for loop to get the set
def gen_data(angle_start, angle_step_size):
    points = []
    indices = []
    x_angle = []
    
    num_steps = round((angle_start/angle_step_size))
    
    curr_angle = angle_start
    
    for i in range(0, num_steps):
        
        x_angle.append(curr_angle)
        
        # ADD RANDOM POINT
        rand_pnt = np.random.uniform(low=0, high=(1/3))
        
        triangle = return_iso_points(curr_angle, [(1/3),0])
        
        # START IN MIDDLE TO MAKE UPPER LEVELS WORK
        #pnts, indx = orbit_points([((1/6)-.001), 0], triangle)
        
        ## NEW RANDOM POINT TEST
        pnts, indx = orbit_points([rand_pnt, 0], triangle)
        
        points.append(pnts)
        indices.append(indx)
        
        curr_angle = curr_angle - angle_step_size 
    
    return points, indices, x_angle<jupyter_output><empty_output><jupyter_text>Clean DataBegin by recovering the wanted data points from each set<jupyter_code># get points we care about
def gen_pure_data(points, indices):
    pure_points = []
    for i in range(0, len(indices)):
        curr_indx = indices[i]
        curr_point = points[i]
        
        pp = curr_point[curr_indx:]
        pure_points.append(pp)
    return pure_points
# method get_point_dist will give the edge value of the given point.
def get_y_dist(angle, point):
    #math.sin(x) takes radians, angle comes in degrees
    # math.radians(x) converts from degrees to radians
    
    # construct angle off of alpha, assume angle is alpha
    angle = (180 - angle) / 2
    
    # first get y value of point, as that is what matters:
    h = point[1]
    angle = math.radians(angle)
    dist = h / (math.sin(angle))
    return dist
# for each pure point get distances, will have to simultaneously determine side and add length
# KEEP IN MIND THE INTERVAL LENGTH WE ARE DOING IS 1, SO AXIS IS 3
def pure_dists(pure_points, angle_set):
    scaled_dists = []
    for i in range(0, len(pure_points)):
        curr_pnt = pure_points[i]
        sub_set = []
        for j in range(0, len(curr_pnt)):
            curr_sub_pnt = curr_pnt[j]
            # determine if x or not
            if(curr_sub_pnt[1] == 0):
                pnt = (1/3) + curr_sub_pnt[0]
                sub_set.append(pnt)
                continue
            
            # determine side of axis of point
            # left axis
            # WAS .5
            if(curr_sub_pnt[0] < (1/6)):
                dist = get_y_dist(angle_set[i], curr_sub_pnt)
                pnt = (1/3) - dist
                sub_set.append(pnt)
            # if on right axis    
            if(curr_sub_pnt[0] > (1/6)):
                dist = get_y_dist(angle_set[i], curr_sub_pnt)
                pnt = (2/3) + dist
                sub_set.append(pnt)
                
        scaled_dists.append(sub_set)
    
    return scaled_dists
# reflect points across axis.  Axis is 1.5.
# make into set at end to ensure unique points
def mirror_points(scaled_dists):
    
    axis = .5
    mirrored_dists = []
    
    for i in scaled_dists:
        sub_mirrors = []
        for j in i:
            # first append point, then look at opposite
            sub_mirrors.append(j)
            
            d = abs((axis - j))
            if (j >= axis):
                nd = axis - d
                sub_mirrors.append(nd)
                """if(nd in sub_mirrors):
                    continue
                else:
                    sub_mirrors.append(nd)"""
            if (j < axis):
                nd = axis + d
                sub_mirrors.append(nd)
                """if(nd in sub_mirrors):
                    continue
                else:
                    sub_mirrors.append(nd)"""
        
        mirrored_dists.append(sub_mirrors)     
        
    return mirrored_dists<jupyter_output><empty_output><jupyter_text>Data Demonstration Now we make everything<jupyter_code>%%time
# enter in angle to start at, and step size
points, indices, x_angle = gen_data(150, 0.05)
pure_points = gen_pure_data(points, indices)
dists = pure_dists(pure_points, x_angle)
final_point_set = mirror_points(dists)<jupyter_output><empty_output><jupyter_text>For both possible orientations, mirrored on one another.  To get 180 mark at end, append empy point to final set, and x_angle<jupyter_code>final_point_set.append([])
x_angle.append(180)
# angles is x, final_point_set is y
for xe, ye in zip(x_angle, final_point_set):
    plt.xticks(np.arange(min(x_angle)-.02, max(x_angle)+1, 30))
    plt.yticks(np.arange(0, 1.001, .5))
    plt.scatter([xe] * len(ye), ye, s=.04, color='black')<jupyter_output><empty_output><jupyter_text>Both orientations, no mirroring<jupyter_code>for xe, ye in zip(x_angle, dists):
    plt.xticks(np.arange(min(x_angle)-.01, max(x_angle)+1, 90))
    plt.yticks(np.arange(0, 1.001, .5))
    plt.scatter([xe] * len(ye), ye, s=.09, color='black')<jupyter_output><empty_output><jupyter_text>Note that copied bars are forming at 0 1, 2, 3.The thing giving the jumps is when the orientation is flipped.   flippingMirror image just gives you flipped view, not actual diagram thoughAll kinks worked out, now acts as expected although the same pretty mirror imagery stuff is not going on as in the one above :)<jupyter_code>def gen_data2(angle_start, angle_step_size):
    points = []
    indices = []
    points2 = []
    indices2 = []
    x_angle = []
    
    num_steps = round((angle_start/angle_step_size))
    
    curr_angle = angle_start
    
    for i in range(0, num_steps):
        
        x_angle.append(curr_angle)
        
        triangle = return_iso_points(curr_angle, [4,0])
        
        pnts, indx = orbit_points([(1/12), 0], triangle)
        pnts2, indx2 = orbit_points([(3/12), 0], triangle)
        
        points.append(pnts)
        indices.append(indx)
        points2.append(pnts)
        indices2.append(indx)
        
        curr_angle = curr_angle - angle_step_size 
    
    return points, indices, points2, indices2, x_angle
#COPY
def gen_pure_data2(points, indices, points2, indices2):
    pure_points = []
    for i in range(0, len(indices)):
        curr_indx = indices[i]
        curr_point = points[i]
        
        pp = curr_point[curr_indx:]
        
        curr_indx2 = indices2[i]
        curr_point2 = points2[i]
        
        pp2 = curr_point[curr_indx2:]
        
        ppp = pp + pp2
        
        pure_points.append(ppp)
    return pure_points<jupyter_output><empty_output><jupyter_text>For just one orientation throughout<jupyter_code>%%time
# enter in angle to start at, and step size
points1, indices1, points2, indices2, x_angle = gen_data2(150, 0.1)
pure_points2 = gen_pure_data2(points1, indices1, points2, indices2)
dists2 = pure_dists(pure_points2, x_angle)
for xe, ye in zip(x_angle, dists2):
    plt.xticks(np.arange(min(x_angle)-.1, max(x_angle)+1, 90))
    plt.yticks(np.arange(0, 1.001, .5))
    plt.scatter([xe] * len(ye), ye, s=.1, color='black')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09064981114622678, 'fraction_numerical': 0.01965620904956448, 'mean_word_length': 2.291222729578894, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 42, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '656311', 'license': 'MIT', 'n_tokens_mistral': 4223, 'n_tokens_neox': 4013, 'n_words': 1180, 'path': 'Bifurcation Diagram.ipynb', 'repo_name': 'samgrassi01/Preliminary-n-Rule-Maps-Work', 'size': '12973'}