from tensorflow.python.eager import context
from tensorflow.python.framework import dtypes
from tensorflow.python.framework import ops
from tensorflow.python.ops import array_ops
from tensorflow.python.ops import cond
from tensorflow.python.ops import confusion_matrix
from tensorflow.python.ops import control_flow_ops
from tensorflow.python.ops import math_ops
from tensorflow.python.ops import nn
from tensorflow.python.ops import nn_ops
from tensorflow.python.ops import weights_broadcast_ops
from tensorflow.python.ops.losses import util
from tensorflow.python.util import dispatch
from tensorflow.python.util.deprecation import deprecated_args
from tensorflow.python.util.deprecation import deprecated_argument_lookup
from tensorflow.python.util.tf_export import tf_export

@tf_export(v1=["losses.Reduction"])
class Reduction:
  """Types of loss reduction.

  Contains the following values:

  * `NONE`: Un-reduced weighted losses with the same shape as input.
  * `SUM`: Scalar sum of weighted losses.
  * `MEAN`: Scalar `SUM` divided by sum of weights. DEPRECATED.
  * `SUM_OVER_BATCH_SIZE`: Scalar `SUM` divided by number of elements in losses.
  * `SUM_OVER_NONZERO_WEIGHTS`: Scalar `SUM` divided by number of non-zero
     weights. DEPRECATED.
  * `SUM_BY_NONZERO_WEIGHTS`: Same as `SUM_OVER_NONZERO_WEIGHTS`. DEPRECATED.
  """

  NONE = "none"
  SUM = "weighted_sum"
  SUM_OVER_BATCH_SIZE = "weighted_sum_over_batch_size"
  MEAN = "weighted_mean"
  SUM_BY_NONZERO_WEIGHTS = "weighted_sum_by_nonzero_weights"
  SUM_OVER_NONZERO_WEIGHTS = SUM_BY_NONZERO_WEIGHTS

  @classmethod
  def all(cls):
    return (
        cls.NONE,
        cls.SUM,
        cls.MEAN,
        cls.SUM_OVER_BATCH_SIZE,
        cls.SUM_OVER_NONZERO_WEIGHTS,
        cls.SUM_BY_NONZERO_WEIGHTS)

  @classmethod
  def validate(cls, key):
    if key not in cls.all():
      raise ValueError(f"Invalid Reduction Key {key}. Key should be one of "
                       f"{cls.all()}.")

def _safe_mean(losses, num_present):
  """Computes a safe mean of the losses.

  Args:
    losses: `Tensor` whose elements contain individual loss measurements.
    num_present: The number of measurable elements in `losses`.

  Returns:
    A scalar representing the mean of `losses`. If `num_present` is zero,
      then zero is returned.
  """
  total_loss = math_ops.reduce_sum(losses)
  return math_ops.div_no_nan(total_loss, num_present, name="value")

def _num_present(losses, weights, per_batch=False):
  """Computes the number of elements in the loss function induced by `weights`.

  A given weights tensor induces different numbers of usable elements in the
  `losses` tensor. The `weights` tensor is broadcast across `losses` for all
  possible dimensions. For example, if `losses` is a tensor of dimension
  `[4, 5, 6, 3]` and `weights` is a tensor of shape `[4, 5]`, then `weights` is,
  in effect, tiled to match the shape of `losses`. Following this effective
  tile, the total number of present elements is the number of non-zero weights.

  Args:
    losses: `Tensor` of shape `[batch_size, d1, ... dN]`.
    weights: `Tensor` of shape `[]`, `[batch_size]` or
      `[batch_size, d1, ... dK]`, where K < N.
    per_batch: Whether to return the number of elements per batch or as a sum
      total.

  Returns:
    The number of present (non-zero) elements in the losses tensor. If
      `per_batch` is `True`, the value is returned as a tensor of size
      `[batch_size]`. Otherwise, a single scalar tensor is returned.
  """
  if ((isinstance(weights, float) and weights != 0.0) or
      (context.executing_eagerly() and weights._rank() == 0  # pylint: disable=protected-access
       and not math_ops.equal(weights, 0.0))):
    return _num_elements(losses)
  with ops.name_scope(None, "num_present", (losses, weights)) as scope:
    weights = math_ops.cast(weights, dtype=dtypes.float32)
    present = array_ops.where(
        math_ops.equal(weights, 0.0),
        array_ops.zeros_like(weights),
        array_ops.ones_like(weights))
    present = weights_broadcast_ops.broadcast_weights(present, losses)
    if per_batch:
      return math_ops.reduce_sum(
          present,
          axis=math_ops.range(1, array_ops.rank(present)),
          keepdims=True,
          name=scope)
    return math_ops.reduce_sum(present, name=scope)

def _num_elements(losses):
  """Computes the number of elements in `losses` tensor."""
  with ops.name_scope(None, "num_elements", values=[losses]) as scope:
    return math_ops.cast(array_ops.size(losses, name=scope), dtype=losses.dtype)

@tf_export(v1=["losses.compute_weighted_loss"])
@dispatch.add_dispatch_support
def compute_weighted_loss(
    losses, weights=1.0, scope=None, loss_collection=ops.GraphKeys.LOSSES,
    reduction=Reduction.SUM_BY_NONZERO_WEIGHTS):
  """Computes the weighted loss.

  Args:
    losses: `Tensor` of shape `[batch_size, d1, ... dN]`.
    weights: Optional `Tensor` whose rank is either 0, or the same rank as
      `losses`, and must be broadcastable to `losses` (i.e., all dimensions must
      be either `1`, or the same as the corresponding `losses` dimension).
    scope: the scope for the operations performed in computing the loss.
    loss_collection: the loss will be added to these collections.
    reduction: Type of reduction to apply to loss.

  Returns:
    Weighted loss `Tensor` of the same type as `losses`. If `reduction` is
    `NONE`, this has the same shape as `losses`; otherwise, it is scalar.

  Raises:
    ValueError: If `weights` is `None` or the shape is not compatible with
      `losses`, or if the number of dimensions (rank) of either `losses` or
      `weights` is missing.

  Note:
    When calculating the gradient of a weighted loss contributions from
    both `losses` and `weights` are considered. If your `weights` depend
    on some model parameters but you do not want this to affect the loss
    gradient, you need to apply `tf.stop_gradient` to `weights` before
    passing them to `compute_weighted_loss`.

  @compatibility(eager)
  The `loss_collection` argument is ignored when executing eagerly. Consider
  holding on to the return value or collecting losses via a `tf.keras.Model`.
  @end_compatibility
  """
  Reduction.validate(reduction)
  with ops.name_scope(scope, "weighted_loss", (losses, weights)):
    # Save the `reduction` argument for loss normalization when distributing
    # to multiple replicas. Used only for estimator + v1 optimizer flow.
    ops.get_default_graph()._last_loss_reduction = reduction  # pylint: disable=protected-access

    def compute_loss(losses, weights, loss_collection, reduction):
      losses = ops.convert_to_tensor(losses)
      input_dtype = losses.dtype
      losses = math_ops.cast(losses, dtype=dtypes.float32)
      weights = math_ops.cast(weights, dtype=dtypes.float32)
      weighted_losses = math_ops.multiply(losses, weights)
      if reduction == Reduction.NONE:
        loss = weighted_losses
      else:
        loss = math_ops.reduce_sum(weighted_losses)
        if reduction == Reduction.MEAN:
          loss = _safe_mean(
              loss, math_ops.reduce_sum(array_ops.ones_like(losses) * weights))
        elif (reduction == Reduction.SUM_BY_NONZERO_WEIGHTS or
              reduction == Reduction.SUM_OVER_NONZERO_WEIGHTS):
          loss = _safe_mean(loss, _num_present(losses, weights))
        elif reduction == Reduction.SUM_OVER_BATCH_SIZE:
          loss = _safe_mean(loss, _num_elements(losses))

      # Convert the result back to the input type.
      loss = math_ops.cast(loss, input_dtype)
      util.add_loss(loss, loss_collection)
      return loss

    # Skip the assert_broadcastable in XLA context because asserts are not
    # supported so it only causes unnecessary ops. Also skip it because it uses
    # a DenseToDenseSetOperation op that is incompatible with XLA when
    # the shape(s) are dynamic.
    if control_flow_ops.get_enclosing_xla_context() is not None:
      return compute_loss(losses, weights, loss_collection, reduction)
    else:
      with ops.control_dependencies(
          (weights_broadcast_ops.assert_broadcastable(weights, losses),)):
        return compute_loss(losses, weights, loss_collection, reduction)

@tf_export(v1=["losses.absolute_difference"])
@dispatch.add_dispatch_support
def absolute_difference(
    labels, predictions, weights=1.0, scope=None,
    loss_collection=ops.GraphKeys.LOSSES,
    reduction=Reduction.SUM_BY_NONZERO_WEIGHTS):
  """Adds an Absolute Difference loss to the training procedure.

  `weights` acts as a coefficient for the loss. If a scalar is provided, then
  the loss is simply scaled by the given value. If `weights` is a `Tensor` of
  shape `[batch_size]`, then the total loss for each sample of the batch is
  rescaled by the corresponding element in the `weights` vector. If the shape of
  `weights` matches the shape of `predictions`, then the loss of each
  measurable element of `predictions` is scaled by the corresponding value of
  `weights`.

  Args:
    labels: The ground truth output tensor, same dimensions as 'predictions'.
    predictions: The predicted outputs.
    weights: Optional `Tensor` whose rank is either 0, or the same rank as
      `labels`, and must be broadcastable to `labels` (i.e., all dimensions must
      be either `1`, or the same as the corresponding `losses` dimension).
    scope: The scope for the operations performed in computing the loss.
    loss_collection: collection to which this loss will be added.
    reduction: Type of reduction to apply to loss.

  Returns:
    Weighted loss float `Tensor`. If `reduction` is `NONE`, this has the same
    shape as `labels`; otherwise, it is scalar.

  Raises:
    ValueError: If the shape of `predictions` doesn't match that of
      `labels` or if the shape of `weights` is invalid or if `labels`
      or `predictions` is None.

  @compatibility(eager)
  The `loss_collection` argument is ignored when executing eagerly. Consider
  holding on to the return value or collecting losses via a `tf.keras.Model`.
  @end_compatibility
  """
  if labels is None:
    raise ValueError("Argument `labels` must not be None.")
  if predictions is None:
    raise ValueError("Argument `predictions` must not be None.")
  with ops.name_scope(scope, "absolute_difference",
                      (predictions, labels, weights)) as scope:
    predictions = math_ops.cast(predictions, dtype=dtypes.float32)
    labels = math_ops.cast(labels, dtype=dtypes.float32)
    predictions.get_shape().assert_is_compatible_with(labels.get_shape())
    losses = math_ops.abs(math_ops.subtract(predictions, labels))
    return compute_weighted_loss(
        losses, weights, scope, loss_collection, reduction=reduction)

