A list of probabilities in normal form and a one-to-one correspondence between the elements of this list and the identifiers of output signals define a preloaded probability profile for an action choice state. This one-to-one correspondence is a permutation of output signals. The purpose of splitting a preloaded probability profile into a probabilities list in normal form and a permutation of output signals is to reduce the memory footprint of an actor, especially of large one.

For a small actor, the normal form of a list of probabilities is simply a sorted list. For a large actor, the normal form of a source list of probabilities is a resulting list of probabilities of leaves of a Huffman tree created for a sorted source list. The indices of probabilities in the resulting list are equal to the indices of corresponding probabilities in the sorted list. Note that resulting probabilities following from the structure of a Huffman tree may differ from input probabilities for creating the Huffman tree.

An actor has a pool of probabilities lists in normal form. The actor does not support removing elements from the pool, except by destroying the actor using the function `qsmm_actor_destroy`. The field `profile_pool_sz` of `qsmm_actor_desc_s` structure specifies the size of that pool when creating the actor by the function `qsmm_actor_create`. You can retrieve that size later by the function `qsmm_get_actor_profile_pool_sz`.

The pool contains unique probabilities lists in normal form. That is, for a large actor, to pool elements there correspond Huffman trees with unique positional arrangements of nodes. Even when preloading a probability profile with a probabilities list in normal form already contained in the pool, the actor creates a temporary Huffman tree to obtain a normal form. The temporary Huffman tree takes up one element in the pool, and, therefore, pool size should generally be greater by 1 than the number of unique probabilities lists in normal form you need to load into the pool.

An actor also has a pool of permutations of output signals. The pool contains unique permutations. As opposed to the pool of probabilities lists in normal form with size specified when creating the actor, the pool of permutations of output signals grows dynamically, and you do not need to specify its size in advance. The actor does not support removing the permutations of output signals from the pool, except by destroying the actor using `qsmm_actor_destroy`.

Use the following function to split a list of weights of output signals of an actor into a unique probabilities list in normal form and a unique permutation of output signals.

Function: int qsmm_actor_profile_add (qsmm_actor_t actor, qsmm_sig_t sig_beg, qsmm_sig_t sig_end, const double *weight_p, int *profile_p, int *permut_p)

This function preloads a list of weights of output signals into an actor. The array weight_p contains the weights. If weight_p is `NULL`, the function interprets this condition as if the array weight_p contains all weights equal to 1.

The arguments sig_beg and sig_end can be both zero or may specify the identifiers of the first signal (inclusive) and last signal (exclusive) for the list of weights. The weight of the first signal of that list has offset sig_beg in the array weight_p. If sig_end is 0, the function uses the total number of actor signals for the identifier of last signal. The function ignores weight_p elements that do not correspond to output signals.

If profile_p is not `NULL`, the function sets *profile_p equal to a non-negative index of a unique probabilities list in normal form for the list of weights. This index identifies either a unique probabilities list in normal form just added to the pool of those lists or such a list already contained in the pool. The length of the unique probabilities list in normal form is equal to the number of positive elements in the array weight_p for output signals in the range specified by sig_beg and sig_end.

If permut_p is not `NULL`, the function sets *permut_p equal to a non-negative index of a unique permutation of output signals for the list of weights. This index identifies either a unique permutation of output signals just added to the pool of those permutations or such a permutation already contained in the pool. The length of the unique permutation of output signals is equal to the length of the unique probabilities list in normal form.

The function returns a non-negative value on success or a negative error code on failure. Currently, the function can return the following error codes.

`QSMM_ERR_INVAL`

The argument sig_beg is greater than or equal to the identifier of last signal for the list of weights, or the argument sig_end is greater than the total number of signals of the actor.

`QSMM_ERR_WEIGHT`

The array weight_p contains a negative or non-finite element for an output signal in the range specified by sig_beg and sig_end.

`QSMM_ERR_INFIN`

The array weight_p contains only finite elements for output signals in the range specified by sig_beg and sig_end, but the sum of elements is infinite.

`QSMM_ERR_NOCHOICE`

The array weight_p does not contain at least one positive element for output signals in the range specified by sig_beg and sig_end.

`QSMM_ERR_MPROF`

No room in the pool of probabilities lists in normal form with size specified in the field `profile_pool_sz` of `qsmm_actor_desc_s` structure when creating the actor.

`QSMM_ERR_STORAGE`

Failure of statistics storage of a large actor. See Getting the Reason of a Storage Failure, for how to get an error message describing the failure.

`QSMM_ERR_STATS`

Inconsistent statistics on an action choice state or cycle type detected for a large actor.

`QSMM_ERR_ILSEQ`

For a large actor, a generated error message is not convertible to a wide string according to a current locale, or a storage redirection function reported `QSMM_ERR_ILSEQ`.

`QSMM_ERR_NOMEM`

There was not enough memory to perform the operation.

The function `qsmm_actor_profile_add` may operate slowly, especially when building a Huffman tree for a large actor. To speed up preloading a number of probability profiles for the same sorted list of output signal weights, you can perform the following procedure.

1. Preload the first probability profile by the function `qsmm_actor_profile_add` returning the index of a probabilities list in normal form and the index of a permutation of output signals identifying the preloaded profile.
2. For every other probability profile, sort its list of output signal weights (all profiles have the same sorted list) to obtain a permutation of output signals. Actually, it is necessary to sort a list of pairs comprised of a weight and an output signal identifier in ascending order of weights.
3. Register every such permutation of output signals by the function `qsmm_actor_permut_add` described below to obtain the index of a unique permutation of output signals. You can use that index along with the index of a probabilities list in normal form obtained in step 1 to identify a preloaded probability profile other than the first one.
Function: int qsmm_actor_permut_add (qsmm_actor_t actor, int sz, const qsmm_sig_t *sig_p)

This function adds a permutation of output signals of an actor to the pool of those permutations in the actor if that pool does not already contain the permutation. The array sig_p with length sz specifies that permutation. A set of signals in the permutation must be a subset of output signals of the actor.

On success, the function returns a non-negative index of a permutation of output signals just added to the pool or already contained in the pool. This index uniquely identifies the permutation in the pool. On failure, the function returns a negative error code. Currently, the function can return the following error codes.

`QSMM_ERR_INVAL`

The value of sz is less than 1, or the array sig_p contains duplicate elements or an element not equal to the identifier of an output signal of the actor.

`QSMM_ERR_NOMEM`

There was not enough memory to add the permutation of output signals to the pool.