# Path: concept_formation/cobweb3.py
# class Cobweb3Tree(CobwebTree):
# class Cobweb3Node(CobwebNode):
#     def __init__(self, scaling=0.5, inner_attr_scaling=True):
#     def clear(self):
#     def get_inner_attr(self, attr):
#     def update_scales(self, instance):
#     def cobweb(self, instance):
#     def ifit(self, instance):
#     def increment_counts(self, instance):
#     def update_counts_from_node(self, node):
#     def expected_correct_guesses(self):
#     def pretty_print(self, depth=0):
#     def get_weighted_values(self, attr, allow_none=True):
#     def predict(self, attr, choice_fn="most likely", allow_none=True):
#     def probability(self, attr, val):
#     def log_likelihood(self, child_leaf):
#     def is_exact_match(self, instance):
#     def output_json(self):
# 
# Path: concept_formation/cobweb3.py
# class Cobweb3Tree(CobwebTree):
#     """
#     The Cobweb3Tree contains the knowledge base of a partiucluar instance of
#     the Cobweb/3 algorithm and can be used to fit and categorize instances.
#     Cobweb/3's main difference over Cobweb is the ability to handle numerical
#     attributes by applying an assumption that they should follow a normal
#     distribution. For the purposes of Cobweb/3's core algorithms a numeric
#     attribute is any value where ``isinstance(instance[attr], Number)`` returns
#     ``True``.
# 
#     The scaling parameter determines whether online normalization of continuous
#     attributes is used, and to what standard deviation the values are scaled
#     to. Scaling divides the std of each attribute by the std of the attribute
#     in the root divided by the scaling constant (i.e., :math:`\\sigma_{root} /
#     scaling` when making category utility calculations.  Scaling is useful to
#     balance the weight of different numerical attributes, without scaling the
#     magnitude of numerical attributes can affect category utility calculation
#     meaning numbers that are naturally larger will recieve preference in the
#     category utility calculation.
# 
#     :param scaling: The number of standard deviations numeric attributes
#         are scaled to. By default this value is 0.5 (half a standard
#         deviation), which is the max std of nominal values. If disabiling
#         scaling is desirable, then it can be set to False or None.
#     :type scaling: a float greater than 0.0, None, or False
#     :param inner_attr_scaling: Whether to use the inner most attribute name
#         when scaling numeric attributes. For example, if `('attr', '?o1')` was
#         an attribute, then the inner most attribute would be 'attr'. When using
#         inner most attributes, some objects might have multiple attributes
#         (i.e., 'attr' for different objects) that contribute to the scaling.
#     :param inner_attr_scaling: boolean
#     """
# 
#     def __init__(self, scaling=0.5, inner_attr_scaling=True):
#         """
#         The tree constructor.
#         """
#         self.root = Cobweb3Node()
#         self.root.tree = self
#         self.scaling = scaling
#         self.inner_attr_scaling = inner_attr_scaling
#         self.attr_scales = {}
# 
#     def clear(self):
#         """
#         Clears the concepts of the tree, but maintains the scaling parameter.
#         """
#         self.root = Cobweb3Node()
#         self.root.tree = self
#         self.attr_scales = {}
# 
#     def get_inner_attr(self, attr):
#         """
#         Extracts the inner most attribute name from the provided attribute, if
#         the attribute is a tuple and inner_attr_scaling is on. Otherwise it
#         just returns the attribute. This is used to for normalizing attributes.
# 
#         >>> t = Cobweb3Tree()
#         >>> t.get_inner_attr(('a', '?object1'))
#         'a'
#         >>> t.get_inner_attr('a')
#         'a'
#         """
#         if isinstance(attr, tuple) and self.inner_attr_scaling:
#             return attr[0]
#         else:
#             return attr
# 
#     def update_scales(self, instance):
#         """
#         Reads through all the attributes in an instance and updates the
#         tree scales object so that the attributes can be properly scaled.
#         """
#         for attr in instance:
#             if isNumber(instance[attr]):
#                 inner_attr = self.get_inner_attr(attr)
#                 if inner_attr not in self.attr_scales:
#                     self.attr_scales[inner_attr] = ContinuousValue()
#                 self.attr_scales[inner_attr].update(instance[attr])
# 
#     def cobweb(self, instance):
#         """
#         A modification of the cobweb function to update the scales object
#         first, so that attribute values can be properly scaled.
#         """
#         self.update_scales(instance)
#         return super(Cobweb3Tree, self).cobweb(instance)
# 
#     def ifit(self, instance):
#         """
#         Incrementally fit a new instance into the tree and return its resulting
#         concept.
# 
#         The cobweb3 version of the :meth:`CobwebTree.ifit` function. This
#         version keeps track of all of the continuous
# 
#         :param instance: An instance to be categorized into the tree.
#         :type instance:  :ref:`Instance<instance-rep>`
#         :return: A concept describing the instance
#         :rtype: Cobweb3Node
# 
#         .. seealso:: :meth:`CobwebTree.cobweb`
#         """
#         self._sanity_check_instance(instance)
#         return self.cobweb(instance)