@tf_export(v1=["losses.cosine_distance"])
@dispatch.add_dispatch_support
@deprecated_args(None, "dim is deprecated, use axis instead", "dim")
def cosine_distance(
    labels, predictions, axis=None, weights=1.0, scope=None,
    loss_collection=ops.GraphKeys.LOSSES,
    reduction=Reduction.SUM_BY_NONZERO_WEIGHTS,
    dim=None):
  """Adds a cosine-distance loss to the training procedure.

  Note that the function assumes that `predictions` and `labels` are already
  unit-normalized.

  Args:
    labels: `Tensor` whose shape matches 'predictions'
    predictions: An arbitrary matrix.
    axis: The dimension along which the cosine distance is computed.
    weights: Optional `Tensor` whose rank is either 0, or the same rank as
      `labels`, and must be broadcastable to `labels` (i.e., all dimensions must
      be either `1`, or the same as the corresponding `losses` dimension).
    scope: The scope for the operations performed in computing the loss.
    loss_collection: collection to which this loss will be added.
    reduction: Type of reduction to apply to loss.
    dim: The old (deprecated) name for `axis`.

  Returns:
    Weighted loss float `Tensor`. If `reduction` is `NONE`, this has the same
    shape as `labels`; otherwise, it is scalar.

  Raises:
    ValueError: If `predictions` shape doesn't match `labels` shape, or
      `axis`, `labels`, `predictions` or `weights` is `None`.

  @compatibility(eager)
  The `loss_collection` argument is ignored when executing eagerly. Consider
  holding on to the return value or collecting losses via a `tf.keras.Model`.
  @end_compatibility
  """
  axis = deprecated_argument_lookup("axis", axis, "dim", dim)
  if axis is None:
    raise ValueError("You must specify argument `axis`.")
  if labels is None:
    raise ValueError("Argument `labels` must not be None.")
  if predictions is None:
    raise ValueError("Argument `predictions` must not be None.")
  with ops.name_scope(scope, "cosine_distance_loss",
                      (predictions, labels, weights)) as scope:
    predictions = math_ops.cast(predictions, dtype=dtypes.float32)
    labels = math_ops.cast(labels, dtype=dtypes.float32)
    predictions.get_shape().assert_is_compatible_with(labels.get_shape())

    radial_diffs = math_ops.multiply(predictions, labels)
    losses = 1 - math_ops.reduce_sum(radial_diffs, axis=(axis,), keepdims=True)
    return compute_weighted_loss(
        losses, weights, scope, loss_collection, reduction=reduction)

@tf_export(v1=["losses.hinge_loss"])
@dispatch.add_dispatch_support
def hinge_loss(labels, logits, weights=1.0, scope=None,
               loss_collection=ops.GraphKeys.LOSSES,
               reduction=Reduction.SUM_BY_NONZERO_WEIGHTS):
  """Adds a hinge loss to the training procedure.

  Args:
    labels: The ground truth output tensor. Its shape should match the shape of
      logits. The values of the tensor are expected to be 0.0 or 1.0. Internally
      the {0,1} labels are converted to {-1,1} when calculating the hinge loss.
    logits: The logits, a float tensor. Note that logits are assumed to be
      unbounded and 0-centered. A value > 0 (resp. < 0) is considered a positive
      (resp. negative) binary prediction.
    weights: Optional `Tensor` whose rank is either 0, or the same rank as
      `labels`, and must be broadcastable to `labels` (i.e., all dimensions must
      be either `1`, or the same as the corresponding `losses` dimension).
    scope: The scope for the operations performed in computing the loss.
    loss_collection: collection to which the loss will be added.
    reduction: Type of reduction to apply to loss.

  Returns:
    Weighted loss float `Tensor`. If `reduction` is `NONE`, this has the same
    shape as `labels`; otherwise, it is scalar.

  Raises:
    ValueError: If the shapes of `logits` and `labels` don't match or
      if `labels` or `logits` is None.

  @compatibility(eager)
  The `loss_collection` argument is ignored when executing eagerly. Consider
  holding on to the return value or collecting losses via a `tf.keras.Model`.
  @end_compatibility
  """
  if labels is None:
    raise ValueError("Argument `labels` must not be None.")
  if logits is None:
    raise ValueError("Argument `logits` must not be None.")
  with ops.name_scope(scope, "hinge_loss", (logits, labels, weights)) as scope:
    logits = math_ops.cast(logits, dtype=dtypes.float32)
    labels = math_ops.cast(labels, dtype=dtypes.float32)
    logits.get_shape().assert_is_compatible_with(labels.get_shape())
    # We first need to convert binary labels to -1/1 labels (as floats).
    all_ones = array_ops.ones_like(labels)
    labels = math_ops.subtract(2 * labels, all_ones)
    losses = nn_ops.relu(
        math_ops.subtract(all_ones, math_ops.multiply(labels, logits)))
    return compute_weighted_loss(
        losses, weights, scope, loss_collection, reduction=reduction)

@tf_export(v1=["losses.huber_loss"])
@dispatch.add_dispatch_support
def huber_loss(labels, predictions, weights=1.0, delta=1.0, scope=None,
               loss_collection=ops.GraphKeys.LOSSES,
               reduction=Reduction.SUM_BY_NONZERO_WEIGHTS):
  """Adds a [Huber Loss](https://en.wikipedia.org/wiki/Huber_loss) term to the training procedure.

  For each value x in `error=labels-predictions`, the following is calculated:

  ```
    0.5 * x^2                  if |x| <= d
    0.5 * d^2 + d * (|x| - d)  if |x| > d
  ```

  where d is `delta`.

  `weights` acts as a coefficient for the loss. If a scalar is provided, then
  the loss is simply scaled by the given value. If `weights` is a tensor of size
  `[batch_size]`, then the total loss for each sample of the batch is rescaled
  by the corresponding element in the `weights` vector. If the shape of
  `weights` matches the shape of `predictions`, then the loss of each
  measurable element of `predictions` is scaled by the corresponding value of
  `weights`.

  Args:
    labels: The ground truth output tensor, same dimensions as 'predictions'.
    predictions: The predicted outputs.
    weights: Optional `Tensor` whose rank is either 0, or the same rank as
      `labels`, and must be broadcastable to `labels` (i.e., all dimensions must
      be either `1`, or the same as the corresponding `losses` dimension).
    delta: `float`, the point where the huber loss function changes from a
      quadratic to linear.
    scope: The scope for the operations performed in computing the loss.
    loss_collection: collection to which the loss will be added.
    reduction: Type of reduction to apply to loss.

  Returns:
    Weighted loss float `Tensor`. If `reduction` is `NONE`, this has the same
    shape as `labels`; otherwise, it is scalar.

  Raises:
    ValueError: If the shape of `predictions` doesn't match that of `labels` or
      if the shape of `weights` is invalid.  Also if `labels` or
     `predictions` is None.

  @compatibility(eager)
  The `loss_collection` argument is ignored when executing eagerly. Consider
  holding on to the return value or collecting losses via a `tf.keras.Model`.
  @end_compatibility
  """
  if labels is None:
    raise ValueError("Argument `labels` must not be None.")
  if predictions is None:
    raise ValueError("Argument `predictions` must not be None.")
  with ops.name_scope(scope, "huber_loss",
                      (predictions, labels, weights)) as scope:
    predictions = math_ops.cast(predictions, dtype=dtypes.float32)
    labels = math_ops.cast(labels, dtype=dtypes.float32)
    predictions.get_shape().assert_is_compatible_with(labels.get_shape())
    error = math_ops.subtract(predictions, labels)
    abs_error = math_ops.abs(error)
    quadratic = math_ops.minimum(abs_error, delta)
    # The following expression is the same in value as
    # tf.maximum(abs_error - delta, 0), but importantly the gradient for the
    # expression when abs_error == delta is 0 (for tf.maximum it would be 1).
    # This is necessary to avoid doubling the gradient, since there is already a
    # nonzero contribution to the gradient from the quadratic term.
    linear = math_ops.subtract(abs_error, quadratic)
    losses = math_ops.add(
        math_ops.multiply(
            ops.convert_to_tensor(0.5, dtype=quadratic.dtype),
            math_ops.multiply(quadratic, quadratic)),
        math_ops.multiply(delta, linear))
    return compute_weighted_loss(
        losses, weights, scope, loss_collection, reduction=reduction)

@tf_export(v1=["losses.log_loss"])
@dispatch.add_dispatch_support
def log_loss(labels, predictions, weights=1.0, epsilon=1e-7, scope=None,
             loss_collection=ops.GraphKeys.LOSSES,
             reduction=Reduction.SUM_BY_NONZERO_WEIGHTS):
  """Adds a Log Loss term to the training procedure.

  `weights` acts as a coefficient for the loss. If a scalar is provided, then
  the loss is simply scaled by the given value. If `weights` is a tensor of size
  `[batch_size]`, then the total loss for each sample of the batch is rescaled
  by the corresponding element in the `weights` vector. If the shape of
  `weights` matches the shape of `predictions`, then the loss of each
  measurable element of `predictions` is scaled by the corresponding value of
  `weights`.

  Args:
    labels: The ground truth output tensor, same dimensions as 'predictions'.
    predictions: The predicted outputs.
    weights: Optional `Tensor` whose rank is either 0, or the same rank as
      `labels`, and must be broadcastable to `labels` (i.e., all dimensions must
      be either `1`, or the same as the corresponding `losses` dimension).
    epsilon: A small increment to add to avoid taking a log of zero.
    scope: The scope for the operations performed in computing the loss.
    loss_collection: collection to which the loss will be added.
    reduction: Type of reduction to apply to loss.

  Returns:
    Weighted loss float `Tensor`. If `reduction` is `NONE`, this has the same
    shape as `labels`; otherwise, it is scalar.

  Raises:
    ValueError: If the shape of `predictions` doesn't match that of `labels` or
      if the shape of `weights` is invalid.  Also if `labels` or `predictions`
      is None.

  @compatibility(eager)
  The `loss_collection` argument is ignored when executing eagerly. Consider
  holding on to the return value or collecting losses via a `tf.keras.Model`.
  @end_compatibility
  """
  if labels is None:
    raise ValueError("Argument `labels` must not be None.")
  if predictions is None:
    raise ValueError("Argument `predictions` must not be None.")
  with ops.name_scope(scope, "log_loss",
                      (predictions, labels, weights)) as scope:
    predictions = math_ops.cast(predictions, dtype=dtypes.float32)
    labels = math_ops.cast(labels, dtype=dtypes.float32)
    predictions.get_shape().assert_is_compatible_with(labels.get_shape())
    losses = -math_ops.multiply(
        labels,
        math_ops.log(predictions + epsilon)) - math_ops.multiply(
            (1 - labels), math_ops.log(1 - predictions + epsilon))
    return compute_weighted_loss(
        losses, weights, scope, loss_collection, reduction=reduction)

# TODO(b/37208492): Add reduction arg.
@tf_export(v1=["losses.mean_pairwise_squared_error"])
@dispatch.add_dispatch_support
def mean_pairwise_squared_error(
    labels, predictions, weights=1.0, scope=None,
    loss_collection=ops.GraphKeys.LOSSES):
  """Adds a pairwise-errors-squared loss to the training procedure.

  Unlike `mean_squared_error`, which is a measure of the differences between
  corresponding elements of `predictions` and `labels`,
  `mean_pairwise_squared_error` is a measure of the differences between pairs of
  corresponding elements of `predictions` and `labels`.

  For example, if `labels`=[a, b, c] and `predictions`=[x, y, z], there are
  three pairs of differences are summed to compute the loss:
    loss = [ ((a-b) - (x-y)).^2 + ((a-c) - (x-z)).^2 + ((b-c) - (y-z)).^2 ] / 3

  Note that since the inputs are of shape `[batch_size, d0, ... dN]`, the
  corresponding pairs are computed within each batch sample but not across
  samples within a batch. For example, if `predictions` represents a batch of
  16 grayscale images of dimension [batch_size, 100, 200], then the set of pairs
  is drawn from each image, but not across images.

  `weights` acts as a coefficient for the loss. If a scalar is provided, then
  the loss is simply scaled by the given value. If `weights` is a tensor of size
  `[batch_size]`, then the total loss for each sample of the batch is rescaled
  by the corresponding element in the `weights` vector.

  Args:
    labels: The ground truth output tensor, whose shape must match the shape of
      `predictions`.
    predictions: The predicted outputs, a tensor of size
      `[batch_size, d0, .. dN]` where N+1 is the total number of dimensions in
      `predictions`.
    weights: Coefficients for the loss a scalar, a tensor of shape
      `[batch_size]` or a tensor whose shape matches `predictions`.
    scope: The scope for the operations performed in computing the loss.
    loss_collection: collection to which the loss will be added.

  Returns:
    A scalar `Tensor` that returns the weighted loss.

  Raises:
    ValueError: If the shape of `predictions` doesn't match that of `labels` or
      if the shape of `weights` is invalid.  Also if `labels` or `predictions`
      is None.

  @compatibility(eager)
  The `loss_collection` argument is ignored when executing eagerly. Consider
  holding on to the return value or collecting losses via a `tf.keras.Model`.
  @end_compatibility
  """
  if labels is None:
    raise ValueError("Argument `labels` must not be None.")
  if predictions is None:
    raise ValueError("Argument `predictions` must not be None.")
  with ops.name_scope(scope, "mean_pairwise_squared_error",
                      (predictions, labels, weights)) as scope:
    weights = math_ops.cast(weights, dtype=dtypes.float32)
    labels = math_ops.cast(labels, dtype=dtypes.float32)

    def compute_loss(labels, predictions, weights, loss_collection):
      predictions = math_ops.cast(predictions, dtype=dtypes.float32)
      predictions.get_shape().assert_is_compatible_with(labels.get_shape())

      diffs = math_ops.subtract(predictions, labels)

      axis = math_ops.range(1, array_ops.rank(diffs))

      sum_squares_diff_per_batch = math_ops.reduce_sum(
          math_ops.square(diffs), axis=axis, keepdims=True)
      num_present_per_batch = _num_present(diffs, weights, per_batch=True)

      term1 = 2.0 * math_ops.div_no_nan(
          sum_squares_diff_per_batch,
          math_ops.maximum(num_present_per_batch - 1, 0),
          name="value")

      sum_diff = math_ops.reduce_sum(diffs, axis=axis, keepdims=True)
      term2 = 2.0 * math_ops.div_no_nan(
          math_ops.square(sum_diff),
          math_ops.maximum(
              math_ops.multiply(num_present_per_batch,
                                num_present_per_batch - 1), 0),
          name="value")

      weighted_losses = math_ops.multiply(term1 - term2, weights)
      loss = math_ops.reduce_sum(weighted_losses)

      mean_loss = array_ops.where(
          math_ops.reduce_sum(num_present_per_batch) > 0,
          loss,
          array_ops.zeros_like(loss),
          name="value")
      util.add_loss(mean_loss, loss_collection)
      return mean_loss

    # Skip the assert_broadcastable in XLA context because asserts are not
    # supported so it only causes unnecessary ops. Also skip it because it uses
    # a DenseToDenseSetOperation op that is incompatible with XLA when
    # the shape(s) are dynamic.
    if control_flow_ops.get_enclosing_xla_context() is not None:
      return compute_loss(labels, predictions, weights, loss_collection)
    else:
      with ops.control_dependencies(
          (weights_broadcast_ops.assert_broadcastable(weights, labels),)):
        return compute_loss(labels, predictions, weights, loss_collection)

