Ejemplo n.º 1
0
def estimating_yandr(components,upper_bound=100000):
  r_bounds=[[upper_bound,0]]*(len(components[0][0])-2)
  r_list=[]
  y_list=[]
  for box1 in components[0]:
    for box2 in components[1]:
        ft_box1= [d.ftconstructor(Bi[0],Bi[1]) for Bi in box1  ]
        ft_box2= [d.ftconstructor(Bi[0],Bi[1]) for Bi in box2  ]
        
        y_list.append([0.5*(q1+q2) for q1,q2 in zip(ft_box1[2:],ft_box2[2:])])
        norm_q1q2=d.distance(box1[2:],box2[2:])
        norm_q1q2=d.ftconstructor(norm_q1q2[0],norm_q1q2[1])
        q1q2=[ft_box1[i]-ft_box2[i] for i in range(2,len(box1)) ]
        
        r=[ ri/norm_q1q2 for ri in q1q2 ]
        r_list.append(r)
  r=[]
  y=[]
  for i in range(len(y_list[0])):
    yi1=min([float(y[i].lower()) for y in y_list  ])
    yi2=max([float(y[i].upper()) for y in y_list  ])
    y.append([yi1,yi2])
  for i in range(len(r_list[0])):
        ri1=min([float(r[i].lower()) for r in r_list  ])
        ri2=max([float(r[i].upper()) for r in r_list  ])
        r.append([ri1,ri2])
  r=d.boxes_intersection(r,[[-1,1]]*(len(components[0][0])-2))          

  return y+r       
def checking_assumptions(
        curve_data):  #the input of this function is the output of Ball_solver
    if len(curve_data[0][1]) != 0:
        return 0
    Ball_sols_ft = [[d.ftconstructor(Bi[0], Bi[1]) for Bi in B]
                    for B in curve_data[1][0]
                    ] + [[d.ftconstructor(Bi[0], Bi[1]) for Bi in B]
                         for B in curve_data[1][1]]
    alph3 = assum_alph3_checker(Ball_sols_ft)
    if alph3 == 1:
        return 1
    else:
        return 0
Ejemplo n.º 3
0
def detecting_nodes(boxes,B,f,X,eps): #boxes are list of cer and uncer curve
    mixes_boxes= [[1,box ] for box in boxes[0] ] +[[0,box ] for box in boxes[1]] #putting flaggs for cer and uncer boxes
    ftboxes=[ [box[0], [d.ftconstructor(boxi[0],boxi[1])  for boxi in box[1]] ] for box in mixes_boxes ]    
    nodes_lifting=[]
    used=[]
    P=[ Pi.replace("\n","") for Pi in   open(f,"r").readlines()  ]
    for i in range(len(ftboxes)):
        for j in range(i+1,len(ftboxes)):
            Mariam_ft=d.boxes_intersection(ftboxes[i][1],ftboxes[j][1])
            Mariam=[[float(Bi.lower()),float(Bi.upper()) ] for Bi in Mariam_ft]
            if (Mariam ==[] and \
             d.boxes_intersection(ftboxes[i][1][:2],ftboxes[j][1][:2])) or\
               (Mariam != [] and enclosing_curve(f,Mariam,X,eps_max=0.1) ==[[],[]] ): #needs to work more
                if i not in used:
                    used.append(i)
                    nodes_lifting.append(ftboxes[i])
                if j not in used:
                    used.append(j)
                    nodes_lifting.append(ftboxes[j])

    components= planner_connected_compnants(nodes_lifting)
    cer_components=[]
    uncer_components=[]
    component_normal=[]
    for component in components:
        boxes_component=[box[1] for box in component]
        component_normal =[ [[ float(Bi.lower()),  float(Bi.upper()) ] for Bi in box[1] ] for box in component ]
        if 0  not in [ box[0] for box in  component]  and eval_file_gen(f,component_normal,X) =="[]\n" :
            cer_components.append(boxes_component)
        else: 
            uncer_components.append(boxes_component)
    return [cer_components,uncer_components]         
