<commit_before>"""
Probability density functions with support for shared and computed parameters.

This module extends the functionality of L{csb.statistics.pdf} with a specialized 
and more sophisticated L{AbstractDensity} -- the L{ParameterizedDensity}, which 
works with L{AbstractParameter} objects rather than simple floats. 

Each L{AbstractParameter} holds two properties - L{AbstractParameter.name} and
L{AbstractParameter.value}:

    >>> class Sigma(AbstractParameter):
    >>>     def _validate(self, value):
    >>>         return float(value)     
    >>>     def _compute(self, base_value):                
    >>>         return 1.0 / base_value ** 0.5
    >>>                            
    >>> s = Sigma(3)
    >>> s.name, s.value
    sigma, 3

L{AbstractParameter}s holding a single float value are indistinguishable from 
the simple float parameters used in L{csb.statistics.pdf.BaseDensity}. 
However, each L{AbstractParameter} supports the concept of binding:

    >>> s.is_virtual
    False
    >>> p = Precision(1) 
    >>> s.bind_to(precision)
    >>> s.is_virtual
    True    
    >>> base_parameter.set(2)  # triggers implicit update in s
    >>> s.set(1)
    ParameterizationError: Virtual parameters can't be updated explicitly
    
The instance of Sigma is now a virtual parameter which receives automatic updates 
from another base parameter using a predefined rule (L{AbstractParameter._compute}).
This is a lazy, on demand process. As soon as Sigma's computed value is 
requested (via C{s.value}), Sigma will query the parameter it depends on 
(Precision), which in turn will get recomputed first based on its own base, etc. 
Thus, the L{AbstractParameter} model supports a parameter dependency chain with 
linear or tree-like topologies::
            
               sigma -- y   
              /              
    precision -- sigma2 -- x 
    
In this graph precision is a base (non-virtual) parameter and sigma, sigma2, x, and y
are all virtual (computed). Binding precision to another parameter will immediately
turn it into a virtual one. However, cycles are not allowed (e.g. precision can't 
be bound to sigma2 or x) and each virtual parameter must have exactly one base.   

Computed parameters can then be used to implement custom PDFs with dependent 
parameters within one PDF or spanning multiple PDFs.
"""

import csb.statistics.pdf as pdf

from abc import abstractmethod

<commit_msg>Fix: improved documentation<commit_after>"""
Probability density functions with support for shared and computed parameters.

This module extends the functionality of L{csb.statistics.pdf} with a specialized 
and more sophisticated L{AbstractDensity} -- the L{ParameterizedDensity}, which 
works with L{AbstractParameter} objects rather than simple floats. 

Each L{AbstractParameter} holds two properties - L{AbstractParameter.name} and
L{AbstractParameter.value}:

    >>> class Sigma(AbstractParameter):
    >>>     def _validate(self, value):
    >>>         return float(value)     
    >>>     def _compute(self, base_value):                
    >>>         return 1.0 / base_value ** 0.5
    >>>                            
    >>> sigma = Sigma(3)
    >>> sigma.name, sigma.value
    sigma, 3

L{AbstractParameter}s holding a single float value are indistinguishable from 
the simple float parameters used in L{csb.statistics.pdf.BaseDensity}. 
However, each L{AbstractParameter} supports the concept of binding:

    >>> sigma.is_virtual
    False
    >>> precision = Precision(1) 
    >>> sigma.bind_to(precision)
    >>> sigma.is_virtual
    True    
    >>> precision.set(2)  # triggers an implicit, lazy update in sigma
    >>> sigma.set(1)
    ParameterizationError: Virtual parameters can't be updated explicitly
    
The instance of Sigma is now a virtual parameter which receives automatic updates 
from another base parameter using a predefined rule (L{AbstractParameter._compute}).
This is a lazy, on demand process. As soon as Sigma's computed value is 
requested (via C{s.value}), Sigma will query the parameter it depends on 
(Precision), which in turn will get recomputed first based on its own base, etc. 
Thus, the L{AbstractParameter} model supports a parameter dependency chain with 
linear or tree-like topologies::
            
               sigma -- y   
              /              
    precision -- sigma2 -- x 
    
In this graph precision is a base (non-virtual) parameter and sigma, sigma2, x, and y
are all virtual (computed). Binding precision to another parameter will immediately
turn it into a virtual one. However, cycles are not allowed (e.g. precision can't 
be bound to sigma2 or x) and each virtual parameter must have exactly one base.   

Computed parameters can then be used to implement custom PDFs with dependent 
parameters within one PDF or spanning multiple PDFs.
"""

import csb.statistics.pdf as pdf

from abc import abstractmethod


{'fraction_non_alphanumeric': 0.07479674796747968, 'fraction_numerical': 0.004878048780487805, 'mean_word_length': 3.138772077375946, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 87, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '802488', 'n_tokens_mistral': 1309, 'n_tokens_neox': 1229, 'n_words': 548}