@tf_export(v1=["losses.mean_squared_error"])
@dispatch.add_dispatch_support
def mean_squared_error(
    labels, predictions, weights=1.0, scope=None,
    loss_collection=ops.GraphKeys.LOSSES,
    reduction=Reduction.SUM_BY_NONZERO_WEIGHTS):
  """Adds a Sum-of-Squares loss to the training procedure.

  `weights` acts as a coefficient for the loss. If a scalar is provided, then
  the loss is simply scaled by the given value. If `weights` is a tensor of size
  `[batch_size]`, then the total loss for each sample of the batch is rescaled
  by the corresponding element in the `weights` vector. If the shape of
  `weights` matches the shape of `predictions`, then the loss of each
  measurable element of `predictions` is scaled by the corresponding value of
  `weights`.

  Args:
    labels: The ground truth output tensor, same dimensions as 'predictions'.
    predictions: The predicted outputs.
    weights: Optional `Tensor` whose rank is either 0, or the same rank as
      `labels`, and must be broadcastable to `labels` (i.e., all dimensions must
      be either `1`, or the same as the corresponding `losses` dimension).
    scope: The scope for the operations performed in computing the loss.
    loss_collection: collection to which the loss will be added.
    reduction: Type of reduction to apply to loss.

  Returns:
    Weighted loss float `Tensor`. If `reduction` is `NONE`, this has the same
    shape as `labels`; otherwise, it is scalar.

  Raises:
    ValueError: If the shape of `predictions` doesn't match that of `labels` or
      if the shape of `weights` is invalid.  Also if `labels` or `predictions`
      is None.

  @compatibility(TF2)

  `tf.compat.v1.losses.mean_squared_error` is mostly compatible with eager
  execution and `tf.function`. But, the `loss_collection` argument is
  ignored when executing eagerly and no loss will be written to the loss
  collections. You will need to either hold on to the return value manually
  or rely on `tf.keras.Model` loss tracking.

  To switch to native TF2 style, instantiate the
   `tf.keras.losses.MeanSquaredError` class and call the object instead.

  #### Structural Mapping to Native TF2

  Before:

  ```python
  loss = tf.compat.v1.losses.mean_squared_error(
    labels=labels,
    predictions=predictions,
    weights=weights,
    reduction=reduction)
  ```

  After:

  ```python
  loss_fn = tf.keras.losses.MeanSquaredError(
    reduction=reduction)
  loss = loss_fn(
    y_true=labels,
    y_pred=predictions,
    sample_weight=weights)
  ```

  #### How to Map Arguments

  | TF1 Arg Name          | TF2 Arg Name     | Note                       |
  | :-------------------- | :--------------- | :------------------------- |
  | `labels`              | `y_true`         | In `__call__()` method     |
  | `predictions`         | `y_pred`         | In `__call__()` method     |
  | `weights`             | `sample_weight`  | In `__call__()` method.    |
  : : : The shape requirements for `sample_weight` is different from      :
  : : : `weights`. Please check the [argument definition][api_docs] for   :
  : : : details.                                                          :
  | `scope`               | Not supported    | -                          |
  | `loss_collection`     | Not supported    | Losses should be tracked   |
  : : : explicitly or with Keras APIs, for example, [add_loss][add_loss], :
  : : : instead of via collections                                        :
  | `reduction`           | `reduction`      | In constructor. Value of   |
  : : : `tf.compat.v1.losses.Reduction.SUM_OVER_BATCH_SIZE`,              :
  : : : `tf.compat.v1.losses.Reduction.SUM`,                              :
  : : : `tf.compat.v1.losses.Reduction.NONE` in                           :
  : : : `tf.compat.v1.losses.softmax_cross_entropy` correspond to         :
  : : : `tf.keras.losses.Reduction.SUM_OVER_BATCH_SIZE`,                  :
  : : : `tf.keras.losses.Reduction.SUM`,                                  :
  : : : `tf.keras.losses.Reduction.NONE`, respectively. If you            :
  : : : used other value for `reduction`, including the default value     :
  : : :  `tf.compat.v1.losses.Reduction.SUM_BY_NONZERO_WEIGHTS`, there is :
  : : : no directly corresponding value. Please modify the loss           :
  : : : implementation manually.                                          :

  [add_loss]:https://www.tensorflow.org/api_docs/python/tf/keras/layers/Layer#add_loss
  [api_docs]:https://www.tensorflow.org/api_docs/python/tf/keras/losses/MeanSquaredError#__call__

  #### Before & After Usage Example

  Before:

  >>> y_true = [1, 2, 3]
  >>> y_pred = [1, 3, 5]
  >>> weights = [0, 1, 0.25]
  >>> # samples with zero-weight are excluded from calculation when `reduction`
  >>> # argument is set to default value `Reduction.SUM_BY_NONZERO_WEIGHTS`
  >>> tf.compat.v1.losses.mean_squared_error(
  ...    labels=y_true,
  ...    predictions=y_pred,
  ...    weights=weights).numpy()
  1.0

  >>> tf.compat.v1.losses.mean_squared_error(
  ...    labels=y_true,
  ...    predictions=y_pred,
  ...    weights=weights,
  ...    reduction=tf.compat.v1.losses.Reduction.SUM_OVER_BATCH_SIZE).numpy()
  0.66667

  After:

  >>> y_true = [[1.0], [2.0], [3.0]]
  >>> y_pred = [[1.0], [3.0], [5.0]]
  >>> weights = [1, 1, 0.25]
  >>> mse = tf.keras.losses.MeanSquaredError(
  ...    reduction=tf.keras.losses.Reduction.SUM_OVER_BATCH_SIZE)
  >>> mse(y_true=y_true, y_pred=y_pred, sample_weight=weights).numpy()
  0.66667

  @end_compatibility
  """
  if labels is None:
    raise ValueError("Argument `labels` must not be None.")
  if predictions is None:
    raise ValueError("Argument `predictions` must not be None.")
  with ops.name_scope(scope, "mean_squared_error",
                      (predictions, labels, weights)) as scope:
    predictions = math_ops.cast(predictions, dtype=dtypes.float32)
    labels = math_ops.cast(labels, dtype=dtypes.float32)
    predictions.get_shape().assert_is_compatible_with(labels.get_shape())
    losses = math_ops.squared_difference(predictions, labels)
    return compute_weighted_loss(
        losses, weights, scope, loss_collection, reduction=reduction)

@tf_export(v1=["losses.sigmoid_cross_entropy"])
@dispatch.add_dispatch_support
def sigmoid_cross_entropy(
    multi_class_labels, logits, weights=1.0, label_smoothing=0, scope=None,
    loss_collection=ops.GraphKeys.LOSSES,
    reduction=Reduction.SUM_BY_NONZERO_WEIGHTS):
  """Creates a cross-entropy loss using tf.nn.sigmoid_cross_entropy_with_logits.

  `weights` acts as a coefficient for the loss. If a scalar is provided,
  then the loss is simply scaled by the given value. If `weights` is a
  tensor of shape `[batch_size]`, then the loss weights apply to each
  corresponding sample.

  If `label_smoothing` is nonzero, smooth the labels towards 1/2:

      new_multiclass_labels = multiclass_labels * (1 - label_smoothing)
                              + 0.5 * label_smoothing

  Args:
    multi_class_labels: `[batch_size, num_classes]` target integer labels in
      `{0, 1}`.
    logits: Float `[batch_size, num_classes]` logits outputs of the network.
    weights: Optional `Tensor` whose rank is either 0, or the same rank as
    `multi_class_labels`, and must be broadcastable to `multi_class_labels`
    (i.e., all dimensions must be either `1`, or the same as the
    corresponding `losses` dimension).
    label_smoothing: If greater than `0` then smooth the labels.
    scope: The scope for the operations performed in computing the loss.
    loss_collection: collection to which the loss will be added.
    reduction: Type of reduction to apply to loss.

  Returns:
    Weighted loss `Tensor` of the same type as `logits`. If `reduction` is
    `NONE`, this has the same shape as `logits`; otherwise, it is scalar.

  Raises:
    ValueError: If the shape of `logits` doesn't match that of
      `multi_class_labels` or if the shape of `weights` is invalid, or if
      `weights` is None.  Also if `multi_class_labels` or `logits` is None.

  @compatibility(eager)
  The `loss_collection` argument is ignored when executing eagerly. Consider
  holding on to the return value or collecting losses via a `tf.keras.Model`.
  @end_compatibility
  """
  if multi_class_labels is None:
    raise ValueError("Argument `multi_class_labels` must not be None.")
  if logits is None:
    raise ValueError("Argument `logits` must not be None.")
  with ops.name_scope(scope, "sigmoid_cross_entropy_loss",
                      (logits, multi_class_labels, weights)) as scope:
    logits = ops.convert_to_tensor(logits)
    multi_class_labels = math_ops.cast(multi_class_labels, logits.dtype)
    logits.get_shape().assert_is_compatible_with(multi_class_labels.get_shape())

    if label_smoothing > 0:
      multi_class_labels = (multi_class_labels * (1 - label_smoothing) +
                            0.5 * label_smoothing)

    losses = nn.sigmoid_cross_entropy_with_logits(labels=multi_class_labels,
                                                  logits=logits,
                                                  name="xentropy")
    return compute_weighted_loss(
        losses, weights, scope, loss_collection, reduction=reduction)