Ejemplo n.º 4
0
def Ball_given_2nboxes(system,X, B1,B2, monotonicity_B1=1,monotonicity_B2=1):
  B1_ft=[d.ftconstructor(Bi[0],Bi[1]) for Bi in B1]
  B2_ft=[d.ftconstructor(Bi[0],Bi[1]) for Bi in B2]
  P=[Pi.replace("\n","") for Pi in  open(system,"r").readlines()]
  sol="Empty"
  if d.boxes_intersection(B1_ft, B2_ft) ==[] and monotonicity_B1== monotonicity_B2==1:
    t=estimating_t([[B1_ft], [B2_ft]])
    y_and_r=estimating_yandr([[B1_ft], [B2_ft]])
    intersec_B1B2_in2d=d.boxes_intersection(B1_ft[:2],B2_ft[:2])
    intersec_B1B2_in2d=[ [float(Bi.lower()),float(Bi.upper())]  for Bi in intersec_B1B2_in2d ]
    B_Ball=intersec_B1B2_in2d +y_and_r +[t]
    Ball_node_gen(system,B_Ball,X)
    os.system("ibexsolve   --eps-max=0.1 -s  eq.txt  > output.txt")
    sol=computing_boxes()
  #if d.boxes_intersection(B1_ft, B2_ft) ==[]:
  #  pass
  return sol  
def Ball_solver(
        equations, B_Ball,
        X):  #the width condition needs to be added  Do not suse this one
    L = [B_Ball]
    certified_boxes = []
    uncertified_boxes = []
    n = len(X)
    while len(L) != 0:
        solvability = 1
        if B_Ball[2*n-2][0] <= 0 <=   B_Ball[2*n-2][1] and \
        d.width([ d.ftconstructor(Bi[0],Bi[1]) for Bi in L[0] ] ) <0.1 :
            Ball_cusp_gen(equations,
                          B_Ball,
                          X,
                          eps_min=eps_min,
                          eps_max=eps_max)
        elif (B_Ball[2*n-2][0] > 0 or 0 >   B_Ball[2*n-2][1] ) \
        and d.width([ d.ftconstructor(Bi[0],Bi[1]) for Bi in L[0] ] ) <0.1:
            Ball_node_gen(equations, B_Ball, X)
        else:
            children = cb.plane_subdivision(L[0])
            L.remove(L[0])
            L += children
            solvability = 0
        if solvability == 1:
            ibex_output = cb.solving_with_ibex()
            if ibex_output[0] == "Empty":

                L.remove(L[0])
            elif len(ibex_output[0]) != 0:

                certified_boxes += cb.computing_boxes(ibex_output[0])
                L.remove(L[0])
            elif len(ibex_output[1]) != 0:

                uncertified_boxes += cb.computing_boxes(ibex_output[1])
                L.remove(L[0])
            else:
                children = cb.plane_subdivision(L[0])
                L.remove(L[0])
                L += children

    return [certified_boxes, uncertified_boxes]
Ejemplo n.º 6
0
def estimating_t(components,upper_bound=19000.8):  #it works only if len(components)==2
  t1=upper_bound
  t2=0
  for box1 in components[0]:
    for box2 in components[1]:
        a=d.distance(box1[2:],box2[2:])
        if t1 > a[0]:
          t1=a[0]
        if t2<a[1]:
           t2=a[1]  
  t=d.ftconstructor(t1,t2)
  t=0.25*d.power_interval(t,2) 
  return [float(t.lower()),float(t.upper())] 
Ejemplo n.º 7
0
def evlist(boxes):
    ftboxes = [[d.ftconstructor(Bi[0], Bi[1]) for Bi in B] for B in boxes]
    n = len(boxes[0])
    m = len(boxes)
    m1 = []
    m2 = []
    for B in ftboxes:
        m1.append(ft.arb(0.0002 * ft.arb.sin(B[2]) * ft.arb.cos(B[2])))
        m2.append(ft.arb(-2 * ft.arb.sin(B[2])**2 * ft.arb.cos(B[2])))
    innrer_loops = [i for i in range(m) if 0 in m1[i] and 0 in m2[i]]
    x1mon = [i for i in range(m) if 0 not in m1[i]]
    x2mon = [i for i in range(m) if 0 in m1[i] and 0 not in m2[i]]
    return [x1mon, x2mon, innrer_loops]
Ejemplo n.º 8
0
def estimating_t1(components,upper_bound=200000):  #it works only if len(components)
  t1=upper_bound
  t2=0
  for box1 in components[0]:
    for box2 in components[1]:
        a=d.distance(box1,box2).lower()
        b=d.distance(box1,box2).upper()
    if t1 > a:
     t1=a 
    if t2<b:
     t2=b 
  t=d.ftconstructor(t1,t2)
  t=0.25*d.power_interval(t,2)     

  return [float(t.lower()),float(t.upper())]     