import unittest
import random
from numbers import Number
from concept_formation.cobweb3 import cv_key
from concept_formation.cobweb3 import Cobweb3Tree
            assert attr in temp

            for val in child.av_counts[attr]:
                if val not in temp[attr]:
                    print(val.concept_name)
                    print(attr)
                    print(node)
                assert val in temp[attr]

                if val == cv_key:
                    temp[attr][val] -= child.av_counts[attr][val].num
                else:
                    temp[attr][val] -= child.av_counts[attr][val]

    assert temp_count == 0

    for attr in temp:
        if isinstance(temp[attr], Number):
            assert temp[attr] == 0.0
        else:
            for val in temp[attr]:
                assert temp[attr][val] == 0.0

    for child in node.children:
        verify_counts(child)


class TestCobweb(unittest.TestCase):

    def test_cobweb(self):

# Path: concept_formation/cobweb3.py
# class Cobweb3Tree(CobwebTree):
# class Cobweb3Node(CobwebNode):
#     def __init__(self, scaling=0.5, inner_attr_scaling=True):
#     def clear(self):
#     def get_inner_attr(self, attr):
#     def update_scales(self, instance):
#     def cobweb(self, instance):
#     def ifit(self, instance):
#     def increment_counts(self, instance):
#     def update_counts_from_node(self, node):
#     def expected_correct_guesses(self):
#     def pretty_print(self, depth=0):
#     def get_weighted_values(self, attr, allow_none=True):
#     def predict(self, attr, choice_fn="most likely", allow_none=True):
#     def probability(self, attr, val):
#     def log_likelihood(self, child_leaf):
#     def is_exact_match(self, instance):
#     def output_json(self):
# 
# Path: concept_formation/cobweb3.py
# class Cobweb3Tree(CobwebTree):
#     """
#     The Cobweb3Tree contains the knowledge base of a partiucluar instance of
#     the Cobweb/3 algorithm and can be used to fit and categorize instances.
#     Cobweb/3's main difference over Cobweb is the ability to handle numerical
#     attributes by applying an assumption that they should follow a normal
#     distribution. For the purposes of Cobweb/3's core algorithms a numeric
#     attribute is any value where ``isinstance(instance[attr], Number)`` returns
#     ``True``.
# 
#     The scaling parameter determines whether online normalization of continuous
#     attributes is used, and to what standard deviation the values are scaled
#     to. Scaling divides the std of each attribute by the std of the attribute
#     in the root divided by the scaling constant (i.e., :math:`\\sigma_{root} /
#     scaling` when making category utility calculations.  Scaling is useful to
#     balance the weight of different numerical attributes, without scaling the
#     magnitude of numerical attributes can affect category utility calculation
#     meaning numbers that are naturally larger will recieve preference in the
#     category utility calculation.
# 
#     :param scaling: The number of standard deviations numeric attributes
#         are scaled to. By default this value is 0.5 (half a standard
#         deviation), which is the max std of nominal values. If disabiling
#         scaling is desirable, then it can be set to False or None.
#     :type scaling: a float greater than 0.0, None, or False
#     :param inner_attr_scaling: Whether to use the inner most attribute name
#         when scaling numeric attributes. For example, if `('attr', '?o1')` was
#         an attribute, then the inner most attribute would be 'attr'. When using
#         inner most attributes, some objects might have multiple attributes
#         (i.e., 'attr' for different objects) that contribute to the scaling.
#     :param inner_attr_scaling: boolean
#     """
# 
#     def __init__(self, scaling=0.5, inner_attr_scaling=True):
#         """
#         The tree constructor.
#         """
#         self.root = Cobweb3Node()
#         self.root.tree = self
#         self.scaling = scaling
#         self.inner_attr_scaling = inner_attr_scaling
#         self.attr_scales = {}
# 
#     def clear(self):
#         """
#         Clears the concepts of the tree, but maintains the scaling parameter.
#         """
#         self.root = Cobweb3Node()
#         self.root.tree = self
#         self.attr_scales = {}
# 
#     def get_inner_attr(self, attr):
#         """
#         Extracts the inner most attribute name from the provided attribute, if
#         the attribute is a tuple and inner_attr_scaling is on. Otherwise it
#         just returns the attribute. This is used to for normalizing attributes.
# 
#         >>> t = Cobweb3Tree()
#         >>> t.get_inner_attr(('a', '?object1'))
#         'a'
#         >>> t.get_inner_attr('a')
#         'a'
#         """
#         if isinstance(attr, tuple) and self.inner_attr_scaling:
#             return attr[0]
#         else:
#             return attr
# 
#     def update_scales(self, instance):
#         """
#         Reads through all the attributes in an instance and updates the
#         tree scales object so that the attributes can be properly scaled.
#         """
#         for attr in instance:
#             if isNumber(instance[attr]):
#                 inner_attr = self.get_inner_attr(attr)
#                 if inner_attr not in self.attr_scales:
#                     self.attr_scales[inner_attr] = ContinuousValue()
#                 self.attr_scales[inner_attr].update(instance[attr])
# 
#     def cobweb(self, instance):
#         """
#         A modification of the cobweb function to update the scales object
#         first, so that attribute values can be properly scaled.
#         """
#         self.update_scales(instance)
#         return super(Cobweb3Tree, self).cobweb(instance)
# 
#     def ifit(self, instance):
#         """
#         Incrementally fit a new instance into the tree and return its resulting
#         concept.
# 
#         The cobweb3 version of the :meth:`CobwebTree.ifit` function. This
#         version keeps track of all of the continuous
# 
#         :param instance: An instance to be categorized into the tree.
#         :type instance:  :ref:`Instance<instance-rep>`
#         :return: A concept describing the instance
#         :rtype: Cobweb3Node
# 
#         .. seealso:: :meth:`CobwebTree.cobweb`
#         """
#         self._sanity_check_instance(instance)
#         return self.cobweb(instance)


# Path: concept_formation/tests/test_cobweb3.py
import unittest
import random
from numbers import Number
from concept_formation.cobweb3 import cv_key
from concept_formation.cobweb3 import Cobweb3Tree

            assert attr in temp

            for val in child.av_counts[attr]:
                if val not in temp[attr]:
                    print(val.concept_name)
                    print(attr)
                    print(node)
                assert val in temp[attr]

                if val == cv_key:
                    temp[attr][val] -= child.av_counts[attr][val].num
                else:
                    temp[attr][val] -= child.av_counts[attr][val]

    assert temp_count == 0

    for attr in temp:
        if isinstance(temp[attr], Number):
            assert temp[attr] == 0.0
        else:
            for val in temp[attr]:
                assert temp[attr][val] == 0.0

    for child in node.children:
        verify_counts(child)


class TestCobweb(unittest.TestCase):

    def test_cobweb(self):

        tree = Cobweb3Tree()