@tf_export(v1=["losses.softmax_cross_entropy"])
@dispatch.add_dispatch_support
def softmax_cross_entropy(
    onehot_labels, logits, weights=1.0, label_smoothing=0, scope=None,
    loss_collection=ops.GraphKeys.LOSSES,
    reduction=Reduction.SUM_BY_NONZERO_WEIGHTS):
  r"""Creates a cross-entropy loss using tf.nn.softmax_cross_entropy_with_logits_v2.

  `weights` acts as a coefficient for the loss. If a scalar is provided,
  then the loss is simply scaled by the given value. If `weights` is a
  tensor of shape `[batch_size]`, then the loss weights apply to each
  corresponding sample.

  If `label_smoothing` is nonzero, smooth the labels towards 1/num_classes:
      new_onehot_labels = onehot_labels * (1 - label_smoothing)
                          + label_smoothing / num_classes

  Note that `onehot_labels` and `logits` must have the same shape,
  e.g. `[batch_size, num_classes]`. The shape of `weights` must be
  broadcastable to loss, whose shape is decided by the shape of `logits`.
  In case the shape of `logits` is `[batch_size, num_classes]`, loss is
  a `Tensor` of shape `[batch_size]`.

  Args:
    onehot_labels: One-hot-encoded labels.
    logits: Logits outputs of the network.
    weights: Optional `Tensor` that is broadcastable to loss.
    label_smoothing: If greater than 0 then smooth the labels.
    scope: the scope for the operations performed in computing the loss.
    loss_collection: collection to which the loss will be added.
    reduction: Type of reduction to apply to loss.

  Returns:
    Weighted loss `Tensor` of the same type as `logits`. If `reduction` is
    `NONE`, this has shape `[batch_size]`; otherwise, it is scalar.

  Raises:
    ValueError: If the shape of `logits` doesn't match that of `onehot_labels`
      or if the shape of `weights` is invalid or if `weights` is None.  Also if
      `onehot_labels` or `logits` is None.

  @compatibility(TF2)

  `tf.compat.v1.losses.softmax_cross_entropy` is mostly compatible with eager
  execution and `tf.function`. But, the `loss_collection` argument is
  ignored when executing eagerly and no loss will be written to the loss
  collections. You will need to either hold on to the return value manually
  or rely on `tf.keras.Model` loss tracking.

  To switch to native TF2 style, instantiate the
   `tf.keras.losses.CategoricalCrossentropy` class with `from_logits` set
  as `True` and call the object instead.

  #### Structural Mapping to Native TF2

  Before:

  ```python
  loss = tf.compat.v1.losses.softmax_cross_entropy(
    onehot_labels=onehot_labels,
    logits=logits,
    weights=weights,
    label_smoothing=smoothing)
  ```

  After:

  ```python
  loss_fn = tf.keras.losses.CategoricalCrossentropy(
    from_logits=True,
    label_smoothing=smoothing)
  loss = loss_fn(
    y_true=onehot_labels,
    y_pred=logits,
    sample_weight=weights)
  ```

  #### How to Map Arguments

  | TF1 Arg Name          | TF2 Arg Name     | Note                       |
  | :-------------------- | :--------------- | :------------------------- |
  |  -                    | `from_logits`    | Set `from_logits` as True  |
  :                       :                  : to have identical behavior :
  | `onehot_labels`       | `y_true`         | In `__call__()` method     |
  | `logits`              | `y_pred`         | In `__call__()` method     |
  | `weights`             | `sample_weight`  | In `__call__()` method     |
  | `label_smoothing`     | `label_smoothing`| In constructor             |
  | `scope`               | Not supported    | -                          |
  | `loss_collection`     | Not supported    | Losses should be tracked   |
  :                       :                  : explicitly or with Keras   :
  :                       :                  : APIs, for example,         :
  :                       :                  : [add_loss][add_loss],      :
  :                       :                  : instead of via collections :
  | `reduction`           | `reduction`      | In constructor. Value of   |
  : : : `tf.compat.v1.losses.Reduction.SUM_OVER_BATCH_SIZE`,              :
  : : : `tf.compat.v1.losses.Reduction.SUM`,                              :
  : : : `tf.compat.v1.losses.Reduction.NONE` in                           :
  : : : `tf.compat.v1.losses.softmax_cross_entropy` correspond to         :
  : : : `tf.keras.losses.Reduction.SUM_OVER_BATCH_SIZE`,                  :
  : : : `tf.keras.losses.Reduction.SUM`,                                  :
  : : : `tf.keras.losses.Reduction.NONE`, respectively. If you            :
  : : : used other value for `reduction`, including the default value     :
  : : :  `tf.compat.v1.losses.Reduction.SUM_BY_NONZERO_WEIGHTS`, there is :
  : : : no directly corresponding value. Please modify the loss           :
  : : : implementation manually.                                          :

  [add_loss]:https://www.tensorflow.org/api_docs/python/tf/keras/layers/Layer#add_loss

  #### Before & After Usage Example

  Before:

  >>> y_true = [[0, 1, 0], [0, 0, 1]]
  >>> y_pred = [[0.05, 0.95, 0], [0.1, 0.8, 0.1]]
  >>> weights = [0.3, 0.7]
  >>> smoothing = 0.2
  >>> tf.compat.v1.losses.softmax_cross_entropy(y_true, y_pred, weights=weights,
  ...   label_smoothing=smoothing).numpy()
  0.57618

  After:

  >>> cce = tf.keras.losses.CategoricalCrossentropy(from_logits=True,
  ...   label_smoothing=smoothing)
  >>> cce(y_true, y_pred, sample_weight=weights).numpy()
  0.57618

  @end_compatibility
  """
  if onehot_labels is None:
    raise ValueError("Argument `onehot_labels` must not be None.")
  if logits is None:
    raise ValueError("Argument `logits` must not be None.")
  with ops.name_scope(scope, "softmax_cross_entropy_loss",
                      (logits, onehot_labels, weights)) as scope:
    logits = ops.convert_to_tensor(logits)
    onehot_labels = math_ops.cast(onehot_labels, logits.dtype)
    logits.get_shape().assert_is_compatible_with(onehot_labels.get_shape())

    if label_smoothing > 0:
      num_classes = math_ops.cast(
          array_ops.shape(onehot_labels)[-1], logits.dtype)
      smooth_positives = 1.0 - label_smoothing
      smooth_negatives = label_smoothing / num_classes
      onehot_labels = onehot_labels * smooth_positives + smooth_negatives

    onehot_labels = array_ops.stop_gradient(
        onehot_labels, name="labels_stop_gradient")
    losses = nn.softmax_cross_entropy_with_logits_v2(
        labels=onehot_labels, logits=logits, name="xentropy")

    return compute_weighted_loss(
        losses, weights, scope, loss_collection, reduction=reduction)

# TODO(ptucker): Merge this with similar method in metrics_impl.
def _remove_squeezable_dimensions(
    labels, predictions, weights=None, expected_rank_diff=0):
  """Internal version of _remove_squeezable_dimensions which handles weights.

  Squeezes `predictions` and `labels` if their ranks differ from expected by
  exactly 1.
  Squeezes `weights` if its rank is 1 more than the new rank of `predictions`

  This will use static shape if available. Otherwise, it will add graph
  operations, which could result in a performance hit.

  Args:
    labels: Label values, a `Tensor` whose dimensions match `predictions`.
    predictions: Predicted values, a `Tensor` of arbitrary dimensions.
    weights: Optional weight `Tensor`. It will be squeezed if it's not scalar,
      and its rank is 1 more than the new rank of `labels`.
    expected_rank_diff: Expected result of `rank(predictions) - rank(labels)`.

  Returns:
    Tuple of `predictions`, `labels` and `weights`, possibly with the last
    dimension squeezed.
  """
  labels, predictions = confusion_matrix.remove_squeezable_dimensions(
      labels, predictions, expected_rank_diff=expected_rank_diff)

  if weights is not None:
    weights = ops.convert_to_tensor(weights)
    labels_rank = labels.get_shape().ndims
    weights_shape = weights.get_shape()
    weights_rank = weights_shape.ndims

    if (labels_rank is not None) and (weights_rank is not None):
      # Use static rank.
      rank_diff = weights_rank - labels_rank
      if rank_diff == 1:
        weights = array_ops.squeeze(weights, [-1])
      return labels, predictions, weights

    # Use dynamic rank.
    rank_diff = array_ops.rank(weights) - array_ops.rank(labels)
    if (weights_rank is None) or (
        weights_rank > 0 and weights_shape.dims[-1].is_compatible_with(1)):
      weights = cond.cond(
          math_ops.equal(1, rank_diff),
          lambda: array_ops.squeeze(weights, [-1]),
          lambda: weights)

  return labels, predictions, weights

@tf_export(v1=["losses.sparse_softmax_cross_entropy"])
@dispatch.add_dispatch_support
def sparse_softmax_cross_entropy(
    labels, logits, weights=1.0, scope=None,
    loss_collection=ops.GraphKeys.LOSSES,
    reduction=Reduction.SUM_BY_NONZERO_WEIGHTS):
  """Cross-entropy loss using `tf.nn.sparse_softmax_cross_entropy_with_logits`.

  `weights` acts as a coefficient for the loss. If a scalar is provided,
  then the loss is simply scaled by the given value. If `weights` is a
  tensor of shape `[batch_size]`, then the loss weights apply to each
  corresponding sample.

  Args:
    labels: `Tensor` of shape `[d_0, d_1, ..., d_{r-1}]` (where `r` is rank of
      `labels` and result) and dtype `int32` or `int64`. Each entry in `labels`
      must be an index in `[0, num_classes)`. Other values will raise an
      exception when this op is run on CPU, and return `NaN` for corresponding
      loss and gradient rows on GPU.
    logits: Unscaled log probabilities of shape
      `[d_0, d_1, ..., d_{r-1}, num_classes]` and dtype `float16`, `float32` or
      `float64`.
    weights: Coefficients for the loss. This must be scalar or broadcastable to
      `labels` (i.e. same rank and each dimension is either 1 or the same).
    scope: the scope for the operations performed in computing the loss.
    loss_collection: collection to which the loss will be added.
    reduction: Type of reduction to apply to loss.

  Returns:
    Weighted loss `Tensor` of the same type as `logits`. If `reduction` is
    `NONE`, this has the same shape as `labels`; otherwise, it is scalar.

  Raises:
    ValueError: If the shapes of `logits`, `labels`, and `weights` are
      incompatible, or if any of them are None.

  @compatibility(eager)
  The `loss_collection` argument is ignored when executing eagerly. Consider
  holding on to the return value or collecting losses via a `tf.keras.Model`.
  @end_compatibility
  """
  if labels is None:
    raise ValueError("Argument `labels` must not be None.")
  if logits is None:
    raise ValueError("Argument `logits` must not be None.")
  with ops.name_scope(scope, "sparse_softmax_cross_entropy_loss",
                      (logits, labels, weights)) as scope:
    # As documented above in Args, labels contain class IDs and logits contains
    # 1 probability per class ID, so we expect rank(logits) - rank(labels) == 1;
    # therefore, expected_rank_diff=1.
    labels, logits, weights = _remove_squeezable_dimensions(
        labels, logits, weights, expected_rank_diff=1)
    losses = nn.sparse_softmax_cross_entropy_with_logits(labels=labels,
                                                         logits=logits,
                                                         name="xentropy")
    return compute_weighted_loss(
        losses, weights, scope, loss_collection, reduction=reduction)


from selenium import webdriver
from fake_useragent import UserAgent
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException
from colorama import Fore
from time import sleep
import os

magenta = Fore.BLUE
red = Fore.RED
green = Fore.GREEN
reset = Fore.RESET

useragent = UserAgent()

WINDOW_SIZE = "1920,1080"
options = webdriver.ChromeOptions()
options.headless = True
options.add_argument(f"user-agent={useragent.chrome}")
options.add_argument("--window-size=%s" % WINDOW_SIZE)
options.add_experimental_option('excludeSwitches', ['enable-logging'])
options.add_experimental_option('detach', True)

os.system("cls")
print(f"""{magenta}
Telegram channel - https://t.me/mctsh\n
Donate (ERC20) - 0xdd8185984AC02E5d9394a278d23271Fb1C9DC54c\n""")

Maillist = open("mails.txt", "r").readlines()
print('Opening a mails file...')