def eval_func(expr,B): 
 x1=Symbol("x1"  )
 x2=Symbol("x2"  )
 x3=Symbol("x3"  )
 r3=Symbol("r3"  )
 t=Symbol("t"  )
 f=srepr( parse_expr (expr) ) 
 B_f=[ d.ftconstructor(Bi[0],Bi[1]) for Bi in B ]  
 f=f.replace("Symbol('x1')", " B_f[ 0] ")  
 f=f.replace("Symbol('x2')", " B_f[ 1] ")  
 f=f.replace("Symbol('x3')", " B_f[ 2] ")  
 f=f.replace("Symbol('r3')", " B_f[ 3] ")  
 f=f.replace("Symbol('t')", " B_f[ 4] ")  
 f=f.replace("Add","d.sevr_add")
 f=f.replace("Mul","d.sevr_mul")
 f=f.replace("Pow","d.power_interval")
 f=f.replace("Integer","int")
 f=f.replace("Float","float")
 f=f.replace(", precision=53", "")
 return eval(f) 
Ejemplo n.º 10
0
def connected_compnants(boxes):
    ftboxes = [[d.ftconstructor(boxi[0], boxi[1]) for boxi in box]
               for box in boxes]
    components = [[ftboxes[0]]]
    for i in range(1, len(ftboxes)):
        boxi_isused = 0
        for j in range(len(components)):
            membership = 0
            for k in range(len(components[j])):
                if d.boxes_intersection(ftboxes[i], components[j][k]) != []:
                    components[j].append(ftboxes[i])
                    membership = 1
                    boxi_isused = 1
                    break

            if membership == 1:
                break
        if boxi_isused == 0:
            components.append([ftboxes[i]])
    return components
def estimating_t(components):  #it works only if len(components)==2
    uni = d.distance(components[0][0], components[1][0])

    for box1 in components[0]:
        for box2 in components[1]:
            #print(uni);input()
            if d.width(box1[2:]) < 1e-6:
                box1[2:] = [[Bi[0] - 1e-6, Bi[1] + 1e-6] for Bi in box1[2:]]
            if d.width(box2[2:]) < 1e-6:
                box2[2:] = [[Bi[0] - 1e-6, Bi[1] + 1e-6] for Bi in box2[2:]]
            a = d.distance(box1[2:], box2[2:])
            #print(a);input()
            uni = d.box_union([uni], [a])[0]
            """if t1 > a[0]:
          t1=a[0]
        if t2<a[1]:
           t2=a[1]"""
    t = d.ftconstructor(uni[0], uni[1])
    t = 0.25 * d.power_interval(t, 2)
    return [float(t.lower()), float(t.upper())]
