




class        UpperCamelCase_					:

    '''simple docstring'''






    def __init__(    self   :			str      ,				UpperCAmelCase__   :			int      ,				UpperCAmelCase__   :			List[str]=None      ,				UpperCAmelCase__   :			int=None)		->str:





           '''simple docstring'''

           A__   				=					data
           A__   				=					previous
           A__   				=					next_node


    def __str__(    self   :			List[str])		->str:





           '''simple docstring'''

           return f"""{self.data}"""


    def  SCREAMING_SNAKE_CASE							(    self   :			List[str])		->int:





           '''simple docstring'''

           return self.data


    def  SCREAMING_SNAKE_CASE							(    self   :			Union[str, Any])		->List[str]:





           '''simple docstring'''

           return self.next





    def  SCREAMING_SNAKE_CASE							(    self   :			Optional[int])		->Any:





           '''simple docstring'''

           return self.previous



class        UpperCamelCase_					:

    '''simple docstring'''






    def __init__(    self   :			Dict      ,				UpperCAmelCase__   :			int)		->List[str]:





           '''simple docstring'''

           A__   				=					head


    def __iter__(    self   :			Tuple)		->List[str]:





           '''simple docstring'''

           return self





    def  SCREAMING_SNAKE_CASE							(    self   :			Any)		->Dict:





           '''simple docstring'''

           if not self.current:
                  raise StopIteration
           else:
                  A__   				=					self.current.get_data()
                  A__   				=					self.current.get_next()
                  return value



class        UpperCamelCase_					:

    '''simple docstring'''






    def __init__(    self   :			Dict)		->Dict:





           '''simple docstring'''

           A__   				=					None  # First node in list
           A__   				=					None  # Last node in list


    def __str__(    self   :			str)		->Optional[int]:





           '''simple docstring'''

           A__   				=					self.head
           A__   				=					[]
           while current is not None:
                  nodes.append(current.get_data())
                  A__   				=					current.get_next()
           return " ".join(str(UpperCAmelCase__) for node in nodes)


    def __contains__(    self   :			List[Any]      ,				UpperCAmelCase__   :			int)		->Union[str, Any]:





           '''simple docstring'''

           A__   				=					self.head
           while current:
                  if current.get_data() == value:
                         return True
                  A__   				=					current.get_next()
           return False


    def __iter__(    self   :			int)		->str:





           '''simple docstring'''

           return LinkedListIterator(self.head)


    def  SCREAMING_SNAKE_CASE							(    self   :			List[Any])		->List[Any]:





           '''simple docstring'''

           if self.head:
                  return self.head.get_data()
           return None


    def  SCREAMING_SNAKE_CASE							(    self   :			Tuple)		->str:





           '''simple docstring'''

           if self.tail:
                  return self.tail.get_data()
           return None


    def  SCREAMING_SNAKE_CASE							(    self   :			Union[str, Any]      ,				UpperCAmelCase__   :			Node)		->None:





           '''simple docstring'''

           if self.head is None:
                  A__   				=					node
                  A__   				=					node
           else:
                  self.insert_before_node(self.head      ,				UpperCAmelCase__)


    def  SCREAMING_SNAKE_CASE							(    self   :			Union[str, Any]      ,				UpperCAmelCase__   :			Node)		->None:





           '''simple docstring'''

           if self.head is None:
                  self.set_head(UpperCAmelCase__)
           else:
                  self.insert_after_node(self.tail      ,				UpperCAmelCase__)


    def  SCREAMING_SNAKE_CASE							(    self   :			Dict      ,				UpperCAmelCase__   :			int)		->None:





           '''simple docstring'''

           A__   				=					Node(UpperCAmelCase__)
           if self.head is None:
                  self.set_head(UpperCAmelCase__)
           else:
                  self.set_tail(UpperCAmelCase__)


    def  SCREAMING_SNAKE_CASE							(    self   :			Any      ,				UpperCAmelCase__   :			Node      ,				UpperCAmelCase__   :			Node)		->None:





           '''simple docstring'''

           A__   				=					node
           A__   				=					node.previous

           if node.get_previous() is None:
                  A__   				=					node_to_insert
           else:
                  A__   				=					node_to_insert

           A__   				=					node_to_insert


    def  SCREAMING_SNAKE_CASE							(    self   :			List[Any]      ,				UpperCAmelCase__   :			Node      ,				UpperCAmelCase__   :			Node)		->None:





           '''simple docstring'''

           A__   				=					node
           A__   				=					node.next

           if node.get_next() is None:
                  A__   				=					node_to_insert
           else:
                  A__   				=					node_to_insert

           A__   				=					node_to_insert


    def  SCREAMING_SNAKE_CASE							(    self   :			Tuple      ,				UpperCAmelCase__   :			int      ,				UpperCAmelCase__   :			int)		->None:





           '''simple docstring'''

           A__   				=					1
           A__   				=					Node(UpperCAmelCase__)
           A__   				=					self.head
           while node:
                  if current_position == position:
                         self.insert_before_node(UpperCAmelCase__      ,				UpperCAmelCase__)
                         return
                  current_position += 1
                  A__   				=					node.next
           self.insert_after_node(self.tail      ,				UpperCAmelCase__)


    def  SCREAMING_SNAKE_CASE							(    self   :			int      ,				UpperCAmelCase__   :			int)		->Node:





           '''simple docstring'''

           A__   				=					self.head
           while node:
                  if node.get_data() == item:
                         return node
                  A__   				=					node.get_next()
           raise Exception('''Node not found''')


    def  SCREAMING_SNAKE_CASE							(    self   :			Union[str, Any]      ,				UpperCAmelCase__   :			List[str])		->Optional[Any]:





           '''simple docstring'''

           if (node := self.get_node(UpperCAmelCase__)) is not None:
                  if node == self.head:
                         A__   				=					self.head.get_next()

                  if node == self.tail:
                         A__   				=					self.tail.get_previous()

                  self.remove_node_pointers(UpperCAmelCase__)


    @staticmethod
    def  SCREAMING_SNAKE_CASE							(    UpperCAmelCase__   :			Node)		->None:





           '''simple docstring'''

           if node.get_next():
                  A__   				=					node.previous

           if node.get_previous():
                  A__   				=					node.next

           A__   				=					None
           A__   				=					None





    def  SCREAMING_SNAKE_CASE							(    self   :			List[str])		->List[str]:





           '''simple docstring'''

           return self.head is None