for combo in Maillist:
    seq = combo.strip()
    acc = seq

    Mail = acc

    driver = webdriver.Chrome(options=options, executable_path=r'chromedriver.exe')
    driver.get("https://www.moonpay.com/web3-passport")
    sleep(0.1)

    usernameInput = driver.find_element(By.CLASS_NAME, 'newsletter_email__RNnZ_')
    usernameInput.send_keys(Mail)
    print('Successfully Pasted An Email, now clicking on cookie...')
    sleep(0.1)
    CookieClick = driver.find_element(By.ID , 'onetrust-accept-btn-handler')
    CookieClick.click()
    print('Successfully Clicked on Cookie, now clicking on CheckBox...')
    sleep(0.1)
    CheckBoxClick = driver.find_element(By.CLASS_NAME, 'newsletter_checkbox__p2LO8')
    CheckBoxClick.click()
    print('Successfully Clicked on CheckBox, sending a request...')
    sleep(0.1)
    lBtn = driver.find_element(By.XPATH, "//*[@id='__next']/div[1]/div/section[1]/div/div[1]/form/div[1]/button")
    lBtn.click()
    print('Successfully Sent a Request, now checking if everything works fine...')
    sleep(0.1)
    try:
        driver.find_element(By.CLASS_NAME, "newsletter_newsletterSubmitted__TYyPD hero_newsletter__q_4M6")
        sleep(5)
        driver.close()
        print(f"[!] {red}BAD: {combo} {reset}")
    except NoSuchElementException:
        print(f"[!] {green}GOOD: {combo} {reset}")
        driver.close()

    input('Proccess is finished, Press ENTER to exit')


import time
import matplotlib.pyplot as plt

class Node:
    def __init__(self, node_number, x, y):
        self.node_number = str(node_number)
        self.x = float(x)
        self.y = float(y)

    def __str__(self):
        return "Node " + self.node_number

class Graph:
    global city_name
    def __init__(self, node_list, algo_name : str = None, tour = []):
        self.node_list = node_list
        self.city_name = city_name
        self.algo_name = algo_name
        self.tour = tour

    def draw(self):
        plt.figure(figsize = (14,7))
        plt.scatter([item.x for item in node_list], [item.y for item in self.node_list], color = 'blue')

        for n in range(dim):
            plt.annotate(str(n), xy=(self.node_list[n].x, self.node_list[n].y), xytext = (self.node_list[n].x-0.1, self.node_list[n].y+0.1), color = 'black')

        if len(self.tour) != 0:
            for n in range(len(self.tour)-1):
                point1 = [self.node_list[self.tour[n]].x,self.node_list[self.tour[n+1]].x]
                point2 = [self.node_list[self.tour[n]].y,self.node_list[self.tour[n+1]].y]
                plt.plot(point1, point2, color= 'red')

        plt.xlabel("X")
        plt.ylabel("Y")
        if self.algo_name is None:
            plt.title("Graph for nodes in {0} data set".format(self.city_name))
        else:
            plt.title("Graph for nodes in {0} data set using the {1} algorithm".format(self.city_name, self.algo_name))
        return plt.show()

def total_distance(tour, distances):
    distance = 0
    for n in range(len(tour)-1):
        distance += distances[(tour[n],tour[n+1])]
    return distance

def nearest_neighbor(node_list, distances, dim, starting_node=0):
    res = [starting_node]

    while len(res) < dim:
        i = res[-1]
        nn = {(i,j): distances[(i,j)] for j in range(dim) if j != i and j not in res}
        new_edge = min(nn.items(), key = lambda x: x[1])
        res.append(new_edge[0][1])

    res.append(starting_node)
    return res, total_distance(res, distances)

def algo_2opt(avail_tour, distances):

    for i in range(len(avail_tour) - 2):
        optimal_change = 0
        for j in range(i+2, len(avail_tour)-1):
            old_cost = distances[(avail_tour[i], avail_tour[i+1])] + distances[(avail_tour[j], avail_tour[j+1])]
            new_cost = distances[(avail_tour[i], avail_tour[j])] + distances[(avail_tour[i+1], avail_tour[j+1])]
            change = new_cost - old_cost

            if change < optimal_change:
                optimal_change = change
                optimal_i, optimal_j = i, j

        #if we found an optimal swapped edges (just one optimal pair for each node i), then update the tour
        if optimal_change < 0:
            avail_tour[optimal_i+1:optimal_j+1] = avail_tour[optimal_i+1:optimal_j+1][::-1]

    return avail_tour, total_distance(avail_tour, distances)

if __name__ == "__main__":
    file_name = input("Enter the name of the data set you want to use: ")
    if file_name[-4:] != ".tsp":
        file_name += ".tsp"

    with open("data_set/" + file_name, 'r') as file:
        for line in file:
            if line.startswith("NAME"):
                city_name = line.strip().split()[-1]
            elif line.startswith("DIMENSION"):
                dim = int(line.strip().split()[-1])
            elif line.startswith("NODE_COORD"):
                # A list of node objects
                node_list = []
                # A list contains tuples of edge
                node_edges = [(i,j) for i in range(dim) for j in range(dim) if i!=j]
                for i in range(int(dim)):
                    node, x, y = next(file).strip().split()
                    node_list.append(Node(int(node)-1,x,y))

    basic_graph = Graph(node_list)
    basic_graph.draw()

    distances = {(i,j):((node_list[i].x-node_list[j].x)**2 + (node_list[i].y-node_list[j].y)**2)**0.5 for i,j in node_edges}

    #timer on, nearest_neighbor, timer off
    start_time = time.time()
    tour_nn, tour_nn_distance = nearest_neighbor(node_list, distances, dim)
    finish_time = time.time()

    time_taken = finish_time - start_time

    #Make a graph of connected nodes
    tour_nn_graph = Graph(node_list, "Nearest-Neighbor", tour_nn)
    print("Nearest-Neighbor tour: {0}\nTotal tour distance: {1}\nTime complexity: O(n^2)\nActual time taken: {2}".format(tour_nn, tour_nn_distance, time_taken))
    tour_nn_graph.draw()

    tour_nn_clone = tour_nn[:]

    #timer on, 2-opt, timer off
    start_time = time.time()
    tour_2opt, tour_2opt_distance = algo_2opt(tour_nn_clone, distances)
    finish_time = time.time()

    time_taken = finish_time - start_time

    #Make a graph of connected nodes
    tour_2opt_graph = Graph(node_list, "2-opt", tour_2opt)

    print("2-opt tour: {0}\nTotal tour distance: {1}\nTime complexity: O(n^2)\nActual time taken: {2}".format(tour_2opt, tour_2opt_distance, time_taken))
    tour_2opt_graph.draw()


#Servidor

from socket import *

servidor = socket(AF_INET, SOCK_STREAM)
tuplaEscuta = ('',12000)
servidor.bind( tuplaEscuta )
servidor.listen(True)

# [matricula, nome, valorHora, horas]

dadosFolha = []
dadosFolha.append([1, "Cebolinha", 12.00, 40])
dadosFolha.append([2, "Cascão"   , 11.30, 40])
dadosFolha.append([3, "Xaveco"   , 8.90 , 30])

while True:
    conexao, endereco = servidor.accept()

    mensagem = conexao.recv(1024)
    mensagem = mensagem.decode()

    comando = mensagem[0]

    if comando == "M":
        msgEmPartes = mensagem.split("-")
        matricula   = int(msgEmPartes[1])

        resposta = "NE"
        for registro in dadosFolha:
            if registro[0] == matricula :
                resposta = "R-" + str(registro[0]) + "-" + registro[1] + "-" + str(registro[2]) + "-" + str(registro[3])

    elif comando == "C":
        # cadastra um funcionário
        resp = "NI"
    else:
        # comando não reconhecido
        resposta = "NR"

    print("Recebido: ", mensagem)
    print("Respondido: ", resposta)
    print(" ")
    resposta = resposta.encode()
    conexao.send(resposta)
    conexao.close()


import pygame
from classes.window import Window

class Tutorial(Window):
    def __init__(self, bg_image_path, caption, text) -> None:
        self.text = text
        super().__init__(bg_image_path, caption=caption)

    def blit_rect(self) -> None:
        x = 1 / 8 * self.WIDTH
        y = 1 / 8 * self.HEIGHT
        width = 3 / 4 * self.WIDTH
        height = 3 / 4 * self.HEIGHT
        pygame.draw.rect(self.screen, self.DARK_GRAY, (x, y, width, height))

        pygame.draw.line(self.screen, self.LIGHT_GRAY, (x, y), (x + width, y), 4)
        pygame.draw.line(
            self.screen, self.LIGHT_GRAY, (x, y + height), (x + width, y + height), 4
        )
        pygame.draw.line(self.screen, self.LIGHT_GRAY, (x, y), (x, y + height), 4)
        pygame.draw.line(
            self.screen, self.LIGHT_GRAY, (x + width, y), (x + width, y + height), 4
        )

        text = "[click anywhere to continue]"
        text_surface = self.render_text(text, int(self.WIDTH * 0.03), self.TEXT_COLOR)
        self.blit_text(text_surface, 0.5 * self.WIDTH, 0.83 * self.HEIGHT, "center")
        return

    def blit_lines(self, lines: [str]) -> None:
        for line in lines:
            pass
        return

    def run(self):
        running = True
        while running:
            for event in pygame.event.get():
                if event.type == pygame.KEYDOWN:
                    running = False
                if event.type == pygame.MOUSEBUTTONDOWN:
                    running = False
                if event.type == pygame.QUIT:
                    pygame.quit()
                    return

            self.screen.blit(self.bg_image, (0, 0))
            self.blit_rect()
            lines = self.divide_text_in_lines(self.text, 15)
            self.blit_lines(lines)

            pygame.display.update()
            self.clock.tick(60)
        return


import datasets
import numpy as np
import pandas as pd
import torch
from torch.utils.data.dataset import Dataset
from tqdm import tqdm

class JigsawData(Dataset):
    """Base dataloader for the Jigsaw Toxic Comment Classification Challenges."""

    def __init__(self, train_csv_file, test_csv_file, train=True, add_test_labels=False):
        if train:
            self.train_set_pd = self.load_data(train_csv_file)
            self.train_set = datasets.Dataset.from_pandas(self.train_set_pd)
            self.data = self.train_set
        else:
            self.data = self.load_val(test_csv_file, add_labels=add_test_labels)

        self.train = train

    def __len__(self):
        return len(self.data)

    def load_data(self, csv_file):
        change_names = {
            "target": "toxicity",
            "toxic": "toxicity",
            "identity_hate": "identity_attack",
            "severe_toxic": "severe_toxicity",
        }
        if isinstance(csv_file, list):
            files = []
            for file in tqdm(csv_file):
                chunks = []
                for chunk in pd.read_csv(file, chunksize=100000):
                    chunks.append(chunk)

                file_df = pd.concat(chunks, axis=0)
                filtered_change_names = {k: v for k, v in change_names.items() if k in file_df.columns}
                if len(filtered_change_names) > 0:
                    file_df.rename(columns=filtered_change_names, inplace=True)
                file_df = file_df.astype({"id": "string"})
                files.append(file_df)

            final_df = pd.concat(files, join="outer")
        elif isinstance(csv_file, str):
            final_df = pd.read_csv(csv_file)
            filtered_change_names = {k: v for k, v in change_names.items() if k in final_df.columns}
            if len(filtered_change_names) > 0:
                final_df.rename(columns=filtered_change_names, inplace=True)
        return final_df

    def load_val(self, test_csv_file, add_labels=False):
        val_set = self.load_data(test_csv_file)
        if add_labels:
            data_labels = pd.read_csv(test_csv_file[:-4] + "_labels.csv")
            for category in data_labels.columns[1:]:
                val_set[category] = data_labels[category]
        val_set = datasets.Dataset.from_pandas(val_set)
        return val_set

    def filter_entry_labels(self, entry, classes, threshold=0.5, soft_labels=False):
        target = {label: -1 if label not in entry or entry[label] is None else entry[label] for label in classes}
        if not soft_labels:
            target.update({label: 1 for label in target if target[label] >= threshold})
            target.update({label: 0 for label in target if 0 <= target[label] < threshold})
        return target