Ejemplo n.º 12
0
def enclosing_singularities(system,boxes,B,X,eps_max=0.1,eps_min=0.01, threshold=0.01): #there still computing Ball  On the case where tow monotonic boxes intersect
  #Defining variables######################################
  ##########################################################
  t1=time.time()
  
  tree_size_ball=0
  n=len(B);
  P=[Pi.replace("\n","") for Pi in  open(system,"r").readlines()]
  ##### Computing Ball for nodes 
  Ball_P=[]
  for Pi in P:
    H=SDP_str(Pi,X)
    Ball_P.append(H[0])
    Ball_P.append(H[1])
  last_eq=""
  for i in range(3,n):
        last_eq += "r"+str(i)+"^2+"
  last_eq += "r" +str(n)+"^2 -1=0; \n"
  Ball_P.append(last_eq)
  



  certified_boxes, uncertified_boxes,tree_size_curve= boxes
  time_ball=[] 
  time_combinatorics=[] 
  ## Classifying boxes into x1-monotonous, x2-but-not-x1 monotonous, non-monotonous and non-smooth boxes 
  #####################################################################################################
  com_start=time.time()
  classes= boxes_classifier(system,boxes,X)
  print(len(classes[0]))
  print(len(classes[1]))
  print(len(classes[2]))
  Lcc=[[ci] for ci in  classes[2]]  #Lcc is tended to be the set of connected components
  mon_boxes=classes[0]+classes[1]
  mon_mid=[[0.5*(Bij[1]+Bij[0]) for Bij in Bi[:2] ] for Bi in mon_boxes ]
  mon_rad=[ 2*d.width(Bi[:2]) for Bi in  mon_boxes ]
  tree = spatial.KDTree(mon_mid)
  Kdtree_boxes=[tree.query_ball_point(m,r=(math.sqrt(2))*r ) for m,r in zip(mon_mid,mon_rad)] 
  L=[]
  for i in range(len(Kdtree_boxes)):
    if len(Kdtree_boxes[i]) >3:
      for j in Kdtree_boxes[i]:
        if j not in L:
          L.append(j)


  L0=[i for i in L if i < len(classes[0])]
  L1=[i for i in L if i >= len(classes[0])]

  graph0=np.zeros((len(L0), len(L0)))
  for i in L0:
    
    for j in Kdtree_boxes[i]:
      if   j in L0 and  d.boxes_intersection( mon_boxes[i], mon_boxes[j]) !=[] :
        #nighboured_boxes0[i].append( mon_boxes[j])
        #print(L0.index(i),L0.index(j))
        #print(graph0[L0.index(i)]);input()
        graph0[L0.index(i),L0.index(j)]=1

        
  graph0 = csr_matrix(graph0)
  n_components0, labels0 = connected_components(csgraph=graph0, directed=False, return_labels=True)
  comp_class_0=empty_lists = [ [] for i in range(n_components0) ]
  for i in range(len(L0)):
    #print(comp_class_0)
    comp_class_0[labels0[i]].append(classes[0][L0[i]])
    #print(comp_class_0);input()
  #ploting_boxes(boxes[0],comp_class_0[0]);input()  
  Lcc=Lcc+ comp_class_0 


  if len(classes[1])>0:
   graph1=np.zeros((len(L1), len(L1)))
   for i in L1:
    
    for j in Kdtree_boxes[i]:
      if   j in L1 and  d.boxes_intersection( mon_boxes[i], mon_boxes[j]) !=[] :
        #nighboured_boxes0[i].append( mon_boxes[j])
        #print(L0.index(i),L0.index(j))
        #print(graph0[L0.index(i)]);input()
        graph1[L1.index(i),L1.index(j)]=1     
   graph1 = csr_matrix(graph1)
   n_components1, labels1 = connected_components(csgraph=graph1, directed=False, return_labels=True)
   comp_class_1=empty_lists = [ [] for i in range(n_components1) ]
   for i in range(len(L1)):
    comp_class_1[labels1[i]].append(mon_boxes[L1[i]])


   Lcc=Lcc+ comp_class_1 
  print("Lcc",len(Lcc))


  """intersting_boxes_filtered=[intersting_boxes_filtered[i] for i in range(len(intersting_boxes_filtered)) \
  if i not in intersting_boxes_filtered]
  if len(intersting_boxes_filtered)>0:   
     interesting_boxes_flattened =[]
     for Box_ind in intersting_boxes_filtered :
       for j in Box_ind:
        if j not in interesting_boxes_flattened:
          interesting_boxes_flattened.append(j)  #use a flattening  function in numpy"""
  t2=time.time() 
  print("Comb", t2-t1)
    
  #############################################################################
  #Computing intersting_boxes= {box in boxes[0] with box has at least three neighbors  in 2D}#
  #intersting_boxes is equivalent to L in Marc's Algorithm
  #############################################################################

  """cck1=[mon_boxes[i] for i in   interesting_boxes_flattened if  mon_boxes[i] in classes[k] ]
   if len(classes[k]) !=0:     
     Lcc=Lcc+ connected_compnants(cck)
  
  com_end=time.time()
  time_combinatorics.append(com_end-com_start)"""

  ###############################################################################################################################
  #For every two distinct connected components of Lcc, we check if they intersect in 2D, if so we compute the ball system ans solve it  #
  ################################################################################################################################ 
  Lcf=[Bij for Bi in Lcc for Bij in Bi   ]
  #ploting_boxes(boxes[0],Lcf)
  Solutions=[[],[]] # list of two lists, certified and uncertified solutions
  for c1_index in range(len(Lcc)-1):
    for c2_index in range(c1_index+1,len(Lcc)):
      ball_start=time.time()
      if d.components_intersection(Lcc[c1_index],Lcc[c2_index] ) == True:
        ####################################################################
        ##Now we discuss several cases depending on how far  0 from t is#####
        #################################################################### 
        uni=[]
        for box in Lcc[c1_index]+Lcc[c2_index] :
            uni = d.box_union(uni,box)
        t=estimating_t([Lcc[c1_index],Lcc[c2_index]]); t1 = d.ftconstructor(t[0],t[1]); t=[float(t1.lower()),float(t1.upper())];
        # t is a away from 0
        if t[0]> threshold:
           
           r=[ [float(ri[0]),float(ri[1])] for ri in  estimating_yandr([Lcc[c1_index],Lcc[c2_index]])]
           B_Ball=uni[:2] +r[:] +[t] 
           B_Ball= check_for_pre(B_Ball)
           Ball_generating_system(Ball_P,B_Ball,X,eps_min)
           os.system("ibexsolve   --eps-max="+ str(eps_max)+"  --eps-min="+ str(eps_min) + " -s  eq.txt  > output.txt")
           ibex_output=computing_boxes()
           Sol=ibex_output[:2]
           tree_size_ball += ibex_output[len(ibex_output)-1]
           if Sol[0] != "Empty" and Sol != [[],[]] :
            Solutions[0]=Solutions[0]+Sol[0] 
            Solutions[1]=Solutions[1]+Sol[1]
           elif Sol == [[],[]]   and d.width(uni[:2]) > eps_min:
                new_B=uni
                res=enclosing_curve(system,new_B,X,eps_max=0.1*eps_max, eps_min=eps_min)
                resul=enclosing_singularities(system,res,new_B,X,eps_max=eps_max,eps_min=eps_min)
                Solutions[0] += resul[0]+resul[1] 
                Solutions[1] += resul[2]
                boxes[1] += res[1]
                tree_size_ball += resul[3]
                tree_size_curve +=resul[4]
           elif   Sol == [[],[]]   and d.width(uni[:2]) <= eps_min:   
                Solutions[1].append(B_Ball)


        # t contains 0  
        elif  t[0] <= 0<= t[1]   :
          
          t1=[t[0],threshold]
          B_Ball=uni[:] +[[-1-eps_min,+1+eps_min]]*(n-2) +[t1]
          B_Ball= check_for_pre(B_Ball) 
          res=cusp_Ball_solver(P,B_Ball,X)
          Sol=res[:2]
          tree_size_ball += res[len(res)-1]
          if Sol[0] != "Empty" and Sol !=[[],[]]:
            Solutions[0]=Solutions[0]+Sol[0] 
            Solutions[1]=Solutions[1]+Sol[1] 
          elif Sol == [[],[]]   and d.width(uni[:2]) > eps_min:
                
                new_B=B_Ball[:n]
                res=enclosing_curve(system,new_B,X,eps_max=0.1*eps_max, eps_min=eps_min)
                resul=enclosing_singularities(system,res,new_B,X,eps_max=eps_max,eps_min=eps_min)
                Solutions[0] += resul[0]+resul[1] 
                Solutions[1] += resul[2]
                boxes[1] += res[1]
                tree_size_ball += resul[3]
                tree_size_curve +=resul[4]
          elif   Sol == [[],[]]   and d.width(uni) <= eps_min:   
                Solutions[1].append(B_Ball)

          if t[1] > threshold:
           
           t2=[threshold,t[1]]
           r=[ [float(ri[0]),float(ri[1])] for ri in  estimating_yandr([Lcc[c1_index],Lcc[c2_index]])]
           B_Ball=uni[:2] +r[:n-2]+[[-1-eps_min,+1+eps_min]]*(n-2) +[t2] 
           Ball_generating_system(Ball_P,B_Ball,X,eps_min)
           os.system("ibexsolve   --eps-max="+ str(eps_max)+"  --eps-min="+ str(eps_min) + " -s  eq.txt  > output.txt")
           #input("hi")
           res=computing_boxes()
           Sol=res[:2]
           tree_size_ball += res[len(res)-1]
           if Sol[0] != "Empty" and Sol !=[[],[]]:
            Solutions[0]=Solutions[0]+Sol[0] 
            Solutions[1]=Solutions[1]+Sol[1]
           elif Sol == [[],[]]   and d.width(uni[:2]) > eps_min:
                
                new_B=uni
                res=enclosing_curve(system,new_B,X,eps_max=0.1*eps_max, eps_min=eps_min)
                resul=enclosing_singularities(system,res,new_B,X,eps_max=eps_max,eps_min=eps_min)
                Solutions[0] += resul[0]+resul[1] 
                Solutions[1] += resul[2]
                boxes[1] += res[1]
                tree_size_ball += resul[3]
                tree_size_curve +=resul[4]
           elif   Sol == [[],[]]   and d.width(uni[:2]) <= eps_min:   
                Solutions[1].append(B_Ball)       
      
        # t does not contain 0   but close enough       
        elif t[1]< threshold :
          
          r=[ [float(ri[0]),float(ri[1])] for ri in  estimating_yandr([Lcc[c1_index],Lcc[c2_index]])]
          B_Ball=uni[:2] +r[:] +[t] 
          B_Ball= check_for_pre(B_Ball)
          res=cusp_Ball_solver(P,B_Ball,X)
          Sol=res[:2]
          tree_size_ball += res[len(res)-1]
          if Sol[0] != "Empty" and Sol !=[[],[]]:
            Solutions[0]=Solutions[0]+Sol[0] 
            Solutions[1]=Solutions[1]+Sol[1] 
          elif Sol == [[],[]]   and d.width(uni[:2]) > eps_min:
                new_B=uni
                res=enclosing_curve(system,new_B,X,eps_max=0.1*eps_max, eps_min=eps_min)
                resul=enclosing_singularities(system,res,new_B,X,eps_max=eps_max,eps_min=eps_min)
                Solutions[0] += resul[0]+resul[1] 
                Solutions[1] += resul[2]
                boxes[1] += res[1]
                tree_size_ball += resul[3]
                tree_size_curve +=resul[4]
          elif   Sol == [[],[]]   and d.width(uni[:2]) <= eps_min:   
                Solutions[1].append(B_Ball)  
        
        # if the width of t is larger than threshold, we detect whether there is a small nodes 
               
      ball_end=time.time()
      time_ball.append(ball_end-ball_start)   

  ####################################################################################################
  #Now we have all ball solutions. We check whether all of them satisfy Conditions alpha2 and alpha3 
  ####################################################################################################
  com_start=time.time()
  nodes=[]
  Sols_with_0in_t=[]
  checker=projection_checker(Solutions[0])
  Solutions[1]= Solutions[1] +checker[1]
  Solutions[0]=[Bi for Bi in checker[0] if Bi[2*n-2][1] >= 0   ] 
  for solution in Solutions[0] :
    if 0 >= solution[2*n-2][0] and 0 <= solution[2*n-2][1]:
      Sols_with_0in_t.append(solution)
    else:
      nodes.append(solution) 
  com_end=time.time()
  time_combinatorics.append(com_end-com_start)    
  #print("combinatorics time: ", sum(time_combinatorics))
  print("Ball time: ", sum(time_ball))
  return [nodes,Sols_with_0in_t, Solutions[1], tree_size_ball, tree_size_curve]    