def SCREAMING_SNAKE_CASE       ( )     -> None:



       """simple docstring"""




if __name__ == "__main__":
  import doctest

  doctest.testmod()








# Logistic Regression from scratch

# In[62]:

# In[63]:

# importing all the required libraries

import numpy as np
from matplotlib import pyplot as plt
from sklearn import datasets







def SCREAMING_SNAKE_CASE       ( lowercase_		)     -> Dict:



       """simple docstring"""

       return 1 / (1 + np.exp(-z		))







def SCREAMING_SNAKE_CASE       ( lowercase_				,       lowercase_		)     -> Optional[int]:



       """simple docstring"""

       return (-y * np.log(lowercase_		) - (1 - y) * np.log(1 - h		)).mean()







def SCREAMING_SNAKE_CASE       ( lowercase_				,       lowercase_				,       lowercase_		)     -> int:



       """simple docstring"""

       A__   				=					np.dot(lowercase_				,       lowercase_		)
       return np.sum(y * scores - np.log(1 + np.exp(lowercase_		)		)		)







def SCREAMING_SNAKE_CASE       ( lowercase_				,       lowercase_				,       lowercase_				,       lowercase_=70_000		)     -> Dict:



       """simple docstring"""

       A__   				=					np.zeros(x.shape[1]		)

       for iterations in range(lowercase_		):
              A__   				=					np.dot(lowercase_				,       lowercase_		)
              A__   				=					sigmoid_function(lowercase_		)
              A__   				=					np.dot(x.T				,       h - y		) / y.size
              A__   				=					theta - alpha * gradient  # updating the weights
              A__   				=					np.dot(lowercase_				,       lowercase_		)
              A__   				=					sigmoid_function(lowercase_		)
              A__   				=					cost_function(lowercase_				,       lowercase_		)
              if iterations % 100 == 0:
                     print(f"""loss: {j} \t"""		)  # printing the loss after every 100 iterations
       return theta


# In[68]:

if __name__ == "__main__":
  _lowerCamelCase			:	str							 =     datasets.load_iris()
  _lowerCamelCase			:	Any							 =     iris.data[:, :2]
  _lowerCamelCase			:	Dict							 =     (iris.target != 0) * 1

  _lowerCamelCase			:	Union[str, Any]							 =     0.1
  _lowerCamelCase			:	Tuple							 =     logistic_reg(alpha, x, y, max_iterations=70000)
  print("""theta: """, theta)  # printing the theta i.e our weights vector







  def SCREAMING_SNAKE_CASE       ( lowercase_		)     -> List[Any]:



         """simple docstring"""

         return sigmoid_function(
             np.dot(lowercase_				,       lowercase_		)		)  # predicting the value of probability from the logistic regression algorithm

  plt.figure(figsize=(10, 6))
  plt.scatter(x[y == 0][:, 0], x[y == 0][:, 1], color="""b""", label="""0""")
  plt.scatter(x[y == 1][:, 0], x[y == 1][:, 1], color="""r""", label="""1""")
  ((_lowerCamelCase) ,    (_lowerCamelCase))			:	int							 =     (x[:, 0].min(), x[:, 0].max())
  ((_lowerCamelCase) ,    (_lowerCamelCase))			:	Union[str, Any]							 =     (x[:, 1].min(), x[:, 1].max())
  ((_lowerCamelCase) ,    (_lowerCamelCase))			:	List[Any]							 =     np.meshgrid(np.linspace(xa_min, xa_max), np.linspace(xa_min, xa_max))
  _lowerCamelCase			:	str							 =     np.c_[xxa.ravel(), xxa.ravel()]
  _lowerCamelCase			:	Tuple							 =     predict_prob(grid).reshape(xxa.shape)
  plt.contour(xxa, xxa, probs, [0.5], linewidths=1, colors="""black""")

  plt.legend()
  plt.show()