class JigsawDataOriginal(JigsawData):
    """Dataloader for the original Jigsaw Toxic Comment Classification Challenge.
    Source: https://www.kaggle.com/c/jigsaw-toxic-comment-classification-challenge
    """

    def __init__(
        self,
        train_csv_file="jigsaw_data/train.csv",
        test_csv_file="jigsaw_data/test.csv",
        train=True,
        add_test_labels=True,
        classes=["toxic"],
    ):

        super().__init__(
            train_csv_file=train_csv_file,
            test_csv_file=test_csv_file,
            train=train,
            add_test_labels=add_test_labels,
        )
        self.classes = classes

    def __getitem__(self, index):
        meta = {}
        entry = self.data[index]
        text_id = entry["id"]
        text = entry["comment_text"]

        target_dict = {label: value for label, value in entry.items() if label in self.classes}

        meta["multi_target"] = torch.tensor(list(target_dict.values()), dtype=torch.int32)
        meta["text_id"] = text_id

        return text, meta

class JigsawDataBias(JigsawData):
    """Dataloader for the Jigsaw Unintended Bias in Toxicity Classification.
    Source: https://www.kaggle.com/c/jigsaw-unintended-bias-in-toxicity-classification/
    """

    def __init__(
        self,
        train_csv_file="jigsaw_data/train.csv",
        test_csv_file="jigsaw_data/test.csv",
        train=True,
        compute_bias_weights=True,
        loss_weight=0.75,
        classes=["toxic"],
        identity_classes=["female"],
        soft_labels=False,
    ):

        self.classes = classes
        self.soft_labels = soft_labels
        self.identity_classes = identity_classes

        super().__init__(train_csv_file=train_csv_file, test_csv_file=test_csv_file, train=train)
        if train:
            if compute_bias_weights:
                self.weights = self.compute_weigths(self.train_set_pd)
            else:
                self.weights = None

        self.train = train
        self.loss_weight = loss_weight

    def __getitem__(self, index):
        meta = {}
        entry = self.data[index]
        text_id = entry["id"]

        if "translated" in entry:
            text = entry["translated"]
        elif "comment_text_en" in entry:
            text = entry["comment_text_en"]
        else:
            text = entry["comment_text"]

        target_dict = self.filter_entry_labels(
            entry,
            self.classes + self.identity_classes,
            threshold=0.5,
            soft_labels=self.soft_labels,
        )
        meta["multi_target"] = torch.tensor(list(target_dict.values()), dtype=torch.float32)
        meta["text_id"] = text_id

        if self.train:
            meta["weights"] = self.weights[index]
            toxic_weight = self.weights[index] * self.loss_weight * 1.0 / len(self.classes)
            identity_weight = (1 - self.loss_weight) * 1.0 / len(self.identity_classes)
            meta["weights1"] = torch.tensor(
                [
                    *[toxic_weight] * len(self.classes),
                    *[identity_weight] * len(self.identity_classes),
                ]
            )

        return text, meta

    def compute_weigths(self, train_df):
        """Inspired from 2nd best solution.
        Source: https://www.kaggle.com/c/jigsaw-unintended-bias-in-toxicity-classification/discussion/100661"""
        subgroup_bool = (train_df[self.identity_classes].fillna(0) >= 0.5).sum(axis=1) > 0
        positive_bool = train_df["toxicity"] >= 0.5
        weights = np.ones(len(train_df)) * 0.25

        # Background Positive and Subgroup Negative
        # i.e. weigh higher toxic comments that don't mention identity and non toxic ones that mention it
        weights[((~subgroup_bool) & (positive_bool)) | ((subgroup_bool) & (~positive_bool))] += 0.25
        weights[(subgroup_bool)] += 0.25
        return weights

class JigsawDataMultilingual(JigsawData):
    """Dataloader for the Jigsaw Multilingual Toxic Comment Classification.
    Source: https://www.kaggle.com/c/jigsaw-multilingual-toxic-comment-classification/
    """

    def __init__(
        self,
        train_csv_file="jigsaw_data/multilingual_challenge/jigsaw-toxic-comment-train.csv",
        test_csv_file="jigsaw_data/multilingual_challenge/validation.csv",
        train=True,
        classes=["toxic"],
    ):

        self.classes = classes
        super().__init__(train_csv_file=train_csv_file, test_csv_file=test_csv_file, train=train)

    def __getitem__(self, index):
        meta = {}
        entry = self.data[index]
        text_id = entry["id"]
        if "translated" in entry:
            text = entry["translated"]
        elif "comment_text_en" in entry:
            text = entry["comment_text_en"]
        else:
            text = entry["comment_text"]

        target_dict = {label: 1 if entry[label] >= 0.5 else 0 for label in self.classes}
        meta["target"] = torch.tensor(list(target_dict.values()), dtype=torch.int32)
        meta["text_id"] = text_id

        return text, meta


import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Circle

n = 100000000
r = 1.0
a,b = (0.0,0.0)
xmin, xmax = a-r, a+r
ymin, ymax = b-r, b+r

x = np.random.uniform(xmin,xmax,n)
y = np.random.uniform(ymin,ymax,n)

fig = plt.figure(figsize=(6,6))
axes = fig.add_subplot(1,1,1)#添加子图
#画子图
plt.plot(x,y,'ko',markersize = 1) #plot绘图 markersize表示点的大小；‘ro’r表示red，o表示圆圈
plt.axis('equal')

d = np.sqrt((x-a)**2 + (y-a)**2)
#res 得到圆中的点数
res = sum(np.where(d<r,1,0)) #numpy.where(conditon,x,y) 满足条件输出x，不满足输出y

pi = res/n*4
print('pi=',pi)
#计算pi的近似值，蒙特卡洛模拟方法，用统计值去近似真实值

#绘制圆形子图
circle = Circle(xy = (a,b), radius = r,alpha = 0.5, color = 'gray')
axes.add_patch(circle)#添加圆形子图
plt.grid(True,linestyle = '--',linewidth = '0.8')
plt.show()


from django.conf.urls import *
from django.contrib.auth.decorators import login_required
from django.views.generic import TemplateView
from .views import (
    QuoteList, QuoteDetail, QuoteCreate, QuoteUpdate, QuoteDelete
)

urlpatterns = patterns(
    '',
    url(r'^$', login_required(QuoteList.as_view()), name='quote_list'),
    url(r'^new/$', login_required(QuoteCreate.as_view()), name='quote_add'),
    url(r'^app/$', TemplateView.as_view(template_name='quotes/app.html'), name='quotes_app'),
    url(r'^(?P<slug>[\d\w\_\-]+)/$', login_required(QuoteDetail.as_view()), name='quote_detail'),
    url(r'^(?P<slug>[\d\w\_\-]+)/edit/$', login_required(QuoteUpdate.as_view()), name='quote_edit'),
    url(r'^(?P<slug>[\d\w\_\-]+)/delete/$', login_required(QuoteDelete.as_view()), name='quote_delete'),
)


from django.conf.urls import url
from . import views

urlpatterns = [
	url(r'^$', views.index, name='index'),
    url(r'^post/(?P<pk>\d+)/$', views.post_detail, name='post_detail'),
    url(r'^post/new/$', views.post_new, name='post_new'),
	url(r'^about', views.about, name='about'),
	url(r'^blog', views.blog, name='blog'),
]


def matmult(m1,m2):
    r1=len(m1)
    r2=len(m2)
    c1=len(m1[0])
    c2=len(m2[0])
    li=[]
    for i in range(r1):
        li.append([])
    for i in range(r1):
        for j in range(c2):
            sum=0
            for k in range(r2):
                sum=sum+li[i][k]*li[k][j]
            li[i].append(sum)
    return (li)


#!usr/bin/env python
# -*- coding:utf-8 -*-
# @author: Johnathon Qiang
# @file  : parse.py
# @time  : 2017/09/26 17:41:51
# @description：to be filled
from bs4 import BeautifulSoup
from python_spider_action.mzitu_spider.download import download_v3
from python_spider_action.mzitu_spider.util import save_v3, mongoUtil, makedir
import datetime

class ParseHtml(object):
    def __init__(self):
        self.download = download_v3.DownHtml()
        self.mkdir = makedir.MakeDir()
        self.save = save_v3.SaveImg()
        self.dbclient = mongoUtil.MongoUtil().connect_mongo()  # 连接本地MongoDB
        self.picdb = self.dbclient['girl_gallery']  # 建立girl_gallery数据库
        self.picset = self.picdb['girl_pic']  # 建立girl_pic集合(相关于表结构)
        self.title = ''  # 保存页面主题
        self.url = ''  # 保存页面地址
        self.img_urls = []  # 初始化一个列表，用来保存图片地址

    def parse_main_page(self, base_url):
        """
        解析主页面
        :param base_url: http://www.mzitu.com/all/
        :return: 每一个a链接，比如韩国MMbebekim性感不失清新 尽显妩媚女人味!
        """
        print('开始爬取主页面{}'.format(base_url))
        main_page = self.download.download_html(base_url, 3)
        main_soup = BeautifulSoup(main_page.text, 'lxml')
        all_a = main_soup.find('div', class_='all').find_all('a')
        for a in all_a:
            title = a.get_text()
            self.title = title  # 将主题保存到self.title中
            print('开始保存：{}'.format(title))
            path = str(title)
            self.mkdir.makedirs(path)
            href = a['href']
            self.url = href  # 将页面地址保存到self.url中
            if self.picset.find_one({'主题页面': href}):
                print('该页面已经爬取过')
            else:
                self.parse_single_page(href)

    def parse_single_page(self, url):
        """
        解析每一组页面
        :param url: 举例：http://www.mzitu.com/103886
        :return:
        """
        print('开始第一层爬取: {}'.format(url))
        page = self.download.download_html(url, 3)
        soup = BeautifulSoup(page.text, 'lxml')
        max_page = soup.find('div', class_='pagenavi').find_all('span')[-2].get_text()
        page_num = 0  #这个当作计数器用 （用来判断图片是否下载完毕）

        for page in range(1, int(max_page) + 1):
            page_num += 1  # 每for循环一次就+1  （当page_num等于max_span的时候，就证明我们的在下载最后一张图片了）
            page_url = url + '/' + str(page)
            print('开始第二层爬取第{}页'.format(page))
            print(page_url)
            self.parse_img(page_url, max_page, page_num)

    def parse_img(self, img_pre_url, max_page, page_num):
        """
        解析每一组图片的每一个页面
        :param img_pre_url: 'http://www.mzitu.com/103886/1[2|3|...]'
        :return: 图片的链接地址src: 'http://i.meizitu.net/2017/09/25b01.jpg'
        """
        img_html = self.download.download_html(img_pre_url, 3)
        img_soup = BeautifulSoup(img_html.text, 'lxml')
        img_url = img_soup.find('div', class_='main-image').find('img')['src']
        self.img_urls.append(img_url)
        if int(max_page) == page_num:
            self.save.saveImg(img_url)
            post = {  # 这是构造一个字典，里面有啥都是中文，很好理解吧！
                '标题': self.title,
                '主题页面': self.url,
                '图片地址': self.img_urls,
                '获取时间': datetime.datetime.now()
            }
            self.picset.save(post)  # 将post中的内容写入数据库。
            print(u'插入数据库成功')
        else:
            self.save.saveImg(img_url)


"""
Приклад 4.2. Знайти індекс найбільшого елементу списку.
"""

# Блок введення списку з клавіатури
N = int(input("Кількість елементів списку "))
l = []            # Створюємо порожній список
for i in range(N):
    x = float(input("Задайте %d-й елемент списку " % (i)))
    l.append(x)   # Додаємо елемент х у список

# Знаходження максимального елементу разом з його індексом
max_elem = l[0] # 0-й елемент списку покладемо найбільшим
max_index = 0   # Індекс найбільшого елементу списку
for i in range(1, len(l)): # Проходимо всі елементи списку
    if max_elem < l[i]: # Якщо поточний максимум
                        # менший за поточний елемент
        max_elem = l[i] # змінюємо поточний максимум
        max_index = i   # змінюємо індекс максимального ел-ту
print("Найбільних елемент %d має індекс %d" % (max_elem, max_index))