Ejemplo n.º 13
0
def plane_subdivision(B):
  
  ft_B2=d.subdivide([d.ftconstructor(Bi[0],Bi[1]) for Bi in B[:2]])
  normal_B2=[d.ft_normal(Bi)  for Bi in ft_B2]
  return d.cartesian_product(normal_B2,[B[2:]])
Ejemplo n.º 14
0
def normal_subdivision(B):
  ft_B=d.subdivide([d.ftconstructor(Bi[0],Bi[1]) for Bi in B[:]])
  return [d.ft_normal(Bi)  for Bi in ft_B]
Ejemplo n.º 15
0
def enclosing_singularities(system,boxes,B,X,eps_max=0.1,eps_min=0.01): #there still computing Ball  On the case where tow monotonic boxes intersect
  combin=[]
  ball=[]
  start_combin=time.time()
  n=len(B);
  P=[Pi.replace("\n","") for Pi in  open(system,"r").readlines()]
  certified_boxes, uncertified_boxes= boxes
  classes= boxes_classifier(system,boxes,X,special_function=[])
  cer_Solutions=[]
  uncer_Solutions=[]
  H=[]
  #############################################################################
  #Solving Ball for B1 and B2 in R^n such that C is monotonic in B1 and B2
  #######################################################################
  #monotonic_pairs=intersect_in_2D(classes[0],classes[0])
  #monotonic_componants=[ Bi[0] for Bi in  monotonic_pairs ] +[ Bi[1] for Bi in  monotonic_pairs ]
  #Guillaume's suggestion:
  mon_mid=[[0.5*(Bij[1]+Bij[0]) for Bij in Bi[:2] ] for Bi in classes[0] ]
  mon_rad=[ max([0.5*(Bij[1]-Bij[0]) for Bij in Bi[:2] ]) for Bi in classes[0] ]
  tree = spatial.KDTree(mon_mid)
  intersting_boxes=[tree.query_ball_point(m,r=(math.sqrt(2))*r) for m,r in zip(mon_mid,mon_rad)] 
  #Ask Guillaume why this step is needed:
  """for i in range(len(ball)):  
   for j in ball[i]:
      if i not in ball[j]:
         ball[j].append(i)"""

  intersting_boxes=[indi for indi in intersting_boxes if len(indi) >3 ]#and len(connected_compnants([classes[0][i] for i in indi])) >1 ]
  discarded_components=[]
  for i in range(len(intersting_boxes)-1):
    for_i_stop=0
    boxi_set=set(intersting_boxes[i])
    for j in range(i+1,len(intersting_boxes)):
      boxj_set=set(intersting_boxes[j])
      if boxj_set.issubset(boxi_set):
        discarded_components.append(j)
      elif  boxi_set < boxj_set:
        discarded_components.append(i)
  intersting_boxes=[intersting_boxes[i] for i in range(len(intersting_boxes)) \
  if i not in discarded_components] 

  interesting_boxes_flattened =[]
  for Box_ind in intersting_boxes :
       for j in Box_ind:
        if j not in interesting_boxes_flattened:
          interesting_boxes_flattened.append(j)      #use a flattening  function in numpy    

  #ploting_boxes([classes[0][i] for i in interesting_boxes_flattened ],[])
  

  plane_components= planner_connected_compnants([classes[0][i] for i in interesting_boxes_flattened ])
  #pprint(plane_components[0]);input()
  end_combin=time.time()
  combin.append(end_combin-start_combin)
  H=[]
  for plane_component in plane_components:  
      if len(plane_component)>1:
        start_combin=time.time()
        components=connected_compnants(plane_component)
        pairs_of_branches=all_pairs_oflist(components)
        end_combin=time.time()
        combin.append(end_combin-start_combin)
        for pair_branches in  pairs_of_branches:
          start_ball=time.time()
          all_boxes=pair_branches[0]+pair_branches[1]
          uni=[]
          for box in all_boxes:
            uni = d.box_union(uni,box)
          t=estimating_t(pair_branches); t1 = d.ftconstructor(t[0],t[1]); t=[float(t1.lower()),float(t1.upper())];
          r=[ [float(ri[0]),float(ri[1])] for ri in  estimating_yandr(pair_branches)]
          B_Ball=uni[:2] +r +[t] 
          cusp_Ball_solver(P,B_Ball,X)

          #planeappend(B_Ball)  
          #print(B_Ball[:3])
          Ball_generating_system(P,B_Ball,X,eps_min)

          os.system("ibexsolve   --eps-max="+ str(eps_max)+"  --eps-min="+ str(eps_min) + " -s  eq.txt  > output.txt")
          #input("hi")
          Solutions=computing_boxes()
          if Solutions != "Empty" and Solutions != [[],[]] :
            cer_Solutions += Solutions[0]
            uncer_Solutions += Solutions[1]
          if Solutions==[[],[]] :
              if d.width(B_Ball[:2]) > eps_min:
                #new_B=d.box_union(d.F_Ballminus(B_Ball),d.F_Ballplus(B_Ball))
                new_B=B_Ball[:2]+B[2:n]
                new_boxes=enclosing_curve(system,new_B,X,eps_max=0.1*eps_max)
                resul=enclosing_singularities(system,new_boxes,new_B,X,eps_max=0.1*eps_max)
                

                cer_Solutions+= resul[0]+resul[1] 
                uncer_Solutions += resul[2]
                boxes[1] += new_boxes[1]
              else:  
                uncer_Solutions.append(B_Ball)
          end_ball=time.time()
          ball.append(end_ball-start_ball)       
    #There still the case B1B2[0],B1B2[1] are not disjoint 
   ########################################################################################################
   #Solving Ball for potential_cusp, a box in  R^n such that C is not monotonic 
   ########################################################################################################
  start_combin=time.time()
  checked_boxes=[]
  all_boxes=boxes[0]+boxes[1]
  checked_boxes=[]
  mon_mid_cusp=[[0.5*(Bij[1]+Bij[0])  for Bij in Bi[:2] ] for Bi  in classes[1] ]
  mon_rad_cusp=[ max([0.5*(Bij[1]-Bij[0]) for Bij in Bi[:2]]) for Bi in classes[1] ]
  potential_cusps=[tree.query_ball_point(m,r=(math.sqrt(2)*(r+eps_max))) for m,r in zip(mon_mid_cusp,mon_rad_cusp)]
  end_combin=time.time()
  combin.append(end_combin-start_combin)
  for  cusp_indx in range(len(classes[1])):
    start_combin=time.time()
    intersecting_boxes=[all_boxes[i] for i in potential_cusps[cusp_indx]\
    if d.boxes_intersection(all_boxes[i],classes[1][cusp_indx])!=[] ] #contains all boxes that intersect the considered potential_cusp 
    
  #for potential_cusp in classes[1]:
    ###finding cusps (or small loops) in potential_cusp####
    
    #plane_intersecting_boxes= intersect_in_2D([potential_cusp],classes[0]+classes[1]+classes[2],monotonicity=0)
    #intersecting_boxes= [pair_i[1] for pair_i in plane_intersecting_boxes \
    # if  d.boxes_intersection(pair_i[1], potential_cusp)!=[] ]     
    
    ##########
    
    H=[]
    uni= classes[1][cusp_indx][:]
    potential_cusp= classes[1][cusp_indx][:]
    checked_boxes.append(potential_cusp)
    for box in intersecting_boxes:
     if box in checked_boxes:
      continue
     uni = d.box_union(uni,box)
     checked_boxes.append(box)
    end_combin=time.time()
    combin.append(end_combin-start_combin) 
    #max_q1q2=d.distance(uni[2:],uni[2:])
    #max_q1q2=d.ftconstructor(max_q1q2[0],max_q1q2[1])
    #t=d.power_interval(max_q1q2,2)/4
    #t=[float(t.lower()),float(t.upper())]
    #if t[0]<0:
    # t[0]=-0.1
    start_ball=time.time()
    t=estimating_t([[potential_cusp],[potential_cusp]])
    """if t[1]-t[0] < 1e-07:
            t[0]=t[0]-0.5 * eps_min
            t[1]=t[1]+0.5 * eps_min"""
    B_Ball=uni +[[-1.01,1.01]]*(n-2)+[t]
    H.append(B_Ball)
  
    sol=cusp_Ball_solver(P,B_Ball,X)
    if sol != "Empty" and sol != [[],[]]:
         cer_Solutions += sol[0]
         uncer_Solutions += sol[1]
    if sol == [[],[]]:
              uncer_Solutions.append(B_Ball) 
    end_ball=time.time() 
    ball.append(end_ball-start_ball)   
    ####finding nodes that have the same projection with potential_cusp
    start_combin=time.time()
    non_intersecting_boxes=[all_boxes[i] for i in potential_cusps[cusp_indx]\
    if d.boxes_intersection(all_boxes[i],classes[1][cusp_indx])==[] ] #contains all boxes that don't intersect the considered potential_cusp but in 2d
    #non_intersecting_boxes= [pair_i[1] for pair_i in plane_intersecting_boxes \
    # if  d.boxes_intersection(pair_i[1], potential_cusp)==[] ] 
    end_combin=time.time()
    combin.append(end_combin-start_combin)
    for aligned in non_intersecting_boxes:
      start_ball=time.time()
      if aligned  in checked_boxes:
        continue
      boxes_intersect_aligned=[B  for B in non_intersecting_boxes if d.boxes_intersection(aligned,B) != []  ]
      uni=aligned[:]
      for boxi  in boxes_intersect_aligned:
          if boxi in checked_boxes:
            continue
          uni=d.box_union(uni,boxi)
          checked_boxes.append(boxi)
      t=estimating_t([[potential_cusp],[uni]])
      """if t[1]-t[0] < 1e-07:
            t[0]=t[0]-0.5 * eps_min
            t[1]=t[1]+0.5 * eps_min"""
      r=[ [float(ri[0]),float(ri[1])] for ri in  estimating_yandr([[potential_cusp],[uni]])]
      B_Ball=potential_cusp[:2]+r +[t]  
      H.append(H)    
      Ball_generating_system(P,B_Ball,X)
      os.system("ibexsolve   --eps-max="+ str(eps_max)+"  --eps-min="+ str(eps_min) + " -s  eq.txt  > output.txt")
      Solutions=computing_boxes()
      if Solutions != "Empty":
          cer_Solutions += Solutions[0]
          uncer_Solutions += Solutions[1] 
      elif Solutions == [[],[]]:
              uncer_Solutions.append(B_Ball)                  
      end_ball=time.time()
      ball.append(end_ball-start_ball)  
  nodes=[]
  cups_or_smallnodes=[]
  start_combin=time.time()
  checker=projection_checker(cer_Solutions)
  uncer_Solutions= uncer_Solutions +checker[1]
  cer_Solutions=[Bi for Bi in checker[0] if Bi[2*n-2][1] >= 0   ] 
  for solution in cer_Solutions :
    if 0 >= solution[2*n-2][0] and 0 <= solution[2*n-2][1]:
      cups_or_smallnodes.append(solution)
    else:
      nodes.append(solution) 
  end_combin=time.time()
  combin.append(end_combin-start_combin)
  print("KDtree ",sum(combin),"Ball ", sum(ball) )    
  return [nodes,cups_or_smallnodes, uncer_Solutions ]