'''
https://leetcode.com/problems/kth-smallest-element-in-a-sorted-matrix/
Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth smallest element in the matrix.
Note that it is the kth smallest element in the sorted order, not the kth distinct element.
'''
'''
Time:X+Klog(X).  X=min(K,N);
Space:O(X)
'''
class Solution:
    def kthSmallest(self, matrix: List[List[int]], k: int) -> int:
        n = len(matrix)
        l = []
        for i in range(min(n, k)):
            heapq.heappush(l, (matrix[i][0], i, 0))
        while k:
            num, r, c = heapq.heappop(l)
            if c<n-1:
                heapq.heappush(l, (matrix[r][c+1], r, c+1))
            k -= 1
        return num

378. Kth Smallest Element in a Sorted Matrix.py


from __future__ import annotations

from typing import Any, Callable, List, Protocol, Tuple, TypeVar, Union, Optional, Dict
from collections import defaultdict
from copy import copy

from attrs import define, Factory, frozen, evolve
import jax
from jax.interpreters.ad import JVPTracer
import jax.numpy as jnp
from interp.tools.jax_tree_util import default_is_leaf

from interp.tools.log import Logger, LoggerCacheAndModify, ModInfo, KeyIdxs, LogCache
import interp.tools.optional as op
from interp.tools.jax_util import stack_tree, sum_iter_nonempty, sum_iter_nonempty_allow_none

T = TypeVar("T")
ListStack = Union[T, List[T], List[List[T]]]

class GradModifierConf(Protocol):
    def get_mod(self, my_val: JVPTracer, all_vals: Dict[GradModifierConf, JVPTracer]) -> Optional[ModInfo]:
        ...

    def get_val(self) -> Optional[Union[jnp.ndarray, float]]:
        ...

    # TODO: maybe this should get moved outside protocol?
    def is_positive(self) -> bool:
        return True

    # python am.i.right
    def forget_type(self) -> GradModifierConf:
        return self

@define
class ModifierCollectionTreeNode:
    # none does nothing, can be nice if you aren't doing reduction
    # inner dim is always reduced over
    # doesn't make sense to only reduce over None
    confs: ListStack[GradModifierConf]
    next_item: ModifierCollectionTreeNodeStack = None

    # setting this changes the default for all descendants (who can override
    # this if desired)
    use_fwd: Optional[bool] = None

    positive: bool = True

    def term(self) -> ModifierCollectionTreeNode:
        return evolve(self, next_item=None)

    def next_item_node_check(self) -> ModifierCollectionTreeNode:
        return check_modifier_collection_tree_node(self.next_item)

    def next_item_list_node_check(self) -> List[ModifierCollectionTreeNode]:
        return check_list_modifier_collection_tree_node(self.next_item)

    def next_item_list_list_node_check(self) -> List[List[ModifierCollectionTreeNode]]:
        return check_list_list_modifier_collection_tree_node(self.next_item)

    def next_item_node_op_check(self) -> Optional[ModifierCollectionTreeNode]:
        return check_modifier_collection_tree_node_op(self.next_item)

    def next_item_list_node_op_check(self) -> List[Optional[ModifierCollectionTreeNode]]:
        return check_list_modifier_collection_tree_node_op(self.next_item)

    def next_item_list_list_node_op_check(self) -> List[List[Optional[ModifierCollectionTreeNode]]]:
        return check_list_list_modifier_collection_tree_node_op(self.next_item)

# maybe we shouldn't allow nones throughout stack? (makes some type stuff harder)
ModifierCollectionTreeNodeStack = ListStack[Optional[ModifierCollectionTreeNode]]

def check_modifier_collection_tree_node(x: ModifierCollectionTreeNodeStack) -> ModifierCollectionTreeNode:
    assert isinstance(x, ModifierCollectionTreeNode)
    return x

def check_list_modifier_collection_tree_node(xs: ModifierCollectionTreeNodeStack) -> List[ModifierCollectionTreeNode]:
    assert isinstance(xs, list)
    return [check_modifier_collection_tree_node(x) for x in xs]

def check_list_list_modifier_collection_tree_node(
    xs: ModifierCollectionTreeNodeStack,
) -> List[List[ModifierCollectionTreeNode]]:
    assert isinstance(xs, list)
    return [check_list_modifier_collection_tree_node(x) for x in xs]

def check_modifier_collection_tree_node_op(x: ModifierCollectionTreeNodeStack) -> Optional[ModifierCollectionTreeNode]:
    assert isinstance(x, ModifierCollectionTreeNode) or x is None
    return x

def check_list_modifier_collection_tree_node_op(
    xs: ModifierCollectionTreeNodeStack,
) -> List[Optional[ModifierCollectionTreeNode]]:
    assert isinstance(xs, list)
    return [check_modifier_collection_tree_node_op(x) for x in xs]

def check_list_list_modifier_collection_tree_node_op(
    xs: ModifierCollectionTreeNodeStack,
) -> List[List[Optional[ModifierCollectionTreeNode]]]:
    assert isinstance(xs, list)
    return [check_list_modifier_collection_tree_node_op(x) for x in xs]

@frozen
class TargetConf:
    log_key_idxs: KeyIdxs
    display_name: str = Factory(lambda self: self.log_key_idxs.key, takes_self=True)
    idx: Any = ...
    select_idx: Callable[[Any, Any], Any] = lambda v, idx: v[idx]

    def select(self, v):
        return self.select_idx(v, self.idx)

@define
class Query:
    targets: List[TargetConf]
    modifier_collection_tree: ModifierCollectionTreeNodeStack = None

    use_fwd: Optional[bool] = None
    allow_non_first_deriv: bool = False

def flatten_list_stack(l: ListStack[T]) -> Tuple[List[T], bool, int, defaultdict[int, int]]:
    out: List[T] = []
    add_dim = False
    num_buckets = 1
    flat_idx_to_bucket = defaultdict(int)
    if isinstance(l, list):
        assert len(l) > 0
        if isinstance(l[0], list):
            add_dim = True
            num_buckets = len(l)
            for bucket, xs in enumerate(l):
                assert isinstance(xs, list), "not all types the same!"
                for x in xs:
                    flat_idx_to_bucket[len(out)] = bucket
                    out.append(x)  # type: ignore
        else:
            for x in l:
                out.append(x)  # type: ignore
    else:
        out.append(l)

    assert len(out) > 0

    return out, add_dim, num_buckets, flat_idx_to_bucket

def stack_buckets(buckets: defaultdict[int, Any], num_buckets: int, add_dim: bool) -> Any:
    stacked = stack_tree(list(buckets[b] for b in range(num_buckets)), axis=-1)
    if not add_dim:
        stacked = jax.tree_util.tree_map(lambda x: x.squeeze(-1), stacked)
    return stacked

class Loggable(Protocol):
    def __call__(self, logger: Logger) -> Any:
        ...

def run_query(
    loggable: Loggable,
    query: Query,
    # copied each time, so effectively frozen...
    conf_vals: Dict[GradModifierConf, JVPTracer] = {},
    rec_call_from_deriv: bool = False,
) -> Dict[str, jnp.ndarray]:
    running_ret_vals: defaultdict[int, Optional[Dict[str, jnp.ndarray]]] = defaultdict(lambda: None)
    flattened_node, add_dim_node, num_buckets_node, flat_idx_to_bucket_node = flatten_list_stack(
        query.modifier_collection_tree
    )
    for i, modifier_collection_tree_node in enumerate(flattened_node):
        if modifier_collection_tree_node is None:
            logger = LoggerCacheAndModify()
            for t in query.targets:
                logger.add(t.log_key_idxs)
            for conf, val in conf_vals.items():
                mod_info = conf.get_mod(val, conf_vals)
                if mod_info is not None:
                    logger.add_mod(mod_info)
            cache: LogCache = loggable(logger=logger)
            out = {t.display_name: t.select(cache.get(t.log_key_idxs)) for t in query.targets}
        else:
            flattened_confs, add_dim_conf, num_buckets_conf, flat_idx_to_bucket_conf = flatten_list_stack(
                modifier_collection_tree_node.confs
            )
            conf_vals_this_iter = copy(conf_vals)

            is_deriv = any(conf.get_val() is not None for conf in flattened_confs)
            if rec_call_from_deriv and is_deriv:
                assert query.allow_non_first_deriv, "is non first deriv!"

            def func(vals):
                running_mul = 1.0
                assert len(vals) == len(flattened_confs)
                for conf, val in zip(flattened_confs, vals):
                    if conf.get_val() is None:
                        running_mul = running_mul + val
                    else:
                        assert conf not in conf_vals_this_iter, "duplicate conf along single path"

                    conf_vals_this_iter[conf] = val

                assert modifier_collection_tree_node is not None
                return jax.tree_map(
                    lambda v: running_mul * v,
                    run_query(
                        loggable,
                        evolve(query, modifier_collection_tree=modifier_collection_tree_node.next_item),
                        conf_vals=conf_vals_this_iter,
                        rec_call_from_deriv=is_deriv or rec_call_from_deriv,
                    ),
                )

            if is_deriv:
                use_fwd = op.unwrap_or(op.or_y(modifier_collection_tree_node.use_fwd, query.use_fwd), True)
                wrapped_func = (jax.jacfwd if use_fwd else jax.jacrev)(func)  # type: ignore[operator]
            else:
                wrapped_func = lambda vals: jax.tree_map(lambda x: [x for _ in vals], func(vals))

            unreduced_out: Dict[str, List[jnp.ndarray]] = wrapped_func(
                [op.unwrap_or(conf.get_val(), 0.0) for conf in flattened_confs]
            )

            def sum_and_bucket(xs):
                buckets: defaultdict[int, Optional[jnp.ndarray]] = defaultdict(lambda: None)
                for j, (x, conf) in enumerate(zip(xs, flattened_confs)):
                    conf_bucket = flat_idx_to_bucket_conf[j]
                    buckets[conf_bucket] = sum_iter_nonempty_allow_none(
                        [buckets[conf_bucket], x if conf.is_positive() else -x]
                    )

                return stack_buckets(buckets, num_buckets_conf, add_dim_conf)

            out = {k: sum_and_bucket(v) for k, v in unreduced_out.items()}

        modifier_collection_tree_bucket = flat_idx_to_bucket_node[i]
        running_ret_vals[modifier_collection_tree_bucket] = jax.tree_util.tree_map(
            lambda x, *running: sum_iter_nonempty(
                [x if modifier_collection_tree_node is None or modifier_collection_tree_node.positive else -x, *running]
            ),
            out,
            *op.it(running_ret_vals[modifier_collection_tree_bucket])
        )

    # hmm, might need to use aux data!
    return stack_buckets(running_ret_vals, num_buckets_node, add_dim_node)

def run_queries(
    loggable: Loggable,
    queries: Dict[str, Query],
    use_fwd: Optional[bool] = None,
) -> Dict[str, Dict[str, jnp.ndarray]]:
    return {
        n: run_query(
            loggable,
            evolve(query, use_fwd=op.or_y(query.use_fwd, use_fwd)),
        )
        for n, query in queries.items()
    }


#Grupo da Maioridade

import datetime
data = datetime.date.today().year
ano = 0
maior = 0
menor = 0
for c in range(1, 8):
    ano = int(input(f'Digite a {c}º data: '))
    idade = data - ano
    if idade >= 18:
        maior = maior + 1
    else:
        menor = menor + 1
print(f'{maior} Pessoas são de maior\n{menor} Pessoas são de menor.')


from pyspark     import SparkContext, SparkConf
from time        import time
import sys
import math
import csv

class Task2Point1():

    def __init__(self):
        self.pearson_similarities = {}

    def setup(self):
        conf = SparkConf().setAppName('DM_assign3_task2point1').setMaster('local[*]')
        sc   = SparkContext.getOrCreate(conf = conf)

        sc.setSystemProperty('spark.driver.memory', '4g')
        sc.setSystemProperty('spark.executor.memory', '4g')
        sc.setLogLevel('ERROR')

        return sc

    def create_rdd_from_file(self, sc, file):

        rdd                = sc.textFile(file).map(lambda row : row.split(','))
        csv_header_data    = rdd.first()
        rdd                = rdd.filter(lambda row : row != csv_header_data)

        return rdd

    def read_and_pre_process_input_file(self, sc):

        training_file, test_file, output_file = sys.argv[1], sys.argv[2], sys.argv[3]

        training_data_rdd = self.create_rdd_from_file(sc, training_file).map(lambda row : (row[0], row[1], float(row[2])))
        test_data_rdd     = self.create_rdd_from_file(sc, test_file).map(lambda row : (row[0], row[1]))
        return training_data_rdd, test_data_rdd, output_file

    def generate_training_data_maps(self, training_data_rdd):

        self.user_biz_rating_map = training_data_rdd.map(lambda row : (row[0], [(row[1],row[2])]))\
                                               .reduceByKey(lambda row1, row2 : row1 + row2)\
                                               .collectAsMap()

        self.biz_user_rating_map = training_data_rdd.map(lambda row : (row[1], [(row[0],row[2])]))\
                                               .reduceByKey(lambda row1, row2 : row1 + row2)\
                                               .collectAsMap()

    # def find_all_rated_businesses(self, uid, user_biz_rating_map):

    #     biz_rating_list = user_biz_rating_map.get(uid)

    #     return [biz_rating[0] for biz_rating in biz_rating_list]

    def find_all_users_rating_this_business(self, bid, biz_user_rating_map):

        user_rating_list = biz_user_rating_map.get(bid)

        return set(user_rating[0] for user_rating in user_rating_list)

    def evaluate_pearson_similarity(self, bid, business):

        # Similarity already calculated for the business
        key_tuple = tuple(sorted((bid, business)))
        if key_tuple in self.pearson_similarities:
            return self.pearson_similarities[key_tuple]

        user_set_for_bid      = self.find_all_users_rating_this_business(bid, self.biz_user_rating_map)
        user_set_for_business = self.find_all_users_rating_this_business(business, self.biz_user_rating_map)

        # find the U for evaluating pearson similarity
        common_user_set       = user_set_for_bid.intersection(user_set_for_business)

        # No users that have rated both items - assign similarity based on how close average ratings are for both items.
        if len(common_user_set) == 0:
            diff_avg_rating = abs(self.business_average_rating[bid] - self.business_average_rating[business])
            if diff_avg_rating <= 1:
                similarity = 0.85
            elif diff_avg_rating <=2:
                similarity = 0.35
            else:
                similarity = 0
            self.pearson_similarities[key_tuple] = similarity
            return similarity

        num = 0.0
        root1, root2 = 0.0,0.0
        user_ratings_map_bid      = dict(self.biz_user_rating_map.get(bid))
        user_ratings_map_business = dict(self.biz_user_rating_map.get(business))
        for user in common_user_set:
            #business_ratings_map = dict(self.user_biz_rating_map.get(user))
            num += (user_ratings_map_bid.get(user) - self.business_average_rating.get(bid)) * (user_ratings_map_business.get(user) - self.business_average_rating.get(business))
            root1 += (user_ratings_map_bid.get(user) - self.business_average_rating.get(bid)) ** 2
            root2 += (user_ratings_map_business.get(user) - self.business_average_rating.get(business)) ** 2

        denom      = math.sqrt(root1) * math.sqrt(root2)

        if denom == 0:
            similarity = 0
        else:
            similarity = num / denom

        self.pearson_similarities[key_tuple] = similarity

        return similarity

    def predict_item_rating(self, similarity_list):

        predicted_rating = 0.0
        num, denom = 0.0,0.0
        for similarity, rating in similarity_list:
            num   += similarity * rating
            denom += abs(similarity)

        if denom == 0:
            return self.total_average_rating

        predicted_rating = num / denom

        predicted_rating = max(0, min(5, predicted_rating))

        return predicted_rating

    def create_rating_prediction(self, user_id, biz_id):

        #edge case 1 : user_id and biz_id both do not exist
        # return half rating (neutral).
        if (user_id not in self.user_biz_rating_map) and ( biz_id not in self.biz_user_rating_map):
            return self.total_average_rating

        #edge case 2 : user_id exists but biz_id does not.
        if user_id not in self.user_biz_rating_map:
            return self.business_average_rating.get(biz_id, self.total_average_rating)

        #edge case 3 : user_id exists but biz_id does not.

        if biz_id not in self.biz_user_rating_map:
            return self.user_average_rating.get(user_id, self.total_average_rating)

        similarity_list = []

        # what if the user has already rated that business?

        for business, rating in self.user_biz_rating_map.get(user_id):
            pearson_similarity  = self.evaluate_pearson_similarity(biz_id, business)
            if pearson_similarity <=0:
                continue
            similarity_list.append((pearson_similarity, rating))

        predicted_rating = self.predict_item_rating(similarity_list)

        return predicted_rating

    def create_predictions_for_test_data(self, test_data_rdd):

        # lets have a separate rdd for the ratings column and remove it from the test_data_rdd
        test_data_results          = test_data_rdd.map(lambda row : (row[0], row[1], self.create_rating_prediction(row[0], row[1]))).collect()

        #print(self.calculateRMSE(test_data_results))
        return test_data_results

    def calculateRMSE(self, test_ratings_data):

        rmse_diff = 0
        for i in range(len(test_ratings_data)):
            rmse_diff += (test_ratings_data[i][0] - test_ratings_data[i][1]) ** 2

        return math.sqrt(rmse_diff / len(test_ratings_data))

    def calculate_default_averages(self, training_data_rdd):

        # Average based on user rating when a business from test data is not found in training data
        self.user_average_rating    = training_data_rdd.map(lambda row: (row[0], (row[2], 1)))\
                                                 .reduceByKey(lambda row1, row2: (row1[0] + row2[0], row1[1] + row2[1]))\
                                                 .map(lambda row: (row[0], row[1][0] / row[1][1]))\
                                                 .collectAsMap()
        # Average based on business rating when a user from test data is not found in training data
        self.business_average_rating = training_data_rdd.map(lambda row: (row[1], (row[2], 1)))\
                                                 .reduceByKey(lambda row1, row2: (row1[0] + row2[0], row1[1] + row2[1]))\
                                                 .map(lambda row: (row[0], row[1][0] / row[1][1]))\
                                                 .collectAsMap()

        # Average of all ratings in data

        self.total_average_rating_rdd = training_data_rdd.map(lambda row : (row[2], 1))\
                                                .reduce(lambda row1, row2 : (row1[0] + row2[0], row1[1] + row2[1]))\

        self.total_average_rating     = self.total_average_rating_rdd[0] / self.total_average_rating_rdd[1]

    def write_results_to_csv(self, test_results, output_file):
        with open(output_file, 'w+') as f:
            writer = csv.writer(f, delimiter=',',quoting=csv.QUOTE_NONE)
            writer.writerow(['user_id',' business_id', ' prediction'])
            for result in test_results:
                writer.writerow([result[0], result[1], result[2]])

    def task2Point1(self):
        start_time = time()
        sc                                            = self.setup()
        training_data_rdd, test_data_rdd, output_file = self.read_and_pre_process_input_file(sc)
        self.calculate_default_averages(training_data_rdd)
        # create user indexed dictionary and business indexed dictionary
        self.generate_training_data_maps(training_data_rdd)

        # start predictions on validation data

        test_results = self.create_predictions_for_test_data(test_data_rdd)
        self.write_results_to_csv(test_results, output_file)
        print("Duration: " + str(time() - start_time))

    def task2Point3(self, sc, training_file, test_file):

        training_data_rdd = self.create_rdd_from_file(sc, training_file).map(lambda row : (row[0], row[1], float(row[2])))
        test_data_rdd     = self.create_rdd_from_file(sc, test_file).map(lambda row : (row[0], row[1]))

        self.calculate_default_averages(training_data_rdd)
        # create user indexed dictionary and business indexed dictionary
        self.generate_training_data_maps(training_data_rdd)

        # start predictions on validation data

        return self.create_predictions_for_test_data(test_data_rdd)

def main():
    t1 = Task2Point1()
    t1.task2Point1()

if __name__ == '__main__':
    main()


# TensorFlow Tutorial #01 Simple Linear Model
# by Magnus Erik Hvass Pedersen http://www.hvass-labs.org/

# imports
###############################
# %matplotlib inline
# import matplotlib.pyplot as plt

import tensorflow as tf
import numpy as np
from sklearn.metrics import confusion_matrix

# load data
###############################

from tensorflow.examples.tutorials.mnist import input_data
data = input_data.read_data_sets("data/MNIST/", one_hot=True)

print("Size of:")
print("- Training-set:\t\t{}".format(len(data.train.labels)))
print("- Test-set:\t\t{}".format(len(data.test.labels)))
print("- Validation-set:\t{}".format(len(data.validation.labels)))

data.test.cls = np.array([label.argmax() for label in data.test.labels])

# Data dimensions
###############################

# We know that MNIST images are 28 pixels in each dimension.
img_size = 28

# Images are stored in one-dimensional arrays of this length.
img_size_flat = img_size * img_size

# Tuple with height and width of images used to reshape arrays.
img_shape = (img_size, img_size)

# Number of classes, one class for each of 10 digits.
num_classes = 10

# Hyperparameters
###############################
# step size of Gradient Descent Optimizer
learning_rate = \
	0.05
	#0.5

batch_size = \
	300
	#100

# build model graph
###############################
x = tf.placeholder(tf.float32, [None, img_size_flat])
y_true = tf.placeholder(tf.float32, [None, num_classes])
y_true_cls = tf.placeholder(tf.int64, [None])

weights = tf.Variable(tf.zeros([img_size_flat, num_classes]))
biases = tf.Variable(tf.zeros([num_classes]))
logits = tf.matmul(x, weights) + biases

y_pred = tf.nn.softmax(logits)
y_pred_cls = tf.argmax(y_pred, dimension=1)

cross_entropy = \
	tf.nn.softmax_cross_entropy_with_logits(logits=logits,labels=y_true)
#tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits,labels=y_true)
cost = tf.reduce_mean(cross_entropy)

optimizer = \
	tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)
	#tf.train.GradientDescentOptimizer(learning_rate=learning_rate).minimize(cost)
	#tf.train.AdagradOptimizer(learning_rate=learning_rate).minimize(cost)

correct_prediction = tf.equal(y_pred_cls, y_true_cls)

accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

# Create TensorFlow session
###############################
session = tf.Session()
session.run(tf.global_variables_initializer())

feed_dict_test = {x: data.test.images,
                  y_true: data.test.labels,
                  y_true_cls: data.test.cls}

def optimize(num_iterations):
    for i in range(num_iterations):
        # Get a batch of training examples.
        # x_batch now holds a batch of images and
        # y_true_batch are the true labels for those images.
        x_batch, y_true_batch = data.train.next_batch(batch_size)

        # Put the batch into a dict with the proper names
        # for placeholder variables in the TensorFlow graph.
        # Note that the placeholder for y_true_cls is not set
        # because it is not used during training.
        feed_dict_train = {x: x_batch,
                           y_true: y_true_batch}

        # Run the optimizer using this batch of training data.
        # TensorFlow assigns the variables in feed_dict_train
        # to the placeholder variables and then runs the optimizer.
        session.run(optimizer, feed_dict=feed_dict_train)

def print_accuracy():
    # Use TensorFlow to compute the accuracy.
    acc = session.run(accuracy, feed_dict=feed_dict_test)

    # Print the accuracy.
    print("Accuracy on test-set: {0:.1%}".format(acc))

def print_confusion_matrix():
    # Get the true classifications for the test-set.
    cls_true = data.test.cls

    # Get the predicted classifications for the test-set.
    cls_pred = session.run(y_pred_cls, feed_dict=feed_dict_test)

    # Get the confusion matrix using sklearn.
    cm = confusion_matrix(y_true=cls_true,
                          y_pred=cls_pred)

    # Print the confusion matrix as text.
    print(cm)

# run tests
###############################

# Performance after 1 optimization iteration
optimize(num_iterations=1)
print_accuracy()
#print_confusion_matrix()

# Performance after 10 optimization iteration
optimize(num_iterations=9)
print_accuracy()
print_confusion_matrix()

# Performance after 1000 optimization iterations
optimize(num_iterations=990)
print_accuracy()
print_confusion_matrix()

#
session.close()