QSMM Programmer Manual

Table of Contents

Next:   [Contents][Index]

QSMM Programmer Manual

This manual documents QSMM, a framework for the development of intelligent systems.

This edition of the manual was updated 26 January 2021 and corresponds to release 1.18 of the framework.

You can find more information about QSMM on the project homepage, http://qsmm.org.

Please submit bugs in this manual to a mailing list for QSMM users. Posting messages to the mailing list requires prior subscription to it. The mailing list information page is available at https://lists.sourceforge.net/lists/listinfo/qsmm-users. Using that page, you can subscribe to the mailing list, unsubscribe from the list, view list archives, and perform other actions.

Copyright © 2012, 2013, 2014, 2015, 2016, 2017, 2019, 2020, 2021 Oleg Volkov.

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with the Invariant Sections being just “GNU General Public License”, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled “GNU Free Documentation License”.


Next: , Previous: , Up: Top   [Contents][Index]

Acknowledgements

The author of this manual expresses thanks to the following people who helped improve its quality:


Next: , Previous: , Up: Top   [Contents][Index]

1 Introduction

QSMM is the recursive acronym for “QSMM State Machine Model.” State machine is a general concept applicable to many fields of knowledge. A state machine has a set of states, an overall machine’s state, and can perform transitions between states from this set. The author believes that the concept of state machine is also fundamental to our experience of conciousness connected with our intelligent behavior. QSMM helps create state machines for systems with intelligent behavior. Algorithms implemented in QSMM and its specific application in a system put constraints on the degree of intelligence of system behavior.

A set of states of a state machine, a specification of possible transitions between them, and rules for performing actual transitions between the states are part of a state model. The state machine executes the state model—performs actual transitions between the states according to the state model and maintains the overall machine’s state. Actual state transitions affect how the system is communicating with an environment, whereas possible state transitions are part of a framework for such communication.

An intelligent state model is a state model that allows a state machine to exhibit intelligent behavior. In QSMM, intelligent behavior implies that rules for performing actual transitions between the states are adaptive with the goal to achieve a desired result—intelligent state model means adaptive state model.

To develop a system, a programmer needs to program its state model for execution by a computer. To facilitate the development, the programmer can use various function libraries and frameworks. QSMM is an intelligent state model development framework. It is a C function and macro library with rudiments of a toolchain for adaptive state model development. By author’s belief, QSMM could advance the development of systems with intelligent behavior.

The QSMM package source code is distributed under the terms of the GNU General Public License, Version 3 or any later version published by the Free Software Foundation. See GNU General Public License, for the text of the License.

This manual specifically is covered by the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation. See GNU Free Documentation License, for the text of the License.

Software described in this manual is without any warranty. The software is provided “as is,” in the hope that it will be useful. See the GNU General Public License, for more details.


Next: , Up: Introduction   [Contents][Index]

1.1 What Is Intelligence?

There are many definitions for intelligence as well as types of intelligence. Most definitions include lists of activities inherent to humans, such as reasoning, planning, solving problems, thinking abstractly, comprehending complex ideas, learning from experience, and adapting effectively to the environment. When attempting to develop intelligent machines, researchers try to make them perform a subset of those activities with as high a level of plausibility as possible. However, from the standpoint of knowledge formalization and for a more precise formulation of research goals, it would be useful to point out the smallest subset of such activities to establish that an animate being or inanimate machine performing them is intelligent enough.

First, it is necessary to mention that intelligence implies a goal (in the “Handbook of Human Intelligence” Sternberg and Salter defined intelligence as “goal-directed adaptive behavior”). In the case of animate being, the goal could be surviving, and in the case of a machine created by humans, the goal could be solving tasks assigned by humans. Animals show their basic intelligence, for example, when they adapt to the environment, seek for food, and build nests. One can say today’s machines show their intelligence by effectively performing tasks people created those machines to perform. This is not a too distorted interpretation of intelligence if we review the book “Symbolic Logic and Intelligent Machines” of Edmund C. Berkeley published in 1959, where the author called intelligent machines electromechanical arrangements capable of solving problems that involve logic.

Let us assume that all animals possess a basic level of intelligence. An advanced level of intelligence would be the production and use of work tools. As it turned out, the production and use of work tools is specific not only to humans but also to chimpanzees and to a number of other animals. For example, chimpanzees are able to find stones of appropriate weights and sizes and crack nuts using them. The chimpanzees are also able to find long and thin sticks and use them to kill small rodents living in the trunks of a certain species of trees and extract killed rodents for food. It is important to mention that the chimpanzees not only find ready-to-use work tools in nature but can also produce them. For example, the chimpanzees can construct arrangements consisting of small tree branches and put them into termite mounds to eat termites crawled on them. Another example is an experiment conducted on a pygmy chimpanzee when experimenters successfully trained him to manufacture a sharp stone tool for cutting a string to open the door of a chamber with sweets.

In a digital world supported by computers, work tools are computer programs helping solve various tasks. In a computer environment, the aforementioned advanced level of intelligence is the capability to synthesize and use computer programs and algorithms. A machine with the advanced level of intelligence should be capable of automated synthesis of algorithms in some form or fashion. Such an algorithm might have a form of an ordinary computer program, possibly containing a set of subroutines.

There does exist a higher level of intelligence—we shall call it an expert level of intelligence,—specific only to humans and not to chimpanzees. Indeed, what is an essential difference between humans’ and chimpanzees’ intelligence if they both produce and use work tools?

In the book “The complete idiot’s guide to Human Prehistory,” its author Robert J. Meier briefly noted an important fact about the production and use of burins. Such specially sharpened stones archaeologists find during excavations corresponding to the time when, tentatively speaking, we can call creatures that have been living on Earth humans. Burins are tools created for manufacturing other tools. The chimpanzees do not make tools for making other tools. That is, the expert level of intelligence peculiar to humans is the ability to organize processing chains where one kind of work tools takes part in the production of other kinds of work tools. The established concept for this is production of the means of production.

For the computer environment, programmers develop such tools as compilers, various operating, execution, and development environments to simplify developing other computer programs. A machine with the expert level of intelligence would be capable of the automated synthesis of algorithms that the machine would execute to synthesize other algorithms to solve problems assigned by humans more efficiently. The creation of such a machine is a quite specific goal researchers could try to achieve.


Next: , Previous: , Up: Introduction   [Contents][Index]

1.2 Spur-driven Behavior

A basic problem one needs to solve when creating an intelligent machine that performs automated synthesis of algorithms is discovering a way or manner in which a job is assigned to the machine. There are sophisticated approaches to solving this problem, for example, by creating specifications consisting of rules and constraints. A simpler approach is reducing an algorithm synthesis task to an optimization task. In this approach, a task resolution assessment unit assesses a result of execution of a version of a synthesized algorithm; the machine makes changes to this version to hopefully produce a version with a better assessment score. A classical approach to solving optimization tasks of this kind is genetic algorithms. A genetic algorithm would evolve a target algorithm by trial and error in multiple iterations to maximize the value of a fitness function.

Another approach to solving an algorithm synthesis task as an optimization task is an approach where the machine synthesizes an algorithm simultaneously with its execution. An executed algorithm may perform necessary interactions with an environment. The task resolution assessment unit provides continuous feedback on results of execution of the algorithm, and the machine continuously attempts to improve it. A behavior exhibited by the machine is reinforcement learning.

A machine can exhibit this behavior without keeping an explicit representation of a synthesized algorithm. QSMM maintains a representation of a synthesized algorithm as a finite automaton.

Historically, a numerical quantity specifying a component of the fitness of a synthesized algorithm is called spur in QSMM; the type of such component is called spur type. QSMM supports multiple spur types for an optimization task, although it is better to use a smaller number of spur types for the optimization to be more efficient. A spur value can be, for example, the logarithm of a probability to maximize, an energy value to minimize, or the sum of rewards or incentives given to a machine when a partially synthesized algorithm reaches some points in solving a task. For time-dependent feedback on the fitness of a synthesized algorithm, QSMM supports the optimization goal “maximize spur increment velocities” or “maximize spur decrement velocities”.

A programmer should provide a spur evaluation method that allows a machine to better understand a correlation between changes made to an algorithm being synthesized and observed changes to spur values. Developing a proper spur evaluation method can be one of the most complex tasks to solve when creating an intelligent machine using the QSMM framework.


Next: , Previous: , Up: Introduction   [Contents][Index]

1.3 Building Blocks for Intelligent Machines

Consider an artificial neuron with one input and many outputs. Activation of the input leads to activation of one of the outputs where the choice of an activated output is probabilistic. A set of such neurons is a probabilistic mapping—a function that ambiguously maps an argument from a set of possible arguments to a result from a set of possible outcomes. Such function, when invoked one time, can return one result, and when invoked another time, can return yet another result for the same argument.

If every argument of a probabilistic mapping has a corresponding set of outcomes with fixed probabilities, we call the probabilistic mapping a fixed probabilistic mapping.

An important concept related to the possibility of using a result of a probabilistic mapping (directly or after transforming) as an argument (or as its part) of this probabilistic mapping is state—a variable that changes its value based on its previous value.

A fixed probabilistic mapping can model a probabilistic finite automaton. An argument of such probabilistic mapping is a superposition of the previous automaton state and an input signal received. A result of the probabilistic mapping is the next automaton state (or a superposition of the next automaton state and an output signal emitted).

To establish a uniform state transition model, it is tempting to treat a set of possible states of a probabilistic mapping as a Cartesian product of sets of possible sub-states making up a full state. In this sometimes useful approach, a resulting set of states can be very large. As sub-states from different sets usually interrelate with each other, the actual number of possible states is often much smaller. They resemble perceived states—mental model states a researcher realizes when learning or programming the behavior of an entity. When using QSMM, we will tend to work with such perceived states.

A probabilistic finite automaton can have a representation in the form of a probabilistic program. In particular, such probabilistic program may be a probabilistic assembler program—an assembler program containing probabilistic jump instructions. If there are no probabilistic jump instructions in the assembler program, the finite automaton and the assembler program are deterministic.

The instruction set of a probabilistic assembler program may consist of:

  1. Custom instructions for performing effective work. Every such instruction can return an outcome from a set of possible outcomes.
  2. The probabilistic jump instruction. It transfers control to a custom instruction at a specific location in the program with a given probability.
  3. The conditional jump instruction. It transfers control to a custom or probabilistic jump instruction at a specific location in the program on the basis of an outcome returned by a previously invoked custom instruction.
  4. The simple jump instruction. It transfers control to a custom instruction at a specific location in the program unconditionally.

Locations of custom instructions in the assembler program represent states of the probabilistic finite automaton. An argument of a fixed probabilistic mapping backing up that finite automaton is a superposition of a location of a custom instruction invoked and an outcome returned by the custom instruction. An outcome of this fixed probabilistic mapping is a location of the next custom instruction to invoke. Simple jump instructions, conditional jump instructions, and probabilistic jump instructions in the assembler program map a particular argument of this probabilistic mapping to a set of possible outcomes with fixed probabilities.

A program usually contains a set of subroutines. A probabilistic assembler program may contain custom instructions for calling subroutines and custom instructions for returning control back. A probabilistic finite automaton may represent every subroutine. Calling a subroutine means pushing a reference to a current probabilistic finite automaton and its current state to a stack and transferring control to the initial state of another probabilistic finite automaton. Returning control from the subroutine means popping the reference to the current automaton and its current state from the stack and transferring control to that state.

We can implement modulating the behavior of a probabilistic mapping by spur. Supposing a result returned by a probabilistic mapping for its specific argument somehow affects the spur, a desired behavior of the probabilistic mapping for this argument would be returning more often an outcome that leads to a greater absolute spur value (a positive value if the goal is to maximize the spur, or a negative value if the goal is to minimize the spur) or a greater spur increment or decrement velocity. We call a probabilistic mapping with such desired behavior an adaptive probabilistic mapping.

An adaptive probabilistic mapping helps produce goal-directed adaptive behavior: return more often outcomes that bring a machine closer to a goal where the spur measures a proximity to the goal. An intelligent machine might include various superpositions of adaptive probabilistic mappings, its inputs and outputs, and those superpositions would specify an adaptive generic state model aimed to solve general or specific problems.

In QSMM, actor is an adaptive probabilistic mapping that works similarly to a fixed probabilistic mapping, but instead of fixed outcome probabilities, it uses probabilities adjusted adaptively. An actor is a generic block for building intelligent machines.

If a fixed probabilistic mapping that backs up a probabilistic finite automaton becomes an adaptive probabilistic mapping, the automaton becomes an adaptive probabilistic finite automaton. Consequently, a probabilistic assembler program the automaton represents becomes an adaptive probabilistic assembler program.

Using QSMM, a researcher can develop adaptive probabilistic assembler programs producing goal-directed behavior. As one may realize, adaptive probabilistic assembler programs is a step towards the automated synthesis of algorithms.

An assembler program represents a state model, and a subroutine of the assembler program represents a state sub-model. In QSMM, node means a callable state sub-model. If a state model contains multiple nodes, we call it multinode model. A node is a probabilistic finite automaton corresponding to a probabilistic assembler program. Node execution is the operation of this finite automaton. The finite automaton and the assembler program turn into their adaptive counterparts during node execution.

The synthesis and execution of subroutines a researcher could relate to setting up processing chains with the production and use of various work tools.


Next: , Previous: , Up: Introduction   [Contents][Index]

1.4 Animate Machines

How to implement a probabilistic mapping? For its particular argument, a machine could generate probabilities of all possible outcomes. Then, the machine would randomly select a particular outcome according to those probabilities, for example, using a random number generator.

How can the machine perform such selection? Let us assume that the random number generator can return two numbers, 0 or 1, with equal probabilities. A straightforward approach to utilizing that random number generator is performing a fixed number of calls to the generator to obtain a binary fractional number in the range 0 to 1. All possible outcomes are non-overlapping segments on a line of length 1, where the length of every segment is equal to the probability of a corresponding outcome. To determine an outcome, the machine finds a segment containing the point at a distance equal to the binary fractional number from the beginning of the line.

For example, if three calls to the random number generator returned numbers 1, 0, and 1, then the binary fractional number is 0.101. This binary number is equal to 1*2-1+0*2-2+1*2-3=2-1+2-3=0.5+0.125=0.625. If four possible outcomes have probabilities 0.125, 0.5, 0.125, and 0.25, then the segments end at distances 0.125, 0.625, 0.75, and 1 from the beginning of the line. Assuming points at the ends of the segments are not parts of those segments, number 0.625 falls in the third segment, that is, the probabilistic mapping returns the third outcome.

At present, QSMM uses this approach to select an outcome of a probabilistic mapping according to probabilities of all possible outcomes. However, this approach has a drawback: it is hard to evaluate how much information from the random number generator the machine uses to select a particular outcome.

A different approach is putting more load on the random number generator to select a less probable outcome and putting less load on the random number generator to select a more probable outcome. In the extreme case, when an outcome has probability 1, and all other outcomes have probability 0, the machine selects the outcome without calling the random number generator at all.

In this approach, the machine builds a binary Huffman tree for a list of outcome probabilities and then traverses nodes of the Huffman tree from the root node to a leaf node representing a selected outcome by calling the random number generator at each traversed non-leaf node to select one of its two child nodes. This approach, however, implies rounding outcome probabilities to 2-k, where k is the depth of a leaf node, and works better for a sufficiently large number of possible outcomes.

Generally, the greater is the probability of a leaf node, the shorter is a path to it from the root node, and, therefore, a lesser number of calls to the random number generator is necessary to select the leaf node. Thus, it is easier to select a more probable outcome, because this selection requires a lesser number of actions to perform.

For our example with outcome probabilities 0.125, 0.5, 0.125, and 0.25, the Huffman tree is:

Huffman Tree for Probabilities 0.125, 0.5, 0.125, and 0.25

Figure 1.1: Huffman Tree for Probabilities 0.125, 0.5, 0.125, and 0.25

For the above Huffman tree, the machine selects the most probable second outcome with probability 0.5 if a call to the random number generator returns 1. The machine selects the least probable first or third outcome with probability 0.125 if three calls to the random number generator return the sequence 0, 1, 0 or 0, 1, 1 respectively. The average number of calls to the random number generator for the Huffman tree is equal to 0.125*3+0.5*1+0.125*3+0.25*2=1.75.

For four equal outcome probabilities 0.25, the Huffman tree is:

Huffman Tree for Four Probabilities 0.25

Figure 1.2: Huffman Tree for Four Probabilities 0.25

For the above Huffman tree, the number of calls to the random number generator to select any outcome is 2. On average, this Huffman tree puts more load on the random number generator to select an outcome compared to the Huffman tree in Figure 1.1.

Thus, in this approach, the average number of calls to the random number generator depends on a degree of difference between outcome probabilities—if some probabilities are much greater than others, the number of calls is less, and, if all probabilities are more or less equal, the number of calls is greater. Looks like this principle is relevant to the physical environment—for a less probable event to occur, more random events have to happen.

Supposing a call to the random number generator has constant choice complexity, selecting a particular outcome of a probabilistic mapping has choice complexity equal to this constant choice complexity multiplied by the number of calls to the random number generator required to perform the selection. Average choice complexity is equal to the constant choice complexity multiplied by the average number of calls to the random number generator required to select an outcome.

However, a call to the random number generator might not have constant choice complexity. Choice complexity for a stochastic act of selecting number 0 or 1 by the random number generator might depend on the number of possible distinguished outcomes the act has. If the outcomes are similar, the number of distinguished outcomes will be less than 2.

The distinguishability of outcomes might affect how the stochastic act changes the entropy of nature. For example, when water is boiling in a kettle, water molecules move rapidly, and a possible location of a water molecule after a fixed period of time varies greatly. However, locations of water molecules in the kettle probably do not affect much—a usable outcome would be hot water in the kettle to make tea. In this case, the complexity of choice lying with a water molecule may be low. On the other hand, if the next location of a molecule affects a resolution of a stochastic optimization task where to search planets in space for colonization, the complexity of choice lying with the molecule may be high.

If nature is a self-sustaining environment, one can interpret the complexity of choice as the amount of change necessary to perform to sustain the environment as a result of various outcomes of a stochastic act. Supposing time is closed like space might be, sustaining the environment requires continuous effort throughout all time-space continuum.

Let us consider an adaptive probabilistic mapping. If an outcome correlates with a desired change in spur, and other outcomes have a lesser correlation, then the outcome will have a greater probability compared to other outcomes. Supposing an outcome always leads to a desired change in spur, and all other outcomes never lead to such change, the outcome would have probability 1 and all other outcomes would have probability 0—the choice of a result of the probabilistic mapping for the argument would be deterministic. On the other hand, if all outcomes equally lead to a desired change in spur, all those outcomes will have equal probabilities (that sum up to 1).

Suppose the machine solves an optimization task consisting in the maximization of spur increment velocity and the machine has learned how to achieve a constant increase in this velocity. The adaptive probabilistic mapping would have an argument with one of its corresponding outcomes with a significantly greater probability than all other outcomes for the argument. This outcome takes part in reinforcing a behavior to constantly increase the spur increment velocity. The machine puts a little load on the random number generator to select an outcome for this argument, because one outcome has a significantly greater probability, and this outcome becomes a result most of the times.

Consider a situation that, at a particular point of time, the increment velocity has gone down, so the machine needs to change its own behavior to increase the increment velocity even more. The outcome with a significantly greater probability has now a lesser probability approximately equal to probabilities of some other outcomes for that argument. The probabilities of outcomes for other arguments may also change in a similar way. The machine engages the random number generator in a greater extent for selecting outcomes according to those new lists of probabilities.

In other words, the machine is now in a difficult situation that means an increase of average complexity of choices the machine has to perform to increase the increment velocity. Would the machine feel that the situation is difficult? (To answer this question, one can consider the amount of energy supplied to the random number generator.)

A computer running a pseudo-random number generator can simulate the behavior of a probabilistic mapping. Running the pseudo-random number generator is a deterministic process—the way today’s computers operate. The computer might use a random number generator implemented as a physical unit running a stochastic physical process. We can consider this unit as an interface to a (probabilistic) mapping provided by nature. A stochastic act will then be calling such mapping to return a result for a particular argument. If a probabilistic mapping is an electric circuit, it is more straightforward to use stochastic physical processes as a source of randomness.

One could relate the abstract idea of good and bad to the concept of choice complexity. The good would support a certain level of choice complexity. The survival of an animate being would be preserving its ability to perform choices with a sufficient degree of complexity. This has something in common with the definition of life as a characteristic which distinguishes objects that have signaling and self-sustaining processes from those that do not. In our case, the signaling is the way of exchanging information within superpositions of probabilistic mappings, and the basic self-sustaining process is supporting certain level of choice complexity.


Next: , Previous: , Up: Introduction   [Contents][Index]

1.5 Obtaining QSMM

The official homepage of QSMM project:

http://qsmm.org

The project profile hosted at SourceForge.net contains additional information on the project:

http://sourceforge.net/projects/qsmm/

A package distribution is available on the project files page provided by SourceForge.net:

http://sourceforge.net/projects/qsmm/files/

Next: , Previous: , Up: Introduction   [Contents][Index]

1.6 Reporting Bugs and Getting Help

The QSMM users mailing list is a place for discussing all things QSMM. To subscribe to the mailing list, unsubscribe from the list, view list archives, and perform other actions, use its information page:

https://lists.sourceforge.net/lists/listinfo/qsmm-users

The following types of feedback should go to the mailing list:

Do not be embarrassed by a small number of messages in the list archives—be the first to report a bug, submit a feature request, or ask a question!


Next: , Previous: , Up: Introduction   [Contents][Index]

1.7 QSMM Components

The QSMM package consists of the following main components:

The QSMM package also includes auxiliary components that may simplify developing programs:


Next: , Previous: , Up: Introduction   [Contents][Index]

1.8 System Requirements

System requirements include operating system requirements, compiler requirements, POSIX threads API notes, a reference hardware environment, library dependencies, and a software environment for building the package documentation.

Operating System—GNU/Linux

QSMM version 1.18 supports building and using on a GNU/Linux system. The author has not tested building this package version in other environments (e.g. Cygwin).

C Compiler—GCC

The author was building the package by gcc version 8.3.

POSIX Threads API Notes

The simple packet exchange API (Side API—see Exchanging Data Packets in a Multithreaded Program, for more information on this API), tests/side1.c, and a few example programs use the POSIX threads API.

On disabling the use of POSIX Threads API, a built QSMM library does not include the Side API, and the command make does not build tests/side1.c.

Reference Hardware Environment

The author was building the package and running example programs in the following hardware environment:

At present, QSMM consumes memory inefficiently: QSMM can allocate large memory blocks that are never or rarely accessed. Eliminating this deficiency will lead to significantly less memory consumption by QSMM.

Library Dependencies

Optional but default library dependencies are the gsl (GNU Scientific Library) and ncurses (console display library). The author used the following versions of those libraries to build the package:

gsl (GNU Scientific Library)

The main default dependency is GNU Scientific Library. This library provides the package with a high-quality pseudo-random number generator. Additionally, a few tests use this library to solve systems of linear equations.

On disabling a dependency on gsl:

The function rand from the standard C library has the following drawbacks:

QSMM starting from version 1.15 can also utilize a user-supplied random number generator, for example, implemented by a developer by hand or which is a wrapper for a random number generator provided by another library.

ncurses (console display library)

A few example programs use ncurses, a console display library. On defining the macro VISUALIZE when building tests/disasm2.c or tests/lookup2.c, those tests also use this library.

On disabling a dependency on ncurses, the command make does not build the example programs labyr2, pic-guess, and maze-asm.

Building the Documentation

Building the QSMM documentation in various formats requires the presence of additional packages in the system. Below is their list along with versions used by the author:


Next: , Previous: , Up: Introduction   [Contents][Index]

1.9 Installation

For package installation instructions, refer to the file INSTALL located in the root of the package distribution. This manual does not include those installation instructions to avoid duplication. The installation instructions also describe building documentation files, including this manual.


Next: , Previous: , Up: Introduction   [Contents][Index]

1.10 API Basics

A C program that uses QSMM includes one or more its header files. The main header file is qsmm.h. The #include <qsmm/qsmm.h> directive includes that file in the C program.

The header file sig.h included in qsmm.h defines datatypes and macros for signals—integer values that are possible outcomes and parts of an argument of a probabilistic mapping.

Object handles reference objects of various types. An object handle of qsmm_actor_t type references an adaptive probabilistic mapping.

All API functions report errors in a unified manner—via a result of int type, where negative results are error codes. A multinode model supports assigning an error handler to it for simpler reacting on errors in usual situations.

There exists an API function for retrieving the version of a QSMM library.


Next: , Up: API Basics   [Contents][Index]

1.10.1 Header Files

The configure script sets the root directory for C header files. By default, it is the directory /usr/local/include/. The command make install installs public QSMM header files to the subdirectory qsmm. Therefore, for default parameters of configure script invocation, the command make install installs the public QSMM header files to the directory /usr/local/include/qsmm/. You can specify a different root directory for C header files by a command-line option of configure script. See the file INSTALL in the root of the package distribution for more information.

Below is the list of public header files installed:

qsmm.h

This is the main header file of QSMM framework. It contains most of datatype, function, and macro definitions a developer may need.

err.h

[New in QSMM 1.17] This header file contains declarations of error codes, the prototype of qsmm_err_str function for obtaining the description of an error code, and declarations necessary for handling error conditions for a multinode model. An error handler function assigned to the multinode model receives information about such error conditions. See Error Handling, for basic information on handling error conditions. The header file qsmm.h includes this header file.

sig.h

[New in QSMM 1.17] This header file contains declarations of qsmm_sig_t and qsmm_ssig_t datatypes and QSMM_SIG_INVALID, QSMM_SIG_MAX, QSMM_FMT_PRI_SIG, QSMM_FMT_PRI_SSIG, and QSMM_FMT_SCN_SIG macros. See Basic Datatypes and Macros, for more information on those datatypes and macros. The header files qsmm.h and err.h include this header file.

handle.h

[New in QSMM 1.17] This header file contains declarations of incomplete types for object handles. See Object Handles, for more information on object handles. Along with the incomplete types for object handles, this header file declares the enumeration qsmm_handle_e listing possible object handle types, the union qsmm_handle_u representing any object handle, and the structure qsmm_handle_s consisting of an object handle type and an object handle value. The header file qsmm.h includes this header file.

refe.h

[New in QSMM 1.17] This header file contains datatypes for entity references. In QSMM version 1.18, entity references unambiguously specify entities related to error conditions for a multinode model. An error handler function assigned to the multinode model can receive entity references as part of an argument. Additionally, entity references identify entities in a multinode model when enumerating them. See Entity References, for more information. The header files qsmm.h and err.h include this header file.

side.h

A self-contained header file for the Side API. That simple API provides means for exchanging data packets, especially signals, between threads in a multithreaded program. In some cases, program structure with a number of interacting sides executing in separate threads and exchanging data packets can increase program work speed or simplify program development or experimenting. See Exchanging Data Packets in a Multithreaded Program, for more information on the Side API.

The command make install installs this header file when the configure script has configured the package to use the POSIX threads API (see the file INSTALL in the root of the package distribution for information on package configuring).

map.h

A self-contained header file for the C implementation of functionality of STL map and multimap templates.

version.h

A header file with the macro QSMM_HEADERS_VERSION defined to package version. A developer can use this macro to check whether versions of the headers and the library conform. The command make generates the content of version.h using the template qsmm/version.h.in in the package distribution. The header file qsmm.h includes this header file.

To include the aforementioned header files in a C program by a preprocessor #include directive, a developer should specify the directory prefix qsmm. For example, to include the header file qsmm.h, the developer should specify

#include <qsmm/qsmm.h>

The extern "C" declarations wrap C functions declared in the header files. When a C++ source file includes the header files, those declarations provide correct linkage with functions contained in the QSMM library.


Next: , Previous: , Up: API Basics   [Contents][Index]

1.10.2 Basic Datatypes and Macros

The basic notion used in QSMM is signal. Signals are parts of an argument of a probabilistic mapping. A result of a probabilistic mapping is also a signal. Signals are the carriers of actions. In QSMM, non-negative integers identify signals. The maximum possible value of a signal identifier depends on a datatype used to hold the identifier. As the number of possible signals can be critical for a particular application, special datatypes exist for signal identifiers. The header file sig.h included in qsmm.h and err.h defines those datatypes.

Data type: qsmm_sig_t

This is an unsigned integer datatype for storing signal identifiers and the numbers of signals. The set of allowed values for this datatype is the range 0 to QSMM_SIG_MAX+1 and the special value QSMM_SIG_INVALID. The current implementation defines the datatype as unsigned int.

In principle, a developer can define this datatype as a smaller unsigned integer type to reduce memory consumption. Corresponding modification of definitions of qsmm_ssig_t datatype and QSMM_SIG_MAX, QSMM_SIG_INVALID, QSMM_FMT_PRI_SIG, QSMM_FMT_PRI_SSIG, and QSMM_FMT_SCN_SIG macros (see below) may be necessary. As of QSMM version 1.17, the developer may not define this datatype as a larger unsigned integer type, because not all package source code has been reworked to support such a type.

The values QSMM_SIG_MAX+1 and QSMM_SIG_INVALID must lie in the range of allowed values of size_t type. This restriction means that the condition “sizeof(qsmm_sig_t)<=sizeof(size_t)” holds true.

Data type: qsmm_ssig_t

[New in QSMM 1.17] This is a signed integer datatype for storing signal identifiers and the numbers of signals. The set of allowed values for this datatype is the range -(qsmm_ssig_t) QSMM_SIG_MAX-1 to QSMM_SIG_MAX+1 and the special value QSMM_SIG_INVALID. The current implementation defines the datatype as int. Specifics of defining this datatype as a different signed integer type are the same as for the datatype qsmm_sig_t. The condition “sizeof(qsmm_ssig_t)==sizeof(qsmm_sig_t)” must hold true.

Signal identifiers not only specify signals themselves but also other entities internally represented by signals. For example, the identifiers of nodes of a multinode model and their states are signal identifiers.

Use the following macros when working with signal identifiers.

Macro: QSMM_SIG_INVALID

Represents an invalid signal identifier. Use it as a substitute for the NULL value of a signal identifier because identifier 0 is valid one. Historically, the macro expands to an unsigned integer value. In QSMM version 1.18, the macro expands to ((1 << (sizeof(qsmm_sig_t)*8-1))-0U).

Macro: QSMM_SIG_MAX

This is the maximum allowed value of a signal identifier. Historically, the macro expands to an unsigned integer value.

Consider two affirmations:

  1. When an array contains information on signals with identifiers in the range 0 to QSMM_SIG_MAX, the number of elements in the array is equal to QSMM_SIG_MAX+1.
  2. When the upper bound of a range of signal identifiers is not inclusive, the range x to QSMM_SIG_MAX has upper bound QSMM_SIG_MAX+1.

To make it possible to use the datatypes qsmm_sig_t and qsmm_ssig_t for specifying the numbers of signals in the first case and signal ranges with not inclusive upper bounds in the second case, those datatypes additionally support storing value QSMM_SIG_MAX+1. The datatype qsmm_ssig_t additionally supports storing value -(qsmm_ssig_t) QSMM_SIG_MAX-1. In QSMM version 1.18, the macro expands to ((1 << (sizeof(qsmm_sig_t)*8-1))-2U).

Macro: QSMM_FMT_PRI_SIG

[New in QSMM 1.17] An optional length modifier and a conversion specifier in format strings for functions similar to printf for printing values of qsmm_sig_t type. The macro expands to ‘u’.

Macro: QSMM_FMT_PRI_SSIG

[New in QSMM 1.17] An optional length modifier and a conversion specifier in format strings for functions similar to printf for printing values of qsmm_ssig_t type. The macro expands to ‘d’.

Macro: QSMM_FMT_SCN_SIG

[New in QSMM 1.17] An optional length modifier and a conversion specifier in format strings for functions similar to scanf for parsing values of qsmm_sig_t type. The macro expands to ‘u’.

A developer should use the aforementioned datatypes and macros to write source code supporting easier adaptation for a smaller or larger number of possible signals. The source code will also be better compatible with future versions of QSMM framework.

Below there is an example of using the datatype qsmm_sig_t and the macro QSMM_FMT_PRI_SIG. The function print_sig_array prints an array of signal identifiers specified by a pointer to the array and a number of its elements.

#include <stdio.h>
#include <qsmm/qsmm.h>

void
print_sig_array(
    const qsmm_sig_t *sigp,
    qsmm_sig_t nsig
) {
    putchar('[');
    for (qsmm_sig_t idx=0; idx<nsig; idx++) {
        if (idx) fputs(", ",stdout);
        printf("%" QSMM_FMT_PRI_SIG,sigp[idx]);
    }
    puts("]");
}

Next: , Previous: , Up: API Basics   [Contents][Index]

1.10.3 Object Handles

QSMM uses handles for referencing various objects visible to an application program. A handle is an opaque typed pointer to a QSMM internal structure. The application program cannot examine or change its content other than by calling API functions that take a handle of this type as an argument. The type of a handle corresponds to the type of an object referenced by the handle. Dereferencing handles does not make sense as they have incomplete types. Because a handle is a pointer, it can have the NULL value.

The table below lists handle types used in QSMM. For each handle type, the table indicates a corresponding object type and a reference to a section in this manual with a detailed description of that handle type.

Handle typeObject typeReference to a section in this manual
qsmm_tmultinode modelCreating a Multinode Model.
qsmm_actor_tactorCreating an Actor.
qsmm_actpair_tactor pairCreating the Model Instance.
qsmm_instr_tassembler instructionBasic Datatypes for Assembler Programs.
qsmm_iter_tmap iteratorPart of C implementation of functionality of STL map and multimap templates. See Creating Maps and Iterators.
qsmm_map_tmapPart of C implementation of functionality of STL map and multimap templates. See Creating Maps and Iterators.
qsmm_msg_tmessageCreating Messages.
qsmm_msglist_tmessage listCreating a Message List.
qsmm_prg_tassembler programBasic Datatypes for Assembler Programs.
qsmm_rng_trandom number generatorCreating a Random Number Generator.
qsmm_side_tinteraction sidePart of Side API. See Registering Interaction Sides.
qsmm_storage_tstatistics storageStorage Types.
qsmm_vec_tvectorOrdinary and Sparse Vectors.

Note: It is generally acceptable to call API functions for different handles in different threads of a multithreaded program concurrently on condition that those handles do not reference interrelated objects (e.g. when an object is a component of another object). Calling API functions for the same handle (in different threads of a multithreaded program concurrently) is not thread-safe except for the Side API intended for communication between threads.

The following enumeration specifies possible handle types.

Enumeration: qsmm_handle_e

This enumeration lists supported types of object handles. The enumeration contains the following elements.

QSMM_HANDLE_INVALID

A special value designating an invalid, unknown, or NULL object handle type.

QSMM_HANDLE_MODEL

A multinode model handle. It has the type qsmm_t.

QSMM_HANDLE_ACTOR

An actor handle. It has the type qsmm_actor_t.

QSMM_HANDLE_ACTPAIR

An actor pair handle. It has the type qsmm_actpair_t.

QSMM_HANDLE_INSTR

An assembler instruction handle. It has the type qsmm_instr_t.

QSMM_HANDLE_ITER

A key-value map iterator handle. It has the type qsmm_iter_t.

QSMM_HANDLE_MAP

A key-value map handle. It has the type qsmm_map_t.

QSMM_HANDLE_MSG

An error, warning, note, or uncategorized message handle. It has the type qsmm_msg_t.

QSMM_HANDLE_MSGLIST

A handle of a list of error, warning, note, or uncategorized messages. The handle has the type qsmm_msglist_t.

QSMM_HANDLE_PRG

An assembler program handle. It has the type qsmm_prg_t.

QSMM_HANDLE_RNG

A random number generator handle. It has the type qsmm_rng_t.

QSMM_HANDLE_SIDE

An interaction side handle. It has the type qsmm_side_t.

QSMM_HANDLE_STORAGE

A statistics storage instance handle. It has the type qsmm_storage_t.

QSMM_HANDLE_VEC

A handle of an ordinary or sparse vector. The handle has the type qsmm_vec_t.

QSMM_HANDLE_COUNT

The number of elements in the enumeration excluding this element.

The following union represents a handle of a specific or generic type.

Union: qsmm_handle_u

This union represents one of typed object handles or an untyped object handle. The union contains the following fields.

Field: qsmm_t qsmm

A multinode model handle.

Field: qsmm_actor_t actor

An actor handle.

Field: qsmm_actpair_t actpair

An actor pair handle.

Field: qsmm_instr_t instr

An assembler instruction handle.

Field: qsmm_iter_t iter

A key-value map iterator handle.

Field: qsmm_map_t map

A key-value map handle.

Field: qsmm_msg_t msg

An error, warning, note, or uncategorized message handle.

Field: qsmm_msglist_t msglist

A handle of a list of error, warning, note, or uncategorized messages.

Field: qsmm_prg_t prg

An assembler program handle.

Field: qsmm_rng_t rng

A random number generator handle.

Field: qsmm_side_t side

An interaction side handle.

Field: qsmm_storage_t storage

A statistics storage instance handle.

Field: qsmm_vec_t vec

A handle of an ordinary or sparse vector.

Field: void * raw_p

An untyped object handle.

The following structure holds the type of a handle along with its value.

Structure: qsmm_handle_s

This structure holds the type of an object handle and its value. The structure contains the following fields.

Field: enum qsmm_handle_e type

An object handle type.

Field: union qsmm_handle_u val

An object handle value corresponding to an object handle type in the field type.


Next: , Previous: , Up: API Basics   [Contents][Index]

1.10.4 Error Handling

If an API function returns a value of int type, then a negative return value is an error code. Zero and positive return values indicate additional information regarding a successful completion of a function call.

If an API function does not return a value of int type, the function may not return an error code, because error condition cannot arise within the function, or, at least, because there was such assumption when the function first appeared in the API.

If not otherwise noted in the description of an error code of an API function, returning the error code by the function means that the state of QSMM framework remained unchanged, that is, just after calling the function, the framework retained its state it had just before calling the function.

Use the following API function from the header file err.h (included in qsmm.h) to get the text description of an error code.

Function: const char * qsmm_err_str (int err)

This function returns the text description of API error code err. For invalid error codes, the function returns ‘?’.

When you are creating a multinode model, you can associate an error handler with the model. In this case, the error handler may receive extended information about an error occurred. The use of an error handler may eliminate the need to check the return codes of calls to API functions that have an argument of qsmm_t type to determine whether or not those functions succeeded. See Error Handling for a Multinode Model, for information on using error handlers.


Previous: , Up: API Basics   [Contents][Index]

1.10.5 Getting Library Version

Currently, the version of a QSMM library has major.minor format. In the future, a QSMM library with a greater major version may have considerable backward-incompatible changes to the API. That is, upgrading existing applications to support versions with a greater major number may require considerable changes to the source code of those applications.

Getting a string representation of library version. Use the following API function from the header file qsmm.h:

Function: const char * qsmm_version ()

This function returns the version of a QSMM library as a string in major.minor format (e.g. ‘1.18’).

Getting a string representation of the version of library header files. Use the following macro from the header file version.h (included in qsmm.h):

Macro: QSMM_HEADERS_VERSION

This macro expands to a string representation of the version of installed header files of a QSMM library (e.g. to ‘1.18’). A C program that uses the library includes the header files. The version of those header files should be equal to the version of a QSMM library used when linking the program. See Header Files, for more information about the header files of QSMM library.


Next: , Previous: , Up: Introduction   [Contents][Index]

1.11 Linking with the Library

The QSMM library may have dependencies on other libraries. The configure script executed at the package configuring phase defines those dependencies. For a shared version of QSMM library, the shared library file has those dependencies included in it. You do not need to specify them in a link command:

gcc example.o -L/usr/local/lib -lqsmm

(If the library resides in the directory /usr/local/lib/, and that directory is not on the standard linker search path, use the option -L/usr/local/lib.)

To link with a static version of QSMM library, you need to specify libraries it depends on in a link command. For this, use linker options -l, such as -lgsl and -lm. The following example command produces a fully statically linked executable:

gcc -static example.o -lqsmm -lgsl -lm

Alternatively, you can link using the libtool program. This program will use the file libqsmm.la copied to the library directory when installing the package. That file describes all dependencies required to produce an executable linked against the QSMM library. The libtool program simplifies static linking.


Previous: , Up: Introduction   [Contents][Index]

1.12 Conventions for Datatypes

The names of all datatypes declared in the QSMM public header files and its source code are in lowercase. The suffixes of those names correspond to C language keywords used for datatype declarations:

typedef

The ‘_t’ suffix. The names of datatypes for function pointers have the ‘_func_t’ suffix.

enum

The ‘_e’ suffix.

struct

The ‘_s’ suffix.

union

The ‘_u’ suffix.

The names of all datatypes declared in the QSMM public header files have the ‘qsmm_’ prefix.

QSMM has conventions for the use of basic C language types and the types size_t, qsmm_sig_t, and qsmm_ssig_t in various situations. The API and the package source code itself1 follow these conventions. C programs using QSMM may also follow them.

The primary conventions are that if a datatype holds signal identifiers or the numbers of signals, and such values

The secondary convention is that for sizes of memory arrays and for non-negative indices of their elements allowed to be greater than 32767, you should use the type size_t.

For other situations, including situations when you choose not to use the type qsmm_sig_t or qsmm_ssig_t according to the first two items of primary conventions stated above, the rules are:

  1. For boolean flags, use the type char or int or use specific bits in values of other numeric types.
  2. For integer quantities that never lie outside the range 0 to 127, use the type char or int.
  3. For integer quantities that may be negative but never lie outside the range -128 to 127, use the type signed char or int.
  4. For non-negative integer quantities that may exceed 127 but never exceed 255, use the type unsigned char or int.
  5. For integer quantities that may be less than -128 but never lie outside the range -32768 to 32767, use the type int.
  6. For integer quantities that may exceed 255 but never lie outside the range -32768 to 32767, use the type int.
  7. For non-negative integer quantities that may exceed 32767 but never exceed 65535, use the type unsigned int.
  8. For non-negative integer quantities that may exceed 65535 but do not have the restriction that they must be at least 64-bit, use the type long or unsigned long.
  9. For integer quantities that may be less than -32768 and may be greater than 32767 but do not have the restriction that they must be at least 64-bit, use the type long.
  10. For integer quantities that must be at least 64-bit, use the type long long or unsigned long long.

For example, in QSMM:

The set of datatypes declared in the API with the ‘_t’ suffix in their names includes the datatypes qsmm_sig_t and qsmm_ssig_t, datatypes for function pointers with the ‘_func_t’ suffix, and datatypes for object handles. See Object Handles, for more information about datatypes for object handles.

Datatypes declared in the API with the ‘_e’ suffix in their names are enumerations. Elements of enumerations are in uppercase.

Datatypes with the suffixes ‘_s’ and ‘_u’ are structures and unions respectively. The order of their fields depends on the datatypes of those fields and is the following:

  1. Fields of basic types (except for pointers of void type). The type order is the following: char, signed char, unsigned char, short, unsigned short, int, unsigned int, long, unsigned long, long long, unsigned long long, float, double, long double.
  2. Fields of types declared in QSMM with the ‘_t’ suffix in their names.
  3. Fields of other types, except for types with names following the specifier ‘enum’, ‘struct’, or ‘union’.
  4. Fields of types with names following the specifier ‘enum’. Enumerations declared in QSMM go first.
  5. Fields of types with names following the specifier ‘struct’. Structures declared in QSMM go first.
  6. Fields of types with names following the specifier ‘union’. Unions declared in QSMM go first.
  7. Fields with pointers of void type.

For every type name within each type category listed above, the type order is the following:

  1. Non-pointer and non-array types (not applicable to the void type).
  2. Arrays (but not pointers to arrays), including arrays of pointers.
  3. Pointer types (except for arrays of pointers) with full names beginning with the const qualifier in the order of increasing the number of asterisks.
  4. Pointer types (except for arrays of pointers) with full names that do not begin with the const qualifier in the order of increasing the number of asterisks.

Next: , Previous: , Up: Top   [Contents][Index]

2 Adaptive Probabilistic Mapping

An adaptive probabilistic mapping2 or actor interacts with an application program or environment by means of exchanging signals. The input and output signals of the actor can be the arguments of the adaptive probabilistic mapping. The output signals3 of the actor are the outcomes of the adaptive probabilistic mapping.

The actor ordinarily receives the input signals, spur (see Spur-driven Behavior) increments, and time increments and emits the output signals with the goal to maximize spur increment or decrement velocity. To achieve that goal, the actor performs basic forecasting of spur increments resulting from emitting various output signals. The author assumes that by combining multiple actors or applying other approaches it is possible to amplify this forecasting capability to create a system intelligently interacting with an environment of real-world complexity.


Next: , Up: Adaptive Probabilistic Mapping   [Contents][Index]

2.1 Event History

Occurrences of input and output signals of an actor with particular moments of time when those occurrences took place is the event history of the actor.

An example event history along with changing spur values represented as a two-dimensional chart is in Figure 2.1.

an event history example as a two-dimensional chart

Figure 2.1: an event history example as a two-dimensional chart

In the chart, filled dots denote events of receiving input signals, and unfilled dots denote events of emitting output signals. Every such event is on a horizontal line denoting a particular input or output signal with an identifier printed after the line end. In QSMM 1.18, a set of input signal identifiers and a set of output signal identifiers ordinarily do not overlap. Every input signal and its corresponding output signal connected by an arrow are on the same vertical line, as the API does not specify the time between receiving an input signal and emitting an output signal by an actor. A plot of single spur value change over time is above the event history.

A fragment of this two-dimensional chart in gray represented as a one-dimensional plot is in Figure 2.2.

an event history fragment as a one-dimensional plot

Figure 2.2: an event history fragment as a one-dimensional plot

We may assume that every event of receiving an input signal encodes an event of receiving a tuple of signals. Identifiers assigned to unique tuples would be input signal identifiers.

For example, we can replace every input signal with a triple of signals. The event history fragment with input signals replaced with triples of signals is in Figure 2.3.

tuples of signals as input signals

Figure 2.3: tuples of signals as input signals

In this figure, input signal 3 has encoded triple <3, 0, 4>, input signal 5 has encoded triple <1, 2, 5>, and input signal 0 has encoded triple <5, 3, 3>.

In this way, by setting one-to-one correspondence between single-value arguments of a probabilistic mapping and n-value tuples, we convert the mapping to an n-ary probabilistic mapping.

By including the previous outcome of a probabilistic mapping in its next n-ary argument, we convert a stateless probabilistic mapping to a stateful mapping—an outcome of a probabilistic mapping becomes its state; in this way, the probabilistic mapping can model a finite automaton. After this conversion, input signal 5 encodes quadruple <21, 1, 2, 5>, and input signal 0 encodes quadruple <19, 5, 3, 3>.

An n-ary argument of an adaptive probabilistic mapping is an action choice state of an actor. An action choice state is an input list of events an actor shall respond to by choosing an action—emitting an output signal. An action choice state might be a guessed or known current system or environment state that requires generating an adaptive action.

In the past, action choice states were meant to be n-grams of events from an event history. The current view is that action choice states are not necessarily n-grams, but the terminology remains the same for compatibility. An action choice state n-gram is a signal identifier list that encodes an action choice state. The tuples <3, 0, 4>, <1, 2, 5>, <5, 3, 3>, <21, 1, 2, 5>, and <19, 5, 3, 3> are action choice state n-grams used to select output signals 21, 19, and 17.


Next: , Previous: , Up: Adaptive Probabilistic Mapping   [Contents][Index]

2.2 Output Signal Selection

An actor emits output signals stochastically according to their probabilities it calculates. The actor collects statistics on observed consequences of emitting various output signals in various action choice states. It treats such observed consequences as dependent only on a specific action choice state and a specific output signal emitted in the action choice state. An event history segment for observing the consequences is a cycle—a segment between an occurrence of that action choice state in the event history and the next occurrence of that action choice state in the event history. The actor uses the collected statistics to calculate the probabilities of emitting allowed output signals in a current action choice state.

For every occurrence of an action choice state in the event history, the actor updates statistics on a cycle type—the pair comprised of this action choice state and an output signal emitted at the previous occurrence of this action choice state in the event history. The actor updates the statistics with the following parameters:

The actor calculates the probabilities of output signals to emit in a current action choice state using statistics collected for pairs comprised of this action choice state and each allowed output signal. Such statistics includes the following parameters for event history segments between an occurrence of this action choice state with emitting the output signal and the next occurrence of this action choice state:

Using the sum of spur increments over the segments and the total time length of those segments, the actor can calculate the mean velocity of spur increment over the segments. The higher the mean spur increment velocity is for segments specified by the pair comprised of an action choice state and an output signal, the greater the probability of emitting the output signal in the action choice state can be.

Let us consider a simplistic example. Suppose the actor has recorded that emitting output signal 18 in an action choice state concluded with spur increment +7 over a period of 40 time units until the action choice state occurred the next time in the event history. Suppose the actor has also recorded that emitting output signal 19 at a different occurrence of this action choice state concluded with spur increment +6 over a period of 30 time units until the action choice state occurred again in the event history. Therefore, when emitting next output signal in this action choice state, the actor will select signal 19 with higher probability than signal 18 because spur increment velocity 6/30 for signal 19 is greater than spur increment velocity 7/40 for signal 18. When the actor emits the same output signal in the same action choice state more than once, it accumulates the statistics and uses mean spur increment velocity to calculate the probability of emitting an output signal.

In QSMM, the actor uses a more complex method of selecting an output signal, so the above example is a simplification that does not fully agree with practice. See Customizing the Relative Probability Function, for more information about available and user-defined functions utilizing various kinds of statistics to calculate the probability of emitting an output signal.

To improve reaction to latest tendencies in the event history, the actor may remember statistics for time periods shorter than the entire event history.


Next: , Previous: , Up: Adaptive Probabilistic Mapping   [Contents][Index]

2.3 Small and Large Actors

The most time-consuming operation frequently performed by an actor is adaptive emitting an output signal. The only actor type implemented before QSMM 1.15 was small actor. A small actor performs the operation of adaptive emitting an output signal in the following steps:

  1. The actor calculates the relative probabilities of all output signals.
  2. The actor stochastically selects an output signal according to those relative probabilities using a random number generator.

From the standpoint of computer implementation, the most time-consuming is the first step when the actor calculates the relative probabilities of all output signals. For example, to adaptively select an output signal from a set of 16 output signals, the small actor has to perform 16 evaluations of a relative probability function. Figure 2.4 illustrates this situation.

emitting an output signal in an action choice state of a small actor

Figure 2.4: emitting an output signal in an action choice state of a small actor

The time necessary to complete the sequential execution of this calculation process is the sum of time periods needed for calculating the value of a relative probability function for every output signal. While calculating every such value can be time-expensive on its own on account of performing many arithmetic operations, fetching their input values from statistics storage can add significant time overhead to the calculation process.

To speed up selecting output signals by an actor, QSMM 1.15 introduces the concept of large actor. If the weights (or the relative profile probabilities) of output signals of a large actor are equal, the number of relative probability function evaluations performed by the large actor is not equal to the number of its output signals but is approximately equal to the product of the logarithm of that number and a logarithm base. Large actors provide fast selection of an output signal when the number of output signals is large or even huge; the only limitation is the amount of memory available for storing the control structures of a large actor.

The adaptivity of behavior of a large actor (as well as small one) depends on a relative probability function used, that is, on a function that returns the relative probability of selecting a signal. The default function used by a large actor can provide moderate efficiency in solving certain kinds of problems, for example, the identification of a current environment state. Developers unsatisfied with results produced using that function can provide a custom function via corresponding API calls.

A large actor performs fast stochastic selection of output signals by using trees containing nodes controlled by a small actor. The following entities correspond to every tree node:

  1. An action choice state: either root one or intermediate one. The root action choice state is the current action choice state of the large actor; it selects an output signal for that state.
  2. A small array of relative probabilities of output signals (this array typically contains a few elements). Those output signals are either output signals of the large actor or intermediate output signals. To every intermediate output signal there corresponds an intermediate action choice state located at a deeper hierarchy level.

Figure 2.5 illustrates this tree structure. Indexed letters “s” denote intermediate action choice states, and indexed letters “a” denote intermediate output signals.

emitting an output signal in an action choice state of a large actor

Figure 2.5: emitting an output signal in an action choice state of a large actor

A large actor performs the operation of adaptive emitting an output signal by the following algorithm:

  1. Assign: current intermediate action choice state = the current action choice state of the large actor.
  2. Adaptively generate an output signal for the current intermediate action choice state by a small actor associated with the large actor. This operation requires calculating the relative probabilities of all output signals (typically a few ones) for the current intermediate action choice state.
  3. An output signal generated in step 2 can be either an intermediate output signal or an output signal of the large actor. If the output signal is the one of the large actor, then finish.
  4. Change the current intermediate action choice state to an intermediate action choice state corresponding to the intermediate output signal and go to step 2.

Thus, using a tree represented in Figure 2.5, the adaptive selection of an output signal from a set of 16 output signals requires only 8 evaluations of a function returning the relative probability of a signal. A taller binary tree would provide the adaptive selection of an output signal from a set of 256 output signals using 16 evaluations of the function.

The structure of the tree affects the weights of output signals of a large actor and the speed of emitting those signals by the large actor. Large actors use n-ary Huffman trees to adaptively generate output signals. Using a Huffman tree built for a specific list of output signal weights, emitting output signals with greater weights requires the same or a smaller number of relative probability function evaluations compared to emitting output signals with lesser weights.

Although having much the same API, small and large actors are not fully interchangeable. There are specifics of using actors of every type.


Next: , Previous: , Up: Adaptive Probabilistic Mapping   [Contents][Index]

2.4 Creating an Actor

An actor handle refers to a small or large actor.

Data type: qsmm_actor_t

This is a type for an actor handle. It is a pointer, so variables of this type can be NULL. The function qsmm_actor_create creates a new actor and returns its handle. The function qsmm_actor_destroy destroys an existing actor addressed by a handle. You can pass an actor handle to API functions taking an argument of qsmm_actor_t type after the creation of an actor and until its destruction.

Use the following functions to create and destroy an actor.

Function: int qsmm_actor_create (const struct qsmm_actor_desc_s *desc_p, qsmm_actor_t *actor_p)

This function creates an actor using parameters in *desc_p and stores an actor handle in *actor_p.

If actor_p is NULL, the function only validates the parameters in *desc_p.

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

QSMM_ERR_INVAL

Parameters in *desc_p are invalid.

QSMM_ERR_NOMEM

There was not enough memory to create an actor.

QSMM_ERR_BIGMDL

A non-NULL field large_desc_p in *desc_p specified to create a large actor, but its multinode model would be too complex. See Creating the Model Instance, for a description of QSMM_ERR_BIGMDL error the function qsmm_engine_create can report on creating a multinode model instance thereby causing the function qsmm_actor_create to return this error code.

Function: void qsmm_actor_destroy (qsmm_actor_t actor)

This function destroys an actor specified by handle actor. You must not use the actor handle after the actor destruction. If actor is NULL, the function has no effect.

Below there are a description of a structure passed in *desc_p to the function qsmm_actor_create and descriptions of a related datatype, a union, and enclosed structures.

Structure: qsmm_actor_desc_s

This structure describes parameters for creating an actor by the function qsmm_actor_create. The structure contains the following fields.

Field: char use_flat_storage

A flag specifying the type of storage the actor will use for collecting statistics on the event history. If this field is non-zero, and the field large_desc_p is NULL, then the actor will use flat storage. If this field is non-zero, and the field large_desc_p is non-NULL, then the function qsmm_actor_create will report QSMM_ERR_INVAL. If this field is zero, then the actor will use map storage.

Flat storage is preallocated storage presumably of large size but with fast access to data elements. Map storage is dynamically allocated storage presumably of smaller size but with slower access to data elements; map storage uses sorted maps for backing storage. See Storage Types, for additional information on statistics storage types.

Field: int nspur

The number of spur types the actor will use. That number must be greater than 0. If the actor is the large one, then a small actor associated with the large actor will use 1+nspur spur types, where an implicitly added spur type with the lowest index corresponds to the automatic spur of the small actor. See Automatic Spur, for more information on that spur.

Field: int ngram_sz

The length of a list of signal identifiers encoding an action choice state. That length must be greater than 0. The longer the list is the more events in the event history the actor typically needs for training.

Field: int profile_pool_sz

Non-negative size of the pool of probabilities lists in normal form. The function qsmm_actor_profile_add adds a unique probabilities list in normal form to that pool. The function qsmm_set_actor_ngram_profile sets the added probabilities list for a particular action choice state n-gram.

For a small actor, the size of the pool of probabilities lists in normal form is the maximum number of unique sorted lists of normalized output signal weights (profile probabilities) the actor can store in its memory.

For a large actor, that size is the maximum number of Huffman trees of unique structure the actor can store in its memory, not counting an automatically created default Huffman tree corresponding to the case when the weights of all output signals are equal. To determine whether or not a Huffman tree is unique, the actor creates a temporary Huffman tree to compare the probabilities of its leaves with the probabilities of leaves of previously stored Huffman trees. That is why the value of this field should generally be greater by 1 than the number of Huffman trees of unique structure required to represent the sorted lists of output signal weights.

Field: int compat

The compatibility level of algorithms used by the actor. That level must be 0, 1, or 2. Value 0 means to use original algorithms implemented before QSMM 1.15. Value 1 means to use enhanced algorithms:

  • – use a simpler formula for automatic spur increment;
  • – in formulas for computing the relative probability of an output signal, additionally multiply mean discrete cycle period by a value returned by the function qsmm_get_actor_naction_per_evt and, if the relative probability function type is QSMM_RELPROB_BUILTIN1, by 2.

Value 2 further improves the algorithms:

  • – calculate output signal probabilities of QSMM_PROB_FQ type by the function qsmm_actor_calc_action_prob based on exact (not sometimes decremented by 1) frequencies of output signals in the event history;
  • – for a small actor, make the function qsmm_get_actor_sig_action select a signal without using a random number generator (i.e. deterministically) if the signal is the only one signal with a positive relative probability.

Set this field to 2 in your new programs. This manual does not include outdated details specific to the original algorithms.

Field: double sparse_fill_max

Maximum fill ratio for sparse vectors holding the relative probabilities of output signals. The actor chooses whether to use sparse vectors or ordinary vectors based on this ratio. It must be a number in the range 0 to 1 inclusive. Value 0 indicates that the actor must always use ordinary vectors. Value 1 indicates that the actor must always use sparse vectors. A value between 0 and 1 indicates the maximum percentage (divided by 100) of non-zero elements in sparse vectors relative to the numbers of vector dimensions.

Note: when creating a large actor (the field large_desc_p is not NULL in this case), forgetting to set the field sparse_fill_max to a positive value, for example, 0.2 or 1, will cause bad actor performance.

Field: qsmm_rng_t rng

The handle of a random number generator the actor will use. See Random Number Generators, for how to create and destroy random number generators and perform other operations on them. If this field is NULL, the function qsmm_actor_create creates an instance of default random number generator for use by the actor until its destruction.

Field: enum qsmm_actor_sig_spec_e sig_spec_type

The type of a specification of the number and directions of signals used by the actor. Here “signal direction” means whether a signal is input one, output one, or belongs to both types.

Value QSMM_ACTOR_SIG_SPEC_IN_OUT indicates that the field sig_spec of this structure specifies the number of input signals and the number of output signals.

Value QSMM_ACTOR_SIG_SPEC_MASK indicates that the field sig_spec of this structure specifies the total number of signals and a mask describing the directions of those signals.

Field: union qsmm_actor_sig_spec_u sig_spec

A specification of the number and directions of signals used by the actor.

If the field sig_spec_type of this structure has value QSMM_ACTOR_SIG_SPEC_IN_OUT, then sig_spec.in_out must contain the specification.

If the field sig_spec_type of this structure has value QSMM_ACTOR_SIG_SPEC_MASK, then sig_spec.mask must contain the specification.

Field: struct qsmm_pair_sig_s * range_sig_p

The ranges of signal identifiers in a list encoding an action choice state. The field ngram_sz of this structure specifies the length of this list. The actor uses those ranges to check the validity of a list of signal identifiers encoding a current action choice state in various API functions, to reduce the memory footprint of flat storage if a small actor uses this type of storage, and to reduce the number of nodes in the multinode model of a large actor. There can be other uses for the ranges in future QSMM versions. Specify the ranges as precisely as possible to reduce the memory footprint of the actor.

If the field range_sig_p is not NULL, then this field must be the pointer to an array of ngram_sz elements, where each element is a pair. Those elements correspond to the positions of signal identifiers in a list encoding an action choice state. The fields first and second of each pair define the minimum value and the maximum value of a corresponding signal identifier. The value of first must be less than or equal to the value of second. The value of second must be less than the total number of signals of the actor specified using the fields sig_spec_type and sig_spec of this structure. If range_sig_p is NULL, this condition means that every signal in the list lies in the range 0 (inclusive) to the total number (exclusive) of signals of the actor.

Field: struct qsmm_actor_large_desc_s * large_desc_p

The parameters of a large actor. A non-NULL value of this field indicates to create a large actor.

To improve compatibility with future versions of QSMM library, zero by the function memset an instance of qsmm_actor_desc_s structure before setting the fields of this instance passed to the function qsmm_actor_create.

Enumeration: qsmm_actor_sig_spec_e

This enumeration defines a method of specification of the number and directions of signals of an actor in the field sig_spec of qsmm_actor_desc_s structure. The enumeration contains the following elements.

QSMM_ACTOR_SIG_SPEC_IN_OUT

The actor has a specified number of input signals and a specified number of output signals. A segment of output signal identifiers follows a segment of input signal identifiers. For example, if the actor has 6 input signals and 4 output signals, then signals 0, 1, 2, 3, 4, 5 will be input ones, and signals 6, 7, 8, 9 will be output ones. The field sig_spec.in_out of qsmm_actor_desc_s structure should contain the number of input and output signals.

QSMM_ACTOR_SIG_SPEC_MASK

The actor has a specified total number of signals. Every signal can be input one. A mask specifies a subset of output signals among those signals. The field sig_spec.mask of qsmm_actor_desc_s structure should contain the total number of signals and the mask.

Union: qsmm_actor_sig_spec_u

This union describes in two possible forms the number and directions of signals of an actor. The field sig_spec of qsmm_actor_desc_s structure holds that information. The union contains the following fields.

Field: struct qsmm_actor_sig_spec_in_out_s in_out

The number of input signals and the number of output signals. The field sig_spec_type of qsmm_actor_desc_s structure should be equal to QSMM_ACTOR_SIG_SPEC_IN_OUT.

Field: struct qsmm_actor_sig_spec_mask_s mask

The total number of signals and a subset of output signals. The field sig_spec_type of qsmm_actor_desc_s structure should be equal to QSMM_ACTOR_SIG_SPEC_MASK.

Structure: qsmm_actor_sig_spec_in_out_s

This structure specifies the number of input signals and the number of output signals of an actor. The structure contains the following fields.

Field: int nsig_in

The number of input signals of the actor. That number must be greater than 0.

Field: int nsig_out

The number of output signals of the actor. That number must be greater than 1.

The sum of values in the fields nsig_in and nsig_out must be less than or equal to QSMM_SIG_MAX+1.

Structure: qsmm_actor_sig_spec_mask_s

This structure specifies the total number of signals and a subset of output signals of an actor. The structure contains the following fields.

Field: char * is_sig_out_p

If this field is NULL, then all actor signals will be output ones; some or all of those signals can be input ones. If this field is not NULL, then the field must contain the pointer to an array of nsig (see the next field) elements. A zero element indicates that a signal with the identifier equal to an element index is an input signal. A non-zero element indicates that a signal with the identifier equal to an element index is an output signal and possibly input one. The array must contain at least two non-zero elements. The function qsmm_actor_create copies the array to an internal structure of the actor.

Field: int nsig

The total number of signals of the actor. That number must be greater than 1 and less than or equal to QSMM_SIG_MAX+1.

Structure: qsmm_pair_sig_s

This structure holds a pair of signals, for example, a signal range. The structure contains the following fields.

Field: qsmm_sig_t first

The first element of the pair. If the pair represents a signal range, then the minimum value of a signal identifier.

Field: qsmm_sig_t second

The second element of the pair. If the pair represents a signal range, then the maximum value of a signal identifier.

Structure: qsmm_actor_large_desc_s

This structure specifies the parameters of a large actor. The structure contains only one field but is a structure to simplify adding new parameters in future QSMM versions.

Field: int tree_arity

The maximum number of child nodes of every node of Huffman trees for adaptive selection of output signals by the large actor. That number must be greater than 1. You can use value 2 in most cases. It is better to use the number of output signals of a large actor equal to a positive integer power of the value of this field.

To improve compatibility with future versions of QSMM library, zero by the function memset an instance of qsmm_actor_large_desc_s structure before setting the value of tree_arity field of this instance passed via the field large_desc_p of qsmm_actor_desc_s structure to the function qsmm_actor_create.

Below there is sample source code for creating a small actor.

struct qsmm_actor_desc_s actor_desc;
memset(&actor_desc,0,sizeof(actor_desc));
actor_desc.nspur=1;
actor_desc.ngram_sz=3;
actor_desc.compat=2;
actor_desc.sig_spec_type=QSMM_ACTOR_SIG_SPEC_IN_OUT;
struct qsmm_actor_sig_spec_in_out_s *const io_p=
    &actor_desc.sig_spec.in_out;
io_p->nsig_in=6;
io_p->nsig_out=4;
qsmm_actor_t actor=0;
const int rc=qsmm_actor_create(&actor_desc,&actor);
if (rc<0) fprintf(stderr,"qsmm_actor_create: %s\n",qsmm_err_str(rc));

Below there is sample source code for creating a large actor.

struct qsmm_actor_desc_s actor_desc;
memset(&actor_desc,0,sizeof(actor_desc));
actor_desc.nspur=1;
actor_desc.ngram_sz=3;
actor_desc.compat=2;
actor_desc.sparse_fill_max=1;
actor_desc.sig_spec_type=QSMM_ACTOR_SIG_SPEC_IN_OUT;
struct qsmm_actor_sig_spec_in_out_s *const io_p=
    &actor_desc.sig_spec.in_out;
io_p->nsig_in=6;
io_p->nsig_out=4096;
struct qsmm_pair_sig_s range_sig[3];
memset(&range_sig,0,sizeof(range_sig));
range_sig[0].second=5;
range_sig[1].second=5;
range_sig[2].second=5;
actor_desc.range_sig_p=range_sig;
    // action choice state consists only of input signals of the actor
struct qsmm_actor_large_desc_s large_desc;
memset(&large_desc,0,sizeof(large_desc));
large_desc.tree_arity=2;
actor_desc.large_desc_p=&large_desc;
qsmm_actor_t actor=0;
const int rc=qsmm_actor_create(&actor_desc,&actor);
if (rc<0) fprintf(stderr,"qsmm_actor_create: %s\n",qsmm_err_str(rc));

You can obtain parameters specified when creating an actor later by the following functions.

Function: int qsmm_get_actor_nspur (qsmm_actor_t actor)

This function returns a positive integer equal to the number of spur types used by actor. The field nspur of qsmm_actor_desc_s structure passed to the function qsmm_actor_create when creating the actor specifies that number.

Function: int qsmm_get_actor_ngram_sz (qsmm_actor_t actor)

This function returns a positive integer number equal to the length of a list of signal identifiers encoding an action choice state of actor. The field ngram_sz of qsmm_actor_desc_s structure passed to the function qsmm_actor_create when creating the actor specifies that length.

Function: int qsmm_get_actor_profile_pool_sz (qsmm_actor_t actor)

This function returns a non-negative integer number equal to the size of the pool of probabilities lists in normal form of actor. The field profile_pool_sz of qsmm_actor_desc_s structure passed to the function qsmm_actor_create when creating the actor specifies that size.

Function: int qsmm_get_actor_compat (qsmm_actor_t actor)

This function returns a non-negative integer number equal to the compatibility level of algorithms used by actor. The field compat of qsmm_actor_desc_s structure passed to the function qsmm_actor_create when creating the actor specifies that level.

Function: int qsmm_get_actor_nsig (qsmm_actor_t actor)

This function returns a positive integer equal to the total number of signals of actor.

If the field sig_spec_type of qsmm_actor_desc_s structure passed to the function qsmm_actor_create when creating the actor is equal to QSMM_ACTOR_SIG_SPEC_IN_OUT, the total number of signals is the sum of sig_spec.in_out.nsig_in and sig_spec.in_out.nsig_out fields of qsmm_actor_desc_s structure.

If the field sig_spec_type is equal to QSMM_ACTOR_SIG_SPEC_MASK, the total number of signals is the field sig_spec.mask.nsig of qsmm_actor_desc_s structure.

Function: int qsmm_get_actor_nsig_out (qsmm_actor_t actor)

This function returns a positive integer equal to the number of output signals of actor.

If the field sig_spec_type of qsmm_actor_desc_s structure passed to the function qsmm_actor_create when creating the actor is equal to QSMM_ACTOR_SIG_SPEC_IN_OUT, the number of output signals is the field sig_spec.in_out.nsig_out of qsmm_actor_desc_s structure.

If the field sig_spec_type is equal to QSMM_ACTOR_SIG_SPEC_MASK, the number of output signals is the number of non-zero elements in the array sig_spec.mask.is_sig_out_p in the structure qsmm_actor_desc_s.

Function: double qsmm_get_actor_sparse_fill_max (qsmm_actor_t actor)

This function returns maximum fill ratio for sparse vectors holding the relative probabilities of output signals. An actor chooses whether to use sparse vectors or ordinary vectors based on this ratio. The field sparse_fill_max of qsmm_actor_desc_s structure passed to the function qsmm_actor_create when creating the actor specifies this ratio.

Function: const struct qsmm_pair_sig_s * qsmm_get_actor_range_sig (qsmm_actor_t actor)

This function returns the pointer to an array in an internal structure of an actor describing allowed ranges of signal identifiers in lists encoding its action choice states. The field range_sig_p of qsmm_actor_desc_s structure passed to the function qsmm_actor_create when creating the actor specifies the content of this array. The number of elements in the array is equal to the length of a list of signal identifiers encoding an action choice state. The function qsmm_get_actor_ngram_sz returns that length. The function qsmm_get_actor_range_sig never returns NULL.

A datatype for the handle of statistics storage is qsmm_storage_t. You can obtain the handle of statistics storage of an actor by the following function.

Function: qsmm_storage_t qsmm_get_actor_storage (qsmm_actor_t actor)

This function returns the handle of storage used by actor for collecting statistics on the event history. If the actor is the large one, the storage contains only part of that statistics. Huffman trees within the multinode model of that large actor hold the other part of that statistics. This function never returns NULL.

A datatype for the multinode model of a large actor is qsmm_t. You can obtain the handle of the multinode model of an actor by the following function.

Function: qsmm_t qsmm_get_actor_large_model (qsmm_actor_t actor)

This function returns the handle of a multinode model used by a large actor to adaptively emit output signals. If actor is a large actor, the function returns a non-NULL handle. If actor is a small actor, the function returns NULL. You can use this function to determine whether an actor is large or small one.


Next: , Previous: , Up: Adaptive Probabilistic Mapping   [Contents][Index]

2.5 Repeated Sequence of Operations

After the creation of an actor and until its destruction, a repeated sequence of operations is receiving a tuple of input signals followed by emitting an output signal. Any number of operations of incrementing spur and incrementing time can precede or follow those two operations.


Next: , Up: Repeated Sequence of Operations   [Contents][Index]

2.5.1 Incrementing Spur

An actor selects output signals adaptively according to spur increments supplied to it along with input signals. Those spur increments are indirect and probabilistic assessment of efficiency of output signal selection. An output signal selected does not have one-to-one correspondence with a spur increment followed—an arbitrary number of output signals selected can cause an arbitrary number of spur increments followed in arbitrary delays.

Each spur increment is an increment of spur of a specific type. See Spur-driven Behavior, for the definitions of spur and spur type.

The function qsmm_actor_create sets the number of spur types for an actor. Every spur type definition has the following parameters: a way of spur perception, spur weight, and a type of time for computing spur increment velocity. A list of spur type definitions along with the methods of performing spur increments specify the spur scheme of an actor.

Use the following function to increment the value of spur of a specific type.

Function: int qsmm_actor_spur_delta (qsmm_actor_t actor, int spur_type, double spur_delta)

This function increments by spur_delta the value of spur of spur_type type an actor has been accumulating. Spur types have zero-based indices. Special spur type -1 of a large actor corresponds to the automatic spur of a small actor associated with the large actor. The value of spur_delta can be negative.

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

One of the following conditions is true:

  • – the actor is the small one, and spur_type is negative;
  • – the actor is the large one, and spur_type is less than -1;
  • spur_type is greater than or equal to the number of spur types specified in the field nspur of qsmm_actor_desc_s structure when creating the actor;
  • spur_delta is non-finite.
QSMM_ERR_INFIN

The incremented spur value would be infinite.

Use the following function to get the current value of spur of a specific type.

Function: int qsmm_get_actor_spur (qsmm_actor_t actor, int spur_type, double *spur_p)

This function sets *spur_p equal to the current value of spur of spur_type type an actor has been accumulating. Spur types have zero-based indices. Special spur type -1 of a large actor corresponds to the automatic spur of a small actor associated with the large actor. If spur_p is NULL, the function does not set *spur_p. Otherwise, *spur_p is finite.

On success, the function returns a non-negative value. If the actor is the small one and spur_type is negative, or if the actor is the large one and spur_type is less than -1, or if spur_type is greater than or equal to the number of spur types specified in the field nspur of qsmm_actor_desc_s structure when creating the actor, the function returns negative error code QSMM_ERR_INVAL.


Next: , Previous: , Up: Repeated Sequence of Operations   [Contents][Index]

2.5.2 Incrementing Time

There are two types of time associated with an actor: discrete time and continuous time.

The actor uses discrete time to calculate the number of output signals emitted within an event history segment. The functions qsmm_actor_shl_sig, qsmm_actor_reg_sig_in, and qsmm_actor_reg_sig_action increment discrete time by 1. The function qsmm_actor_shr_sig decrements discrete time by 1. The functions qsmm_get_actor_naction_per_evt and qsmm_set_actor_naction_per_evt retrieve and set a multiplier for converting discrete time to the number of output signals emitted.

The actor can also track continuous time equal to a logical period of time an event history occupies. The actor can use continuous time to compute spur increment velocities when calculating the probabilities of output signals.

Use the function described below to convey to an actor information that a period of continuous time passed in the event history. The actor should not receive input signals during this period. If there are input signals to receive, split the period into segments containing no input signals to receive and call this function for every such segment in consecutive order. Between those calls, call appropriate API functions to convey the input signals to the actor and emit output signals.

Function: int qsmm_actor_time_delta (qsmm_actor_t actor, double time_delta)

This function increments by time_delta continuous time associated with an actor.

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 time_delta is not finite, or incremented continuous time would be negative.

QSMM_ERR_INFIN

Incremented continuous time would be positive infinity.

Use the following function to get the current value of continuous time associated with an actor.

Function: double qsmm_get_actor_continuous_time (qsmm_actor_t actor)

This function returns the value of continuous time associated with an actor. A returned value is always finite and non-negative.

Use the following functions to get the value of discrete time associated with an actor or set discrete time to an arbitrary value.

Function: long qsmm_get_actor_discrete_time (qsmm_actor_t actor)

This function returns the value of discrete time associated with an actor.

Function: void qsmm_set_actor_discrete_time (qsmm_actor_t actor, long tmd)

This function sets to tmd the value of discrete time associated with an actor.

The following enumeration specifies a type of time used by a small actor for calculating spur increment velocity.

Enumeration: qsmm_time_e

This enumeration specifies a type of time. It contains the following elements.

QSMM_TIME_DISCRETE

Discrete time.

QSMM_TIME_CONTINUOUS

Continuous time.

By default, an actor uses continuous time for calculating spur increment velocities, with the exception that a small actor associated with a large actor uses discrete time to calculate the increment velocity of automatic spur. See Automatic Spur, for more information on the concept of automatic spur.

Use the following functions to query or set the type of time for calculating the increment velocity of spur of a particular type by a small actor.

Function: int qsmm_get_actor_spur_time (qsmm_actor_t actor, int spur_type, enum qsmm_time_e *time_type_p)

If time_type_p is not NULL, this function sets *time_type_p equal to the type of time for calculating the increment velocity of spur of spur_type type by a small actor. Spur types have zero-based indices.

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 spur_type is negative or greater than or equal to the number of spur types specified in the field nspur of qsmm_actor_desc_s structure when creating the actor.

QSMM_ERR_NOTSUP

The actor is the large one.

Function: int qsmm_set_actor_spur_time (qsmm_actor_t actor, int spur_type, enum qsmm_time_e time_type)

This function sets to time_type the type of time for calculating the increment velocity of spur of spur_type type by a small actor. Spur types have zero-based indices. The values of time_type not matching to the elements of qsmm_time_e enumeration lead to undefined actor behavior.

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 spur_type is negative or greater than or equal to the number of spur types specified in the field nspur of qsmm_actor_desc_s structure when creating the actor.

QSMM_ERR_NOTSUP

The actor is the large one.

The function qsmm_actor_create initializes the types of time for all spur types of a newly created small actor to QSMM_TIME_CONTINUOUS.


Next: , Previous: , Up: Repeated Sequence of Operations   [Contents][Index]

2.5.3 Receiving Input Signals

An actor has a buffer containing an n-gram of identifiers of signals from the event history or a list of signal identifiers encoding a current action choice state. The field ngram_sz of qsmm_actor_desc_s structure passed to the function qsmm_actor_create when creating the actor specifies the number of signal identifiers in the buffer. The function qsmm_get_actor_ngram_sz returns that number for a created actor.

The function qsmm_actor_create initializes the elements of that buffer to minimum allowed signal identifiers specified by the field range_sig_p of qsmm_actor_desc_s structure when creating the actor.

The function qsmm_get_actor_sig_ngram provides direct access to the buffer as an array of signal identifiers.

The functions qsmm_actor_shl_sig and qsmm_actor_reg_sig_in shift the buffer one signal left and append a new signal to the buffer. Shifting the buffer one signal left implies incrementing by 1 discrete time tracked by the actor.

Call the function qsmm_actor_shl_sig to shift the buffer one signal left and append a new signal to the buffer without updating statistics on action choice states.

Call the function qsmm_actor_reg_sig_in if after shifting the buffer one signal left and appending a new signal to the buffer, it encodes a current action choice state. That function updates statistics on the current action choice state using information recorded when that action choice state occurred the previous time in the event history.

To set a current action choice state for an actor, use a series of calls to qsmm_actor_shl_sig followed by a call to qsmm_actor_reg_sig_in. Alternatively, obtain a pointer to the buffer by qsmm_get_actor_sig_ngram, set the content of that buffer shifted one signal right, and call qsmm_actor_reg_sig_in to shift the buffer one signal left with setting the rightmost signal of the current action choice state.

Use the following function to shift the buffer containing an n-gram of signals from the event history one signal left, append a signal to the buffer, and increment by 1 discrete time without updating information on action choice states.

Function: int qsmm_actor_shl_sig (qsmm_actor_t actor, qsmm_sig_t sig_last, qsmm_sig_t *sig_first_p)

This function shifts one signal left the content of the buffer in actor containing an n-gram of signals from the event history and appends signal sig_last to the end of that buffer. The function increments by 1 discrete time tracked by the actor. If sig_first_p is not NULL, the function returns in *sig_first_p the leftmost signal in the buffer before the shift.

On success, the function returns a non-negative value. If sig_last is greater than or equal to the number of signals of the actor, the function returns negative error code QSMM_ERR_INVAL.

For example, if the buffer contained signals <3, 6, 2>, then after executing the lines

qsmm_sig_t sig_first=QSMM_SIG_INVALID;
qsmm_actor_shl_sig(actor,4,&sig_first);

the buffer would contain signals <6, 2, 4>, and sig_first would be equal to 3.

Use the following function to perform the operation opposite to the operation performed by the function qsmm_actor_shl_sig.

Function: int qsmm_actor_shr_sig (qsmm_actor_t actor, qsmm_sig_t sig_first, qsmm_sig_t *sig_last_p)

This function shifts one signal right the content of the buffer in actor containing an n-gram of signals from the event history and prepends signal sig_first to the beginning of that buffer. The function decrements by 1 discrete time tracked by the actor. If sig_last_p is not NULL, the function returns in *sig_last_p the rightmost signal in the buffer before the shift.

On success, the function returns a non-negative value. If sig_first is greater than or equal to the number of signals of the actor, the function returns negative error code QSMM_ERR_INVAL.

Use the following function to shift the buffer containing an n-gram of signals from the event history one signal left, append a signal to the buffer, and increment by 1 discrete time with updating statistics on a current action choice state.

Function: int qsmm_actor_reg_sig_in (qsmm_actor_t actor, qsmm_sig_t sig)

This function shifts one signal left the content of the buffer in actor containing an n-gram of signals from the event history and appends signal sig to the end of that buffer. The resulting content of the buffer shall encode an action choice state. The function increments by 1 discrete time tracked by the actor.

If the action choice state did not occur earlier in the event history, the function finishes execution and reports success. If the action choice state occurred earlier in the event history, the function processes a cycle between the two occurrences of the same action choice state. A cycle type is the pair comprised of that action choice state and an output signal emitted when that action choice state occurred the previous time in the event history (we refer to that time as the time of cycle start). The output signal emitted is the cycle direction.

If current discrete time is less than or equal to the discrete time of cycle start, the function finishes execution and reports success. Otherwise, the function updates statistics on the cycle type in the following way:

If the actor uses automatic spur, the function increments it by the logarithm of observed probability of that cycle type in the event history (see Automatic Spur, for additional information).

To be able to query mean discrete cycle period by the function qsmm_get_actor_discrete_cycle_period_mean, the function qsmm_actor_reg_sig_in increments by 1 the total number of cycles processed and increments the total sum of discrete cycle periods.

The function qsmm_actor_reg_sig_in 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 value of sig is greater than or equal to the number of signals of the actor.

QSMM_ERR_NGRAM

After shifting one signal left the content of the buffer and appending signal sig to its end, the buffer would not encode a valid action choice state. To determine the validity of an action choice state, the function checks the content of the buffer for accordance with allowed ranges of signal identifiers specified by the field range_sig_p of qsmm_actor_desc_s structure when creating the actor.

QSMM_ERR_INFIN

The operation of computing the increment of automatic spur or the operation of increasing the sum of spur increments for the cycle type returned an infinite result.

QSMM_ERR_STORAGE

Statistics storage failure. 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.

QSMM_ERR_ILSEQ

A statistics storage access function generated an error message but cannot convert it to a wide string according to a current locale, or a storage redirection function reported QSMM_ERR_ILSEQ.

QSMM_ERR_NOMEM

A statistics storage access function reported out of memory error.

Note: you should call the function qsmm_actor_reg_sig_in for increasing values of discrete time tracked by the actor. Otherwise, that function might finish execution just after making the buffer encode an action choice state.

Use the following function to obtain direct access to the buffer.

Function: qsmm_sig_t * qsmm_get_actor_sig_ngram (qsmm_actor_t actor)

This function returns the pointer to the buffer in actor containing an n-gram of signals from the event history. That buffer is an array of signal identifiers with the number of elements equal to the field ngram_sz of qsmm_actor_desc_s structure passed to the function qsmm_actor_create when creating the actor; the function qsmm_get_actor_ngram_sz returns that number for an actor. The function qsmm_get_actor_sig_ngram never returns NULL.

Use the function qsmm_get_actor_sig_ngram to temporarily replace the content of the buffer to calculate the probabilities of output signals for another action choice state. For that, save the content in another array, replace the content with a signal list encoding another action choice state, calculate the probabilities of output signals for the action choice state by the function qsmm_actor_calc_action_prob, and restore original content.

To obtain the number of output signals emitted by an actor, it multiplies discrete time by a parameter in the range 0 to 1 set by the function qsmm_set_actor_naction_per_evt and retrieved by the function qsmm_get_actor_naction_per_evt. The default value of that parameter is 0.5.

Let us suppose that the field ngram_sz of qsmm_actor_desc_s structure passed to the function qsmm_actor_create when creating an actor was equal to NGRAM_SZ. There are three common modes of setting a current action choice state for the actor.

  1. Action choice states solely consist of input signals of the actor. Let us suppose that qsmm_sig_t sig_ngram[NGRAM_SZ] is an array of signal identifiers encoding an action choice state.
    1. Using the functions qsmm_actor_shl_sig and qsmm_actor_reg_sig_in.

      The call qsmm_set_actor_naction_per_evt(actor,1.0/(NGRAM_SZ+1)) is necessary at the beginning if the function for computing the relative probability of an output signal depends on the number of output signals emitted by the actor.

      In the general case, use a block of source code like this to set the action choice state as the current one:

      int rc;
      for (int ii=0; ii<NGRAM_SZ-1; ii++)
          if ((rc=qsmm_actor_shl_sig(actor,sig_ngram[ii],0))<0)
              REPORT_ERROR(rc);
      if ((rc=qsmm_actor_reg_sig_in(actor,sig_ngram[NGRAM_SZ-1]))<0)
          REPORT_ERROR(rc);
      

      If NGRAM_SZ is equal to 1, this block of source code reduces to:

      const int rc=qsmm_actor_reg_sig_in(actor,sig_ngram[0]);
      if (rc<0) REPORT_ERROR(rc);
      

      If NGRAM_SZ is equal to 2, the block reduces to:

      int rc;
      if ((rc=qsmm_actor_shl_sig(actor,sig_ngram[0],0))<0)
          REPORT_ERROR(rc);
      if ((rc=qsmm_actor_reg_sig_in(actor,sig_ngram[1]))<0)
          REPORT_ERROR(rc);
      
    2. Using the functions qsmm_get_actor_sig_ngram and qsmm_actor_reg_sig_in.

      In the general case, use a block of source code like this to set the action choice state as the current one:

      memmove(qsmm_get_actor_sig_ngram(actor)+1,
              sig_ngram, (NGRAM_SZ-1)*sizeof(*sig_ngram));
      const int rc=qsmm_actor_reg_sig_in(actor,sig_ngram[NGRAM_SZ-1]);
      if (rc<0) REPORT_ERROR(rc);
      

      If NGRAM_SZ is equal to 1, this block of source code reduces to:

      const int rc=qsmm_actor_reg_sig_in(actor,sig_ngram[0]);
      if (rc<0) REPORT_ERROR(rc);
      

      If NGRAM_SZ is equal to 2, the block reduces to:

      qsmm_get_actor_sig_ngram(actor)[1]=sig_ngram[0];
      const int rc=qsmm_actor_reg_sig_in(actor,sig_ngram[1]);
      if (rc<0) REPORT_ERROR(rc);
      
  2. Action choice states consist of last output signal emitted and input signals. Let us suppose that qsmm_sig_t sig_ngram[NGRAM_SZ-1] is an array of input signals. We are not completely replacing buffer content with input signals—last signal emitted stored in the rightmost buffer element should become the leftmost buffer element.

    If state0 is an output signal denoting the initial state of a finite automaton, the call qsmm_actor_shl_sig(actor,state0,0) is necessary at the beginning.

    1. Using the functions qsmm_actor_shl_sig and qsmm_actor_reg_sig_in.

      The call qsmm_set_actor_naction_per_evt(actor,1.0/NGRAM_SZ) is also necessary at the beginning if the function for computing the relative probability of an output signal depends on the number of output signals emitted by the actor.

      In the general case, use a block of source code like this to set the current action choice state:

      for (int ii=0; ii<NGRAM_SZ-2; ii++)
          if ((rc=qsmm_actor_shl_sig(actor,sig_ngram[ii],0))<0)
              REPORT_ERROR(rc);
      if ((rc=qsmm_actor_reg_sig_in(actor,sig_ngram[NGRAM_SZ-2]))<0)
          REPORT_ERROR(rc);
      

      If NGRAM_SZ is equal to 2, this block of source code reduces to:

      const int rc=qsmm_actor_reg_sig_in(actor,sig_ngram[0]);
      if (rc<0) REPORT_ERROR(rc);
      

      If NGRAM_SZ is equal to 3, the block reduces to:

      int rc;
      if ((rc=qsmm_actor_shl_sig(actor,sig_ngram[0],0))<0)
          REPORT_ERROR(rc);
      if ((rc=qsmm_actor_reg_sig_in(actor,sig_ngram[1]))<0)
          REPORT_ERROR(rc);
      
    2. Using the functions qsmm_get_actor_sig_ngram and qsmm_actor_reg_sig_in.

      In the general case, use a block of source code like this to set the current action choice state:

      qsmm_sig_t *const sig_ngram_p=qsmm_get_actor_sig_ngram(actor);
      sig_ngram_p[1]=sig_ngram_p[NGRAM_SZ-1];
      memmove(sig_ngram_p+2,sig_ngram,(NGRAM_SZ-2)*sizeof(*sig_ngram));
      const int rc=qsmm_actor_reg_sig_in(actor,sig_ngram[NGRAM_SZ-2]);
      if (rc<0) REPORT_ERROR(rc);
      

      If NGRAM_SZ is equal to 2, this block of source code reduces to:

      const int rc=qsmm_actor_reg_sig_in(actor,sig_ngram[0]);
      if (rc<0) REPORT_ERROR(rc);
      

      If NGRAM_SZ is equal to 3, the block reduces to:

      qsmm_sig_t *const sig_ngram_p=qsmm_get_actor_sig_ngram(actor);
      sig_ngram_p[1]=sig_ngram_p[2];
      sig_ngram_p[2]=sig_ngram[0];
      const int rc=qsmm_actor_reg_sig_in(actor,sig_ngram[1]);
      if (rc<0) REPORT_ERROR(rc);
      
  3. Action choice states are n-grams of events from the event history; input and output signals interleave. If sig_in is an input signal, append it to the current action choice state n-gram and shift it by the call qsmm_actor_reg_sig_in(actor,sig_in). This mode of setting a current action choice state may be inefficient.

Using the following functions, you can obtain the discrete cycle period of last cycle registered by the function qsmm_actor_reg_sig_in and the mean discrete cycle period of all cycles registered by that function since creating an actor. You can use this information in a custom function for computing the relative probability of an output signal.

Function: long qsmm_get_actor_discrete_cycle_period_last (qsmm_actor_t actor)

This function returns the discrete cycle period of last cycle registered for actor by the function qsmm_actor_reg_sig_in. A returned value is always non-negative.

If there was no call to the function qsmm_actor_reg_sig_in yet, or at the last call that function did not register a cycle, the function qsmm_get_actor_discrete_cycle_period_last returns 0.

Function: double qsmm_get_actor_discrete_cycle_period_mean (qsmm_actor_t actor)

This function returns the mean discrete cycle period of all cycles registered for actor by the function qsmm_actor_reg_sig_in since creating the actor.

If qsmm_actor_reg_sig_in has not registered a cycle yet, the function qsmm_get_actor_discrete_cycle_period_mean returns 0. This function returns only finite and non-negative values.


Previous: , Up: Repeated Sequence of Operations   [Contents][Index]

2.5.4 Emitting an Output Signal

Emitting an output signal includes the following steps:

  1. Calculate by the function qsmm_actor_calc_action_prob the probabilities of output signals for a current action choice state. This step is only necessary for a small actor.
  2. Select by the function qsmm_get_actor_sig_action an output signal to emit. For a small actor, that function uses output signal probabilities calculated in the previous step. For a large actor, that function uses a Huffman tree corresponding to the current action choice state.
  3. Append by the function qsmm_actor_reg_sig_action the output signal to the buffer containing an n-gram of signals from the event history (at this point—containing the current action choice state). That function records the following information for the current action choice state: current discrete time, current continuous time, current spur values, and the output signal emitted.

In order to correctly calculate the probabilities of output signals, the actor should have a correct parameter specifying a relation between discrete time and the number of output signals emitted. Use the following functions to query or set the value of this parameter.

Function: double qsmm_get_actor_naction_per_evt (qsmm_actor_t actor)

This function returns a number greater than 0 and less than or equal to 1 specifying the mean number of output signals emitted by an actor per one unit of discrete time passed.

Function: int qsmm_set_actor_naction_per_evt (qsmm_actor_t actor, double val)

This function sets to val the mean number of output signals emitted by an actor per one unit of discrete time passed.

On success, the function returns a non-negative value. If val is not a finite number or is a number less than or equal to 0 or is a number greater than 1, the function returns negative error code QSMM_ERR_INVAL.

The function qsmm_actor_create initializes the mean number of output signals emitted per one unit of discrete time passed to 0.5.

Let us suppose that the field ngram_sz of qsmm_actor_desc_s structure passed to the function qsmm_actor_create when creating an actor was equal to NGRAM_SZ. The general rules of setting the parameter specifying the mean number of output signals emitted per one unit of discrete time passed are the following:

  1. If you use the functions qsmm_actor_shl_sig and qsmm_actor_reg_sig_in to set a current action choice state, and it solely consists of input signals of the actor, then set this parameter to 1.0/(NGRAM_SZ+1).
  2. If you use the functions qsmm_actor_shl_sig and qsmm_actor_reg_sig_in to set a current action choice state, and it consists of last output signal emitted and input signals, then set this parameter to 1.0/NGRAM_SZ.
  3. If you use the functions qsmm_get_actor_sig_ngram and qsmm_actor_reg_sig_in to set a current action choice state, then use default parameter value 0.5.
  4. If action choice states are n-grams of signals from the event history, and input and output signals interleave, then use default parameter value 0.5.

The types of probabilities of output signals are the following.

Enumeration: qsmm_prob_e

This enumeration specifies a type of probabilities. The enumeration contains the following elements.

QSMM_PROB_AGGR

Aggregate probabilities based on learned and profile probabilities.

For a small actor, to calculate probabilities of QSMM_PROB_AGGR type, the function qsmm_actor_calc_action_prob calculates probabilities of QSMM_PROB_LEARNED and QSMM_PROB_PROFILE types (see below), multiplies each learned probability by a corresponding profile probability, and normalizes a resulting array. For a large actor, the function qsmm_actor_calc_action_prob called for an associated small actor performs this operation for the nodes of a Huffman tree to obtain the aggregate probabilities of tree leaves.

For a small actor, if you do not use profile probabilities, it is faster to calculate probabilities of QSMM_PROB_LEARNED type—they are equal to probabilities of QSMM_PROB_AGGR type in this case.

QSMM_PROB_LEARNED

For a small actor, learned probabilities for producing adaptive actions. For a large actor, probabilities of QSMM_PROB_AGGR type.

QSMM_PROB_PROFILE

For a small actor, profile probabilities specified a priori in statistics storage (see Structures for Accessing Storage, for how to pass profile probabilities to storage access functions to write them to storage). For a large actor, profile probabilities following from a subordination relationship of nodes of Huffman tree of an action choice state and from the probabilities of edges connecting parent tree nodes with their child nodes.

QSMM_PROB_FQ

Probabilities proportional to observed frequencies of output signals registered by the function qsmm_actor_reg_sig_action. For a large actor, calculating probabilities of this type is faster compared to the other types.

QSMM_PROB_COUNT

The last element of this enumeration equal to the number of supported probability types.

Use the following function to calculate the probabilities of output signals for a current action choice state.

Function: int qsmm_actor_calc_action_prob (qsmm_actor_t actor, int rez1, qsmm_sig_t sig_beg, qsmm_sig_t sig_end, enum qsmm_prob_e prob_type)

This function fills the internal array of actor with probabilities of prob_type type calculated for an action choice state encoded by the buffer containing an n-gram of signals from the event history. The functions qsmm_actor_shl_sig, qsmm_actor_shr_sig, qsmm_actor_reg_sig_in, and qsmm_actor_reg_sig_action access that buffer, and the function qsmm_get_actor_sig_ngram returns a pointer to the buffer. The argument rez1 is for future use and must be equal to 0.

For a small actor, the function qsmm_get_actor_sig_action stochastically selects an output signal according to probabilities in that internal array. The function qsmm_actor_calc_action_prob is much slower for a large actor compared to a small actor; you should call this function for a large actor only to obtain explicit probability values—large actors support calling qsmm_get_actor_sig_action without prior calling qsmm_actor_calc_action_prob.

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) of a signal segment for calculating the probabilities. The probability of the first signal of this signal segment has offset sig_beg in the internal array. The function zeroes array elements that do not correspond to output signals. If sig_end is 0, the function uses the total number of actor signals for the identifier of last signal. The function operates faster when the signal segment is shorter, so specify the segment as precisely as possible.

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 value of sig_beg is greater than or equal to the identifier of last signal of the signal segment, or the value of sig_end is greater than the total number of signals of the actor, or prob_type is invalid.

QSMM_ERR_NGRAM

The buffer does not encode a valid action choice state. To determine the validity of an action choice state, the function checks the content of the buffer for accordance with allowed ranges of signal identifiers specified by the field range_sig_p of qsmm_actor_desc_s structure when creating the actor.

QSMM_ERR_CALLBACK

A helper function of QSMM_RELPROB_USER1 or QSMM_RELPROB_USER2 type for calculating the relative probability of an output signal reported an error by returning NaN.

QSMM_ERR_STORAGE

Statistics storage failure. 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.

QSMM_ERR_ILSEQ

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.

Errors QSMM_ERR_STORAGE, QSMM_ERR_STATS, QSMM_ERR_ILSEQ, and QSMM_ERR_NOMEM can leave a large actor in inconsistent state. If the large actor is in inconsistent state, then, if after removing a reason of an error a repeated call to this function succeeds, the actor’s state becomes consistent.

Use the following function to obtain a pointer to the internal array with the probabilities of output signals calculated by the function qsmm_actor_calc_action_prob.

Function: double * qsmm_get_actor_choice_sig_prob (qsmm_actor_t actor)

This function returns a pointer to the internal array of actor holding the relative probabilities of output signals. This function never returns NULL. The number of elements in the array is equal to the total number of actor signals returned by the function qsmm_get_actor_nsig. The function qsmm_actor_calc_action_prob fills the array with probabilities of a desired type.

For a small actor, the function qsmm_get_actor_sig_action stochastically selects an output signal according to probabilities in that array. A program can modify the array to affect this stochastic selection. The function qsmm_get_actor_sig_action handles the situation when the array contains elements equal to positive infinity or values that do not sum up to 1. Conversely, modifying the array does not affect the behavior of qsmm_get_actor_sig_action for a large actor.

The function qsmm_get_actor_choice_sig_prob locks the internal array: if a sparse vector backs up the internal array, this function converts the sparse vector to an ordinary vector. After this conversion, the actor keeps the internal array as an ordinary vector until the function qsmm_actor_choice_sig_prob_release releases that internal array. Forgetting to call qsmm_actor_choice_sig_prob_release after a call to qsmm_get_actor_choice_sig_prob may dramatically decrease actor performance.

Use the following function to release a locked internal array.

Function: void qsmm_actor_choice_sig_prob_release (qsmm_actor_t actor)

This function releases the internal array of actor locked by the function qsmm_get_actor_choice_sig_prob. That internal array holds the relative probabilities of output signals. If qsmm_get_actor_choice_sig_prob has not locked the internal array, qsmm_actor_choice_sig_prob_release has no effect. You must not use a pointer obtained by qsmm_get_actor_choice_sig_prob after releasing the array.

When the function qsmm_get_actor_choice_sig_prob has locked the internal array, and you call the function qsmm_actor_calc_action_prob, or when you call it for a large actor, qsmm_actor_calc_action_prob uses an ordinary vector for storing the probabilities of output signals, so you can access the elements of this ordinary vector via a pointer returned by qsmm_get_actor_choice_sig_prob. When the internal array is in released state, qsmm_actor_calc_action_prob called for a small actor can use an ordinary or sparse vector for storing the probabilities of output signals depending on the properties of a probability profile and the value of sparse_fill_max field of qsmm_actor_desc_s structure specified when creating the actor.

You can obtain the handle of an ordinary or sparse vector holding the relative probabilities of output signals. It is a cheap operation that does not perform locking or converting a sparse vector to an ordinary vector. You can access a returned vector in read-only mode. See Ordinary and Sparse Vectors, for how to access vector elements.

Function: qsmm_vec_t qsmm_get_actor_choice_sig_prob_vec (qsmm_actor_t actor)

This function returns the handle of an ordinary or sparse vector of actor holding the relative probabilities of output signals. This function never returns NULL. The function qsmm_actor_calc_action_prob fills the vector with probabilities of a desired type. For a small actor, the function qsmm_get_actor_sig_action stochastically selects an output signal according to probabilities in that vector.

Use the following function to stochastically select an output signal.

Function: int qsmm_get_actor_sig_action (qsmm_actor_t actor, int rez1, qsmm_sig_t sig_beg, qsmm_sig_t sig_end, qsmm_sig_t *sig_out_p)

If actor is a small one, this function stochastically selects an output signal according to relative probabilities stored in the internal array of relative probabilities of output signals. The function qsmm_actor_calc_action_prob fills the internal array with probabilities of a desired type. The function qsmm_get_actor_choice_sig_prob returns a pointer to the elements of that array. The function qsmm_get_actor_choice_sig_prob_vec returns a read-only view of that array for speeding up accessing its content.

If actor is a large one, the function qsmm_get_actor_sig_action selects an output signal for an action choice state encoded by the buffer containing an n-gram of signals from the event history without using the aforementioned internal array. The functions qsmm_actor_shl_sig, qsmm_actor_shr_sig, qsmm_actor_reg_sig_in, and qsmm_actor_reg_sig_action access that buffer, and the function qsmm_get_actor_sig_ngram returns a pointer to the buffer. The function qsmm_get_actor_sig_action uses the Huffman tree of this action choice state to perform fast choice of an output signal (the number of those signals can be very large) according to probabilities of QSMM_PROB_AGGR type. The function qsmm_actor_calc_action_prob can compute those probabilities; however, for a large actor, there is no need to call that function before calling qsmm_get_actor_sig_action. You should minimize the number of calls to the function qsmm_actor_calc_action_prob to calculate probabilities of QSMM_PROB_AGGR type for a large actor, because that function operates slowly in this mode.

The function qsmm_get_actor_sig_action stores a selected output signal in *sig_out_p if sig_out_p is not NULL. The argument rez1 is for future use and must be equal to 0.

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) of a segment for selecting an output signal. However, for a large actor, the signal segment must include all output signals of the actor; see Specifying Output Signal Weights, for how to adaptively select an output signal from various subsets of output signals of a large actor. For a small actor, the probability of the first signal of this signal segment has offset sig_beg in the internal array. If sig_end is 0, the function uses the total number of actor signals for the identifier of last signal. The function operates faster when the signal segment is shorter, so specify the segment as precisely as possible. For a small actor, the function does not check whether a signal it selects actually belongs to a set of output signals—if an internal array element within the signal segment is positive, then the function may select a corresponding signal. For a small actor, if at least one relative probability in the internal array within the signal segment is positive infinity, the function selects an output signal as a uniformly distributed random element from a set of all signals (within the signal segment) with relative probabilities equal to positive infinity.

To stochastically select an output signal, the function uses either a random number generator provided via the field rng of qsmm_actor_desc_s structure when creating the actor by the function qsmm_actor_create or an instance of default random number generator allocated automatically if that field was NULL. Call the function qsmm_get_actor_rng to obtain the handle of a random number generator used by an actor, for example, to seed the generator.

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

One of the following conditions is true:

  • sig_beg is greater than or equal to the identifier of last signal of the signal segment;
  • sig_end is greater than the total number of signals of the actor;
  • sig_beg is greater than the lowest output signal identifier of a large actor;
  • sig_end is less than or equal to the highest output signal identifier of a large actor.
QSMM_ERR_WEIGHT

For a small actor, the internal array contains (within the signal segment) a negative element or a non-finite element different from positive infinity.

QSMM_ERR_INFIN

For a small actor, the internal array does not contain elements (within the signal segment) equal to positive infinity, but the sum of array elements is positive infinity. For a large actor, the function qsmm_get_actor_sig_action or qsmm_actor_reg_sig_in called for an associated small actor when traversing a Huffman tree from the root node to a leaf node reported QSMM_ERR_INFIN. This error can leave the large actor in inconsistent state.

QSMM_ERR_NOCHOICE

For a small actor, the internal array does not contain at least one positive element (within the signal segment).

QSMM_ERR_NGRAM

For a large actor, the buffer does not encode a valid action choice state. To determine the validity of an action choice state, the function checks the content of the buffer for accordance with allowed ranges of signal identifiers specified by the field range_sig_p of qsmm_actor_desc_s structure when creating the actor.

QSMM_ERR_CALLBACK

For a large actor, a helper function of QSMM_RELPROB_USER1 or QSMM_RELPROB_USER2 type for calculating the relative probability of an output signal reported an error by returning NaN. The function qsmm_actor_calc_action_prob called for an associated small actor when traversing a Huffman tree from the root node to a leaf node calls this helper function. This error can leave the large actor in inconsistent state.

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. This error can leave the large actor in inconsistent state.

QSMM_ERR_STATS

Inconsistent statistics on an action choice state or cycle type detected for a large actor. This error can leave the large actor in inconsistent state.

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. This error can leave the large actor in inconsistent state.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation by a large actor. This error can leave the large actor in inconsistent state.

Use the following function to register a selected output signal.

Function: int qsmm_actor_reg_sig_action (qsmm_actor_t actor, qsmm_sig_t sig)

This function registers sig as an output signal of actor emitted in an action choice state encoded by the buffer for an n-gram of signals from the event history.

The function records the following information for the action choice state:

Finally, the function shifts the buffer one signal left, appends sig to the end of that buffer, and increments by 1 discrete time tracked by the actor.

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

Signal sig is not an output signal of the actor.

QSMM_ERR_NGRAM

The buffer does not encode a valid action choice state. To determine the validity of an action choice state, the function checks the content of the buffer for accordance with allowed ranges of signal identifiers specified by the field range_sig_p of qsmm_actor_desc_s structure when creating the actor.

QSMM_ERR_STORAGE

Statistics storage failure. 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.

QSMM_ERR_ILSEQ

A statistics storage access function generated an error message but cannot convert it to a wide string according to a current locale, or a storage redirection function reported QSMM_ERR_ILSEQ.

QSMM_ERR_NOMEM

A statistics storage access function reported out of memory error.

For a small actor, adaptively emit an output signal by a sequence of function calls like this:

int rc;
if ((rc=
     qsmm_actor_calc_action_prob(actor, 0, NSIG_IN, NSIG_IN+NSIG_OUT,
                                 QSMM_PROB_LEARNED))<0)
    REPORT_ERROR(rc);
qsmm_sig_t sig_out=QSMM_SIG_INVALID;
if ((rc=
     qsmm_get_actor_sig_action(actor, 0, NSIG_IN, NSIG_IN+NSIG_OUT,
                               &sig_out))<0)
    REPORT_ERROR(rc);
if ((rc=qsmm_actor_reg_sig_action(actor,sig_out))<0) REPORT_ERROR(rc);

For a large actor, a call to qsmm_actor_calc_action_prob is redundant and only decreases performance. The sequence of function calls looks like this:

int rc;
qsmm_sig_t sig_out=QSMM_SIG_INVALID;
if ((rc=
     qsmm_get_actor_sig_action(actor, 0, NSIG_IN, NSIG_IN+NSIG_OUT,
                               &sig_out))<0)
    REPORT_ERROR(rc);
if ((rc=qsmm_actor_reg_sig_action(actor,sig_out))<0) REPORT_ERROR(rc);

For a small actor, you can override an output signal selected by the function qsmm_get_actor_sig_action or omit calling that function. That is, you can pass to the function qsmm_actor_reg_sig_action an output signal not obtained by qsmm_get_actor_sig_action. This possibility does not exist for a large actor—it is incorrect to omit a call to qsmm_get_actor_sig_action before calling qsmm_actor_reg_sig_action or to pass to the latter function a signal different from a signal returned by a preceding call to qsmm_get_actor_sig_action.

Note: you should not call the functions qsmm_actor_spur_delta (see Incrementing Spur) and qsmm_actor_time_delta (see Incrementing Time) between a call to qsmm_actor_reg_sig_in and a subsequent call to qsmm_actor_reg_sig_action.

In QSMM 1.16 there appeared a function returning the probability of last output signal selected. You can use this function to implement timed emitting output signals, for example, according to the exponential probability distribution.

Function: double qsmm_get_actor_prob_action (qsmm_actor_t actor)

This function returns the probability of last output signal selected by the function qsmm_get_actor_sig_action for an actor. For a small actor, it is a probability corresponding to an element of internal array of relative probabilities of output signals. For a large actor, it is the probability of a path from the root node of a Huffman tree to its leaf node corresponding to the output signal. The returned value is always in the range 0 to 1 (inclusive). If there was no call to qsmm_get_actor_sig_action yet, qsmm_get_actor_prob_action returns 0.


Next: , Previous: , Up: Adaptive Probabilistic Mapping   [Contents][Index]

2.6 Customizing the Relative Probability Function

The efficiency of operation of a small or large actor, that is, the optimality of output signals the actor adaptively emits, depends on the form of a function returning the relative probability of an output signal. It may well be true that, for different kinds of applications, different functions are more suitable. QSMM provides a few built-in functions a developer may select for use by an actor. Unfortunately, the author of QSMM experiences problems with: (1) providing a sound theoretical basis for using those functions in QSMM (that basis might not exist for some functions); (2) devising functions that give better efficiency than the functions currently provided in QSMM. The author’s own experimenting had shown that, for some special cases, there do exist more efficient functions, but he did fail to find general forms for those functions making it possible to utilize them for wider ranges of values of actor parameters. To provide a way to solve these problems by developers, QSMM starting from version 1.15 supports specifying a custom relative probability function.

The main parameter of a relative probability function is its type. If the type specifies a custom form for the function, the developer shall provide a helper function for this form. Common relative probability function forms depend on the number of output signals and the way of spur perception and spur weight for every spur type. All relative probability function forms depend on actor temperature.


Next: , Up: Customizing the Relative Probability Function   [Contents][Index]

2.6.1 Relative Probability Function Types

Use the following functions to query or set the type of a relative probability function used by an actor.

Function: enum qsmm_relprob_e qsmm_get_actor_relprob_type (qsmm_actor_t actor)

This function returns the type of a function used by an actor to calculate the relative probability of an output signal. If the actor is the large one, the function returns the type of a function used by a small actor associated with the large actor.

Function: void qsmm_set_actor_relprob_type (qsmm_actor_t actor, enum qsmm_relprob_e relprob_type)

This function sets to relprob_type the type of a function used by an actor to calculate the relative probability of an output signal. If the actor is the large one, qsmm_set_actor_relprob_type sets the type of a function used by a small actor associated with the large actor. The values of relprob_type not matching to the elements of qsmm_relprob_e enumeration lead to undefined actor behavior.

Below there is a description of an enumeration specifying supported relative probability function types.

Enumeration: qsmm_relprob_e

This enumeration specifies the supported types of a function used by an actor to calculate the relative probability of an output signal.

The descriptions of elements of this enumeration use the following notations.

h

An action choice state.

z

An output signal.

ne

The number of spur types.

T

Actor temperature multiplied by some constant.

F(h,z)

The relative probability of emitting output signal z in action choice state h.

L

Mean discrete cycle period—mean discrete time period between every occurrence of action choice state h with emitting output signal z and a subsequent occurrence of h—multiplied by a value returned by the function qsmm_get_actor_naction_per_evt.

nout

The mean number of output signals of the actor (for more information on computing this number, see Number of Output Signals).

W[i]

Spur weight for spur type i.

C(h,z,i)

The ratio of spur increment velocities computed depending on the way of spur perception (see Spur Perception) for spur type i.

The enumeration contains the following elements.

QSMM_RELPROB_BUILTIN1

The relative probability function has the formula

relprob_builtin1.formula

where κ=2L.  The paper “An Approach to Optimal Action Generation for a System that Interacts with the Environment” available from the project homepage provides more details about this formula.

QSMM_RELPROB_BUILTIN2

The relative probability function has the formula

relprob_builtin2.formula

The author has empirically found this formula when developing QSMM 1.15 and making an actor emit output signals with frequencies proportional to output signal probabilities specified a priori. A spur increment supplied to the actor just after emitting an output signal was equal to the logarithm of its probability.

QSMM_RELPROB_BUILTIN3

The relative probability function has the formula

relprob_builtin3.formula

This formula is a simplification of QSMM_RELPROB_BUILTIN2 and is for developers who prefer beauty and/or simplicity.

QSMM_RELPROB_USER1

The relative probability function has the formula

relprob_user1.formula

where f(L) is a function of qsmm_relprob_user1_func_t type provided by a developer via a call to qsmm_set_actor_relprob_helper (see Helper Relative Probability Functions). If the developer has not provided the function f(L), that function is equal to 1 by default.

QSMM_RELPROB_USER2

The relative probability function has the formula

relprob_user2.formula

where g is a function of qsmm_relprob_user2_func_t type provided by a developer via a call to qsmm_set_actor_relprob_helper (see Helper Relative Probability Functions). The function g receives the value of z and statistics associated with h and z. These function arguments may be necessary to devise a sophisticated relative probability function.

When creating a small actor, the function qsmm_actor_create initializes the type of relative probability function of this small actor to QSMM_RELPROB_BUILTIN1. When creating a large actor, the function qsmm_actor_create initializes the type of relative probability function of a small actor associated with the large actor to QSMM_RELPROB_BUILTIN2.


Next: , Previous: , Up: Customizing the Relative Probability Function   [Contents][Index]

2.6.2 Helper Relative Probability Functions

Below there are descriptions of types for functions f(L) and g.

Data type: qsmm_relprob_user1_func_t

This is a type for the pointer to a helper function provided by a developer for relative probability function type QSMM_RELPROB_USER1. The following declaration corresponds to this type:

typedef double
(*qsmm_relprob_user1_func_t)(
    qsmm_actor_t actor,
    double cycle_period,
    void *paramp
);

The argument actor specifies an actor called the helper function. The argument cycle_period holds the value of L. The argument paramp is a user parameter specified when setting the helper function for the actor.

On success, the helper function should return the value of f(L). On failure, the helper function should return NaN; in this case, the function qsmm_actor_calc_action_prob returns QSMM_ERR_CALLBACK.

Data type: qsmm_relprob_user2_func_t

This is a type for the pointer to a helper function provided by a developer for relative probability function type QSMM_RELPROB_USER2. The following declaration corresponds to this type:

typedef double
(*qsmm_relprob_user2_func_t)(
    qsmm_actor_t actor,
    qsmm_sig_t sig_cycle,
    const struct qsmm_state_s *state_p,
    const struct qsmm_cycle_s *cycle_p,
    const struct qsmm_sspur_s *sspur_p,
    const struct qsmm_cspur_s *cspur_p,
    void *paramp
);

The argument actor specifies an actor called the helper function. The argument sig_cycle holds the value of z. The arguments state_p, cycle_p, sspur_p, and cspur_p hold statistics associated with h and z. See Structures for Accessing Storage, for the descriptions of corresponding structures. The argument paramp is a user parameter specified when setting the helper function for the actor.

On success, the helper function should return the value of g. On failure, the helper function should return NaN; in this case, the function qsmm_actor_calc_action_prob returns QSMM_ERR_CALLBACK.

To obtain working parameters of an actor, you may call such functions as qsmm_get_actor_nsig_ctrl and qsmm_get_actor_discrete_cycle_period_mean in a helper function. Call the function qsmm_get_actor_sig_ngram to obtain the n-gram of h if you need to access application-specific information associated with h.

Use the following functions to retrieve or set a helper function for an actor.

Function: void qsmm_get_actor_relprob_helper (qsmm_actor_t actor, void **helper_func_pp, void **helper_func_param_pp)

This function retrieves information on a helper function used by an actor when calculating the relative probabilities of output signals. If there is such helper function set for the actor, and helper_func_pp is not NULL, the function qsmm_get_actor_relprob_helper sets *helper_func_pp equal to the pointer to the helper function. If there is no such helper function set for the actor, and helper_func_pp is not NULL, qsmm_get_actor_relprob_helper sets *helper_func_pp to NULL. If helper_func_param_pp is not NULL, this function sets *helper_func_param_pp equal to the user parameter of that helper function specified when setting it for the actor. If the actor is the large one, qsmm_get_actor_relprob_helper retrieves information on a helper function used by a small actor associated with the large actor. A particular interpretation of a pointer stored in *helper_func_pp depends on a relative probability function type set for the actor by a call to qsmm_set_actor_relprob_type.

Function: void qsmm_set_actor_relprob_helper (qsmm_actor_t actor, void *helper_func_p, void *helper_func_param_p)

This function sets the pointer to a helper function used by an actor when calculating the relative probabilities of output signals. The argument helper_func_p specifies that pointer. Additionally, the function qsmm_set_actor_relprob_helper sets the user parameter of this helper function to helper_func_param_p. If the actor is the large one, qsmm_set_actor_relprob_helper sets the helper function for a small actor associated with the large actor.

A particular interpretation of a helper_func_p pointer depends on a relative probability function type set for the actor by a call to qsmm_set_actor_relprob_type. Passing a pointer that does not conform with the relative probability function type leads to undefined behavior.

The value of helper_func_p can be NULL. This NULL value means the absence of a helper function for the actor. Setting the NULL value makes a certain sense when the relative probability function type is QSMM_RELPROB_USER1.

To provide an example of using the functions qsmm_set_actor_relprob_type and qsmm_set_actor_relprob_helper, let us suppose a developer has proved that it is mathematically correct to use a function for calculating the relative probability of an output signal similar to the function QSMM_RELPROB_BUILTIN2 but with the following one difference: the numerator of the exponent contains the expression L instead of L+1. To make an actor calculate the relative probability of an output signal by this function, the developer may define the helper function as:

#include <math.h>

static double
get_relprob_exp_mlt(
    qsmm_actor_t actor,
    double cycle_period,
    void *paramp
) {
    return log(qsmm_get_actor_nsig_ctrl(actor))*cycle_period/2;
}

To set this helper function for an actor, the developer may add the function calls:

qsmm_set_actor_relprob_type(actor,QSMM_RELPROB_USER1);
qsmm_set_actor_relprob_helper(actor,&get_relprob_exp_mlt,0);

Alternatively, the developer may add the function calls shown below. See Actor Temperature, for a description of qsmm_set_actor_ktemperature function.

qsmm_set_actor_relprob_type(actor,QSMM_RELPROB_BUILTIN3);
qsmm_set_actor_ktemperature(actor,2);

Next: , Previous: , Up: Customizing the Relative Probability Function   [Contents][Index]

2.6.3 Spur Perception

Most of relative probability function formulas in Relative Probability Function Types contain the function C(h,z,i) equal to ratio between spur increment velocity and mean spur increment velocity. The method of computing C(h,z,i) depends on the way of spur perception for spur type i. The way of spur perception determines whether the ratio will be generally positive or negative for generally positive or negative spur increments supplied to the actor. There are two ways of spur perception: normal and inverse. The normal way of spur perception provides generally positive ratio for generally positive spur increments and generally negative ratio for generally negative spur increments. The inverse way of spur perception provides generally negative ratio for generally positive spur increments and generally positive ratio for generally negative spur increments.

The following enumeration specifies the way of perception of spur of a particular type.

Enumeration: qsmm_spur_perception_e

This enumeration specifies the way of spur perception for a spur type.

Below there are notations used in the descriptions of elements of this enumeration. In the descriptions of notations, a cycle of type <h,z> is the event history segment between an occurrence of action choice state h with emitting output signal z and a subsequent occurrence of h.

t

Discrete or continuous time for computing spur increment velocity.

E[i]

The value of spur of i type the actor accumulated.

H(h,z)[i]

The sum of increments of spur of i type over cycles of <h,z> type.

ω(h,z) 

The sum of discrete or continuous cycle periods for cycles of <h,z> type.

The enumeration contains the following elements.

QSMM_SPUR_PERCEPTION_NORMAL

The value of C(h,z,i) is the ratio of spur increment velocity to the absolute value of mean spur increment velocity for a cycle type:

percept_normal.formula

When spur increments over the event history are non-negative, C(h,z,i) increases as spur increment velocity increases. If spur increment velocity for a cycle type is positive and equal to mean spur increment velocity, C(h,z,i) is equal to 1.

QSMM_SPUR_PERCEPTION_INVERSE

The value of C(h,z,i) is the negative ratio of the absolute value of mean spur increment velocity to spur increment velocity for a cycle type:

percept_inverse.formula

When spur increments over the event history are negative, C(h,z,i) increases as spur increment velocity increases. If spur increment velocity for a cycle type is negative and equal to mean spur increment velocity, C(h,z,i) is equal to 1.

You can use the inverse way of spur perception to countervail negative spur with the other negative spur perceived as positive one because of inverse way of spur perception specified.

Use the following functions to query or set the way of spur perception for a spur type.

Function: int qsmm_get_actor_spur_perception (qsmm_actor_t actor, int spur_type, enum qsmm_spur_perception_e *spur_perception_p)
Function: int qsmm_set_actor_spur_perception (qsmm_actor_t actor, int spur_type, enum qsmm_spur_perception_e spur_perception)

If spur_perception_p is not NULL, the function qsmm_get_actor_spur_perception sets *spur_perception_p equal to the way of spur perception by an actor. The function qsmm_set_actor_spur_perception sets the way of spur perception by an actor to spur_perception. The values of spur_perception not matching to the elements of qsmm_spur_perception_e enumeration lead to undefined actor behavior.

The argument actor specifies an actor handle. The argument spur_type specifies a spur type and cannot be less than -1 or greater than or equal to the number of spur types returned by the function qsmm_get_actor_nspur for the actor. If the actor is the small one, specifying spur type -1 is incorrect.

If the actor is the large one, the functions query or set the way of spur perception for a corresponding spur type of a small actor associated with the large actor. Special spur type -1 of a large actor corresponds to the automatic spur of an associated small actor (i.e. its spur type 0).

On success, the functions return a non-negative value. On invalid spur_type, the functions return negative error code QSMM_ERR_INVAL. The value of spur_type is invalid in the following cases:

The function qsmm_actor_create initializes the ways of spur perception for all spur types of a newly created actor to QSMM_SPUR_PERCEPTION_NORMAL.


Next: , Previous: , Up: Customizing the Relative Probability Function   [Contents][Index]

2.6.4 Spur Weight

Use the following functions to query or set spur weight denoted by W[i] in relative probability function formulas mentioned in Relative Probability Function Types.

Function: int qsmm_get_actor_spur_weight (qsmm_actor_t actor, int spur_type, double *weight_p)
Function: int qsmm_set_actor_spur_weight (qsmm_actor_t actor, int spur_type, double weight)

If weight_p is not NULL, the function qsmm_get_actor_spur_weight sets *weight_p equal to weight for a spur type of an actor. The value of *weight_p obtained in this way is always finite. The function qsmm_set_actor_spur_weight sets weight for a spur type of an actor to weight.

The argument actor specifies an actor handle. The argument spur_type specifies a spur type and cannot be less than -1 or greater than or equal to the number of spur types returned by the function qsmm_get_actor_nspur for the actor. If the actor is the small one, specifying spur type -1 is incorrect.

If the actor is the large one, the functions query or set the weight of a corresponding spur type of a small actor associated with the large actor. Special spur type -1 of a large actor corresponds to the automatic spur of an associated small actor (i.e. its spur type 0).

On success, the functions return a non-negative value. On failure, the functions return negative error code QSMM_ERR_INVAL. The following cases are failures:

The function qsmm_actor_create initializes the weights of all spur types of a newly created actor to 1.


Next: , Previous: , Up: Customizing the Relative Probability Function   [Contents][Index]

2.6.5 Number of Output Signals

A function returning the relative probability of an output signal typically uses a parameter equal to the number of output signals of an actor to perform the calculation. The function qsmm_actor_create creates an actor with a particular number of output signals. However, the function qsmm_set_actor_sig_weight can change output signal weights for a small actor, or the function qsmm_set_actor_ngram_profile can assign preloaded probability profiles to action choice states, and output signal weights may define a lesser number of output signals. For example, if the actor had four output signals, and qsmm_set_actor_sig_weight set the weight of one of them to zero, the nominal number of output signals is three. The same applies to a probability profile for an action choice state (set in the statistics storage of a small actor or by qsmm_set_actor_ngram_profile for a large actor): if the profile probability of an output signal is zero, the nominal number of output signals is less than the number of output signals defined when creating the actor.

However, the concept of the nominal number of output signals is weak. The weakness shows up when positive weights (or profile probabilities) of output signals are different. In this case, the nominal number of output signals might not be simply the number of output signals with positive weights (or profile probabilities). For example, if four signals have weights <0.33, 0.33, 0.33, 0.01>, the nominal number of output signals is rather three than four.

When loading an assembler program into a node or changing the values of controlled probability variables of a node, QSMM uses the following algorithm for the approximate calculation of the nominal number of output signals for a list of weights:

  1. Zero c, the resulting nominal number of output signals.
  2. Calculate a, the arithmetic mean of all positive weights of output signals.
  3. For every output signal weight b, if b>a, then add 1 to c, otherwise add b/a to c.

Different action choice states in the event history can have different nominal numbers of output signals. If a function returning the relative probability of an output signal depends on the number of output signals, the function can use the mean nominal number of output signals for this parameter. An actor can compute the mean nominal number of output signals based on the nominal numbers of output signals calculated for the weights of the output signals of action choice states occurred in the event history. The mean nominal number of output signals might be the arithmetic or geometric mean of those nominal numbers of output signals. The concept of the mean nominal number of output signals is weaker than the concept of the nominal number of output signals.

You can retrieve or set the mean nominal number of output signals by the following functions.

Function: double qsmm_get_actor_nsig_ctrl (qsmm_actor_t actor)

This function returns the mean nominal number of output signals of an actor. That number is either the number of output signals calculated from the structure qsmm_actor_desc_s passed to the function qsmm_actor_create when creating the actor, or the number of output signals previously set by the function qsmm_set_actor_nsig_ctrl. You can call the function qsmm_get_actor_nsig_ctrl from a helper function for computing the relative probability of an output signal if the helper function depends on the number of output signals. A value returned by qsmm_get_actor_nsig_ctrl is always finite and greater than or equal to 2.

Function: int qsmm_set_actor_nsig_ctrl (qsmm_actor_t actor, double val)

This function sets the mean nominal number of output signals of an actor to val. Built-in functions returning the relative probability of an output signal use that number. A helper function for computing the relative probability of an output signal provided by a developer can also use that number.

On success, the function returns a non-negative value. If val is not a finite number or is a number less than 2, the function returns negative error code QSMM_ERR_INVAL.

In the simplest case, if you do not change output signal weights and do not use profile probabilities, there is no need to modify the mean nominal number of output signals initially set by the function qsmm_actor_create for a small actor. Otherwise, if a function returning the relative probability of an output signal depends on the number of output signals, you need to calculate in some way the mean nominal number of output signals and set that number for the small actor by the function qsmm_set_actor_nsig_ctrl. Because a large actor typically uses Huffman trees with a fixed number of child nodes of every tree node, and qsmm_actor_create sets this number as the mean nominal number of output signals of a small actor associated with the large actor, you might not need to modify the mean nominal number of output signals for the large actor.

If an array of output signal weights or a probability profile allows an actor to select only one output signal, that is, if the array contains a single positive element, or a probability profile for an action choice state contains a single positive probability of an output signal, then the best will be not to call the functions qsmm_actor_shl_sig, qsmm_actor_reg_sig_in, and qsmm_actor_reg_sig_action at all. In this case, you can perform the selection of an output signal in a deterministic way (without using the actor) and shall not increment discrete time.

To calculate the mean nominal number of output signals, you can fetch the precomputed nominal number of output signals for an action choice state from a probability profile if the action choice state has the probability profile specified. You still need to store the nominal number of output signals computed in advance in the profile. Use the following function to fetch the precomputed nominal number of output signals from the probability profile of an action choice state and to obtain an output signal if the profile specifies the deterministic selection of this output signal.

Function: int qsmm_get_actor_profile_nsig_ctrl (qsmm_actor_t actor, int *nsig_pos_p, double *nsig_ctrl_p, qsmm_sig_t *sig_out_p)

This function retrieves information from the statistics storage of an actor about a probability profile for a current action choice state encoded by the buffer for an n-gram of signals from the event history.

If nsig_pos_p is not NULL, the function sets *nsig_pos_p to the number of output signals with positive profile probabilities; the actor can emit one of those output signals in its current action choice state. If nsig_pos_p is not NULL, and the current action choice state does not have a probability profile specified, the function sets *nsig_pos_p to 0.

If nsig_ctrl_p is not NULL, the function sets *nsig_ctrl_p to the nominal number of output signals the actor can emit in its current action choice state. If nsig_ctrl_p is not NULL, and the current action choice state does not have a probability profile specified, the function sets *nsig_ctrl_p to 0.

If the probability profile allows an actor to emit only one output signal, the function sets *nsig_pos_p to 1 (if nsig_pos_p is not NULL), *nsig_ctrl_p to 1 (if nsig_ctrl_p is not NULL), and *sig_out_p to this output signal (if sig_out_p is not NULL). If sig_out_p is not NULL, and the current action choice state does not have a probability profile specified, or the probability profile defines nondeterministic selection of an output signal, the function sets *sig_out_p to QSMM_SIG_INVALID.

See Structures for Accessing Storage, for how to pass the number of output signals with positive profile probabilities, the nominal number of output signals, and an output signal to emit deterministically (if it exists) to storage access functions to write them to statistics storage with a handle obtained by the function qsmm_get_actor_storage to be able to retrieve those parameters later by the function qsmm_get_actor_profile_nsig_ctrl.

If the current action choice state has a probability profile specified, the function returns a positive value. If the current action choice state does not have a probability profile specified, the function returns 0.

On failure, the function returns a negative error code. Currently, the function can return the following error codes.

QSMM_ERR_NGRAM

The buffer does not encode a valid action choice state. To determine the validity of an action choice state, the function checks the content of the buffer for accordance with allowed ranges of signal identifiers specified by the field range_sig_p of qsmm_actor_desc_s structure when creating the actor.

QSMM_ERR_STORAGE

Statistics storage failure. 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 detected.

QSMM_ERR_ILSEQ

A statistics storage access function generated an error message but cannot convert it to a wide string according to a current locale, or a storage redirection function reported QSMM_ERR_ILSEQ.

QSMM_ERR_NOMEM

A statistics storage access function reported out of memory error.


Previous: , Up: Customizing the Relative Probability Function   [Contents][Index]

2.6.6 Actor Temperature

In all relative probability function formulas mentioned in Relative Probability Function Types, T denotes actor temperature multiplied by some constant. Actor temperature is a concept that follows from the use of exponential forms for the relative probability function resembling formulas related to the Boltzmann distribution. In most relative probability function formulas, actor temperature is a divisor of every spur weight.

The perfect relative probability function is the one that makes it possible for an actor to generate most optimal behavior without the need to tune up actor temperature by hand. That is, for such function, you would always use default temperature equal to 1. If the function is imperfect, its application is not intended one, or when applying the simulated annealing approach for solving a problem, use the following API functions to adjust the temperature of an actor for producing more optimal behavior.

Function: double qsmm_get_actor_ktemperature (qsmm_actor_t actor)

This function returns the temperature (multiplied by some constant) of an actor. If the actor is the large one, the function returns the temperature of a small actor associated with the large actor. A returned value is always finite and positive.

Function: int qsmm_set_actor_ktemperature (qsmm_actor_t actor, double val)

This function sets the temperature (multiplied by some constant) of an actor to val. If the actor is the large one, the function sets the temperature of a small actor associated with the large actor.

On success, the function returns a non-negative value. If val is not a finite or positive number, the function returns negative error code QSMM_ERR_INVAL.

The function qsmm_actor_create initializes the temperature (multiplied by some constant) of a newly created actor to 1.


Next: , Previous: , Up: Adaptive Probabilistic Mapping   [Contents][Index]

2.7 Specifying Output Signal Weights

The weight of an output signal of an actor is a coefficient for multiplying the probability of selecting this output signal by the actor. The coefficient is a hint—it increases or decreases that probability. To disable emitting an output signal, set its weight equal to 0.

In the simplest case, the actor uses the weight of an output signal when selecting the output signal in all action choice states. On binding the weight to a specific action choice state, the actor uses that weight when selecting the output signal only in this action choice state.

Large actors do not support setting the weight of an output signal for all action choice states at once. However, all actors support binding output signal weights to specific action choice states.

A preloaded probability profile is a prepared list of output signal weights loaded into an actor. You can assign the preloaded probability profile to specific action choice states for setting output signal weights for those action choice states.

For a small actor, you can also bind output signal weights to an action choice state by specifying a probability profile for the action choice state held in the statistics storage of this small actor. See Structures for Accessing Storage, for how to pass profile probabilities to storage access functions to write them to statistics storage.

It is essential to note that by reasons described in Number of Output Signals, changing the default weights of output signals of a small actor, in general, makes its behavior ill-defined. Therefore, you should avoid doing that. Changing the weights seems to be a correct procedure only for a large actor, because this procedure does not alter the number of choice alternatives at decision points along the pathways to output signals.


Next: , Up: Specifying Output Signal Weights   [Contents][Index]

2.7.1 Setting a Weight for an Output Signal

Small actors support setting the weight of an output signal for all possible action choice states at once. The functions qsmm_get_actor_sig_weight and qsmm_set_actor_sig_weight described below can inspect or modify the array of weights of output signals of a small actor. A large actor does not support setting the weight of an output signal for all possible action choice states at once and does not use that array.

The function qsmm_actor_create initializes to 1 the weights of all output signals of a newly created small actor in the array. If an output signal of a small actor has a profile probability specified for an action choice state in statistics storage, the overall weight of this output signal is the product of a corresponding weight in the array and the profile probability.

The function qsmm_actor_calc_action_prob always applies weights contained in the array to computed relative probabilities, disregarding of a requested type of probabilities to calculate. After multiplying computed relative probabilities by corresponding weights, qsmm_actor_calc_action_prob normalizes a resulting array to obtain probabilities that sum up to 1.

Function: int qsmm_get_actor_sig_weight (qsmm_actor_t actor, qsmm_sig_t sig, double *weight_p)

This function sets *weight_p to the weight of output signal sig of an actor. If weight_p is NULL, the function does not set *weight_p. Otherwise, *weight_p is a finite and non-negative number.

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

Signal sig is not an output signal of the actor.

QSMM_ERR_NOTSUP

The actor is the large one.

Function: int qsmm_set_actor_sig_weight (qsmm_actor_t actor, qsmm_sig_t sig, double weight)

This function sets the weight of output signal sig of an actor to weight.

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

Signal sig is not an output signal of the actor, or weight is not a finite number or is a negative number.

QSMM_ERR_NOTSUP

The actor is the large one.


Next: , Previous: , Up: Specifying Output Signal Weights   [Contents][Index]

2.7.2 Preloading a Probability Profile

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.


Previous: , Up: Specifying Output Signal Weights   [Contents][Index]

2.7.3 Assigning a Preloaded Probability Profile

You can assign a preloaded probability profile to a number of action choice states. Output signals emittable in those action choice states will have weights defined by the preloaded probability profile.

If the current action choice state is an action choice state with that preloaded probability profile assigned, the function qsmm_actor_calc_action_prob called for a small actor applies the weights by copying them from the preloaded probability profile to the array of output signal weights accessible by the functions qsmm_get_actor_sig_weight and qsmm_set_actor_sig_weight.

For a large actor, the function qsmm_get_actor_sig_action uses a Huffman tree defined by the preloaded probability profile to select an output signal in an action choice state with that preloaded probability profile assigned.

The purpose of the following functions is to retrieve or set up a correspondence between an action choice state and a preloaded probability profile.

Function: int qsmm_get_actor_ngram_profile (qsmm_actor_t actor, int rez1, int *profile_p, int *permut_p, const qsmm_sig_t *sig_ngram_p)

This function retrieves a correspondence between an action choice state of an actor and a preloaded probability profile. A probabilities list in normal form and a permutation of output signals define the preloaded probability profile. The array sig_ngram_p with length specified in the field ngram_sz of qsmm_actor_desc_s structure when creating the actor encodes the action choice state. The argument rez1 is for future use and must be equal to 0.

If profile_p is not NULL, the function sets *profile_p equal to the index of a probabilities list in normal form for the preloaded probability profile. If permut_p is not NULL, the function sets *permut_p equal to the index of a permutation of output signals for the preloaded probability profile. If the function sets *profile_p and *permut_p to -1, this is an indication that the action choice state has default output signal weights. For a small actor, default output signal weights are all equal. For a large actor, default output signal weights following from the structure of a default Huffman tree are equal only if the number of output signals is a positive integer power of tree arity.

On success, the function returns a non-negative value. If the array sig_ngram_p does not encode a valid action choice state, the function returns negative error code QSMM_ERR_NGRAM.

Function: int qsmm_set_actor_ngram_profile (qsmm_actor_t actor, int rez1, int profile, int permut, const qsmm_sig_t *sig_ngram_p)

This function sets up a correspondence between an action choice state of an actor and a preloaded probability profile. A probabilities list in normal form and a permutation of output signals define the preloaded probability profile. The argument profile specifies the index of this probabilities list in normal form. The argument permut specifies the index of this permutation of output signals. The array sig_ngram_p with length specified in the field ngram_sz of qsmm_actor_desc_s structure when creating the actor encodes the action choice state. The argument rez1 is for future use and must be equal to 0.

A special combination of profile and permut both equal to -1 is an indication to assign default output signal weights to the action choice state. For a small actor, default output signal weights are all equal. For a large actor, default output signal weights following from the structure of a default Huffman tree are equal only if the number of output signals is a positive integer power of tree arity.

The function keeps intact statistics collected for the action choice state and held in statistics storage with a handle retrievable by the function qsmm_get_actor_storage for the actor. However, for a large actor, the function qsmm_set_actor_ngram_profile destroys the Huffman tree of the action choice state encoded by sig_ngram_p. That Huffman tree holds the other part of statistics collected for the action choice state.

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 profile is not a valid index of a probabilities list in normal form, or the argument permut is not a valid index of a permutation of output signals, and, at the same time, profile and permut are not both equal to -1, or the length of a probabilities list in normal form specified by profile is not equal to the length of a permutation of output signals specified by permut.

QSMM_ERR_NGRAM

The array sig_ngram_p does not encode a valid action choice state. To determine the validity of an action choice state, the function checks that array for accordance with allowed ranges of signal identifiers specified by the field range_sig_p of qsmm_actor_desc_s structure when creating the actor.

QSMM_ERR_NOTSUP

For a small actor, the number of possible action choice states calculated on the basis of allowed ranges of signal identifiers specified by the field range_sig_p of qsmm_actor_desc_s structure when creating the actor is too large.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation. This error can leave the actor in inconsistent state. If after removing a reason of this error a repeated call to this function succeeds, the actor’s state becomes consistent.


Next: , Previous: , Up: Adaptive Probabilistic Mapping   [Contents][Index]

2.8 Automatic Spur

Automatic spur is a means to implement the idea that an intrinsic feature of an intelligent system is adherence to the principle of minimum energy (or maximum probability). The use of automatic spur may substantially increase the optimality of output signals an actor emits. The automatic spur also makes it possible to use the actor in cases when there are no explicit spur increments supplied to it.

The automatic spur is useful when the actor models a finite automaton. In this case, the output signals of the actor represent its internal states, that is, finite automaton states, and each action choice state is a superposition of the previous internal state and an input signal received when the actor was in that previous internal state. The automatic spur is a measure of adequacy of a model of internal states to a sequence of input signals received.

In QSMM, a common approach to building a model of internal states of an entity to solve a problem is the use of a spur scheme with two spur types for inhibitory (negative) spur and excitatory (positive) spur countervailing each other. The inhibitory spur is the automatic spur typically with a normal way of perception. The excitatory spur is specific to the problem to solve.

If an actor uses the automatic spur, it is equal to the sum of automatic spur increments calculated by the function qsmm_actor_reg_sig_in for action choice states that have prior occurrences in the event history. For such an action choice state, qsmm_actor_reg_sig_in knows an output signal emitted at the previous occurrence of this action choice state. Note that for the last occurrence, an output signal emitted in the action choice state is not yet known in qsmm_actor_reg_sig_in.

The actor calculates an automatic spur increment for a pair representing the logical consequence h → z and consisting of an action choice state h and an output signal z emitted in this action choice state. The automatic spur increment is equal to the natural logarithm of the probability of occurrence of this pair in the event history:

auto_spur_incr.formula

This formula uses the following notations:

v(h,z)

The number of occurrences of the pair in the event history.

t0

The discrete time of the previous occurrence of the pair in the event history. The function qsmm_actor_reg_sig_action records that time.

0<K≤1 

The mean number of output signals emitted per one unit of discrete time passed.

If an actor uses a single spur type, and it corresponds to the automatic spur, it is better to set the type of a relative probability function for the actor to QSMM_RELPROB_BUILTIN2 or QSMM_RELPROB_BUILTIN3. However, it is also better to use the automatic spur in conjunction with the other countervailing spur evaluating progress in solving a problem in some other way.

Use the functions described below to query or set a spur type for the automatic spur. By default, an actor created by the function qsmm_actor_create does not use the automatic spur, except that an implicitly created small actor associated with the large actor uses it.

Function: int qsmm_get_actor_auto_spur_type (qsmm_actor_t actor)

This function returns the non-negative index of a spur type for automatic spur used by an actor or negative error code QSMM_ERR_NOTFOUND if the actor does not use the automatic spur.

Function: int qsmm_set_actor_auto_spur_type (qsmm_actor_t actor, int spur_type)

This function sets to spur_type the spur type for the automatic spur of an actor. Spur types have zero-based indices. If spur_type is equal to -1, the actor does not use the automatic spur; this condition does not affect the use of the automatic spur by a small actor associated with the large actor.

On success, the function returns a non-negative value. If spur_type is less than -1 or is greater than or equal to the number of spur types specified in the field nspur of qsmm_actor_desc_s structure when creating the actor, the function returns negative error code QSMM_ERR_INVAL.

Use the functions qsmm_get_actor_naction_per_evt and qsmm_set_actor_naction_per_evt to query and set the value of K.

A small actor can use at most one spur type for the automatic spur. The functions qsmm_get_actor_auto_spur_type and qsmm_set_actor_auto_spur_type called for a small actor query and set the index of a spur type for that automatic spur.

A large actor can use at most two spur types for the automatic spur. A small actor associated with the large actor can use the automatic spur of the first type—increment it for action choice states occurring in the event history of this small actor. Those action choice states represent Huffman tree nodes traversed to generate output signals by the large actor. The large actor itself can use the automatic spur of the second type—increment it for action choice states occurring in the event history of that large actor. The functions qsmm_get_actor_auto_spur_type and qsmm_set_actor_auto_spur_type called for a large actor query and set the index of a spur type for the latter automatic spur.

Historically, the function qsmm_actor_create creates a large actor with the automatic spur of the first type turned on by default. You may want to turn it off and make the large actor use the automatic spur of the second type instead. To turn off the use of the automatic spur of the first type by a large actor actor_large, write:

qsmm_set_actor_auto_spur_type(
    qsmm_get_actpair_actor_env(
        qsmm_get_actpair(qsmm_get_actor_large_model(actor_large))),
    -1)

To conserve memory, you can reuse a spur type for the automatic spur of the first type for another purpose. For a small actor associated with the large actor, this spur type has index 0. By default, the small actor uses discrete time to compute spur increment velocity for this spur type. For the large actor, this spur type has special index -1.


Next: , Previous: , Up: Adaptive Probabilistic Mapping   [Contents][Index]

2.9 Switching Adaptive or Random Behavior

An actor uses a random number generator to select a signal from a set of possible signals according to their relative probabilities. The function qsmm_get_actor_sig_action performs this selection. The actor does not use the random number generator if there is only one signal with a positive relative probability—the actor simply selects this signal.

For a small actor, qsmm_get_actor_sig_action selects an output signal based on the relative probabilities of output signals previously calculated by the function qsmm_actor_calc_action_prob. When selecting an output signal of a large actor, the function qsmm_get_actor_sig_action indirectly calls itself a number of times for a small actor associated with the large actor. As a consequence of this, the large actor traverses the Huffman tree of a current action choice state and selects an output signal corresponding to one of tree leaves.

You can obtain a random number generator used by an actor—either provided when creating the actor or an instance of a default random number generator allocated automatically if not provided.

Function: qsmm_rng_t qsmm_get_actor_rng (qsmm_actor_t actor)

This function returns a random number generator used by an actor to select output signals. The function never returns NULL.

You typically use a returned random number generator to seed the generator after creating the actor. See Random Number Generators, for how to seed a random number generator and perform other operations on it.

A useful approach to determine the amount of contribution of an actor to the optimality of behavior of a system is comparing a measure of optimality for this system with the actor behaving adaptively versus a measure of optimality with the actor behaving randomly. The greater the difference is between those values the more contribution the actor makes to the overall optimality of system behavior.

Use the following functions to query the current mode of behavior of an actor and to switch the actor to random or adaptive (normal) behavior mode.

Function: int qsmm_get_actor_random (qsmm_actor_t actor)

This function returns a positive value if an actor is currently in random behavior mode or zero if the actor is in adaptive (normal) behavior mode. The function never returns negative values.

Function: void qsmm_set_actor_random (qsmm_actor_t actor, int flag)

This function switches the current mode of behavior of an actor to random or adaptive (normal) mode. If flag is non-zero, the function switches the current mode to random mode. If flag is zero, the function switches the current mode to adaptive mode.

For a small actor, random and adaptive behavior modes affect how the function qsmm_actor_calc_action_prob calculates probabilities of QSMM_PROB_AGGR or QSMM_PROB_LEARNED type.

In the random mode, qsmm_actor_calc_action_prob called for a small actor does not calculate the relative probabilities of output signals in the normal way but uses output signal weights for those relative probabilities. If the type of probabilities to calculate is QSMM_PROB_AGGR, that function additionally applies a probability profile to those weights if the probability profile exists in statistics storage for a current action choice state. Finally, the function normalizes the resulting values.

For a large actor, random and adaptive behavior modes are actually the behavior modes of a small actor associated with the large actor.

The function qsmm_actor_create initializes the current mode of behavior of a newly created actor to adaptive (normal) mode.


Next: , Previous: , Up: Adaptive Probabilistic Mapping   [Contents][Index]

2.10 Revising Action Choice States

Revising action choice states includes enumerating and removing them. You may need to enumerate the action choice states of an actor to clear or update statistics on them. The following function enumerates action choice states that have pieces of information stored in the memory of an actor.

Function: int qsmm_actor_enum_ngrams (qsmm_actor_t actor, int ngram_prefix_sz, const qsmm_sig_t *sig_ngram_prefix_p, qsmm_enum_ngram_callback_func_t callback_func, void *paramp)

This function enumerates the lists of signal identifiers encoding action choice states that have pieces of information stored in the memory of an actor. For a small actor, those action choice states have pieces of information held in statistics storage with a handle retrievable by the function qsmm_get_actor_storage. For a large actor, those action choice states are the union of the following state sets:

The function qsmm_actor_enum_ngrams enumerates the aforementioned action choice states encoded by the lists of signal identifiers with a prefix sig_ngram_prefix_p that has length ngram_prefix_sz. If ngram_prefix_sz is 0, then sig_ngram_prefix_p can be NULL.

The process of enumeration is repeated calling a callback function callback_func. The callback function receives a user parameter paramp and an array of signal identifiers encoding an enumerated action choice state. If the callback function returns a positive value, qsmm_actor_enum_ngrams continues the enumeration. If the callback function returns zero, qsmm_actor_enum_ngrams terminates the enumeration and reports success. If the callback function returns a negative value, qsmm_actor_enum_ngrams terminates the enumeration and reports failure.

The function qsmm_actor_enum_ngrams does not support recursive calling from the callback function for the same actor.

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 ngram_prefix_sz is less than 0 or greater than the length of a list of signal identifiers encoding an action choice state.

QSMM_ERR_CALLBACK

The callback function reported an error.

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 type of a pointer to a callback function called for every enumerated action choice state is below.

Data type: qsmm_enum_ngram_callback_func_t

This is a type of a callback function pointer with the following declaration:

typedef int
(*qsmm_enum_ngram_callback_func_t)(
    qsmm_actor_t actor,
    const qsmm_sig_t *sig_ngram_p,
    void *paramp
);

The function qsmm_actor_enum_ngrams calls the callback function for every enumerated action choice state of an actor. The argument sig_ngram_p specifies an array of signal identifiers encoding an action choice state. The length of this array is in the field ngram_sz of qsmm_actor_desc_s structure passed to the function qsmm_actor_create when creating the actor. You can retrieve that length later by the function qsmm_get_actor_ngram_sz. The argument paramp is a user parameter passed to qsmm_actor_enum_ngrams.

The callback function shall return a positive value to continue the process of enumeration, zero to terminate the process of enumeration, or a negative value on error.

Use the following function to remove information on an action choice state from the memory of an actor.

Function: int qsmm_actor_remove_ngram (qsmm_actor_t actor, const qsmm_sig_t *sig_ngram_p)

This function removes information on an action choice state encoded by an array of signal identifiers sig_ngram_p from the memory of an actor. The length of this array is in the field ngram_sz of qsmm_actor_desc_s structure passed to the function qsmm_actor_create when creating the actor. You can retrieve that length later by the function qsmm_get_actor_ngram_sz.

For a small actor, the function removes information on the action choice state held in statistics storage with a handle retrievable by the function qsmm_get_actor_storage. For a large actor, the function removes the following pieces of information if they exist:

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_NGRAM

The array sig_ngram_p does not encode a valid action choice state. To determine the validity of an action choice state, the function checks that array for accordance with allowed ranges of signal identifiers specified by the field range_sig_p of qsmm_actor_desc_s structure when creating the actor.

QSMM_ERR_NOTFOUND

No information on the action choice state—nothing to remove.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation for a large actor. This error can leave the large actor in inconsistent state. If after removing a reason of this error a repeated call to this function succeeds, or the function reports QSMM_ERR_NOTFOUND, the actor’s state becomes consistent.


Previous: , Up: Adaptive Probabilistic Mapping   [Contents][Index]

2.11 Example of Using the Actor API

In the example of using the Actor API, an agent controlled by a sample program has to find a short path to gold located in a labyrinth and then to an exit from the labyrinth. The source code of the sample program contains the picture of that labyrinth encoded using a subset of ASCII characters resembling pseudographics. You can change that picture to test agent behavior for various labyrinth configurations.

To find a resulting path, the agent visits the labyrinth the number of times defined by the macro NVISIT. Moving the agent to a cell designated as a labyrinth exit finishes a labyrinth visit. A custom function returning the relative probability of an output signal is the exponent of an expression equal to mean spur increment for a cycle type divided by actor temperature. The sample program uses a simulated annealing approach, where actor temperature gradually decreases with every subsequent labyrinth visit. The macro KT_0 defines initial actor temperature, and the macro KT_1 defines final temperature.

At last labyrinth visit, the sample program shows the picture of the labyrinth and agent movements in it, prints an indication whether the agent took the gold, and displays the current length of a visiting path. After finishing the last visit, a user can press Q to create the files labyr_0.asy and labyr_1.asy, print the number of labyrinth visits when the agent took the gold, and exit the sample program. Those two files correspond to the case before taking the gold by the agent and the case after taking the gold respectively. Each file includes the file labyr.asy and represents a labyrinth picture containing the following information:

To process both files by Asymptote and produce the image files labyr_0.png and labyr_1.png, use the commands:

asy -f png labyr_0.asy
asy -f png labyr_1.asy

You can specify a random seed by a program argument. If the random seed is non-negative, the actor operates adaptively (normally). If the random seed is negative, the actor operates randomly. You can compare agent behavior and resulting files labyr_0.png and labyr_1.png for these two modes of program execution.

For example, after executing the command

./labyr2 1

the file labyr_0.png produced from labyr_0.asy contains the image

image labyr_0.png produced from labyr_0.asy

Figure 2.6: image labyr_0.png produced from labyr_0.asy

and the file labyr_1.png produced from labyr_1.asy contains the image

image labyr_1.png produced from labyr_1.asy

Figure 2.7: image labyr_1.png produced from labyr_1.asy

In the source code of the sample program, each labyrinth cell is a rectangle 4x3 (WxH). The picture of a labyrinth cell is represented in Figure 2.8. Adjacent cells have common border columns or rows. For adjacent cells located vertically, row 2 of an upper cell and row 0 of a lower cell are the same rows. For adjacent cells located horizontally, column 3 of a left cell and column 0 of a right cell are the same columns.

labyrinth cell

Figure 2.8: labyrinth cell

The macros MAX_X and MAX_Y define maximum zero-based coordinates of a labyrinth cell. Thus, the labyrinth has (MAX_X+1)*3+1 character columns in width and (MAX_Y+1)*2+1 character rows in height. The macros ENTRY_X and ENTRY_Y define zero-based coordinates of the entry cell of the labyrinth relative to its upper left corner.

Within a labyrinth cell, space characters denote allowed movement paths, and other characters denote disallowed movement paths. Let us denote a character in column x and row y of a labyrinth cell by <x,y>. If a cell is reachable from the labyrinth entry, then characters <1,1> and <2,1> of the cell must be spaces; small circles denote them in the figure. If the cell allows the agent to move to a left and/or right adjacent cell, then characters <0,1> and/or <3,1> respectively must be spaces; left and right arrows denote them in the figure. If the cell allows the agent to move to an upper adjacent cell, then characters <1,0> and <2,0> must be spaces; up arrows denote them in the figure. If the cell allows the agent to move to a lower adjacent cell, then characters <1,2> and <2,2> must be spaces; down arrows denote them in the figure.

If characters <0,0>, <3,0>, <0,2>, and <3,2> of a cell are the characters ‘*’, the cell contains gold. If there are multiple such cells, visiting any of them means taking the gold. It is in a single copy per labyrinth visit—if there are multiple cells with the gold, visiting any of them implicitly removes it from the others until the next labyrinth visit. If characters at the cell corners are the characters ‘#’, the cell is a labyrinth exit. A labyrinth can have more than one exit. When modifying the picture of a labyrinth, make sure that its cells are properly aligned and connected, and there are no paths outside of the labyrinth—violating these rules leads to undefined program behavior.

The file samples/labyr2.c in the package distribution provides the source code of this sample program. Below is a copy of that source code. The command make builds the sample program if the configure script has configured QSMM to use the ncurses library. See the file INSTALL in the root of the package distribution for information on the configure script.

#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#if defined(HAVE_CURSES_H)
#   include <curses.h>
#elif defined(HAVE_NCURSES_CURSES_H)
#   include <ncurses/curses.h>
#endif

#include <qsmm/qsmm.h>

#define NVISIT  200
#define MAX_X   14
#define MAX_Y   14
#define ENTRY_X 0
#define ENTRY_Y 14
#define NSIG_IN (MAX_X+1>MAX_Y+1?MAX_X+1:MAX_Y+1)
#define KT_0    (NVISIT*2)
#define KT_1    (1.0/KT_0)


#define CHK_FAIL(func, ...)                                               \
    do {                                                                  \
        const int rc=func(__VA_ARGS__);                                   \
        if (rc<0) {                                                       \
            fprintf(stderr, #func ": %s\n", qsmm_err_str(rc));            \
            goto Exit;                                                    \
        }                                                                 \
    }                                                                     \
    while (0)


#define ERREXIT(fmt, ...)                                                 \
    do {                                                                  \
        fprintf(stderr,fmt "\n", ## __VA_ARGS__);                         \
        goto Exit;                                                        \
    }                                                                     \
    while (0)


enum direct_e {
    DIRECT_NORTH,  // move one step up
    DIRECT_EAST,   // move one step right
    DIRECT_SOUTH,  // move one step down
    DIRECT_WEST,   // move one step left
    DIRECT_COUNT   // number of movement directions
};


static char last_path[2][MAX_Y+1][MAX_X+1];
static long fq_max[3], state_fq[3][MAX_Y+1][MAX_X+1];
static qsmm_actor_t actor=0;


// Generate an Asymptote file containing a picture of the labyrinth with
// learned movement gradients for the cases when the gold was or was not
// taken.
// Returns: 0 = success;
//         -1 = failure.

static int
create_pic(
    const char **pic_pp,
    char is_gf
) {
    char fln[]="labyr_?.asy";
    int ii, result=-1;
    fln[6]=is_gf?'1':'0';
    FILE *const filep=fopen(fln,"w");
    if (!filep) ERREXIT("%s: failed to open the file for writing",fln);
    fprintf(filep,"import labyr;\n\n");
    fprintf(filep,"set_dims(%d,%d);\n",MAX_X,MAX_Y);
    qsmm_sig_t *const sig_ngram_p=qsmm_get_actor_sig_ngram(actor);
    sig_ngram_p[0]=is_gf;
    for (int yy=0; yy<=MAX_Y; yy++)
        for (int xx=0; xx<=MAX_X; xx++) {
            if (state_fq[2][yy][xx]<1) {
                fprintf(filep,"black_box(%d,%d);\n",xx,yy);
                continue;
            }
            fprintf(filep, "fill_box(%d,%d,%.2f);\n",
                    xx, yy, (double) state_fq[(int) is_gf][yy][xx]/
                            fq_max[(int) is_gf]);
            const int row=yy*2, col=xx*3;
            for (const char *ccp="#*"; *ccp; ccp++)
                if (pic_pp[row][col]==*ccp && pic_pp[row][col+3]==*ccp &&
                    pic_pp[row+2][col+3]==*ccp && pic_pp[row+2][col]==*ccp)
                    fprintf(filep, "%s(%d,%d);\n",
                            *ccp=='#'?"exit":"gold", xx, yy);
            sig_ngram_p[1]=xx;
            sig_ngram_p[2]=yy;
            CHK_FAIL(qsmm_actor_calc_action_prob, actor,
                     0, NSIG_IN, NSIG_IN+DIRECT_COUNT, QSMM_PROB_LEARNED);
            const double *const prob_p=
                qsmm_get_actor_choice_sig_prob(actor);
            double prob_max=0, ww[DIRECT_COUNT];
            for (ii=0; ii<DIRECT_COUNT; ii++) {
                const double prob=prob_p[NSIG_IN+ii];
                if (prob_max<prob) prob_max=prob;
                ww[ii]=prob;
            }
            for (ii=0; ii<DIRECT_COUNT; ii++) ww[ii]/=prob_max;
            fprintf(filep, "arrows(%s,%d,%d,%.2f,%.2f,%.2f,%.2f);\n",
                    last_path[(int) is_gf][yy][xx]?"true":"false",
                    xx, yy, ww[0], ww[1], ww[2], ww[3]);
            qsmm_actor_choice_sig_prob_release(actor);
        }
    fprintf(filep,"entry(%d,%d);\n",ENTRY_X,ENTRY_Y);
    if (ferror(filep)) ERREXIT("%s: failed to write to the file",fln);
    result=0;

Exit:
    if (filep) fclose(filep);
    return result;
}


// Make a movement in the labyrinth in a specified direction possibly
// showing the movement on the screen.
// Returns: 3 = movement resulted in exiting the labyrinth;
//          2 = movement resulted in taking the gold;
//          1 = movement made successfully;
//          0 = cannot make the movement because a new location cell of the
//              agent is not empty.

static int
opaque_maze(
    enum direct_e direct
) {
    static const char *picture[]={
        // 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14
        "+--------+-----+--------------------------#..#",
        "|        |     |                             |",  // 0
        "|  *  *  |     |                          #  #",
        "|        |     |                             |",  // 1
        "|  *  *  |     |     +-----+                 |",
        "|        |     |     |     |                 |",  // 2
        "|        |     |     |     |     +-----+     |",
        "|        |     |     |     |     |     |     |",  // 3
        "|        |     |     |     |     |     |     |",
        "|        |     |     |     |     |     |     |",  // 4
        "|        +-----+     |     |     |     |     |",
        "|                    |     |     |     |     |",  // 5
        "|                    |     |     |     |     |",
        "|                    |     |     |     |     |",  // 6
        "|  +-----------+     +-----+     |     |     |",
        "|  |           |                 |     |     |",  // 7
        "|  |           |                 |     |     |",
        "|  |           |                 |     |     |",  // 8
        "|  +-----------+     +-----+     |     |     |",
        "|                    |     |     |     |     |",  // 9
        "|                    |     |     |     |     |",
        "|                    |     |     |     |     |",  // 10
        "+--------------+     |     |     +-----+     |",
        "|              |     |     |                 |",  // 11
        "|              |     |     |                 |",
        "|              |     |     |                 |",  // 12
        "+--------------+     +-----+     +-----+     |",
        "|                                |     |     |",  // 13
        "|                                |     |     |",
        "|                                |     |     |",  // 14
        "+..+-----------------------------+-----+-----+"
    };
    static char is_gf=0;
    static int path_len, visit=0, xx=-1, yy=-1;
    int ii, col, row;
    if (xx<0 || yy<0) {
        if (visit==NVISIT-1) {
            if (!initscr()) exit(2);
            noecho();
            for (row=0; row<(MAX_Y+1)*2+1; row++)
                mvaddstr(row,0,picture[row]);
        }
        xx=ENTRY_X;
        yy=ENTRY_Y;
        path_len=0;
    }
    assert(xx>=0 && xx<=MAX_X);
    assert(yy>=0 && yy<=MAX_Y);
    if (visit==NVISIT-1) last_path[(int) is_gf][yy][xx]=1;
    col=xx*3+1;
    row=yy*2+1;
    assert(picture[row][col]==' ' && picture[row][col+1]==' ');
    assert((picture[row-1][col]==' ' && picture[row-1][col+1]==' ') ||
           (picture[row-1][col]!=' ' && picture[row-1][col+1]!=' '));
    assert((picture[row+1][col]==' ' && picture[row+1][col+1]==' ') ||
           (picture[row+1][col]!=' ' && picture[row+1][col+1]!=' '));
    switch (direct) {
        case DIRECT_NORTH:
            if (picture[row-1][col]!=' ' || picture[row-1][col+1]!=' ')
                return 0;
            yy--;
            break;
        case DIRECT_EAST:
            if (picture[row][col+2]!=' ') return 0;
            xx++;
            break;
        case DIRECT_SOUTH:
            if (picture[row+1][col]!=' ' || picture[row+1][col+1]!=' ')
                return 0;
            yy++;
            break;
        case DIRECT_WEST:
            if (picture[row][col-1]!=' ') return 0;
            xx--;
            break;
        default:
            assert(0);
    }
    path_len++;
    if (visit==NVISIT-1) mvaddstr(row,col,"  ");
    col=xx*3+1;
    row=yy*2+1;
    state_fq[2][yy][xx]++;
    state_fq[(int) is_gf][yy][xx]++;
    for (ii=0; ii<3; ii++)
        if (fq_max[ii]<state_fq[ii][yy][xx])
            fq_max[ii]=state_fq[ii][yy][xx];
    if (visit==NVISIT-1) {
        char ss[64];
        const int picture_w=strlen(picture[0]);
        mvaddstr(row,col,"[]");
        sprintf(ss," Gold found: %d",is_gf);
        mvaddstr(1,picture_w+2,ss);
        sprintf(ss,"Path length: %d",path_len);
        mvaddstr(3,picture_w+2,ss);
        move((MAX_Y+1)*2+3,0);
        refresh();
        usleep(125000);
    }
    int result=1;
    for (const char *ccp="#*"; *ccp; ccp++)
        if (picture[row-1][col-1]==*ccp && picture[row-1][col+2]==*ccp &&
            picture[row+1][col-1]==*ccp && picture[row+1][col+2]==*ccp) {
            if (*ccp=='#') {
                is_gf=0;
                result=3;
                xx=-1;
                yy=-1;
                if (visit==NVISIT-1) {
                    row=(MAX_Y+1)*2+3;
                    mvaddstr(row,0,"Press [Q] to exit");
                    while (1) {
                        int key=getch();
                        if (key=='q' || key=='Q') break;
                    }
                    for (ii=0; ii<2; ii++)
                        if (create_pic(picture,ii)<0) exit(2);
                    endwin();
                }
                else visit++;
            }
            else if (!is_gf) {
                is_gf=1;
                result=2;
            }
            break;
        }
    return result;
}


// Helper function for computing the relative probability of an
// output signal.

static double
relprob_user2(
    qsmm_actor_t actor,
    qsmm_sig_t sig_cycle,
    const struct qsmm_state_s *state_p,
    const struct qsmm_cycle_s *cycle_p,
    const struct qsmm_sspur_s *sspur_p,
    const struct qsmm_cspur_s *cspur_p,
    void *paramp
) {
    const double period_sum_c=cycle_p->period_sum_c;
    return (period_sum_c?cspur_p[0].delta_sum/period_sum_c:0)/
        qsmm_get_actor_ktemperature(actor);
}


// Find a path to gold in the labyrinth and then to its exit.

int
main(
    int argc,
    char **argv
) {
    int exit_code=1;
    struct qsmm_pair_sig_s range_sig[3];
    memset(range_sig,0,sizeof(range_sig));
    range_sig[0].second=1;
    range_sig[1].second=MAX_X;
    range_sig[2].second=MAX_Y;
    struct qsmm_actor_desc_s actor_desc;
    memset(&actor_desc,0,sizeof(actor_desc));
    actor_desc.nspur=1;
    actor_desc.ngram_sz=3;
    actor_desc.compat=1;
    actor_desc.sig_spec_type=QSMM_ACTOR_SIG_SPEC_IN_OUT;
    actor_desc.range_sig_p=range_sig;
    struct qsmm_actor_sig_spec_in_out_s *const iop=&actor_desc.sig_spec.in_out;
    iop->nsig_in=NSIG_IN;
    iop->nsig_out=DIRECT_COUNT;
    CHK_FAIL(qsmm_actor_create,&actor_desc,&actor);
    qsmm_set_actor_relprob_type(actor,QSMM_RELPROB_USER2);
    qsmm_set_actor_relprob_helper(actor,&relprob_user2,0);
    const int seed=(argc>1?atoi(argv[1]):0);
    if (seed<0) qsmm_set_actor_random(actor,1);
    qsmm_rng_seed(qsmm_get_actor_rng(actor),abs(seed));
    int n_gold_found=0;
    const double mut=pow(KT_1/KT_0,1.0/NVISIT);
    double ktemperature=KT_0;
    for (int visit=0; visit<NVISIT; visit++) {
        char is_gf=0;
        int xx=ENTRY_X, yy=ENTRY_Y;
        qsmm_sig_t sig_action=QSMM_SIG_INVALID;
        CHK_FAIL(qsmm_set_actor_ktemperature,actor,ktemperature);
        while (1) {
            CHK_FAIL(qsmm_actor_shl_sig,actor,is_gf,0);
            CHK_FAIL(qsmm_actor_shl_sig,actor,xx,0);
            CHK_FAIL(qsmm_actor_reg_sig_in,actor,yy);
            CHK_FAIL(qsmm_actor_calc_action_prob, actor,
                     0, NSIG_IN, NSIG_IN+DIRECT_COUNT, QSMM_PROB_LEARNED);
            CHK_FAIL(qsmm_get_actor_sig_action, actor,
                     0, NSIG_IN, NSIG_IN+DIRECT_COUNT, &sig_action);
            CHK_FAIL(qsmm_actor_reg_sig_action,actor,sig_action);
            CHK_FAIL(qsmm_actor_time_delta,actor,1);
            const enum direct_e direct=sig_action-NSIG_IN;
            const int rc=opaque_maze(direct);
            switch (rc) {
                case 0:
                    continue;
                case 1:
                    break;
                case 2:
                    is_gf=1;
                    n_gold_found++;
                    break;
                case 3:
                    if (is_gf) CHK_FAIL(qsmm_actor_spur_delta,actor,0,1);
                    break;
                default:
                    assert(0);
            }
            if (rc==3) break;
            switch (direct) {
                case DIRECT_NORTH: yy--; break;
                case DIRECT_EAST:  xx++; break;
                case DIRECT_SOUTH: yy++; break;
                case DIRECT_WEST:  xx--; break;
                default: assert(0);
            }
        }
        ktemperature*=mut;
    }
    printf("\nn_gold_found %d\n",n_gold_found);
    exit_code=0;

Exit:
    qsmm_actor_destroy(actor);
    return exit_code;
}

Next: , Previous: , Up: Top   [Contents][Index]

3 Statistics Storage

Statistics storage holds information on action choice states and cycle types registered by an actor throughout event history. Additionally, statistics storage can hold probability profiles assigned to action choice states.

The function qsmm_actor_create creates statistics storage for an actor. The function qsmm_actor_destroy destroys statistics storage for an actor. The field use_flat_storage of qsmm_actor_desc_s structure passed to the function qsmm_actor_create when creating an actor specifies the type of storage the actor will use—flat storage or map storage.

Storage API functions retrieve or store information on action choice states or cycle types via data structures describing the condition of an action choice state, the condition of a spur type for an action choice state, statistics on a cycle type, and statistics on a spur type for a cycle type. Storage API functions provide means to query the number of spur types supported by storage, to retrieve and store the condition of an action choice state and statistics on a cycle type, to remove information on an action choice state from storage, and to enumerate action choice states and cycle types that have information in storage.

Statistics storage supports setting redirection functions for altering the behavior of storage access operations or intercepting them. Storage redirection functions for obtaining the initial condition of an action choice state, the initial statistics of a cycle type, and the next cycle direction for a cycle type make it possible to generate the probability profile of an action choice state on demand. This approach helps reduce the initial memory footprint of a model and speed up its preparation. QSMM uses those redirection functions internally to implement deferred setting a probability profile for a number of nodes of a multinode model.

Specifying a storage redirection function to intercept updating cycle type statistics makes it possible to organize keeping cycle type statistics for the tail of an event history rather than for the entire event history.


Next: , Up: Statistics Storage   [Contents][Index]

3.1 Storage Types

QSMM supports two types of statistics storage: flat and map. You specify the type of statistics storage of an actor using the field use_flat_storage of qsmm_actor_desc_s structure when creating the actor by the function qsmm_actor_create.

Flat Storage

Flat storage uses preallocated arrays and does not perform memory allocation on writing statistics to the storage. Therefore, the flat storage is fast but may require a huge amount of working memory. To reduce the amount of memory occupied by the flat storage of an actor, specify allowed ranges of signal identifiers in the field range_sig_p of qsmm_actor_desc_s structure as precisely as possible when creating the actor by the function qsmm_actor_create.

Map Storage

Map storage uses binary trees to hold statistics and dynamically allocates working memory when needed. When map storage does not hold probability profiles, it contains information on action choice states and cycle types registered at least once throughout event history. In this case, at the beginning of actor operation the storage occupies a small amount of memory. This amount of memory gradually increases as the actor registers more action choice states and cycle types the first time throughout the event history.

Map storage has two shortcomings. The first is that map storage is slower compared to flat storage. The second is that when map storage holds statistics on all possible action choice states and cycle types, it occupies much more memory than the flat storage would occupy. The second shortcoming is not a hindrance, because not all possible action choice states and cycle types usually occur in the event history, and because the actor usually operates shorter time than it is necessary for a large number of action choice states and cycle types to occur the first time in the event history.

Storage Handle

A storage handle refers to flat or map storage.

Data type: qsmm_storage_t

This is a type for a storage handle. It is a pointer, so variables of this type can be NULL. The function qsmm_get_actor_storage returns the storage handle of an actor. You can pass a returned handle to API functions taking an argument of qsmm_storage_t type until destroying the actor.

Use the following function to query the number of spur types supported by storage referred to by a storage handle.

Function: int qsmm_get_storage_nspur (qsmm_storage_t storage)

This function returns the number of spur types supported by storage. The storage can hold statistics for that number of spur types equal to the number of spur types supported by an actor owning the storage. A returned value is always non-negative.


Next: , Previous: , Up: Statistics Storage   [Contents][Index]

3.2 Structures for Accessing Storage

The following structure holds the condition of an action choice state.

Structure: qsmm_state_s

This structure holds the condition of an action choice state h (see Relative Probability Function Types, for formulas involving h). The structure contains the following fields.

Field: int nsig_pos

This field contains information on the number of cycle types <h,x> (i.e. starting at this action choice state h) with positive profile probabilities assigned, where x is a possible cycle direction. The meanings of various values of this field are below.

0

The action choice state does not have a probability profile specified.

i>1

The number i of types of cycles that start at this action choice state and have positive profile probabilities assigned. At present, an actor uses that number to determine whether to utilize ordinary vectors or sparse vectors to store the relative probabilities of output signals.

i<0

Only one cycle type has a positive profile probability assigned, and -i-1 is equal to the identifier x of an output signal only allowed by the probability profile.

1

Disallowed and causes undefined behavior.

The default value is 0.

Field: long tmd0

The discrete time of last occurrence of a cycle of <h,z> type throughout event history, where the field sig_cycle_next of this structure specifies z. If the field tmd0 is non-negative, and sig_cycle_next is not QSMM_SIG_INVALID, tmd0 indicates the discrete time of last emitting output signal z in action choice state h. The function qsmm_actor_reg_sig_action records that discrete time before incrementing it. The default value of this field is -1.

Field: double tmc0

The continuous time of last occurrence of a cycle of <h,z> type throughout event history, where the field sig_cycle_next of this structure specifies z. That continuous time corresponds to discrete time in the field tmd0 of this structure. If the field tmc0 is non-negative, and sig_cycle_next is not QSMM_SIG_INVALID, tmc0 indicates the continuous time of last emitting output signal z in action choice state h. The function qsmm_actor_reg_sig_action records that continuous time. The default value of this field is -1.

Field: double nsig_ctrl

The nominal number of output signals for the probability profile of this action choice state. See Number of Output Signals, for the explanation of the concept of the nominal number of output signals for an action choice state. If the field nsig_pos of this structure is greater than 1, the field nsig_ctrl must be greater than 1 and less than or equal to nsig_pos. If nsig_pos is 0, nsig_ctrl must be 0. If nsig_pos is negative, nsig_ctrl must be 1. The default value of this field is 0.

Field: qsmm_sig_t sig_cycle_next

An output signal indicating the direction of last cycle started at this action choice state. If no cycles started at this action choice state yet, then QSMM_SIG_INVALID. The default value is QSMM_SIG_INVALID.

The condition of an action choice state includes an array of instances of a structure holding the value of spur recorded by the function qsmm_actor_reg_sig_action for last cycle started at the action choice state. The number of elements in the array is equal to the number of spur types supported by storage.

The structure contains only one field but is designed as a structure to simplify associating other information with an action choice state and a spur type for research purposes. When storage prepares an instance of that structure for first use, it initializes the instance with zeroes by the function memset, so fields you may have added will initially be zero.

The structure description is below.

Structure: qsmm_sspur_s

This structure holds condition associated with an action choice state and a spur type. The structure contains the following field.

Field: double val0

The value of spur recorded for last cycle started at the action choice state, that is, at the latest time when the function qsmm_actor_reg_sig_action registered emitting an output signal in that action choice state.

The following structure holds statistics on a cycle type.

Structure: qsmm_cycle_s

This structure holds statistics on a cycle type—a pair comprised of an action choice state and a cycle direction (i.e. an output signal emittable in the action choice state). In Spur Perception, the notation <h,z> is a cycle type for action choice state h and cycle direction z. The structure contains the following fields.

Field: long fq

The number of cycles of <h,z> type registered throughout event history.

Field: long period_sum_d

The total length of cycles of <h,z> type measured in discrete time. In Spur Perception, the notation ω(h,z)  is that total length measured in discrete or continuous time.

Field: double period_sum_c

The total length of cycles of <h,z> type measured in continuous time. In Spur Perception, the notation ω(h,z)  is that total length measured in discrete or continuous time.

Field: double profile

A profile probability—weight to multiply the relative probability of output signal z selectable in action choice state h. The function qsmm_actor_calc_action_prob uses this field if the field nsig_pos of qsmm_state_s structure holding the condition of action choice state h is non-zero. In this case, the sum of profile probabilities of all cycle types for action choice state h must be equal to 1.

The statistics on a cycle type includes an array of instances of a structure holding the sum of spur increments over cycles of this type. The number of elements in the array is equal to the number of spur types supported by storage.

The structure contains only one field but is designed as a structure to simplify associating other information with a cycle type and a spur type for research purposes. When storage prepares an instance of that structure for first use, it initializes the instance with zeroes by the function memset, so fields you may have added will initially be zero.

The structure description is below.

Structure: qsmm_cspur_s

This structure holds statistics associated with cycle type <h,z> and spur type i. The structure contains the following field.

Field: double delta_sum

The sum of increments of spur of i type over cycles of <h,z> type throughout event history. In Spur Perception, the notation H(h,z)[i] is that sum. Each spur increment is the difference between a spur value at the time of cycle end and a spur value at the time of cycle start stored in the field val0 of qsmm_sspur_s structure.

The time of cycle start is the time of an occurrence of action choice state h with emitting output signal z. The time of cycle end is the time of the next occurrence of action choice state h in the event history.


Next: , Previous: , Up: Statistics Storage   [Contents][Index]

3.3 Retrieving and Storing Statistics

Use the following functions to retrieve or store the condition of an action choice state.

Function: int qsmm_get_storage_state_stats (qsmm_storage_t storage, int ngram_sz, const qsmm_sig_t *sig_ngram_p, struct qsmm_state_s *state_p, struct qsmm_sspur_s *sspur_p)

This function retrieves from storage the condition of an action choice state encoded by an array of signal identifiers sig_ngram_p holding ngram_sz elements. If state_p is not NULL, the function copies the condition to *state_p. If sspur_p is not NULL, the function copies conditions for all spur types associated with the action choice state to an array addressed by sspur_p. The array must be capable of holding the number of elements returned by the function qsmm_get_storage_nspur.

If the storage does not contain the condition of the action choice state, and the storage has a set redirection function for retrieving the initial condition of an action choice state, the function qsmm_get_storage_state_stats calls this redirection function to obtain the initial condition of the action choice state. When validating the field sig_cycle_next of qsmm_state_s structure obtained by this redirection function, the function qsmm_get_storage_state_stats may also call a redirection function for retrieving the initial statistics of a cycle type. See Providing Initial Statistics, for more information on those redirection functions.

If the storage contained the condition of the action choice state, or the storage did not contain the condition, but the redirection function has retrieved it, qsmm_get_storage_state_stats returns a positive value. If the storage did not contain the condition, and the redirection function has not retrieved it, qsmm_get_storage_state_stats returns 0 and the constant default condition. On failure, qsmm_get_storage_state_stats returns a negative error code. Currently, this function can return the following error codes.

QSMM_ERR_INVAL

The storage does not support length ngram_sz for arrays of signal identifiers encoding action choice states.

QSMM_ERR_NGRAM

The storage does not support holding information on an action choice state encoded using sig_ngram_p and valid ngram_sz. A set of action choice states supported by storage is equal to a set of action choice states supported by an actor owning the storage.

QSMM_ERR_STORAGE

The storage did not contain the condition of the action choice state, and a redirection function called to obtain the initial condition of the action choice state has reported QSMM_ERR_STORAGE or an unexpected error code, or the redirection function succeeded, but the function qsmm_get_storage_cycle_stats called to validate the field sig_cycle_next of qsmm_state_s structure obtained by that redirection function has reported QSMM_ERR_STORAGE.

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

QSMM_ERR_STATS

A redirection function for retrieving the initial condition of an action choice state reported QSMM_ERR_STATS, or condition retrieved by this redirection function is inconsistent.

QSMM_ERR_ILSEQ

A redirection function for retrieving the initial condition of an action choice state or the initial statistics of a cycle type reported QSMM_ERR_ILSEQ, or a generated error message is not convertible to a wide string according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Function: int qsmm_set_storage_state_stats (qsmm_storage_t storage, int ngram_sz, const qsmm_sig_t *sig_ngram_p, const struct qsmm_state_s *state_p, const struct qsmm_sspur_s *sspur_p)

This function writes to storage the condition of an action choice state encoded by an array of signal identifiers sig_ngram_p holding ngram_sz elements. If state_p is not NULL, the function copies the condition from *state_p. If sspur_p is not NULL, the function copies conditions for all spur types associated with the action choice state from an array addressed by sspur_p. The function qsmm_get_storage_nspur returns the number of elements of sspur_p array copied.

The function qsmm_set_storage_state_stats may call a redirection function for obtaining the initial condition of an action choice state when adding information on it to the storage. The function qsmm_set_storage_state_stats may also call a redirection function for obtaining the initial statistics of a cycle type when validating the field sig_cycle_next of qsmm_state_s structure. See Providing Initial Statistics, for more information on those redirection functions.

The function qsmm_set_storage_state_stats 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 storage does not support length ngram_sz for arrays of signal identifiers encoding action choice states.

QSMM_ERR_NGRAM

The storage does not support holding information on an action choice state encoded using sig_ngram_p and valid ngram_sz. A set of action choice states supported by storage is equal to a set of action choice states supported by an actor owning the storage.

QSMM_ERR_STORAGE

The function qsmm_get_storage_cycle_stats called to validate the field sig_cycle_next of *state_p or an instance of qsmm_state_s structure obtained by a redirection function for retrieving the initial condition of an action choice state reported QSMM_ERR_STORAGE, or the redirection function reported QSMM_ERR_STORAGE or an unexpected error code.

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

QSMM_ERR_STATS

Inconsistent condition in *state_p, or a redirection function for retrieving the initial condition of an action choice state reported QSMM_ERR_STATS, or condition retrieved by the redirection function is inconsistent.

Condition in qsmm_state_s is inconsistent in the following cases:

  • nsig_pos is equal to 1;
  • nsig_pos is negative, but -nsig_pos-1 is not an output signal of an actor owning the storage;
  • nsig_pos is greater than 1, but nsig_ctrl is less than or equal to 1 or greater than nsig_pos;
  • sig_cycle_next is not QSMM_SIG_INVALID but also not an output signal of an actor owning the storage;
  • sig_cycle_next is not QSMM_SIG_INVALID, and tmd0 is negative;
  • sig_cycle_next is not QSMM_SIG_INVALID, and tmc0 is negative;
  • sig_cycle_next is not QSMM_SIG_INVALID, nsig_pos is not 0, and the function qsmm_get_storage_cycle_stats called to check the presence of statistics on a cycle type for the action choice state and cycle direction sig_cycle_next returned 0 or reported QSMM_ERR_STATS.
QSMM_ERR_ILSEQ

A redirection function for retrieving the initial condition of an action choice state or the initial statistics of a cycle type reported QSMM_ERR_ILSEQ, or a generated error message is not convertible to a wide string according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

On errors QSMM_ERR_STORAGE, QSMM_ERR_STATS, QSMM_ERR_ILSEQ, and QSMM_ERR_NOMEM, the function may leave the condition of the action choice state updated in an unexpected way.

To update the condition of an action choice state, you first need to retrieve existing condition by the function qsmm_get_storage_state_stats, then change some fields, and, finally, store the condition by the function qsmm_set_storage_state_stats. For example, you can update the parameters of the probability profile of an action choice state to new values nsig_pos and nsig_ctrl using a block of code like this:

int rc;
struct qsmm_state_s state;
if ((rc=
     qsmm_get_storage_state_stats(storage, ngram_sz, sig_ngram_p,
                                  &state, 0))<0)
    REPORT_ERROR(rc);
state.nsig_pos=nsig_pos;
state.nsig_ctrl=nsig_ctrl;
if ((rc=
     qsmm_set_storage_state_stats(storage, ngram_sz, sig_ngram_p,
                                  &state, 0))<0)
    REPORT_ERROR(rc);

Use the following functions to retrieve or store statistics on a cycle type.

Function: int qsmm_get_storage_cycle_stats (qsmm_storage_t storage, int ngram_sz, const qsmm_sig_t *sig_ngram_p, qsmm_sig_t sig_cycle, struct qsmm_cycle_s *cycle_p, struct qsmm_cspur_s *cspur_p)

This function retrieves statistics on a cycle type from storage. An action choice state and cycle direction sig_cycle specify the cycle type. An array of signal identifiers sig_ngram_p holding ngram_sz elements encodes the action choice state.

If cycle_p is not NULL, the function copies the statistics to *cycle_p. If cspur_p is not NULL, the function copies statistics on all spur types associated with the cycle type to an array addressed by cspur_p. The array must be capable of holding the number of elements returned by the function qsmm_get_storage_nspur.

If the storage does not contain statistics on the cycle type, and the storage has a set redirection function for retrieving the initial statistics of a cycle type, the function qsmm_get_storage_cycle_stats calls this redirection function to obtain initial statistics on the cycle type. See Providing Initial Statistics, for more information on this redirection function.

If the storage contained statistics on the cycle type, or the storage did not contain the statistics, but the redirection function has retrieved it, qsmm_get_storage_cycle_stats returns a positive value. If the storage did not contain the statistics, and the redirection function has not retrieved it, qsmm_get_storage_cycle_stats returns 0 and zero statistics. On failure, qsmm_get_storage_cycle_stats returns a negative error code. Currently, this function can return the following error codes.

QSMM_ERR_INVAL

The storage does not support length ngram_sz for arrays of signal identifiers encoding action choice states, or signal sig_cycle is not an output signal of an actor owning the storage.

QSMM_ERR_NGRAM

The storage does not support holding information on an action choice state encoded using sig_ngram_p and valid ngram_sz. A set of action choice states supported by storage is equal to a set of action choice states supported by an actor owning the storage.

QSMM_ERR_STORAGE

The storage did not contain statistics on the cycle type, and a redirection function called to obtain initial statistics on the cycle type has reported QSMM_ERR_STORAGE or an unexpected error code. See Getting the Reason of a Storage Failure, for how to get an error message describing the failure.

QSMM_ERR_STATS

A redirection function for retrieving the initial statistics of a cycle type reported QSMM_ERR_STATS, or statistics retrieved by this redirection function is inconsistent.

QSMM_ERR_ILSEQ

A redirection function for retrieving the initial statistics of a cycle type reported QSMM_ERR_ILSEQ, or a generated error message is not convertible to a wide string according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Function: int qsmm_set_storage_cycle_stats (qsmm_storage_t storage, int ngram_sz, const qsmm_sig_t *sig_ngram_p, qsmm_sig_t sig_cycle, const struct qsmm_cycle_s *cycle_p, const struct qsmm_cspur_s *cspur_p)

This function writes statistics on a cycle type to storage. An action choice state and cycle direction sig_cycle specify the cycle type. An array of signal identifiers sig_ngram_p holding ngram_sz elements encodes the action choice state.

If cycle_p is not NULL, the function copies the statistics from *cycle_p. If cspur_p is not NULL, the function copies statistics for all spur types associated with the cycle type from an array addressed by cspur_p. The function qsmm_get_storage_nspur returns the number of elements of cspur_p array copied.

The function qsmm_set_storage_cycle_stats calls a redirection function for the interception of updating statistics on a cycle type if the storage has such redirection function set. See Intercepting the Updates of Cycle Type Statistics, for more information on this redirection function. The function qsmm_set_storage_cycle_stats may call redirection functions for obtaining the initial condition of an action choice state or the initial statistics of a cycle type when adding information on it to the storage. See Providing Initial Statistics, for more information on these redirection functions.

The function qsmm_set_storage_cycle_stats 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 storage does not support length ngram_sz for arrays of signal identifiers encoding action choice states, or signal sig_cycle is not an output signal of an actor owning the storage.

QSMM_ERR_NGRAM

The storage does not support holding information on an action choice state encoded using sig_ngram_p and valid ngram_sz. A set of action choice states supported by storage is equal to a set of action choice states supported by an actor owning the storage.

QSMM_ERR_STORAGE

A storage redirection function reported QSMM_ERR_STORAGE or an unexpected error code. See Getting the Reason of a Storage Failure, for how to get an error message describing the failure.

QSMM_ERR_STATS

Inconsistent statistics in *cycle_p, or a storage redirection function reported QSMM_ERR_STATS, or statistics obtained from a storage redirection function is inconsistent.

Statistics in qsmm_cycle_s is inconsistent in the following cases:

  • fq is negative;
  • period_sum_d is negative;
  • period_sum_c is negative;
  • profile is negative or greater than 1;
  • fq is zero, but period_sum_d is positive;
  • fq is zero, but period_sum_c is positive.
QSMM_ERR_ILSEQ

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

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

On errors QSMM_ERR_STORAGE, QSMM_ERR_STATS, QSMM_ERR_ILSEQ, and QSMM_ERR_NOMEM, the function may leave the condition of the action choice state or the statistics of the cycle type updated in an unexpected way.

To update statistics on a cycle type, you first need to retrieve existing statistics by the function qsmm_get_storage_cycle_stats, then change some fields, and, finally, store the statistics by the function qsmm_set_storage_cycle_stats. For example, you can update a profile probability4 for a cycle type to a new value profile using a block of code like this:

int rc;
struct qsmm_cycle_s cycle;
if ((rc=
     qsmm_get_storage_cycle_stats(storage, ngram_sz, sig_ngram_p,
                                  sig_cycle, &cycle, 0))<0)
    REPORT_ERROR(rc);
cycle.profile=profile;
if ((rc=
     qsmm_set_storage_cycle_stats(storage, ngram_sz, sig_ngram_p,
                                  sig_cycle, &cycle, 0))<0)
    REPORT_ERROR(rc);

At present, an actor uses storage to hold statistics on action choice states encoded by arrays of signal identifiers with a fixed number of elements. The argument ngram_sz of Storage API functions must be equal to this fixed length. In the future, storage may hold statistics on action choice states encoded by arrays of signal identifiers with varying lengths, so that argument may have multiple valid values.

Use the following function to remove information on an action choice state from storage.

Function: int qsmm_storage_remove_state (qsmm_storage_t storage, int ngram_sz, const qsmm_sig_t *sig_ngram_p)

This function removes from storage information on an action choice state encoded by an array of signal identifiers sig_ngram_p holding ngram_sz elements. The information includes the condition of this action choice state and statistics on all types of cycles starting at the action choice state. For map storage, the function frees memory allocated for holding that information.

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 storage does not support length ngram_sz for arrays of signal identifiers encoding action choice states.

QSMM_ERR_NGRAM

The storage does not support holding information on an action choice state encoded using sig_ngram_p and valid ngram_sz. A set of action choice states supported by storage is equal to a set of action choice states supported by an actor owning the storage.

QSMM_ERR_NOTFOUND

Information on the action choice state not found in the storage—nothing to remove.


Next: , Previous: , Up: Statistics Storage   [Contents][Index]

3.4 Enumerating Action Choice States and Cycle Types

Use the following function to enumerate action choice states that have pieces of information held in storage.

Function: int qsmm_storage_enum_states (qsmm_storage_t storage, int ngram_prefix_sz, const qsmm_sig_t *sig_ngram_prefix_p, qsmm_enum_state_callback_func_t callback_func, void *paramp)

This function enumerates action choice states that have pieces of information held in storage. The function enumerates action choice states encoded by lists of signal identifiers that have a prefix sig_ngram_prefix_p with length ngram_prefix_sz. If ngram_prefix_sz is 0, then sig_ngram_prefix_p can be NULL.

The process of enumeration is repeated calling a callback function callback_func receiving an array of signal identifiers encoding an action choice state and receiving a user parameter paramp. If the callback function returns a positive value, the function qsmm_storage_enum_states continues the enumeration. If the callback function returns zero, qsmm_storage_enum_states terminates the enumeration and reports success. If the callback function returns a negative value, qsmm_storage_enum_states terminates the enumeration and reports failure.

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 ngram_prefix_sz is less than 0 or greater than the length of a list of signal identifiers encoding an action choice state.

QSMM_ERR_CALLBACK

The callback function reported an error.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

The type of a pointer to a callback function called for every enumerated action choice state is below.

Data type: qsmm_enum_state_callback_func_t

This is a type of a callback function pointer with the following declaration:

typedef int
(*qsmm_enum_state_callback_func_t)(
    qsmm_storage_t storage,
    int ngram_sz,
    const qsmm_sig_t *sig_ngram_p,
    void *paramp
);

The function qsmm_storage_enum_states calls the callback function for every enumerated action choice state of storage. The argument sig_ngram_p specifies an array of signal identifiers encoding an action choice state. The argument ngram_sz specifies the length of this array. The argument paramp is a user parameter passed to qsmm_storage_enum_states.

The callback function shall return a positive value to continue the process of enumeration, zero to terminate the process of enumeration, or a negative value on error.

Use a function described below to enumerate the types of cycles starting at an action choice state. A cycle direction and the action choice state make up an enumerated cycle type.

Function: int qsmm_get_storage_cycle_next (qsmm_storage_t storage, int ngram_sz, const qsmm_sig_t *sig_ngram_p, qsmm_sig_t *sig_cycle_next_p)

This function retrieves the next cycle type that has a piece of information held in storage. An action choice state and a cycle direction specify the cycle type. An array of signal identifiers sig_ngram_p holding ngram_sz elements encodes the action choice state.

If *sig_cycle_next_p is QSMM_SIG_INVALID, then on successful function completion, *sig_cycle_next_p will contain the first minimum cycle direction. If *sig_cycle_next_p is not QSMM_SIG_INVALID, then on successful function completion, *sig_cycle_next_p will contain the next cycle direction greater than a cycle direction specified in *sig_cycle_next_p when calling the function. If the first or next cycle direction does not exist, then on successful function completion, *sig_cycle_next_p will be QSMM_SIG_INVALID.

If the storage has a set redirection function for retrieving the next cycle type of an action choice state, the function qsmm_get_storage_cycle_next calls the redirection function to obtain the next cycle type. If the redirection function reports that it has not retrieved the next cycle type, qsmm_get_storage_cycle_next proceeds as if the storage does not have such redirection function set.

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 storage does not support length ngram_sz for arrays of signal identifiers encoding action choice states.

QSMM_ERR_NGRAM

The storage does not support holding information on an action choice state encoded using sig_ngram_p and valid ngram_sz. A set of action choice states supported by storage is equal to a set of action choice states supported by an actor owning the storage.

QSMM_ERR_STORAGE

The storage redirection function reported QSMM_ERR_STORAGE or an unexpected error code. See Getting the Reason of a Storage Failure, for how to get an error message describing the failure.

QSMM_ERR_STATS

The storage redirection function reported QSMM_ERR_STATS, or a cycle direction obtained by that redirection function is not QSMM_SIG_INVALID and is not an output signal of an actor owning the storage.

QSMM_ERR_ILSEQ

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

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.


Next: , Previous: , Up: Statistics Storage   [Contents][Index]

3.5 Providing Initial Statistics

Before first use, Storage API functions initialize by the function memset with zeroes the instances of qsmm_state_s, qsmm_sspur_s, qsmm_cycle_s, and qsmm_cspur_s structures holding conditions for action choice states and statistics on cycle types. For every instance of qsmm_state_s structure, the Storage API functions also perform the following assignments: set the fields tmd0 and tmc0 to -1 and the field sig_cycle_next to QSMM_SIG_INVALID.

An application program can provide redirection functions called by the Storage API functions just after the above initialization. Those redirection functions may perform application-specific initialization. The Storage API functions will call those functions on accessing condition for an action choice state or statistics on a cycle type when storage does not contain requested information about the action choice state or the cycle type.

Storage redirection functions performing application-specific initialization may set the parameters of a probability profile for an action choice state. They may also call Storage API functions for other action choice states, for example, to copy the parameters of a probability profile from another action choice state.

Data type: qsmm_get_state_stats_func_t

This is the type of a pointer to a redirection function for application-specific initialization of condition of an action choice state. The type has the following declaration:

typedef int
(*qsmm_get_state_stats_func_t)(
    qsmm_storage_t storage,
    int ngram_sz,
    const qsmm_sig_t *sig_ngram_p,
    struct qsmm_state_s *state_p,
    struct qsmm_sspur_s *sspur_p,
    void *paramp
);

The argument storage is a storage handle with this redirection function set. On calling this function, *state_p and the array sspur_p contain preinitialized values. The function can set *state_p and/or elements of sspur_p array to application-specific initial condition for an action choice state. An array of signal identifiers sig_ngram_p holding ngram_sz elements encodes the action choice state. The elements of sspur_p array correspond to spur types supported by the storage. The function qsmm_get_storage_nspur returns the number of those elements in the array. The argument paramp is a user parameter specified when setting the redirection function for the storage.

If the function has performed the redirection and possibly modified the preinitialized values in *state_p or the array sspur_p, the function shall return a positive result. If the function has not performed the redirection and has left those preinitialized values intact, the function shall return 0. On failure, the function shall return one of the following negative error codes.

QSMM_ERR_STORAGE

Storage failure. Before reporting this error, the function shall add to the storage message list at least one message describing the reason of the failure. See Getting the Reason of a Storage Failure, for more information on the storage message list.

QSMM_ERR_STATS

Inconsistent statistics on an action choice state or cycle type detected.

QSMM_ERR_ILSEQ

Unable to convert a multibyte string to a wide string or vice versa according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Use the following functions to retrieve or set a redirection function for application-specific initialization of condition of an action choice state.

Function: int qsmm_get_storage_state_stats_redir (qsmm_storage_t storage, qsmm_get_state_stats_func_t *get_state_stats_func_p, void **param_pp)

This function retrieves a previously set redirection function for application-specific initialization of conditions of action choice states in storage. If get_state_stats_func_p is not NULL, the function qsmm_get_storage_state_stats_redir sets *get_state_stats_func_p to a pointer to the redirection function or to NULL if the storage does not have such function assigned. If param_pp is not NULL, qsmm_get_storage_state_stats_redir sets *param_pp to a user parameter of that redirection function specified when assigning it to the storage. The function qsmm_get_storage_state_stats_redir returns a non-negative value.

Function: int qsmm_set_storage_state_stats_redir (qsmm_storage_t storage, qsmm_get_state_stats_func_t get_state_stats_func, void *paramp)

This function sets a redirection function for application-specific initialization of conditions of action choice states in storage. The argument get_state_stats_func specifies a pointer to the redirection function. The argument paramp specifies the user parameter of that redirection function. If get_state_stats_func is NULL, then the storage will not use a redirection function for application-specific initialization of conditions of action choice states. The function qsmm_set_storage_state_stats_redir returns a non-negative value.

Data type: qsmm_get_cycle_stats_func_t

This is the type of a pointer to a redirection function for application-specific initialization of statistics on a cycle type. The pointer type has the following declaration:

typedef int
(*qsmm_get_cycle_stats_func_t)(
    qsmm_storage_t storage,
    int ngram_sz,
    const qsmm_sig_t *sig_ngram_p,
    qsmm_sig_t sig_cycle,
    struct qsmm_cycle_s *cycle_p,
    struct qsmm_cspur_s *cspur_p,
    void *paramp
);

The argument storage is a storage handle with this redirection function set. On calling this function, *cycle_p and the array cspur_p contain preinitialized values. The function can set *cycle_p and/or elements of cspur_p array to application-specific initial statistics on a cycle type. An action choice state and output signal sig_cycle indicating a cycle direction specify the cycle type. An array of signal identifiers sig_ngram_p holding ngram_sz elements encodes the action choice state. The elements of cspur_p array correspond to spur types supported by the storage. The function qsmm_get_storage_nspur returns the number of those elements in the array. The argument paramp is a user parameter specified when setting the redirection function for the storage.

If the function has performed the redirection and possibly modified the preinitialized values in *cycle_p or the array cspur_p, the function shall return a positive result. If the function has not performed the redirection and has left those preinitialized values intact, the function shall return 0. On failure, the function shall return one of the following negative error codes.

QSMM_ERR_STORAGE

Storage failure. Before reporting this error, the function shall add to the storage message list at least one message describing the reason of the failure. See Getting the Reason of a Storage Failure, for more information on the storage message list.

QSMM_ERR_STATS

Inconsistent statistics on an action choice state or cycle type detected.

QSMM_ERR_ILSEQ

Unable to convert a multibyte string to a wide string or vice versa according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Use the following functions to retrieve or set a redirection function for application-specific initialization of statistics on a cycle type.

Function: int qsmm_get_storage_cycle_stats_redir (qsmm_storage_t storage, qsmm_get_cycle_stats_func_t *get_cycle_stats_func_p, void **param_pp)

This function retrieves a previously set redirection function for application-specific initialization of statistics on cycle types in storage. If get_cycle_stats_func_p is not NULL, the function qsmm_get_storage_cycle_stats_redir sets *get_cycle_stats_func_p to a pointer to the redirection function or to NULL if the storage does not have such function assigned. If param_pp is not NULL, qsmm_get_storage_cycle_stats_redir sets *param_pp to a user parameter of that redirection function specified when assigning it to the storage. The function qsmm_get_storage_cycle_stats_redir returns a non-negative value.

Function: int qsmm_set_storage_cycle_stats_redir (qsmm_storage_t storage, qsmm_get_cycle_stats_func_t get_cycle_stats_func, void *paramp)

This function sets a redirection function for application-specific initialization of statistics on cycle types in storage. The argument get_cycle_stats_func specifies a pointer to the redirection function. The argument paramp specifies the user parameter of that redirection function. If get_cycle_stats_func is NULL, then the storage will not use a redirection function for application-specific initialization of statistics on cycle types. The function qsmm_set_storage_cycle_stats_redir returns a non-negative value.

If an application sets a redirection function for custom initialization of statistics on cycle types, the application may need to provide a redirection function for retrieving the next cycle type for an action choice state. The latter redirection function will enable correct enumeration of cycle types with initial statistics provided by the former redirection function. Enumerating cycle types that do not yet have information in storage is necessary for generating the probability profiles of action choice states on demand—on read access to information on action choice states and their cycle types before the first write access to this information.

Data type: qsmm_get_cycle_next_func_t

This is the type of a pointer to a redirection function for retrieving the next cycle type for an action choice state. The pointer type has the following declaration:

typedef int
(*qsmm_get_cycle_next_func_t)(
    qsmm_storage_t storage,
    int ngram_sz,
    const qsmm_sig_t *sig_ngram_p,
    qsmm_sig_t *sig_cycle_next_p,
    void *paramp
);

The argument storage is a storage handle with this redirection function set passed to the function qsmm_get_storage_cycle_next. The array of signal identifiers sig_ngram_p holding ngram_sz elements encodes the action choice state. The argument paramp is a user parameter specified when setting the redirection function for the storage.

If *sig_cycle_next_p is QSMM_SIG_INVALID, then on successfully performed redirection, *sig_cycle_next_p shall contain a minimum output signal that along with the action choice state specify the first cycle type for that action choice state. If *sig_cycle_next_p is not QSMM_SIG_INVALID, then on successfully performed redirection, *sig_cycle_next_p shall contain the next output signal greater than a signal specified in *sig_cycle_next_p when calling the redirection function; that output signal along with the action choice state shall specify the next cycle type for the action choice state. If the first or next cycle type does not exist, then on successful function completion, *sig_cycle_next_p shall be QSMM_SIG_INVALID.

If the function has performed the redirection and possibly updated *sig_cycle_next_p, the function shall return a positive value. If the function has not performed the redirection and has left *sig_cycle_next_p intact, the function shall return 0; in this case, qsmm_get_storage_cycle_next retrieves the next cycle type without the redirection. On failure, the redirection function shall return one of the following negative error codes.

QSMM_ERR_STORAGE

Storage failure. Before reporting this error, the function shall add to the storage message list at least one message describing the reason of the failure. See Getting the Reason of a Storage Failure, for more information on the storage message list.

QSMM_ERR_STATS

Inconsistent statistics on an action choice state or cycle type detected.

QSMM_ERR_ILSEQ

Unable to convert a multibyte string to a wide string or vice versa according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Use the following functions to retrieve or set a redirection function for obtaining the next cycle type for an action choice state.

Function: int qsmm_get_storage_cycle_next_redir (qsmm_storage_t storage, qsmm_get_cycle_next_func_t *get_cycle_next_func_p, void **param_pp)

This function retrieves a previously set redirection function for obtaining the next cycle type that has a piece of information in storage. If get_cycle_next_func_p is not NULL, the function qsmm_get_storage_cycle_next_redir sets *get_cycle_next_func_p to a pointer to the redirection function or to NULL if the storage does not have such function assigned. If param_pp is not NULL, qsmm_get_storage_cycle_next_redir sets *param_pp to a user parameter of that redirection function specified when assigning it to the storage. The function qsmm_get_storage_cycle_next_redir returns a non-negative value.

Function: int qsmm_set_storage_cycle_next_redir (qsmm_storage_t storage, qsmm_get_cycle_next_func_t get_cycle_next_func, void *paramp)

This function sets a redirection function for obtaining the next cycle type that has a piece of information in storage. The argument get_cycle_next_func specifies a pointer to the redirection function. The argument paramp specifies the user parameter of that redirection function. If get_cycle_next_func is NULL, then the storage will not use a redirection function for obtaining the next cycle type. The function qsmm_set_storage_cycle_next_redir returns a non-negative value.


Next: , Previous: , Up: Statistics Storage   [Contents][Index]

3.6 Intercepting the Updates of Cycle Type Statistics

Intercepting the updates of statistics on cycle types may be necessary to organize keeping this statistics only for latest events in an event history rather than for the entire event history. Keeping statistics just for the tail of the event history may improve the response of a system to latest tendencies in the event history. Using a different methodology, by making a state model less stable, the system can try more state model variations and then select a variation that occurs more frequently.

The function qsmm_set_storage_cycle_stats calls a storage redirection function for intercepting the updates of statistics on cycle types if storage has such redirection function set. The type of a pointer to the redirection function is below.

Data type: qsmm_update_cycle_stats_func_t

This is the type of a pointer to a redirection function for intercepting the updates of statistics on cycle types. The pointer type has the following declaration:

typedef int
(*qsmm_update_cycle_stats_func_t)(
    qsmm_storage_t storage,
    int ngram_sz,
    const qsmm_sig_t *sig_ngram_p,
    qsmm_sig_t sig_cycle,
    const struct qsmm_cycle_s *cycle_new_p,
    struct qsmm_cycle_s *cycle_result_p,
    const struct qsmm_cspur_s *cspur_new_p,
    struct qsmm_cspur_s *cspur_result_p,
    void *paramp
);

The argument storage is a storage handle with this redirection function set passed to the function qsmm_set_storage_cycle_stats. An action choice state and output signal sig_cycle indicating a cycle direction specify a cycle type. An array of signal identifiers sig_ngram_p holding ngram_sz elements encodes the action choice state.

New statistics on the cycle type is in *cycle_new_p and the array cspur_new_p. On calling the function, current statistics on the cycle type is in *cycle_result_p and the array cspur_result_p. The arrays cspur_new_p and cspur_result_p hold the number of elements returned by the function qsmm_get_storage_nspur. The redirection function can compute the difference between *cycle_new_p and *cycle_result_p and between the elements of cspur_new_p and cspur_result_p.

To directly use *cycle_result_p and the array cspur_result_p as the new statistics on the cycle type, the function shall return a positive value; in this case, the function can change *cycle_result_p and the array cspur_result_p in its own way. To replace *cycle_result_p with *cycle_new_p, replace the elements of cspur_result_p with the elements of cspur_new_p, and use *cycle_result_p and the array cspur_result_p as the new statistics on the cycle type, the function shall return 0. On failure, the function shall return one of the following negative error codes.

QSMM_ERR_STORAGE

Storage failure. Before reporting this error, the function shall add to the storage message list at least one message describing the reason of the failure. See Getting the Reason of a Storage Failure, for more information on the storage message list.

QSMM_ERR_STATS

Inconsistent statistics on an action choice state or cycle type detected.

QSMM_ERR_ILSEQ

Unable to convert a multibyte string to a wide string or vice versa according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

To organize keeping statistics on cycle types for the event history tail, a storage redirection function intercepting the updates of statistics on cycle types keeps a queue of records, where every record contains the following information about an update of statistics on a cycle type:

The redirection function does the following:

  1. Prevents recursive calls to itself when calling the function qsmm_set_storage_cycle_stats to decrement statistics on cycle types.
  2. Removes too old records from the queue with decrementing statistics on cycle types specified by removed records and with decrementing spur accumulated by the actor. A removed record contains differences to statistics on the cycle type and a difference to spur tracked by the actor relative to the previously added record. After removing the old records, storage contains statistics on cycle types and the actor holds spur only for the event history tail.
  3. Adds a new record to the queue.

Use the following functions to retrieve or set a redirection function for intercepting the updates of statistics on cycle types.

Function: int qsmm_get_storage_cycle_update_hook (qsmm_storage_t storage, qsmm_update_cycle_stats_func_t *update_cycle_stats_func_p, void **param_pp)

This function retrieves a previously set redirection function for intercepting the updates of statistics on cycle types by the function qsmm_set_storage_cycle_stats called for storage. If update_cycle_stats_func_p is not NULL, the function qsmm_get_storage_cycle_update_hook sets *update_cycle_stats_func_p to a pointer to the redirection function or to NULL if the storage does not have such function assigned. If param_pp is not NULL, qsmm_get_storage_cycle_update_hook sets *param_pp to a user parameter of that redirection function specified when assigning it to the storage. The function qsmm_get_storage_cycle_update_hook returns a non-negative value.

Function: int qsmm_set_storage_cycle_update_hook (qsmm_storage_t storage, qsmm_update_cycle_stats_func_t update_cycle_stats_func, void *paramp)

This function sets a redirection function for intercepting the updates of statistics on cycle types by the function qsmm_set_storage_cycle_stats called for storage. The argument update_cycle_stats_func specifies a pointer to the redirection function. The argument paramp specifies the user parameter of that redirection function. If update_cycle_stats_func is NULL, then the storage will not use a redirection function for intercepting the updates of statistics on cycle types. The function qsmm_set_storage_cycle_update_hook returns a non-negative value.


Next: , Previous: , Up: Statistics Storage   [Contents][Index]

3.7 Getting the Reason of a Storage Failure

When a Storage API function returns error code QSMM_ERR_STORAGE, the function clears a storage message list and adds to it at least one message describing a failure.

A handle of qsmm_msglist_t type represents a message list. See Messages and Message Lists, for how to work with message lists. Use the following function to obtain a message list associated with storage.

Function: qsmm_msglist_t qsmm_get_storage_msglist (qsmm_storage_t storage)

This function returns the handle of a message list associated with storage. The function never returns NULL.

To dump to stderr the message list of storage in an application program with an executable named prg_name, use lines of code like these:

const int rc=qsmm_msglist_dump(qsmm_get_storage_msglist(storage),
                               prg_name, 0, 0, stderr);
if (rc<0) REPORT_ERROR(rc);

If an Actor API function returns error code QSMM_ERR_STORAGE, and the actor is the small one, the message list of storage owned by that actor contains at least one message describing a storage failure. Use the function qsmm_get_actor_storage to get the handle of storage owned by the small actor.

If an Actor API function returns error code QSMM_ERR_STORAGE, and the actor is the large one, then failed storage can be the storage of that actor itself or the storage of an associated small actor representing the environment state identification engine or the storage of an associated small actor representing the instruction emitting engine. Provided that all storage message lists were empty before calling the Actor API function, one of them is non-empty and contains a message describing the failure.

The following function returns the handle of failed storage of a small or large actor or NULL if the storage message lists are empty:

qsmm_storage_t
get_err_storage(
    qsmm_actor_t actor
) {
    qsmm_storage_t storage=qsmm_get_actor_storage(actor);
    if (qsmm_get_msglist_sz(qsmm_get_storage_msglist(storage))) return storage;
    const qsmm_t qsmm_large=qsmm_get_actor_large_model(actor);
    if (!qsmm_large) return 0;
    const qsmm_actpair_t actpair=qsmm_get_actpair(qsmm_large);
    if ((storage=get_err_storage(qsmm_get_actpair_actor_env(actpair)))) return storage;
    if ((storage=get_err_storage(qsmm_get_actpair_actor_opt(actpair)))) return storage;
    return 0;
}

Previous: , Up: Statistics Storage   [Contents][Index]

3.8 Example of Using the Storage API

When working with an actor, a helpful feature would be the ability to save the state of the actor to a file and restore that state from the file later. This is not a built-in feature, but a developer can program it using the Actor and Storage APIs. Example functions actor_save and actor_load for saving and loading the state of a small actor are available in the file samples/load_save.c in the package distribution. This section includes them too.

The function actor_save saves the following information for a small actor:

  1. The mode of behavior: adaptive or random.
  2. The number of signals.
  3. The number of spur types.
  4. The length of a signal list encoding an action choice state.
  5. The index of a spur type for the automatic spur.
  6. Discrete time.
  7. Continuous time.
  8. The number of output signals emitted per one unit of discrete time passed.
  9. The nominal number of output signals.
  10. Actor temperature.
  11. The ranges of signals in a list encoding an action choice state. For every range, the function saves the following information:
    1. Minimum allowed signal identifier.
    2. Maximum allowed signal identifier.
  12. Spur type parameters. For every spur type, the function saves the following information:
    1. Spur value.
    2. Spur weight.
    3. The way of spur perception: normal or inverse.
    4. The type of time for computing spur increment velocity: discrete or continuous.
  13. Output signal weights. For every output signal, the function saves the following information:
    1. Signal identifier.
    2. Signal weight.
  14. The content of the buffer for an n-gram of signals from the event history.
  15. Information on action choice states held in statistics storage. For every action choice state, the callback function wr_acstate saves the following information:
    1. Signal list encoding the action choice state.
    2. The condition of the action choice state itself.
    3. The condition of every spur type for the action choice state.
    4. Cycle type statistics. For every cycle type, the callback function wr_acstate saves the following information:
      1. Cycle direction.
      2. Statistics on the cycle type itself.
      3. Statistics on every spur type for the cycle type.

The functions actor_save and actor_load do not save and load the following parameters:

  1. The type of a function returning the relative probability of an output signal. The function qsmm_get_actor_relprob_type queries that type. The function qsmm_set_actor_relprob_type sets that type.
  2. A helper function for computing the relative probability of an output signal. The function qsmm_get_actor_relprob_helper retrieves the helper function. The function qsmm_set_actor_relprob_helper sets the helper function.
  3. The content of the internal array holding the relative probabilities of output signals. The function qsmm_get_actor_choice_sig_prob returns a pointer to the array. The function qsmm_actor_choice_sig_prob_release releases the pointer after accessing the array. The function qsmm_get_actor_choice_sig_prob_vec returns a read-only view of that array as an ordinary or sparse vector.
  4. The content of the pool of probabilities lists in normal form. The function qsmm_actor_profile_add adds a probabilities list to the pool.
  5. The content of the pool of permutations of output signals. The functions qsmm_actor_profile_add and qsmm_actor_permut_add add a permutation of output signals to the pool.
  6. Preloaded probability profiles assigned to action choice states. The function qsmm_get_actor_ngram_profile queries a preloaded probability profile assigned to an action choice state. The function qsmm_set_actor_ngram_profile assigns a preloaded probability profile to an action choice state.
  7. Last discrete cycle period. The function qsmm_get_actor_discrete_cycle_period_last returns this cycle period.
  8. Mean discrete cycle period. The function qsmm_get_actor_discrete_cycle_period_mean returns this cycle period.
  9. Storage redirection functions if used. The functions qsmm_get_storage_state_stats_redir, qsmm_get_storage_cycle_stats_redir, qsmm_get_storage_cycle_next_redir, and qsmm_get_storage_cycle_update_hook retrieve those storage redirection functions. The functions qsmm_set_storage_state_stats_redir, qsmm_set_storage_cycle_stats_redir, qsmm_set_storage_cycle_next_redir, and qsmm_set_storage_cycle_update_hook set those storage redirection functions.

The function actor_save saves the state of a small actor to a file. That function returns 0 on success or prints an error message to stderr and returns -1 on failure.

The function actor_load loads the state of an existing small actor from a file. The existing actor must have the following parameters set equal to parameters contained in the file:

  1. The number of signals.
  2. The number of spur types.
  3. The length of a signal list encoding an action choice state.
  4. The ranges of signals in a list encoding an action choice state.
  5. The set of identifiers of output signals.

The function actor_load adds information on action choice states read from a file to storage. That function does not clear existing information on action choice states in the storage. The function returns 0 on success or prints an error message to stderr and returns -1 on failure.

#include <math.h>
#include <stdlib.h>
#include <string.h>

#include <qsmm/qsmm.h>


#define ERREXIT(fmt, ...)                                                 \
    do {                                                                  \
        fprintf(stderr,"%s: " fmt "\n", prg_name, ## __VA_ARGS__);        \
        goto Exit;                                                        \
    }                                                                     \
    while (0)


#define ERRFILE(fmt, ...) ERREXIT("%s: " fmt, fln, ## __VA_ARGS__);


#define CHK_FAIL(func, ...)                                               \
    do {                                                                  \
        const int rc=func(__VA_ARGS__);                                   \
        if (rc<0) ERREXIT(#func ": %s", qsmm_err_str(rc));                \
    }                                                                     \
    while (0)


#define READ(var)                                                         \
    do {                                                                  \
        if (fread(&(var),sizeof(var),1,filep)!=1) ERRFILE("read error");  \
    }                                                                     \
    while (0)


#define WRITE(var)                                                        \
    do {                                                                  \
        if (fwrite(&(var),sizeof(var),1,filep)!=1)                        \
            ERRFILE("write error");                                       \
    }                                                                     \
    while (0)


struct wr_acstate_param_s {

    const char *prg_name;  // program name
    const char *fln;       // output stream file name;

    FILE       *filep;     // output stream
};


// Write the condition of an enumerated action choice state and
// statistics on its cycle types to a stream.
// Returns: 1 = success;
//         -1 = failure.

static int
wr_acstate(
    qsmm_storage_t storage,
    int ngram_sz,
    const qsmm_sig_t *sig_ngram_p,
    void *paramp
) {
    int spur_type, result=-1;
    struct wr_acstate_param_s *const param_p=paramp;
    const char *const prg_name=param_p->prg_name, *const fln=param_p->fln;
    FILE *const filep=param_p->filep;
    WRITE(ngram_sz);
    for (int ii=0; ii<ngram_sz; ii++) WRITE(sig_ngram_p[ii]);
    const int nspur=qsmm_get_storage_nspur(storage);
    {
        struct qsmm_state_s state;
        struct qsmm_sspur_s sspur[nspur];
        CHK_FAIL(qsmm_get_storage_state_stats, storage,
                 ngram_sz, sig_ngram_p, &state, sspur);
        WRITE(state);
        for (spur_type=0; spur_type<nspur; spur_type++)
            WRITE(sspur[spur_type]);
    }
    qsmm_sig_t sig=QSMM_SIG_INVALID;
    while (1) {
        CHK_FAIL(qsmm_get_storage_cycle_next, storage,
                 ngram_sz, sig_ngram_p, &sig);
        WRITE(sig);
        if (sig==QSMM_SIG_INVALID) break;
        struct qsmm_cycle_s cycle;
        struct qsmm_cspur_s cspur[nspur];
        CHK_FAIL(qsmm_get_storage_cycle_stats, storage,
                 ngram_sz, sig_ngram_p, sig, &cycle, cspur);
        WRITE(cycle);
        for (spur_type=0; spur_type<nspur; spur_type++)
            WRITE(cspur[spur_type]);
    }
    result=1;

Exit:
    return result;
}


// Save the state of a small actor to a file.
// Returns: 0 = success;
//         -1 = failure.

int
actor_save(
    const char *prg_name,
    const char *fln,
    qsmm_actor_t actor
) {
    int ii, result=-1;
    FILE *filep=0;
    if (qsmm_get_actor_large_model(actor))
        ERREXIT("saving the state of a large actor not supported");
    if (!(filep=fopen(fln,"w")))
        ERRFILE("failed to open the file for writing");
    const char is_random=!!qsmm_get_actor_random(actor);
    WRITE(is_random);
    const int nsig=qsmm_get_actor_nsig(actor);
    WRITE(nsig);
    const int nspur=qsmm_get_actor_nspur(actor);
    WRITE(nspur);
    const int ngram_sz=qsmm_get_actor_ngram_sz(actor);
    WRITE(ngram_sz);
    int auto_spur_type=qsmm_get_actor_auto_spur_type(actor);
    if (auto_spur_type==QSMM_ERR_NOTFOUND) auto_spur_type=-1;
    WRITE(auto_spur_type);
    const long tmd=qsmm_get_actor_discrete_time(actor);
    WRITE(tmd);
    const double tmc=qsmm_get_actor_continuous_time(actor);
    WRITE(tmc);
    const double naction_per_evt=qsmm_get_actor_naction_per_evt(actor);
    WRITE(naction_per_evt);
    const double nsig_ctrl=qsmm_get_actor_nsig_ctrl(actor);
    WRITE(nsig_ctrl);
    const double ktemperature=qsmm_get_actor_ktemperature(actor);
    WRITE(ktemperature);
    const struct qsmm_pair_sig_s *const range_sig_p=qsmm_get_actor_range_sig(actor);
    for (ii=0; ii<ngram_sz; ii++) {
        const struct qsmm_pair_sig_s *const pair_p=range_sig_p+ii;
        WRITE(pair_p->first);
        WRITE(pair_p->second);
    }
    for (int spur_type=0; spur_type<nspur; spur_type++) {
        double spur_val=0, spur_weight=0;
        CHK_FAIL(qsmm_get_actor_spur,actor,spur_type,&spur_val);
        WRITE(spur_val);
        CHK_FAIL(qsmm_get_actor_spur_weight,actor,spur_type,&spur_weight);
        WRITE(spur_weight);
        enum qsmm_spur_perception_e spur_perception=QSMM_SPUR_PERCEPTION_NORMAL;
        CHK_FAIL(qsmm_get_actor_spur_perception, actor,
                 spur_type, &spur_perception);
        WRITE(spur_perception);
        enum qsmm_time_e spur_time=QSMM_TIME_CONTINUOUS;
        CHK_FAIL(qsmm_get_actor_spur_time,actor,spur_type,&spur_time);
        WRITE(spur_time);
    }
    qsmm_sig_t sig_next;
    for (sig_next=0; sig_next<nsig; sig_next++) {
        double weight_sig=0;
        const int rc=qsmm_get_actor_sig_weight(actor,sig_next,&weight_sig);
        if (rc<0) {
            if (rc==QSMM_ERR_INVAL) continue;
            ERREXIT("qsmm_get_actor_sig_weight: %s",qsmm_err_str(rc));
        }
        WRITE(sig_next);
        WRITE(weight_sig);
    }
    sig_next=QSMM_SIG_INVALID;
    WRITE(sig_next);
    const qsmm_sig_t *const sig_ngram_p=qsmm_get_actor_sig_ngram(actor);
    for (ii=0; ii<ngram_sz; ii++) WRITE(sig_ngram_p[ii]);
    struct wr_acstate_param_s wr_acstate_param;
    memset(&wr_acstate_param,0,sizeof(wr_acstate_param));
    wr_acstate_param.prg_name=prg_name;
    wr_acstate_param.fln=fln;
    wr_acstate_param.filep=filep;
    CHK_FAIL(qsmm_storage_enum_states, qsmm_get_actor_storage(actor),
             0, 0, &wr_acstate, &wr_acstate_param);
    ii=0;
    WRITE(ii);
    result=0;

Exit:
    if (filep) fclose(filep);
    return result;
}


// Load the state of a small actor from a file.
// Returns: 0 = success;
//         -1 = failure.
// WARNING: possible loss of atomicity: on failure, the state of the actor
//          may be partially updated.

int
actor_load(
    const char *prg_name,
    const char *fln,
    qsmm_actor_t actor
) {
    int ii, spur_type, result=-1;
    FILE *filep=0;
    if (qsmm_get_actor_large_model(actor))
        ERREXIT("loading the state of a large actor not supported");
    if (!(filep=fopen(fln,"r"))) ERRFILE("failed to open the file");
    char is_random=0;
    READ(is_random);
    int nsig_stream=0, nspur_stream=0, ngram_sz_stream=0,
        auto_spur_type=-1;
    READ(nsig_stream);
    const int nsig_actor=qsmm_get_actor_nsig(actor);
    if (nsig_stream!=nsig_actor)
        ERREXIT(
               "number of signals does not match: %d (file) != %d (actor)",
                nsig_stream, nsig_actor);
    READ(nspur_stream);
    const int nspur_actor=qsmm_get_actor_nspur(actor);
    if (nspur_stream!=nspur_actor)
        ERREXIT(
            "number of spur types does not match: %d (file) != %d (actor)",
                nspur_stream, nspur_actor);
    READ(ngram_sz_stream);
    const int ngram_sz_actor=qsmm_get_actor_ngram_sz(actor);
    if (ngram_sz_stream!=ngram_sz_actor)
        ERREXIT("n-gram length does not match: %d (file) != %d (actor)",
                ngram_sz_stream, ngram_sz_actor);
    READ(auto_spur_type);
    long tmd=0;
    READ(tmd);
    double tmc=0, naction_per_evt=0, nsig_ctrl=0, ktemperature=0; 
    READ(tmc);
    if (!isfinite(tmc) || tmc<0)
        ERREXIT("invalid continuous time (%g)",tmc);
    READ(naction_per_evt);
    READ(nsig_ctrl);
    READ(ktemperature);
    const struct qsmm_pair_sig_s *pair_p,
        *const range_sig_p=qsmm_get_actor_range_sig(actor);
    for (ii=0; ii<ngram_sz_stream; ii++) {
        struct qsmm_pair_sig_s range;
        READ(range.first);
        READ(range.second);
        pair_p=range_sig_p+ii;
        if (range.first!=pair_p->first)
            ERREXIT("range %d: minimum allowed signal does not match: %"
                    QSMM_FMT_PRI_SIG " (file) != %" QSMM_FMT_PRI_SIG
                    " (actor)", ii, range.first, pair_p->first);
        if (range.second!=pair_p->second)
            ERREXIT("range %d: maximum allowed signal does not match: %"
                    QSMM_FMT_PRI_SIG " (file) != %" QSMM_FMT_PRI_SIG
                    " (actor)", ii, range.second, pair_p->second);
    }
    qsmm_set_actor_random(actor,is_random);
    CHK_FAIL(qsmm_set_actor_auto_spur_type,actor,auto_spur_type);
    qsmm_set_actor_discrete_time(actor,tmd);
    CHK_FAIL(qsmm_actor_time_delta, actor,
             tmc-qsmm_get_actor_continuous_time(actor));
    CHK_FAIL(qsmm_set_actor_naction_per_evt,actor,naction_per_evt);
    CHK_FAIL(qsmm_set_actor_nsig_ctrl,actor,nsig_ctrl);
    CHK_FAIL(qsmm_set_actor_ktemperature,actor,ktemperature);
    for (spur_type=0; spur_type<nspur_stream; spur_type++) {
        double spur=0, spur0=0, spur_weight=0;
        enum qsmm_spur_perception_e spur_perception=QSMM_SPUR_PERCEPTION_NORMAL;
        enum qsmm_time_e spur_time=QSMM_TIME_CONTINUOUS;
        READ(spur);
        if (!isfinite(spur))
            ERREXIT("spur type %d: invalid spur value (%g)",
                    spur_type, spur);
        CHK_FAIL(qsmm_get_actor_spur,actor,spur_type,&spur0);
        CHK_FAIL(qsmm_actor_spur_delta,actor,spur_type,spur-spur0);
        READ(spur_weight);
        CHK_FAIL(qsmm_set_actor_spur_weight,actor,spur_type,spur_weight);
        READ(spur_perception);
        if (spur_perception!=QSMM_SPUR_PERCEPTION_NORMAL &&
            spur_perception!=QSMM_SPUR_PERCEPTION_INVERSE)
            ERREXIT("spur type %d: invalid spur perception (%d)",
                    spur_type, spur_perception);
        CHK_FAIL(qsmm_set_actor_spur_perception, actor,
                 spur_type, spur_perception);
        READ(spur_time);
        if (spur_time!=QSMM_TIME_DISCRETE &&
            spur_time!=QSMM_TIME_CONTINUOUS)
            ERREXIT("spur type %d: invalid spur time (%d)",
                    spur_type, spur_time);
        CHK_FAIL(qsmm_set_actor_spur_time,actor,spur_type,spur_time);
    }
    qsmm_sig_t sig;
    while (1) {
        READ(sig);
        if (sig==QSMM_SIG_INVALID) break;
        double weight_sig=0;
        READ(weight_sig);
        CHK_FAIL(qsmm_set_actor_sig_weight,actor,sig,weight_sig);
    }
    qsmm_sig_t *const sig_ngram_p=qsmm_get_actor_sig_ngram(actor);
    for (ii=0; ii<ngram_sz_stream; ii++) {
        READ(sig);
        pair_p=range_sig_p+ii;
        if (sig<pair_p->first)
            ERREXIT("n-gram signal #%d (%" QSMM_FMT_PRI_SIG
                    ") is less than the minimum allowed signal (%"
                    QSMM_FMT_PRI_SIG ")", ii, sig, pair_p->first);
        if (sig>pair_p->second)
            ERREXIT("n-gram signal #%d (%" QSMM_FMT_PRI_SIG
                    ") is greater than the maximum allowed signal (%"
                    QSMM_FMT_PRI_SIG ")", ii, sig, pair_p->second);
        sig_ngram_p[ii]=sig;
    }
    const qsmm_storage_t storage=qsmm_get_actor_storage(actor);
    while (1) {
        int ngram_storage_sz=0;
        struct qsmm_state_s state;
        READ(ngram_storage_sz);
        if (ngram_storage_sz<1) break;
        if (ngram_storage_sz!=ngram_sz_actor)
            ERREXIT(
                   "n-gram length does not match: %d (file) != %d (actor)",
                    ngram_storage_sz, ngram_sz_actor);
        qsmm_sig_t sig_ngram_storage[ngram_storage_sz];
        for (ii=0; ii<ngram_storage_sz; ii++) READ(sig_ngram_storage[ii]);
        READ(state);
        struct qsmm_sspur_s sspur[nspur_stream];
        for (spur_type=0; spur_type<nspur_stream; spur_type++)
            READ(sspur[spur_type]);
        CHK_FAIL(qsmm_set_storage_state_stats, storage,
                 ngram_storage_sz, sig_ngram_storage, &state, sspur);
        while (1) {
            struct qsmm_cycle_s cycle;
            READ(sig);
            if (sig==QSMM_SIG_INVALID) break;
            READ(cycle);
            struct qsmm_cspur_s cspur[nspur_stream];
            for (spur_type=0; spur_type<nspur_stream; spur_type++)
                READ(cspur[spur_type]);
            CHK_FAIL(qsmm_set_storage_cycle_stats, storage,
                     ngram_storage_sz, sig_ngram_storage,
                     sig, &cycle, cspur);
        }
    }
    result=0;

Exit:
    if (filep) fclose(filep);
    return result;
}

Next: , Previous: , Up: Top   [Contents][Index]

4 Multinode Model

Multinode model is the concept of using an individual actor or a pair of actors in multiple contexts where producing adaptive actions is necessary. The contexts might relate to the components of a system you develop or entities external to the system. The nodes of a multinode model are adaptive programmatic representations of those contexts. They provide learning capabilities to the system, the ability to produce actions based on learned interactions, and can define preprogrammed behavior. A special case of multinode model is a single-node model.

A node possesses control when it performs interactions with other entities by executing the instructions of a possibly nondeterministic subroutine contained in the node. The execution of this subroutine we briefly call node execution. At present, QSMM supports not more than one node in a multinode model possessing control at any moment of time; in addition to that, a node can execute not more than one instruction at any time. A node can pass control to another node while executing an instruction at some location in the subroutine, and the other node can return control to that location afterwards.

A node learns something when the subroutine becomes more deterministic or stable. This added determinism affects subsequent interactions of this node with other entities.

Considering the sources of deterministic and stochastic behavior, their location, and their ability to influence each other gives answers to the questions “Which entity is choosing actions?” and “Is it easy for that entity to choose actions?” For example, a node can use a stochastic physical process, such as the interference of individual electrons, to produce random numbers for the subroutine to choose actions. If the node is not using a stochastic physical process, and hardware for executing the subroutine operates deterministically, then information the node receives from the environment may define the choice of actions.

Working with a multinode model begins with its preparation. It includes registering meta-classes for instructions executable by nodes and registering the sets of instruction classes—different nodes can have different instruction sets. The multinode model learns and performs useful work during execution phase—the execution of nodes and transferring control between them. Various information about a multinode model is available at various points in its lifetime.


Next: , Up: Multinode Model   [Contents][Index]

4.1 Principle of Operation

A schematic diagram of a multinode model implementation is in Figure 4.1.

An environment state identification engine, instruction emitting engine, and instruction execution environment are main model components taking part in model execution.

The environment state identification engine is a small or large actor keeping the adaptive state model of an environment and identifying node states according to that model. This identification is a bidirectional process: the current state of a node depends on the state of the environment and needs identification; conversely, the node acts on the environment, and, therefore, the state of the environment depends on an identified node state. For a single-node model, its node corresponds to the entire environment. For a multinode model, a node corresponds to part of the environment.

Along with the adaptive state model, the environment state identification engine keeps the identifier of a currently executed node, the index of its previous state, an optional array of identifiers of look-ahead signals (see Setting Look-ahead Signals), and, as an actor, it keeps the current values of spur and continuous time.

The structures of tuples encoding the action choice states of an environment state identification engine for a single-node model and a multinode model are in Figure 4.2. The environment state identification engine identifies a current node state based on a previous node state and an array of input signals specifying last instruction emitted by the instruction emitting engine, the outcome of this instruction, and optional look-ahead signals. For a multinode model, the identifier of a currently executed node takes part in identifying the current node state.

The environment state identification engine sends the identifier of a currently executed node and the index of its current identified state to the instruction emitting engine. The latter engine is a small or large actor keeping an adaptive model of emitting various assembler instructions in various node states. As an actor, the instruction emitting engine keeps the current values of spur and continuous time, and they can be different from those values for the environment state identification engine.

The structures of tuples encoding the action choice states of an instruction emitting engine for a single-node model and a multinode model are in Figure 4.3. The instruction emitting engine selects an output signal encoding an assembler instruction. A current node state received from the environment state identification engine takes part in selecting the output signal. For a multinode model, the identifier of a currently executed node received from the environment state identification engine also takes part in selecting the output signal.

The instruction emitting engine sends a selected assembler instruction to the instruction execution environment for performing effective work and to the environment state identification engine for identifying the next node state. That instruction execution environment represents everything else in the multinode model, interacts with application logic or incorporates it, and is aware of all parameters of the environment state identification engine and instruction emitting engine. An assembler instruction returns an instruction outcome after execution. The instruction execution environment sends the outcome to the environment state identification engine for identifying the next node state.

The instruction execution environment keeps a node call stack for the execution of nodes to be similar to the execution of program subroutines (functions or procedures) calling each other and returning control to caller subroutines. An executed assembler instruction can push the identifier of a currently executed node and the index of its current state to the node call stack and transfer control to another node with resetting the current node state to the initial node state corresponding to the beginning of execution of a subroutine. The assembler instruction can also return control to a previously executed node by popping the identifier of this node and the index of its current state from the stack.

The assembler instruction can change look-ahead signals taking part in identifying the next node state and increment the current values of spur and continuous time tracked by the environment state identification engine and instruction emitting engine.

multinode model implementation

Figure 4.1: multinode model implementation

action choice states of an environment state identification engine

Figure 4.2: action choice states of an environment state identification engine

action choice states of an instruction emitting engine

Figure 4.3: action choice states of an instruction emitting engine

A helpful feature of a multinode model is the ability to convert internal data stored in its environment state identification engine and instruction emitting engine to a representation in the form of an assembler program (see Assembler Programs). One can think about this feature as automatic synthesis of an assembler program solving an assigned task.

An important point the developer should realize is that automatic program synthesis may work only if there exists a steady state model solving an assigned task. Steady state model is a model where states have predictable input from an environment.

Below there is a list of concepts for enabling the automatic synthesis of assembler programs.

Instruction meta-class

Represents an instruction name without taking into account optional instruction parameters following the instruction name after a whitespace character. The name of an instruction meta-class is the name of an instruction without including instruction parameters. Example:

move

This instruction meta-class might represent an instruction that moves an agent in an environment one step in a specific direction. The name of this instruction meta-class does not include a movement direction.

Instruction class

Represents an instruction name optionally followed by instruction parameters. Distinct strings, where every string consists of an instruction name and instruction parameters in canonical form (see Setting Text Instruction Parameters), identify distinct instruction classes. Example:

move north

This instruction class might represent an instruction that moves an agent in the environment one step in the north direction.

Instruction outcome

An instruction class has a specific number of instruction outcomes. An environment state identification engine uses the outcome of an emitted instruction to identify the next node state. The instruction emitting engine uses that next node state to select the next instruction.

For example, the instruction ‘move north’ as well as other movement instructions might return a bitmask of four bits (i.e. an integer number in the range 0 to 15) after performing a move. A bit of this bitmask equal to 0 might indicate that there is an obstacle in a corresponding direction, thus giving a piece of information to the agent about the configuration of an environment. It might also be useful to return special outcome 16 if there is an obstacle in a direction specified by an emitted instruction, and this obstacle disallows the agent to move.

Instruction class set

Represents a set of instruction classes and its properties and is a class for nodes. For example, the instruction class set ‘walker’ intended for investigating an environment might contain the instruction classes

move north
move east
move south
move west

A node belonging to this node class might represent an agent investigating the environment.

Instruction instance

An instance of an instruction class in an assembler program. For example, in the assembler program fragment

        move north
        joe  14, return_back
        move north
        ...
return_back:
        move south
        ...

there are two instances of ‘move north’ instruction class.


Next: , Previous: , Up: Multinode Model   [Contents][Index]

4.2 Creating a Multinode Model

A handle of qsmm_t type refers to a multinode model. The function qsmm_create creates a multinode model according to specified initial parameters and returns its handle. The function qsmm_destroy destroys a multinode model specified by its handle. A number of functions fetch initial model parameters after creating a model.

After creating an empty model, register instruction meta-classes and instruction class sets defining assembler instruction sets for model nodes and specifying instruction-centric and node-centric model behavior respectively. An instruction meta-class biuniquely corresponds to what we call an assembler instruction name. An instruction class belongs to an instruction meta-class, is a member of an instruction class set, and represents an assembler instruction with specific parameters. Every instruction meta-class and instruction class set needs providing an event handler function.

After registering one or more instruction class sets, create nodes belonging to node classes represented by those instruction class sets. The basic parameters of a node include its identifier and the number of internal states for holding a state model. The extended parameters of a node include its state transition matrix maintained by the environment state identification engine and its action emission matrix maintained by the instruction emitting engine. Both engines exist in the scope of model instance holding the parameters of an executed model. After creating the model instance, it may be necessary to override the default parameters of actors representing those engines.

To use model-specific parameters in the event handler functions of instruction meta-classes and instruction class sets called for multiple model handles, you can associate arbitrary pointers with the handle of a multinode model or its any node.


Next: , Up: Creating a Multinode Model   [Contents][Index]

4.2.1 Creating a Handle

A model handle refers to a multinode model.

Data type: qsmm_t

This is a type for a model handle. It is a pointer, so variables of this type can be NULL. The function qsmm_create creates a new model and returns its handle. The function qsmm_destroy destroys an existing model addressed by a handle. You can pass a model handle to API functions taking an argument of qsmm_t type after the creation of a model and until its destruction.

Use the following functions to create and destroy a multinode model.

Function: int qsmm_create (const struct qsmm_desc_s *desc_p, qsmm_t *model_p)

This function creates a multinode model using parameters in *desc_p and stores a model handle in *model_p.

If model_p is NULL, the function only validates the parameters in *desc_p.

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

QSMM_ERR_INVAL

Parameters in *desc_p are invalid.

QSMM_ERR_NOMEM

There was not enough memory to create a multinode model.

Function: void qsmm_destroy (qsmm_t model)

This function destroys a multinode model specified by handle model. You must not use the model handle after the model destruction. If model is NULL, the function has no effect.

Below there is a description of a structure passed in *desc_p to the function qsmm_create.

Structure: qsmm_desc_s

This structure describes parameters for creating a multinode model by the function qsmm_create. The structure contains the following fields.

Field: char use_flat_storage

A flag specifying the type of storage the environment state identification engine and instruction emitting engine will use: flat storage if the flag is non-zero, or map storage if the flag is zero. The function qsmm_engine_create assigns this flag to the field use_flat_storage of qsmm_actor_desc_s structure passed to the function qsmm_actor_create when creating both engines. It is permissible to use flat storage if the fields is_large_env and is_large_opt of this structure are zero.

Field: char dont_use_instr_class_weights

A flag defining whether to set the weights of output signals of the instruction emitting engine equal to the weights of instruction classes specified by the functions qsmm_set_instr_class_weight, qsmm_set_instr_class_weight_by_name_f, and qsmm_set_instr_meta_class_weight (see Setting Instruction Classes Weights, for the descriptions of those functions). A zero flag means to set the weights, and a non-zero flag means to not set them. If the flag is non-zero, those functions will report QSMM_ERR_NOTSUP. If the field is_determ_opt or is_large_opt of this structure is non-zero, the function qsmm_create implicitly sets this flag to a non-zero value. Eliminating the need to set the weights speeds up model execution, especially when the action emission matrix has a sparse probability profile, and the number of instruction classes in the instruction class set is large.

Field: char is_determ_opt

A flag imposing the following restriction on the probability profile of action emission matrix of every model node: for every node state, that probability profile must define a deterministic choice of an instruction class emitted in the node state. If this flag is non-zero, the node assembler considers that node states begin just before user and mixed-type instructions—marking unnamed node states by stt instructions becomes unnecessary. It is permissible to set this flag to a non-zero value only if the field is_large_opt of this structure is zero.

Field: char is_large_env

A flag specifying whether to create a small or large actor for the environment state identification engine: a small actor if this flag is zero, or a large actor if this flag is non-zero. The large actor uses binary Huffman trees. It is permissible to set this flag to a non-zero value only if the field use_flat_storage of this structure is zero, and the field compat is positive.

Field: char is_large_opt

A flag specifying whether to create a small or large actor for the instruction emitting engine: a small actor if this flag is zero, or a large actor if this flag is non-zero. The large actor uses binary Huffman trees. It is permissible to set this flag to a non-zero value only if the fields use_flat_storage and is_determ_opt of this structure are zero, and the field compat is positive.

Field: int nspur

The number of spur types. This number includes the automatic spur, although the model might not really use that spur. If the field is_determ_opt of this structure is zero, the field nspur must be greater than 1. If is_determ_opt is non-zero, nspur must be greater than 0.

Field: int stack_sz_max

The maximum allowed number of frames in the node call stack. If the actual number of stack frames exceeds the maximum allowed number, the function qsmm_node_call_default reports QSMM_ERR_STACKOVR. If the maximum allowed number of stack frames is too large, a stack overflow may occur without reporting this error. This kind of stack overflow typically causes a segmentation fault. The value of this field must be positive.

Field: int ngram_env_la_sz

The length of a segment of extra signals in a signal list encoding an action choice state of the environment state identification engine. Those extra signals take part in the identification of a current node state. See Setting Look-ahead Signals, for more information on them. The node assembler does not support loading assembler programs into the nodes of a model with positive length of look-ahead signal segment. The value of this field must be non-negative.

Field: int nsig_ngram_env_la

An upper bound on the identifier of every signal in the look-ahead signal segment with length specified in the field ngram_env_la_sz of this structure. Every identifier must be less than the upper bound. If the length is positive, then the upper bound must also be positive. If the length is zero, then the upper bound must also be zero.

Field: int profile_pool_env_sz

Non-negative size of the pool of probabilities lists in normal form for the environment state identification engine. The function qsmm_engine_create assigns this size to the field profile_pool_sz of qsmm_actor_desc_s structure passed to the function qsmm_actor_create when creating the engine.

Field: int profile_pool_opt_sz

Non-negative size of the pool of probabilities lists in normal form for the instruction emitting engine. The function qsmm_engine_create assigns this size to the field profile_pool_sz of qsmm_actor_desc_s structure passed to the function qsmm_actor_create when creating the engine.

Field: int compat

The compatibility level of algorithms. Must be 0, 1, or 2. The function qsmm_engine_create assigns that level to the field compat of qsmm_actor_desc_s structure passed to the function qsmm_actor_create when creating the environment state identification engine and instruction emitting engine. Additionally, value 2 means:

  • Optimize setting the weights of output signals of the instruction emitting engine equal to the weights of instruction classes specified by the functions qsmm_set_instr_class_weight, qsmm_set_instr_class_weight_by_name_f, and qsmm_set_instr_meta_class_weight (if the field dont_use_instr_class_weights of this structure is zero): set all those weights only on calling a node or returning control to it from another node and update a specific output signal weight by those functions if a node identifier passed to them is equal to the identifier of a currently executed node.
  • The function qsmm_get_nnode returns the actual number of existing nodes in the model rather than the number of reserved nodes—those numbers are equal only in certain cases.
  • The environment state identification engine increments discrete time disregarding whether or not the choice of a current node state is deterministic.
  • The instruction emitting engine increments discrete time disregarding whether or not the choice of an emitted instruction is deterministic.
  • Compute the relative probabilities of QSMM_RELPROB_BUILTIN1 type by the environment state identification engine and instruction emitting engine independently of the number of nodes in the model and the value of ngram_env_la_sz field of this structure.

Set this field to 2 in your new programs. This manual does not include outdated details specific to previous algorithms.

Field: double sparse_fill_max

Maximum fill ratio for sparse vectors holding the relative probabilities of output signals. The environment state identification engine and instruction emitting engine choose whether to use sparse vectors or ordinary vectors based on this ratio. It must be a number in the range 0 to 1 inclusive. Value 0 indicates that both engines must always use ordinary vectors. Value 1 indicates that both engines must always use sparse vectors. A value between 0 and 1 indicates the maximum percentage (divided by 100) of non-zero elements in sparse vectors relative to the numbers of vector dimensions. The function qsmm_engine_create assigns this number to the field sparse_fill_max of qsmm_actor_desc_s structure passed to the function qsmm_actor_create when creating both engines.

Note: if the field is_large_env or is_large_opt of this structure is non-zero, or when loading large assembler programs specifying sparse probability profiles into model nodes, forgetting to set the field sparse_fill_max to a positive value, for example, 0.2 or 1, will cause bad model performance.

Field: qsmm_rng_t rng

The handle of a random number generator the environment state identification engine and instruction emitting engine will use. See Random Number Generators, for how to create and destroy random number generators and perform other operations on them. If this field is NULL, the function qsmm_create creates an instance of default random number generator for use by both engines until model destruction.

Field: struct qsmm_pair_sig_s * range_sig_env_la_p

The ranges of signal identifiers in the look-ahead signal segment. The field ngram_env_la_sz of this structure specifies the length of that segment. The multinode model uses those ranges to check the validity of that segment, to reduce the memory footprint of flat storage if a small actor representing the environment state identification engine uses this type of storage, and to reduce the number of nodes in the multinode model of a large actor representing the engine. There can be other uses for the ranges in future QSMM versions. Specify the ranges as precisely as possible to reduce the memory footprint of that engine.

If the field range_sig_env_la_p is not NULL, then this field must be the pointer to an array holding ngram_env_la_sz elements, where each element is a pair (see Creating an Actor, for a description of qsmm_pair_sig_s structure). The positions of those elements are the positions of signal identifiers in the look-ahead signal segment. The fields first and second of each pair define the minimum value and maximum value of a corresponding signal identifier. The value of first must be less than or equal to the value of second. The value of second must be less than the value of nsig_ngram_env_la field of this structure. If range_sig_env_la_p is NULL, this condition means that every signal in the segment lies in the range 0 (inclusive) to nsig_ngram_env_la (exclusive).

To improve compatibility with future versions of QSMM library, zero by the function memset an instance of qsmm_desc_s structure before setting the fields of this instance passed to the function qsmm_create.

You can retrieve some initial model parameters later by the following functions.

Function: int qsmm_get_use_instr_class_weights (qsmm_t model)

This function returns a positive value if the function qsmm_node_call_default sets the weights of output signals of the instruction emitting engine of a multinode model equal to the weights of instruction classes of a currently executed node, and the functions qsmm_set_instr_class_weight, qsmm_set_instr_class_weight_by_name_f, and qsmm_set_instr_meta_class_weight support setting the weights of instruction classes. If qsmm_node_call_default does not set the weights, and qsmm_set_instr_class_weight, qsmm_set_instr_class_weight_by_name_f, and qsmm_set_instr_meta_class_weight report QSMM_ERR_NOTSUP, the function qsmm_get_use_instr_class_weights returns 0. This function returns a positive value if the field dont_use_instr_class_weights of qsmm_desc_s structure passed to the function qsmm_create was zero when creating the multinode model or returns 0 if that field was non-zero. A returned value is always non-negative.

Function: int qsmm_get_determ_opt (qsmm_t model)

This function returns a positive value if the action emission matrices of all nodes of a multinode model have the restriction to define only deterministic choices of assembler instructions in all node states. The function returns a positive value if the field is_determ_opt of qsmm_desc_s structure passed to the function qsmm_create was non-zero when creating the multinode model or returns 0 if that field was zero. A returned value is always non-negative.

Function: int qsmm_get_nspur (qsmm_t model)

This function returns the number of spur types of a multinode model. It is a number specified in the field nspur of qsmm_desc_s structure passed to the function qsmm_create when creating the multinode model. A returned value is always positive.

Function: int qsmm_get_stack_sz_max (qsmm_t model)

This function returns the maximum allowed number of frames in the node call stack of a multinode model. It is a number specified in the field stack_sz_max of qsmm_desc_s structure passed to the function qsmm_create when creating the multinode model. A returned value is always positive.

Function: int qsmm_get_ngram_env_la_sz (qsmm_t model)

This function returns the length of look-ahead signal segment of a multinode model. It is length specified in the field ngram_env_la_sz of qsmm_desc_s structure passed to the function qsmm_create when creating the multinode model. A returned value is always non-negative.

Function: int qsmm_get_nsig_ngram_env_la (qsmm_t model)

This function returns an upper bound on the identifier of every signal in the look-ahead signal segment of a multinode model. It is a number specified in the field nsig_ngram_env_la of qsmm_desc_s structure passed to the function qsmm_create when creating the multinode model. A returned value is always non-negative.


Next: , Previous: , Up: Creating a Multinode Model   [Contents][Index]

4.2.2 Defining Instruction Meta-classes

An instruction meta-class represents an assembler instruction with a specific name and encapsulates logic associated with the instruction. The name of an instruction meta-class is the name of an assembler instruction. Various instruction classes derived from the instruction meta-class represent this assembler instruction followed by various parameter strings.

Every instruction meta-class has an event handler function processing the initialization of instruction classes derived from the instruction meta-class and the invocation of instructions belonging to those instruction classes during model execution. By default, the name of such event handler function is the name of an instruction meta-class.

An instruction class has various identifiers including binary parameters and text parameters convertible from the binary parameters. An instruction meta-class name along with the text parameters converted to canonical form according to a set of rules, such as removing all whitespace characters from a parameter string, make up an instruction class name for identifying instructions belonging to the instruction class in assembler programs.

The initialization of an instruction class by the event handler function of an instruction meta-class typically includes setting the text parameters and the number of instruction outcomes. An invoked assembler instruction sends its outcome to the environment state identification engine to affect the identification of the next state of an assembler program encoding the environment.


Next: , Up: Defining Instruction Meta-classes   [Contents][Index]

4.2.2.1 Function Declaration

You should declare or define an instruction meta-class using the following macro.

Macro: QSMM_INSTR_META_CLASS (instr_meta_class_name)

This macro declares the prototype of a function named instr_meta_class_name that represents an instruction meta-class with the same name and is the event handler function of this instruction meta-class. You can prepend the macro with the static keyword to declare or define the static function. A pointer to the function has the type qsmm_instr_meta_class_func_t. The function has the return type int and the following arguments.

Function argument: qsmm_t qsmm

The handle of a multinode model containing the instruction meta-class.

Function argument: int qsmm_evt

The type of an event to process by the event handler function: QSMM_EVT_ENT_INIT, QSMM_EVT_ENT_DONE, QSMM_EVT_INSTR_CLASS_INIT, QSMM_EVT_INSTR_CLASS_DONE, QSMM_EVT_ENGINE_INIT, QSMM_EVT_ENGINE_DONE, or QSMM_EVT_ACTIVATE.

Function argument: int qsmm_node

The identifier of an executed node. Is a valid identifier for an event QSMM_EVT_ACTIVATE. For other events is equal to -1.

Function argument: void * qsmm_param_p

The user parameter of this event handler function. Is equal to the corresponding argument of qsmm_reg_instr_meta_class function called to register the instruction meta-class.

For example, declare the prototype of a static function representing the instruction meta-class ‘move’ as follows:

static QSMM_INSTR_META_CLASS(move);

Define the static function ‘move’ as follows:

static QSMM_INSTR_META_CLASS(move) {
    ...
}
Data type: qsmm_instr_meta_class_func_t

This is a type of a pointer to the event handler function of an instruction meta-class. The type has the following declaration:

typedef int
(*qsmm_instr_meta_class_func_t)(
    qsmm_t qsmm,
    int qsmm_evt,
    int qsmm_node,
    void *qsmm_param_p
);

See above for the description of arguments of that event handler function. To improve compatibility with future versions of QSMM library, avoid declaring event handler functions with this prototype explicitly—use the macro QSMM_INSTR_META_CLASS instead.


Next: , Previous: , Up: Defining Instruction Meta-classes   [Contents][Index]

4.2.2.2 Event Handling

The event handler function of an instruction meta-class can process events with types represented by the macros listed below. The argument qsmm_evt of that event handler function specifies an event type.

Macro: QSMM_EVT_ENT_INIT

Instruction meta-class initialization. The function qsmm_reg_instr_meta_class called to register the instruction meta-class sends this event.

This event can trigger initial assignments to variables and allocating resources used by the instruction meta-class for all model runs.

Macro: QSMM_EVT_ENT_DONE

Instruction meta-class uninitialization. The function qsmm_destroy called to destroy the multinode model sends this event to all registered instruction meta-class event handlers.

This event can trigger deallocating resources allocated on processing an event QSMM_EVT_ENT_INIT.

Macro: QSMM_EVT_INSTR_CLASS_INIT

Instruction class initialization. The function qsmm_reg_instr_class_v2 (see Registering Instruction Classes) called to register an instruction class derived from the instruction meta-class sends this event. The event handler of an instruction class set usually calls qsmm_reg_instr_class_v2 on processing an event QSMM_EVT_ENT_INIT to register the instruction class as belonging to this instruction class set.

This event typically triggers the following operations:

Macro: QSMM_EVT_INSTR_CLASS_DONE

Instruction class uninitialization. The function qsmm_destroy called to destroy the multinode model sends this event to instruction meta-class event handlers for instruction classes registered by the function qsmm_reg_instr_class_v2 and then sends the event QSMM_EVT_ENT_DONE to those event handlers.

This event can trigger the uninitialization of binary instruction class parameters (see Accessing Binary Instruction Parameters) and the deallocation of additional resources associated with the instruction class allocated on processing an event QSMM_EVT_INSTR_CLASS_INIT.

Macro: QSMM_EVT_ENGINE_INIT

Model instance initialization. The function qsmm_engine_create called to create the model instance sends this event to all registered instruction meta-class event handlers at the end of execution of that function.

This event can trigger initial assignments to variables and allocating resources used by the instruction meta-class for a current model run.

Macro: QSMM_EVT_ENGINE_DONE

Model instance uninitialization. The function qsmm_engine_destroy called to destroy the model instance sends this event to all registered instruction meta-class event handlers at the beginning of execution of that function in reverse order relative to the order of sending events QSMM_EVT_ENGINE_INIT. The function qsmm_engine_create calls qsmm_engine_destroy implicitly when recreating the model instance. The function qsmm_destroy calls qsmm_engine_destroy implicitly when destroying the multinode model.

This event can trigger deallocating resources allocated on processing an event QSMM_EVT_ENGINE_INIT.

Macro: QSMM_EVT_ACTIVATE

Instruction invocation. See Handling Instruction Invocation.

On successful completion, the event handler function shall return a non-negative value. A specific non-negative value has no effect on model operation. On error, the event handler function shall return a negative value. Such negative value causes the invocation of an error handler function with passing QSMM_ERR_EVTHNDLR to it if the model has an error handler set.


Next: , Previous: , Up: Defining Instruction Meta-classes   [Contents][Index]

4.2.2.3 Registering the Function

Use the following macro to register the event handler function of an instruction meta-class.

Macro: QSMM_REG_INSTR_META_CLASS_PARAM (model, instr_meta_class_name, paramp)

This macro registers an instruction meta-class instr_meta_class_name for a multinode model. The event handler function of this instruction meta-class will be receiving the parameter paramp in the argument qsmm_param_p on all events. The macro QSMM_INSTR_META_CLASS should previously define the instruction meta-class.

The macro QSMM_REG_INSTR_META_CLASS_PARAM expands to:

qsmm_reg_instr_meta_class((model), #instr_meta_class_name,
                          &instr_meta_class_name, (paramp))

Below there is the description of a function called by the macro QSMM_REG_INSTR_META_CLASS_PARAM.

Function: int qsmm_reg_instr_meta_class (qsmm_t model, const char *instr_meta_class_name, qsmm_instr_meta_class_func_t instr_meta_class_func, void *paramp)

This function registers an instruction meta-class instr_meta_class_name for a multinode model. The function instr_meta_class_func is the event handler of this instruction meta-class. That event handler will be receiving the parameter paramp in the argument qsmm_param_p on all events.

A string instr_meta_class_name must begin with an English letter or an underscore followed by zero or more characters where each character is an English letter, a decimal digit, or an underscore.

After registering the instruction meta-class, the function sends an event QSMM_EVT_ENT_INIT to the event handler, and it can perform the initialization of that instruction meta-class.

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 string instr_meta_class_name has invalid format.

QSMM_ERR_EXIST

A program has already registered an instruction meta-class or instruction class set named instr_meta_class_name in the multinode model.

QSMM_ERR_UNTIMELY

The model instance already exists—cannot change model structure.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Use the following function to get a pointer to the event handler of an instruction meta-class and the user parameter of that event handler.

Function: int qsmm_get_instr_meta_class_handler (qsmm_t model, const char *instr_meta_class_name, qsmm_instr_meta_class_func_t *instr_meta_class_func_p, void **param_pp)

This function retrieves the parameters of the event handler of an instruction meta-class instr_meta_class_name registered for a multinode model. If instr_meta_class_func_p is not NULL, the function sets *instr_meta_class_func_p to a pointer to that event handler. If param_pp is not NULL, the function sets *param_pp to the value of qsmm_param_p argument of that event handler passed on all events.

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_NOTFOUND

The instruction meta-class instr_meta_class_name not found.

QSMM_ERR_TYPE

An entity named instr_meta_class_name is not an instruction meta-class. The entity is an instruction class set.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.


Next: , Previous: , Up: Defining Instruction Meta-classes   [Contents][Index]

4.2.2.4 Instruction Class Identifiers

An instruction class has the following identifiers unique in various scopes:

The following tuples containing identifiers of an instruction class are unique in the scope of a multinode model:

The function qsmm_reg_instr_class_v2 registers an instruction class as belonging to an instruction class set. Use the function described below to get the name of this instruction class set when processing an event by the event handler of an instruction meta-class. You can also use that function to get the name of an instruction class set when processing an event by the event handler of this instruction class set.

Function: int qsmm_get_eh_instr_class_set_name (qsmm_t model, const char **instr_class_set_name_pp)

This function retrieves the name of instruction class set of an event processed by an event handler of a multinode model. If instr_class_set_name_pp is not NULL, the function sets *instr_class_set_name_pp to the name of that instruction class set.

If the event handler of an instruction meta-class calls this function while processing an event QSMM_EVT_INSTR_CLASS_INIT, QSMM_EVT_INSTR_CLASS_DONE, or QSMM_EVT_ACTIVATE, the function retrieves the name of an instruction class set containing an instruction class associated with the event. If the event handler of an instruction class set calls this function, it retrieves the name of this instruction class set.

On success, the function returns a non-negative value. If the context of calling the function is not the event handler of an instruction meta-class on processing an event QSMM_EVT_INSTR_CLASS_INIT, QSMM_EVT_INSTR_CLASS_DONE, or QSMM_EVT_ACTIVATE and not the event handler of an instruction class set, the function returns negative error code QSMM_ERR_UNTIMELY.


Next: , Previous: , Up: Defining Instruction Meta-classes   [Contents][Index]

4.2.2.5 Accessing Binary Instruction Parameters

The function qsmm_reg_instr_class_v2 registers an instruction class and sets its binary parameters. The purpose of the following function is to fetch those binary parameters to a buffer in the event handler of an instruction meta-class. The buffer might be a variable or a structure instance.

Function: int qsmm_get_eh_instr_param (qsmm_t model, int bufsz, void *bufp)

This function fetches the binary parameters of an instruction class of a multinode model. The function copies such parameters associated with a processed event to a buffer bufp with size bufsz bytes. You can call this function from the event handler of an instruction meta-class on processing an event QSMM_EVT_INSTR_CLASS_INIT, QSMM_EVT_INSTR_CLASS_DONE, or QSMM_EVT_ACTIVATE.

The size bufsz must be greater than or equal to the size of binary parameters specified when registering the instruction class by the function qsmm_reg_instr_class_v2. If bufsz is greater than the size of binary parameters, the function leaves intact the remaining content of bufp.

On success, the function returns the size of binary parameters copied to bufp. On failure, the function returns a negative error code. Currently, the function can return the following error codes.

QSMM_ERR_INVAL

The argument bufsz is less than the size of binary parameters specified when registering the instruction class by the function qsmm_reg_instr_class_v2.

QSMM_ERR_UNTIMELY

The context of calling this function is not the event handler of an instruction meta-class on processing an event QSMM_EVT_INSTR_CLASS_INIT, QSMM_EVT_INSTR_CLASS_DONE, or QSMM_EVT_ACTIVATE.

Because the binary parameters of an instruction class are necessary when processing multiple event types, it is reasonable to fetch those binary parameters at the beginning of an event handler on processing events of those types. To prevent reporting QSMM_ERR_UNTIMELY and a possible invocation of a model error handler because of an inappropriate event type, use the following macro to check whether the type of an event is appropriate to call the function qsmm_get_eh_instr_param.

Macro: QSMM_HAS_INSTR_CLASS (evt)

This macro expands to:

((evt)==QSMM_EVT_INSTR_CLASS_INIT ||
 (evt)==QSMM_EVT_INSTR_CLASS_DONE ||
 (evt)==QSMM_EVT_ACTIVATE)

The purpose of this macro is to check whether an event of evt type has an associated instruction class, and it is safe to call the function qsmm_get_eh_instr_param and other functions that use an instruction class context.

For example, to fetch the binary parameters of an instruction class at the beginning of event handler of ‘move’ instruction meta-class, declare an enumeration for possible movement directions and define the instruction meta-class as follows:

enum direct_e {
    DIRECT_NORTH,  // move one step up
    DIRECT_EAST,   // move one step right
    DIRECT_SOUTH,  // move one step down
    DIRECT_WEST,   // move one step left
    DIRECT_COUNT   // number of movement directions
};

...

static QSMM_INSTR_META_CLASS(move) {
    enum direct_e direct=0;
    if (QSMM_HAS_INSTR_CLASS(qsmm_evt))
        qsmm_get_eh_instr_param(qsmm,sizeof(direct),&direct);
    ...
}

Next: , Previous: , Up: Defining Instruction Meta-classes   [Contents][Index]

4.2.2.6 Setting Text Instruction Parameters

If the text parameters of an instruction class are not empty, then the event handler of a corresponding instruction meta-class must set them on processing an event QSMM_EVT_INSTR_CLASS_INIT. Use the following function to set the text parameters.

Function: int qsmm_set_eh_instr_param_str_f (qsmm_t model, const char *fmt, ...)

This function sets the text parameters of an instruction class associated with a processed event. You can call this function from the event handler of a corresponding instruction meta-class of a multinode model on processing an event QSMM_EVT_INSTR_CLASS_INIT. The function formats the text parameters according to the argument fmt and subsequent arguments. Their meaning is the same as in the function printf. After formatting, the function converts the text parameters to a canonical 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 text parameters have invalid format.

QSMM_ERR_UNTIMELY

The context of calling this function is not the event handler of an instruction meta-class on processing an event QSMM_EVT_INSTR_CLASS_INIT.

QSMM_ERR_ILSEQ

Unable to convert the text parameters to a wide string according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

For example, the following code block sets the text parameters of an instruction class derived from the instruction meta-class ‘move’:

const char *ccp=0;
switch (direct) {
    case DIRECT_NORTH: ccp="north"; break;
    case DIRECT_EAST:  ccp="east";  break;
    case DIRECT_SOUTH: ccp="south"; break;
    case DIRECT_WEST:  ccp="west";  break;
    default:           assert(0);
}
if (ccp) qsmm_set_eh_instr_param_str_f(qsmm,"%s",ccp);

A call to qsmm_get_eh_instr_param can retrieve the content of direct earlier in the event handler (see the example in Accessing Binary Instruction Parameters).

String Literals

The text parameters of an instruction class can contain string literals. You must enclose such string literals in double quotes.

The character ‘\’ within a string literal is the escape character. In ‘\\’, the second ‘\’ is not the escape character if the first ‘\’ is the escape character. Functions parsing string literals convert every ‘\\’ with the first escape character to ‘\’.

The escape character is the beginning of an escape sequence. A three-digit octal character code or ‘x’ and a two-digit hexadecimal character code can follow the escape character. The functions parsing string literals convert such escape sequences to characters with those codes. Additionally, the character ‘a’, ‘b’, ‘f’, ‘n’, ‘r’, ‘t’, ‘v’, ‘'’, or ‘"’ can follow the escape character; the meaning of these escape sequences is the same as in the C programming language.

Canonical Form

The function qsmm_set_eh_instr_param_str_f converts the text parameters of an instruction class to a canonical form. All instruction classes derived from an instruction meta-class and contained in an instruction class set have distinct text parameters in the canonical form. The process of converting the text parameters to the canonical form consists of the following steps:

  1. Convert a source string to a wide string according to a current locale.
  2. Discard as a comment all characters in the wide string starting from the first character L;’ outside a string literal.
  3. Remove all whitespace characters outside string literals.
  4. Reformat all string literals by parsing them to the arrays of wide characters and formatting the arrays by the following rules:
    1. Replace the wide characters L\a’, L\b’, L\f’, L\n’, L\r’, L\t’, L\v’, L"’, and L\\’ with the corresponding escape sequences.
    2. Replace other wide characters with codes less than 32 with corresponding octal escape sequences.
    3. Copy all other wide characters to the formatted string as is.
    4. Enclose a resulting formatted string in double quotes.

Use the function described below to retrieve in the event handler of an instruction meta-class the text parameters of an instruction class in the canonical form.

Function: int qsmm_get_eh_instr_param_str (qsmm_t model, const char **param_str_pp)

This function fetches the text parameters of an instruction class associated with a processed event. If param_str_pp is not NULL, the function sets *param_str_pp to the text parameters in canonical form. A pointer returned in *param_str_pp is valid until the next call to this function or the function qsmm_get_instr_class_param_str (see Registering Instruction Classes) for the instruction class. You can call the function qsmm_get_eh_instr_param_str from the event handler of an instruction meta-class of a multinode model on processing an event QSMM_EVT_INSTR_CLASS_INIT, QSMM_EVT_INSTR_CLASS_DONE, or QSMM_EVT_ACTIVATE.

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_UNTIMELY

The context of calling this function is not the event handler of an instruction meta-class on processing an event QSMM_EVT_INSTR_CLASS_INIT, QSMM_EVT_INSTR_CLASS_DONE, or QSMM_EVT_ACTIVATE.

QSMM_ERR_ILSEQ

Unable to convert the text parameters in canonical form to a multibyte string according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.


Next: , Previous: , Up: Defining Instruction Meta-classes   [Contents][Index]

4.2.2.7 Setting the Number of Instruction Outcomes

An instruction class has a specific number of instruction outcomes. Instructions belonging to the instruction class can return those outcomes. A returned outcome may affect further execution of an assembler program.

The number of instruction outcomes must be non-negative. Special value 0 indicates that an instruction may analyze the outcome of previous instruction invoked, use that outcome as its own outcome, or change it to a non-negative value less than the maximum number of outcomes of instruction classes in the instruction class set. The default number of outcomes of every instruction class is 1.

The purpose of the following function is to set the number of instruction outcomes on processing an event QSMM_EVT_INSTR_CLASS_INIT by the event handler of an instruction meta-class.

Function: int qsmm_set_eh_noutcome (qsmm_t model, int noutcome)

This function sets the number of outcomes of an instruction class associated with a processed event. You can call this function from the event handler of a corresponding instruction meta-class of a multinode model on processing an event QSMM_EVT_INSTR_CLASS_INIT.

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 noutcome is negative.

QSMM_ERR_UNTIMELY

The context of calling this function is not the event handler of an instruction meta-class on processing an event QSMM_EVT_INSTR_CLASS_INIT.

Use the following function to get the number of outcomes of an instruction class associated with an event processed by the event handler of an instruction meta-class.

Function: int qsmm_get_eh_noutcome (qsmm_t model)

This function returns the number of outcomes of an instruction class associated with a processed event. You can call this function from the event handler of an instruction meta-class of a multinode model on processing an event QSMM_EVT_INSTR_CLASS_INIT, QSMM_EVT_INSTR_CLASS_DONE, or QSMM_EVT_ACTIVATE.

On success, the function returns a non-negative value. If the context of calling this function is not the event handler of an instruction meta-class on processing an event QSMM_EVT_INSTR_CLASS_INIT, QSMM_EVT_INSTR_CLASS_DONE, or QSMM_EVT_ACTIVATE, the function returns negative error code QSMM_ERR_UNTIMELY.


Previous: , Up: Defining Instruction Meta-classes   [Contents][Index]

4.2.2.8 Function Layout

A template for the event handler of an instruction meta-class:

QSMM_INSTR_META_CLASS(instr_meta_class_name) {
    // TODO: declare (and possibly initialize) automatic variables used in
    //       a more than one "case" branch below.
    struct ic_param_s ic_param;
        // structure "ic_param_s" is for holding the binary parameters of
        // an instruction class
    if (QSMM_HAS_INSTR_CLASS(qsmm_evt))
        qsmm_get_eh_instr_param(qsmm,sizeof(ic_param),&ic_param);
            // fetch the binary parameters of an instruction class
    struct model_param_s *const model_param_p=qsmm_get_ptr(qsmm,0);
        // obtain model parameters specific to this model; a call
        // qsmm_set_ptr(qsmm,0,ptr_p) should have set a pointer ptr_p
        // addressing those parameters
    switch (qsmm_evt) {
        case QSMM_EVT_ENT_INIT:
            // TODO: initialize variables and allocate resources used by
            //       the instruction meta-class for all model runs.
            break;
        case QSMM_EVT_ENT_DONE:
            // TODO: deallocate resources allocated on QSMM_EVT_ENT_INIT.
            break;
        case QSMM_EVT_INSTR_CLASS_INIT:
            qsmm_set_eh_instr_param_str_f(qsmm, fmt,
                                          ic_param.field, ...);
                // set the text parameters of an instruction class;
                // you may access the fields of *model_param_p for
                // model-specific information
            qsmm_set_eh_noutcome(qsmm,noutcome);
                // set the number of outcomes of this instruction class if
                // that number is not equal to 1
            break;
        case QSMM_EVT_INSTR_CLASS_DONE:
            // TODO: deallocate fields of "ic_param_s" (held in "ic_param")
            //       allocated before a call to "qsmm_reg_instr_class_v2";
            //       deallocate resources allocated on
            //       processing QSMM_EVT_INSTR_CLASS_INIT.
            break;
        case QSMM_EVT_ENGINE_INIT:
            // TODO: initialize variables and allocate resources used by
            //       the instruction meta-class for a current model run.
            break;
        case QSMM_EVT_ENGINE_DONE:
            // TODO: deallocate resources allocated on
            //       processing QSMM_EVT_ENGINE_INIT.
            break;
        case QSMM_EVT_ACTIVATE: {
            struct stack_frame_s *stack_frame_p=0;
                // structure "stack_frame_s" is for holding a user frame of
                // node call stack
            qsmm_get_stack_frame(qsmm,0,(void **) &stack_frame_p);
                // obtain a current frame of node call stack
            // TODO: perform custom actions that affect a system or
            //       environment and/or use parameters in *model_param_p,
            //       *stack_frame_p, or "ic_param".
            qsmm_time_delta(qsmm,time_delta);
                // increment continuous time
            qsmm_spur_delta(qsmm,spur_type,spur_delta);
                // increment spur

            // qsmm_node_call_default(qsmm,node,param_p);
            //     call another node with optional parameters

            qsmm_set_instr_outcome(qsmm,outcome);
                // set an instruction outcome if the instruction class has
                // multiple outcomes
            // OR:
            // qsmm_return_to_caller_node(qsmm);
            //     return control to a node that called a current node
            // OR:
            // QSMM_TERMINATE();
            //     terminate model execution

            break;
        }
    }
    return 0;
}

Next: , Previous: , Up: Creating a Multinode Model   [Contents][Index]

4.2.3 Defining Instruction Class Sets

An instruction class set is a container of instruction classes and a node class. The instruction class set defines an assembler instruction set for nodes belonging to the node class and specifies associated model behavior.

A name and event handler function specify an instruction class set. By default, the name of such event handler function is the name of an instruction class set.

The event handler function typically processes the initialization of an instruction class set, loading assembler programs into nodes of a node class represented by the instruction class set on creating the model instance, and transferring control to the nodes and returning control from them during model execution.

The initialization of an instruction class set typically includes adding instruction classes to it, setting the maximum number of node states, and creating nodes belonging to the node class.


Next: , Up: Defining Instruction Class Sets   [Contents][Index]

4.2.3.1 Function Declaration

You should declare or define an instruction class set using the following macro.

Macro: QSMM_INSTR_CLASS_SET (instr_class_set_name)

This macro declares the prototype of a function named instr_class_set_name that represents an instruction class set with the same name and is the event handler function of this instruction class set. You can prepend the macro with the static keyword to declare or define the static function. A pointer to the function has the type qsmm_instr_class_set_func_t. The function has the return type int and the following arguments.

Function argument: qsmm_t qsmm

The handle of a multinode model containing the instruction class set.

Function argument: int qsmm_evt

The type of an event to process by the event handler function: QSMM_EVT_ENT_INIT, QSMM_EVT_ENT_DONE, QSMM_EVT_ENGINE_INIT, QSMM_EVT_ENGINE_DONE, QSMM_EVT_NODE_ENTER, or QSMM_EVT_NODE_LEAVE.

Function argument: int qsmm_node

The identifier of a node that receives or returns control. Is a valid identifier for events QSMM_EVT_NODE_ENTER and QSMM_EVT_NODE_LEAVE. For other events is equal to -1.

Function argument: void * qsmm_param_p

The user parameter of this event handler function. For events QSMM_EVT_ENT_INIT, QSMM_EVT_ENT_DONE, QSMM_EVT_ENGINE_INIT, and QSMM_EVT_ENGINE_DONE, the parameter is equal to the corresponding argument of qsmm_reg_instr_class_set function invoked to register the instruction class set. For events QSMM_EVT_NODE_ENTER and QSMM_EVT_NODE_LEAVE, the parameter is equal to the corresponding argument of qsmm_node_call_default function invoked to call the node.

For example, declare the prototype of a static function representing the instruction class set ‘walker’ as follows:

static QSMM_INSTR_CLASS_SET(walker);

Define the static function ‘walker’ as follows:

static QSMM_INSTR_CLASS_SET(walker) {
    ...
}
Data type: qsmm_instr_class_set_func_t

This is a type of a pointer to the event handler function of an instruction class set. The type has the following declaration:

typedef int
(*qsmm_instr_class_set_func_t)(
    qsmm_t qsmm,
    int qsmm_evt,
    int qsmm_node,
    void *qsmm_param_p
);

See above for a description of arguments of that event handler function. To improve compatibility with future versions of QSMM library, avoid declaring event handler functions with this prototype explicitly—use the macro QSMM_INSTR_CLASS_SET instead.


Next: , Previous: , Up: Defining Instruction Class Sets   [Contents][Index]

4.2.3.2 Event Handling

The event handler function of an instruction class set can process events with types represented by the macros listed below. The argument qsmm_evt of that event handler function specifies an event type.

Macro: QSMM_EVT_ENT_INIT

Instruction class set initialization. The function qsmm_reg_instr_class_set called to register the instruction class set sends this event.

This event can trigger the following operations:

  1. Register instruction classes belonging to the instruction class set by the macros QSMM_REG_INSTR_CLASS and QSMM_REG_INSTR_CLASS_PARAM. See Registering Instruction Classes.
  2. Register controlled probability variables by the macro QSMM_REG_VAR_PROB. See Controlled Variables.
  3. Set the maximum number of states of nodes belonging to a node class represented by the instruction class set by the function qsmm_set_nstate_max. See Setting the Number of States.
  4. Create nodes belonging to the node class by the function qsmm_node_create_v2 or macro QSMM_NODE_CREATE and set the number of states of each created node to a required value by the function qsmm_set_node_nstate. See Creating Nodes.
  5. Associate user parameters with created nodes by the function qsmm_set_node_ptr. See Associating Parameters with a Model.

This event can also trigger initial assignments to variables and allocating resources used by the instruction class set for all model runs.

Macro: QSMM_EVT_ENT_DONE

Instruction class set uninitialization. The function qsmm_destroy called to destroy the multinode model sends this event to all registered event handlers of instruction class sets.

This event can trigger deallocating resources allocated on processing an event QSMM_EVT_ENT_INIT.

Macro: QSMM_EVT_ENGINE_INIT

Model instance initialization. The function qsmm_engine_create called to create the model instance sends this event to all registered event handlers of instruction class sets at the end of execution of that function.

This event can trigger the following operations:

  1. Load assembler programs into nodes by the function qsmm_node_asm. See Loading a Parsed Program into a Node.
  2. Clone node probability profiles by the function qsmm_node_profile_clone. See Cloning the Probability Profile.
  3. Clone node probability profiles in deferred mode by the function qsmm_set_node_profile_source. See Memory Efficient Cloning the Probability Profile.
  4. Set parameters of actors representing the environment state identification engine and instruction emitting engine. See Creating the Model Instance.

This event can also trigger initial assignments to variables and allocating resources used by the instruction class set for a current model run.

Macro: QSMM_EVT_ENGINE_DONE

Model instance uninitialization. The function qsmm_engine_destroy called to destroy the model instance sends this event to all registered event handlers of instruction class sets at the beginning of execution of that function in reverse order relative to the order of sending events QSMM_EVT_ENGINE_INIT. The function qsmm_engine_create calls qsmm_engine_destroy implicitly when recreating the model instance. The function qsmm_destroy calls qsmm_engine_destroy implicitly when destroying the multinode model.

This event can trigger accumulating statistics collected during a current model run and deallocating resources allocated on processing an event QSMM_EVT_ENGINE_INIT.

Macro: QSMM_EVT_NODE_ENTER

Transferring control to a node belonging to a node class represented by the instruction class set. The function qsmm_node_call_default sends this event on calling a node. The event handler receives the identifier of this node via the argument qsmm_node and a user parameter of qsmm_node_call_default via the argument qsmm_param_p. Before sending this event to the event handler, qsmm_node_call_default creates a frame in the node call stack comprised of a system frame and, if user frame size is positive, a user frame.

This event can trigger the initialization of this user frame and setting its fields according to the argument qsmm_param_p.

Macro: QSMM_EVT_NODE_LEAVE

Returning control from a node belonging to a node class represented by the instruction class set. The function qsmm_node_call_default sends this event on finishing calling a node. The event handler receives the identifier of this node via the argument qsmm_node and a user parameter of qsmm_node_call_default via the argument qsmm_param_p. After sending this event to the event handler, qsmm_node_call_default destroys a current frame in the node call stack comprised of a system frame and, if user frame size is positive, a user frame.

This event can trigger setting a value addressed by qsmm_param_p according to the fields of this user frame with its subsequent uninitialization.

On successful completion, the event handler function shall return a non-negative value. A specific non-negative value has no effect on model operation. On error, the event handler function shall return a negative value. Such negative value causes the invocation of an error handler function with passing QSMM_ERR_EVTHNDLR to it if the model has an error handler set.

The name of an instruction class set and the name of its event handler function can be different in special cases. Use the function qsmm_get_eh_instr_class_set_name to get the name of an instruction class set while processing an event by the event handler of this instruction class set.


Next: , Previous: , Up: Defining Instruction Class Sets   [Contents][Index]

4.2.3.3 Registering the Function

Use the following macro to register the event handler function of an instruction class set.

Macro: QSMM_REG_INSTR_CLASS_SET_PARAM (model, instr_class_set_name, paramp)

This macro registers an instruction class set instr_class_set_name for a multinode model. The event handler function of this instruction class set will be receiving the parameter paramp in the argument qsmm_param_p on events QSMM_EVT_ENT_INIT, QSMM_EVT_ENT_DONE, QSMM_EVT_ENGINE_INIT, and QSMM_EVT_ENGINE_DONE. The macro QSMM_INSTR_CLASS_SET should previously define the instruction class set.

The macro QSMM_REG_INSTR_CLASS_SET_PARAM expands to:

qsmm_reg_instr_class_set((model), #instr_class_set_name,
                         &instr_class_set_name, (paramp))

Below there is the description of a function called by the macro QSMM_REG_INSTR_CLASS_SET_PARAM.

Function: int qsmm_reg_instr_class_set (qsmm_t model, const char *instr_class_set_name, qsmm_instr_class_set_func_t instr_class_set_func, void *paramp)

This function registers an instruction class set instr_class_set_name for a multinode model. The function instr_class_set_func is the event handler of this instruction class set. That event handler will be receiving the parameter paramp in the argument qsmm_param_p on events QSMM_EVT_ENT_INIT, QSMM_EVT_ENT_DONE, QSMM_EVT_ENGINE_INIT, and QSMM_EVT_ENGINE_DONE.

After registering the instruction class set, the function sends an event QSMM_EVT_ENT_INIT to the event handler, and it can perform the initialization of that instruction class set.

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_EXIST

A program has already registered an instruction class set or instruction meta-class named instr_class_set_name in the multinode model.

QSMM_ERR_UNTIMELY

The model instance already exists—cannot change model structure.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Use the following function to get a pointer to the event handler of an instruction class set and a user parameter passed to that event handler in certain cases.

Function: int qsmm_get_instr_class_set_handler (qsmm_t model, const char *instr_class_set_name, qsmm_instr_class_set_func_t *instr_class_set_func_p, void **param_pp)

This function retrieves the parameters of the event handler of an instruction class set instr_class_set_name registered for a multinode model. If instr_class_set_func_p is not NULL, the function sets *instr_class_set_func_p to a pointer to that event handler. If param_pp is not NULL, the function sets *param_pp to the value of qsmm_param_p argument of that event handler passed on events QSMM_EVT_ENT_INIT, QSMM_EVT_ENT_DONE, QSMM_EVT_ENGINE_INIT, and QSMM_EVT_ENGINE_DONE.

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_NOTFOUND

The instruction class set instr_class_set_name not found.

QSMM_ERR_TYPE

An entity named instr_class_set_name is not an instruction class set. The entity is an instruction meta-class.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.


Next: , Previous: , Up: Defining Instruction Class Sets   [Contents][Index]

4.2.3.4 Registering Instruction Classes

Every instruction class is an entity related to two other entities: an instruction meta-class and instruction class set. An instruction class is a subclass of an instruction meta-class and is an element of an instruction class set. Identical subclasses of an instruction meta-class can be the elements of multiple instruction class sets. Registering an instruction class must not violate uniqueness constraints listed in Instruction Class Identifiers.

Use the following function to register an instruction class.

Function: int qsmm_reg_instr_class_v2 (qsmm_t model, const char *instr_meta_class_name, const char *instr_class_set_name, int rez1, size_t param_bin_sz, const void *param_bin_p, qsmm_sig_t *instr_class_p)

This function registers an instruction class of a multinode model. The instruction class becomes a subclass of instr_meta_class_name instruction meta-class and an element of instr_class_set_name instruction class set. The arguments param_bin_p and param_bin_sz specify the content and size in bytes of a buffer with binary instruction class parameters. The function copies the buffer to an internal structure. If param_bin_sz is 0, then param_bin_p can be NULL. The argument rez1 is for future use and must be equal to 0.

The function sends an event QSMM_EVT_INSTR_CLASS_INIT to an instruction meta-class event handler. This event can trigger setting text instruction class parameters by the function qsmm_set_eh_instr_param_str_f and the number of instruction outcomes by the function qsmm_set_eh_noutcome.

On success, the function returns a non-negative value and, if instr_class_p is not NULL, sets *instr_class_p to an instruction class index—a number that uniquely identifies a registered instruction class in the instruction class set. On failure, the function returns a negative error code. Currently, the function can return the following error codes.

QSMM_ERR_NOTFOUND

The instruction meta-class instr_meta_class_name or instruction class set instr_class_set_name does not exist.

QSMM_ERR_TYPE

An entity named instr_meta_class_name is not an instruction meta-class, or an entity named instr_class_set_name is not an instruction class set.

QSMM_ERR_EXIST

The instruction class set instr_class_set_name already contains an instruction class derived from the instruction meta-class instr_meta_class_name with the same binary or text parameters. The arguments param_bin_p and param_bin_sz specify the binary parameters. The instruction meta-class event handler can set the text parameters by the function qsmm_set_eh_instr_param_str_f on processing an event QSMM_EVT_INSTR_CLASS_INIT sent by the function qsmm_reg_instr_class_v2.

QSMM_ERR_UNTIMELY

The model instance already exists—cannot change model structure.

QSMM_ERR_VIOLNODE

There exist nodes belonging to a node class represented by the instruction class set instr_class_set_name—cannot change the instruction class set.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Use the following macros to register an instruction class belonging to an instruction class set in the event handler of this instruction class set on processing an event QSMM_EVT_ENT_INIT. The macros expect that the name of the event handler function is equal to the name of the instruction class set and the variable qsmm holding the handle of a multinode model is accessible in the event handler function. Normally, that variable is an event handler function argument.

Macro: QSMM_REG_INSTR_CLASS (meta_class_name)

This macro registers an instruction class derived from an instruction meta-class meta_class_name without binary parameters.

The macro expands to:

qsmm_reg_instr_class_v2((qsmm),#meta_class_name,__FUNCTION__,0,0,0,0)
Macro: QSMM_REG_INSTR_CLASS_PARAM (meta_class_name, param_bin)

This macro registers an instruction class derived from an instruction meta-class meta_class_name with binary parameters in a variable param_bin.

The macro expands to:

qsmm_reg_instr_class_v2((qsmm), #meta_class_name, __FUNCTION__, 0,
                        sizeof(param_bin), &(param_bin), 0)

The binary parameters of an instruction class to register by the macro QSMM_REG_INSTR_CLASS_PARAM must be a variable and not a constant. This is because the macro takes the address of a variable using ‘&’. If you need to specify a constant as the binary parameters, assign the constant to a variable of an appropriate type and pass this variable to QSMM_REG_INSTR_CLASS_PARAM.

For example, to use the element DIRECT_NORTH of direct_e enumeration mentioned in Accessing Binary Instruction Parameters as a binary parameter of an instruction class derived from the instruction meta-class ‘move’, write:

const enum direct_e direct=DIRECT_NORTH;
QSMM_REG_INSTR_CLASS_PARAM(move,direct);

Use the following lines to register instruction classes derived from the instruction meta-class ‘move’ for all movement directions declared by the enumeration direct_e:

for (enum direct_e direct=0; direct<DIRECT_COUNT; direct++)
    QSMM_REG_INSTR_CLASS_PARAM(move,direct);

Use the following function to get the total number of instruction classes contained in an instruction class set. An instruction class index returned by the function qsmm_reg_instr_class_v2 is never greater than or equal to the size of an instruction class set.

Function: int qsmm_get_instr_class_set_sz_v2 (qsmm_t model, const char *instr_class_set_name, int rez1, unsigned int flags, qsmm_sig_t *n_instr_class_p)

This function retrieves the number of instruction classes contained in an instruction class set instr_class_set_name in a multinode model.

If flags contain bitmask QSMM_EXCEPT_NOTFOUND, and the instruction class set does not exist, the function reports QSMM_ERR_NOTFOUND. If flags contain bitmask QSMM_EXCEPT_TYPE, and an entity named instr_class_set_name is not an instruction class set, the function reports QSMM_ERR_TYPE. Bitmask QSMM_EXCEPT_ALL includes QSMM_EXCEPT_NOTFOUND and QSMM_EXCEPT_TYPE.

The argument rez1 is for future use and must be equal to 0.

On success, the function returns a non-negative value and sets *n_instr_class_p if n_instr_class_p is not NULL. If an entity named instr_class_set_name exists and is an instruction class set, the function sets *n_instr_class_p to the number of instruction classes in the instruction class set. If the entity does not exist, and flags do not contain QSMM_EXCEPT_NOTFOUND, the function sets *n_instr_class_p to QSMM_SIG_INVALID. If the entity exists but is not an instruction class set, and flags do not contain QSMM_EXCEPT_TYPE, the function sets *n_instr_class_p to QSMM_SIG_INVALID.

If n_instr_class_p is not NULL, and *n_instr_class_p is 0 or QSMM_SIG_INVALID or would be set to one of these values if n_instr_class_p were not NULL, the function returns 0. If the instruction class set contains a single instruction class, the function returns 1. If the instruction class set contains multiple instruction classes, the function returns 2.

On failure, the function returns a negative error code. Currently, the function can return the following error codes.

QSMM_ERR_NOTFOUND

The instruction class set instr_class_set_name does not exist. The function reports this error if flags include bitmask QSMM_EXCEPT_NOTFOUND. Otherwise, the function sets *n_instr_class_p to QSMM_SIG_INVALID (if n_instr_class_p is not NULL) and returns 0.

QSMM_ERR_TYPE

An entity named instr_class_set_name is not an instruction class set. The entity is an instruction meta-class. The function reports this error if flags include bitmask QSMM_EXCEPT_TYPE. Otherwise, the function sets *n_instr_class_p to QSMM_SIG_INVALID (if n_instr_class_p is not NULL) and returns 0.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Use the following functions to get an instruction class index by an instruction class name.

Function: int qsmm_find_instr_class_in_set_f_v2 (qsmm_t model, qsmm_sig_t *instr_class_p, const char *instr_class_set_name, int rez1, unsigned int flags, const char *fmt, ...)
Function: int qsmm_find_instr_class_in_set_fv_v2 (qsmm_t model, qsmm_sig_t *instr_class_p, const char *instr_class_set_name, int rez1, unsigned int flags, const char *fmt, va_list ap)

These functions retrieve the index of an instruction class in an instruction class set instr_class_set_name in a multinode model by the name of the instruction class. That index as well as name in canonical form uniquely identify the instruction class in the instruction class set. An instruction meta-class name optionally followed by at least one whitespace character and text instruction class parameters make up an instruction class name.

The function qsmm_find_instr_class_in_set_f_v2 formats an instruction class name according to the argument fmt and subsequent arguments interpreted as in the function printf. The function qsmm_find_instr_class_in_set_fv_v2 formats an instruction class name according to the arguments fmt and ap interpreted as in the function vprintf.

Before searching the instruction class in the set, the functions convert the formatted name to canonical form: they remove whitespace characters before the instruction meta-class name, replace whitespace characters after the instruction meta-class name with a single space character, and convert the text parameters of that instruction class to their canonical form according to rules described in Setting Text Instruction Parameters.

If flags contain bitmask QSMM_EXCEPT_NOTFOUND, and the instruction class not found in the instruction class set, the functions report QSMM_ERR_NOTFOUND. The argument rez1 is for future use and must be equal to 0.

On success, the functions return a non-negative value and set *instr_class_p if instr_class_p is not NULL. If the instruction class found in the instruction class set, the functions set *instr_class_p to the index of that instruction class. If the instruction class set exists, but the instruction class not found in it, and flags do not contain QSMM_EXCEPT_NOTFOUND, the functions set *instr_class_p to QSMM_SIG_INVALID.

On failure, the functions return a negative error code. Currently, the functions can return the following error codes.

QSMM_ERR_NOTFOUND

The instruction class set instr_class_set_name does not exist, or the instruction class not found in the instruction class set. In the latter case, the functions report this error if flags include bitmask QSMM_EXCEPT_NOTFOUND; otherwise, the functions set *instr_class_p to QSMM_SIG_INVALID (if instr_class_p is not NULL) and return a non-negative value.

QSMM_ERR_TYPE

An entity named instr_class_set_name is not an instruction class set. The entity is an instruction meta-class.

QSMM_ERR_INVAL

An instruction class name has invalid format.

QSMM_ERR_ILSEQ

Unable to convert an instruction class name to a wide string according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Use the following functions to get information about an instruction class specified by its index.

Function: int qsmm_get_instr_class_name (qsmm_t model, const char *instr_class_set_name, qsmm_sig_t instr_class, const char **instr_class_name_pp)

This function retrieves the canonicalized name of an instruction class specified by its index instr_class in an instruction class set instr_class_set_name in a multinode model. That canonicalized name is the name of an instruction meta-class optionally followed by the space character and the text parameters of this instruction class in their canonical form. The function sets *instr_class_name_pp to the canonicalized name if instr_class_name_pp is not NULL. A pointer returned in *instr_class_name_pp is valid until the next call to this function for this instruction class.

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 instr_class is greater than or equal to the number of instruction classes in the instruction class set instr_class_set_name.

QSMM_ERR_NOTFOUND

The instruction class set instr_class_set_name does not exist.

QSMM_ERR_TYPE

An entity named instr_class_set_name is not an instruction class set. The entity is an instruction meta-class.

QSMM_ERR_ILSEQ

Unable to convert the canonicalized name of an instruction class to a multibyte string according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Function: int qsmm_get_instr_class_meta_name (qsmm_t model, const char *instr_class_set_name, qsmm_sig_t instr_class, const char **instr_meta_class_name_pp)

This function retrieves the name of the instruction meta-class of an instruction class specified by its index instr_class in an instruction class set instr_class_set_name in a multinode model. The function sets *instr_meta_class_name_pp to the instruction meta-class name if instr_meta_class_name_pp is not NULL.

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 instr_class is greater than or equal to the number of instruction classes in the instruction class set instr_class_set_name.

QSMM_ERR_NOTFOUND

The instruction class set instr_class_set_name does not exist.

QSMM_ERR_TYPE

An entity named instr_class_set_name is not an instruction class set. The entity is an instruction meta-class.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Function: int qsmm_get_instr_class_param_str (qsmm_t model, const char *instr_class_set_name, qsmm_sig_t instr_class, const char **param_str_pp)

This function retrieves the canonicalized text parameters of an instruction class specified by its index instr_class in an instruction class set instr_class_set_name in a multinode model. The function sets *param_str_pp to the canonicalized text parameters if param_str_pp is not NULL. If the instruction class does not have text parameters, or its canonicalized text parameters are the empty string, the function sets *param_str_pp to NULL. A pointer returned in *param_str_pp is valid until the next call to this function or the function qsmm_get_eh_instr_param_str for the instruction class.

If the canonicalized text parameters have positive length, the function returns a positive value. If the instruction class does not have text parameters, or its canonicalized text parameters are the empty string, the function returns 0. On failure, the function returns a negative error code. Currently, the function can return the following error codes.

QSMM_ERR_INVAL

The argument instr_class is greater than or equal to the number of instruction classes in the instruction class set instr_class_set_name.

QSMM_ERR_NOTFOUND

The instruction class set instr_class_set_name does not exist.

QSMM_ERR_TYPE

An entity named instr_class_set_name is not an instruction class set. The entity is an instruction meta-class.

QSMM_ERR_ILSEQ

Unable to convert the canonicalized text parameters of an instruction class to a multibyte string according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Function: int qsmm_get_instr_class_param_bin (qsmm_t model, const char *instr_class_set_name, qsmm_sig_t instr_class, size_t *param_bin_sz_p, const void **param_bin_pp)

This function retrieves the binary parameters of an instruction class specified by its index instr_class in an instruction class set instr_class_set_name in a multinode model. If param_bin_sz_p is not NULL, the function sets *param_bin_sz_p to the size of those binary parameters in bytes. If param_bin_pp is not NULL, the function sets *param_bin_pp to a pointer to those binary parameters. If the instruction class does not have binary parameters (i.e. their size is 0), the function sets *param_bin_pp to NULL.

If the instruction class has binary parameters (i.e. their size is positive), the function returns a positive value. If the instruction class does not have binary parameters, the function returns 0. On failure, the function returns a negative error code. Currently, the function can return the following error codes.

QSMM_ERR_INVAL

The argument instr_class is greater than or equal to the number of instruction classes in the instruction class set instr_class_set_name.

QSMM_ERR_NOTFOUND

The instruction class set instr_class_set_name does not exist.

QSMM_ERR_TYPE

An entity named instr_class_set_name is not an instruction class set. The entity is an instruction meta-class.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Function: int qsmm_get_instr_class_noutcome_v2 (qsmm_t model, const char *instr_class_set_name, int rez1, qsmm_sig_t instr_class, qsmm_sig_t *noutcome_p)

This function retrieves the number of outcomes of an instruction class specified by its index instr_class in an instruction class set instr_class_set_name in a multinode model. If noutcome_p is not NULL, the function sets *noutcome_p to the number of outcomes. That number equal to 0 has special meaning described in Setting the Number of Instruction Outcomes. The argument rez1 is for future use and must be equal to 0.

If the instruction class has multiple outcomes, the function returns 2. If the instruction class has a single outcome, the function returns 1. If the instruction class has special number of outcomes 0, the function returns 0. On failure, the function returns a negative error code. Currently, the function can return the following error codes.

QSMM_ERR_INVAL

The argument instr_class is greater than or equal to the number of instruction classes in the instruction class set instr_class_set_name.

QSMM_ERR_NOTFOUND

The instruction class set instr_class_set_name does not exist.

QSMM_ERR_TYPE

An entity named instr_class_set_name is not an instruction class set. The entity is an instruction meta-class.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.


Next: , Previous: , Up: Defining Instruction Class Sets   [Contents][Index]

4.2.3.5 Setting the Number of States

Every node of a multinode model has a certain number of states. One of those states is a current node state. It changes deterministically or stochastically by the environment state identification engine according to the input from the instruction emitting engine and instruction execution environment: the index of last invoked instruction, its outcome, and the look-ahead signal segment if the multinode model uses that segment.

A prerequisite for successful learning a state model by a node is that it has a sufficient number of states. On the other hand, the more states a node has, the more instructions the node generally needs to execute to learn a state model.

The number of states of a just created node is equal to the number of states specified for the node class (represented by an instruction class set) of this node. The number of states specified for the node class is the default number of states for newly created nodes and, at the same time, the maximum allowed number of states of nodes belonging to the node class. After creating a node, you can change its number of states to a value less than maximum allowed one.

Use the following functions to retrieve or set the maximum number of states for a node class.

Function: int qsmm_get_nstate_max_v2 (qsmm_t model, const char *node_class_name, int rez1, unsigned int flags, qsmm_sig_t *nstate_p)

This function retrieves the maximum allowed number of states of nodes belonging to a node class of a multinode model. That number is also the default number of states for newly created nodes belonging to the node class. An instruction class set named node_class_name represents the node class.

If flags contain bitmask QSMM_EXCEPT_NOTFOUND, and the instruction class set does not exist, the function reports QSMM_ERR_NOTFOUND. If flags contain bitmask QSMM_EXCEPT_TYPE, and an entity named node_class_name is not an instruction class set, the function reports QSMM_ERR_TYPE. Bitmask QSMM_EXCEPT_ALL includes QSMM_EXCEPT_NOTFOUND and QSMM_EXCEPT_TYPE.

The argument rez1 is for future use and must be equal to 0.

On success, the function returns a non-negative value and sets *nstate_p if nstate_p is not NULL. If an entity named node_class_name exists and is an instruction class set, the function sets *nstate_p to the maximum allowed number of states for the instruction class set. If the entity does not exist, and flags do not contain QSMM_EXCEPT_NOTFOUND, the function sets *nstate_p to QSMM_SIG_INVALID. If the entity exists but is not an instruction class set, and flags do not contain QSMM_EXCEPT_TYPE, the function sets *nstate_p to QSMM_SIG_INVALID.

On failure, the function returns a negative error code. Currently, the function can return the following error codes.

QSMM_ERR_NOTFOUND

The instruction class set node_class_name does not exist. The function reports this error if flags include bitmask QSMM_EXCEPT_NOTFOUND. Otherwise, the function sets *nstate_p to QSMM_SIG_INVALID (if nstate_p is not NULL) and returns a non-negative value.

QSMM_ERR_TYPE

An entity named node_class_name is not an instruction class set. The entity is an instruction meta-class. The function reports this error if flags include bitmask QSMM_EXCEPT_TYPE. Otherwise, the function sets *nstate_p to QSMM_SIG_INVALID (if nstate_p is not NULL) and returns a non-negative value.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Function: int qsmm_set_nstate_max (qsmm_t model, const char *node_class_name, qsmm_sig_t nstate)

This function sets to nstate the maximum allowed number of states of nodes belonging to a node class of a multinode model. That number is also the default number of states for newly created nodes belonging to the node class. An instruction class set named node_class_name represents the node class.

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 nstate is less than 2.

QSMM_ERR_NOTFOUND

The instruction class set node_class_name does not exist.

QSMM_ERR_TYPE

An entity named node_class_name is not an instruction class set. The entity is an instruction meta-class.

QSMM_ERR_VIOLAP

The model instance exists, and nstate is greater than the number of states of the environment state identification engine. On creating the model instance, the function qsmm_engine_create creates that engine with the number of states equal to a maximum number among the maximum allowed numbers of states specified by qsmm_set_nstate_max for all instruction class sets in the multinode model.

QSMM_ERR_VIOLNODE

The argument nstate is less than the number of states of one or more already created nodes belonging to the node class.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

The default number of states for newly registered instruction class sets is 2.


Previous: , Up: Defining Instruction Class Sets   [Contents][Index]

4.2.3.6 Function Layout

A template for the event handler of an instruction class set:

static QSMM_INSTR_CLASS_SET(instr_class_set_name) {
    // TODO: declare (and possibly initialize) automatic variables used in
    //       a more than one "case" branch below.
    struct stack_frame_s *stack_frame_p=0;
        // structure "stack_frame_s" represents a user stack frame
    struct node_param_s *node_param_p;
        // structure "node_param_s" holds user parameters
        // associated with a node
    struct model_param_s *const model_param_p=qsmm_get_ptr(qsmm,0);
        // obtain model parameters specific to this model; a call
        // qsmm_set_ptr(qsmm,0,ptr_p) should have set a pointer ptr_p
        // addressing those parameters
    switch (qsmm_evt) {
        case QSMM_EVT_ENT_INIT:

            // Register instruction classes.
            QSMM_REG_INSTR_CLASS(meta_class_1);
            QSMM_REG_INSTR_CLASS(meta_class_2);
            // ...
            QSMM_REG_INSTR_CLASS_PARAM(meta_class_a,var_a);
            QSMM_REG_INSTR_CLASS_PARAM(meta_class_b,var_b);
            // ...

            qsmm_set_nstate_max(qsmm,__FUNCTION__,nstate);
                // set the maximum allowed and default number of
                // states for nodes belonging to this node class

            // Create the nodes.
            QSMM_NODE_CREATE(node1);
            QSMM_NODE_CREATE(node2);
            // ...
            QSMM_NODE_CREATE(nodeN);

            // Associate user parameters with created nodes. The pointers
            // ptr1, ptr2, ..., ptrN reference allocated and initialized
            // instances of "node_param_s" structure.
            qsmm_set_node_ptr(qsmm,node1,0,ptr1);
            qsmm_set_node_ptr(qsmm,node2,0,ptr2);
            // ...
            qsmm_set_node_ptr(qsmm,nodeN,0,ptrN);

            // TODO: initialize variables and allocate resources used by
            //       the instruction class set for all model runs.
            // TODO: perform other initialization procedures.
            break;
        case QSMM_EVT_ENT_DONE:
            // TODO: deallocate resources allocated on QSMM_EVT_ENT_INIT.
            break;
        case QSMM_EVT_ENGINE_INIT:

            // Load assembler programs into nodes.
            qsmm_node_asm(qsmm,node1,0,prg1,msglist);
            qsmm_node_asm(qsmm,node2,0,prg2,msglist);
            // ...
            qsmm_node_asm(qsmm,nodeN,0,prgN,msglist);

            // TODO: set the parameters of actors representing the
            //       environment state identification engine and
            //       instruction emitting engine.
            // TODO: initialize variables and allocate resources used by
            //       the instruction class set for a current model run.
            break;
        case QSMM_EVT_ENGINE_DONE:
            // TODO: accumulate statistics collected during a current model
            //       run and deallocate resources allocated on
            //       processing QSMM_EVT_ENGINE_INIT.
            break;
        case QSMM_EVT_NODE_ENTER:
            node_param_p=qsmm_get_node_ptr(qsmm,qsmm_node,0);
                // obtain the parameters of an executed node
            qsmm_get_stack_frame(qsmm,0,(void **) &stack_frame_p);
                // obtain a current frame of node call stack
            // TODO: initialize *stack_frame_p, possibly according to
            //       *node_param_p, *model_param_p, and the content of a
            //       structure addressed by qsmm_param_p.
            break;
        case QSMM_EVT_NODE_LEAVE:
            node_param_p=qsmm_get_node_ptr(qsmm,qsmm_node,0);
                // obtain the parameters of an executed node
            qsmm_get_stack_frame(qsmm,0,(void **) &stack_frame_p);
                // obtain a current frame of node call stack
            // TODO: set the content of a structure addressed by
            //       qsmm_param_p according to *stack_frame_p and,
            //       possibly, *node_param_p* and *model_param_p* and
            //       uninitialize *stack_frame_p.
            break;
    }
    return 0;
}

Next: , Previous: , Up: Creating a Multinode Model   [Contents][Index]

4.2.4 Node Parameters

A model node has the following basic parameters:

  1. Node identifier (index) in the scope of a multinode model. The function qsmm_node_create_v2 and the macro QSMM_NODE_CREATE create a node with a specified identifier. The function qsmm_node_create_v2 can find an unused identifier for a new node. See Creating Nodes.
  2. The number of states. The function qsmm_set_nstate_max called for a node class the node belongs to specifies the default number of node states. That number is also the maximum allowed number of node states. The function qsmm_set_node_nstate can set the number of node states to a lesser value.
  3. An instruction class set specifying a node class for the node. The function qsmm_node_create_v2 has an argument for the name of an instruction class set. The macro QSMM_NODE_CREATE uses ‘__FUNCTION__’ as the name of an instruction class set.
  4. User parameters specified by pointers. The function qsmm_set_node_ptr associates a user pointer with a node. See Associating Parameters with a Model.
  5. A list of controlled probability variables taken from an instruction class set. The function qsmm_reg_var_prob and the macro QSMM_REG_VAR_PROB register a controlled probability variable for the instruction class set. Every list element includes the name of a controlled probability variable, its index, and a probability value. The function qsmm_set_node_var_prob sets the probability value for the node. The initial probability value is 0. See Controlled Variables.
  6. The weights of all instruction classes of an instruction class set. The functions qsmm_set_instr_class_weight, qsmm_set_instr_class_weight_by_name_f, and qsmm_set_instr_meta_class_weight change those weights for the node. By default, all weights are equal to 1. See Setting Instruction Classes Weights.

The existence of model nodes is unrelated to the existence of model instance (see Creating the Model Instance). However, when the model instance exists, the node has extended parameters:

  1. The state transition matrix along with collected statistics for refilling the matrix and keeping it up-to-date maintained by the environment state identification engine. The identifiers of rows of that matrix are quadruples consisting of a previous node state, the index of instruction class of last instruction invoked by the node, the outcome of this instruction, and the content of look-ahead signal segment. The identifiers of columns of that matrix are the indices of next node states. The cells of that matrix hold state transition probabilities with types declared by the enumeration qsmm_prob_e. See Dumping the State Transition Matrix.
  2. The action emission matrix along with collected statistics for refilling the matrix and keeping it up-to-date maintained by the instruction emitting engine. The identifiers of rows of that matrix are the indices of node states. The identifiers of columns of that matrix are the indices of instruction classes. The cells of that matrix hold instruction emission probabilities with types declared by the enumeration qsmm_prob_e. See Dumping the Action Emission Matrix.
  3. A node probability profile written to the state transition matrix and action emission matrix by the function qsmm_node_asm or qsmm_node_profile_clone or copied from the state transition matrix and action emission matrix of another node in deferred mode by the function qsmm_set_node_profile_source. The probability profile occupies the number of states less than or equal to the number of node states specified using the functions qsmm_set_nstate_max and qsmm_set_node_nstate.

    By default, the node has an unset probability profile. The unset probability profile is an implicit uniform probability profile occupying all node states. In this uniform probability profile, the probabilities of transitions between all node states are equal, and the probabilities of emitting all instructions in all node states are equal. The implicit uniform probability profile does not exist for a model:

  4. An indication that the node is the source of a probability profile for other nodes or is a user of a probability profile provided by another node. The function qsmm_set_node_profile_source sets this mode. In this mode, some operations on the node result in reporting QSMM_ERR_PROFSRCP or QSMM_ERR_PROFSRCU respectively. See Memory Efficient Cloning the Probability Profile.
  5. The initial values of controlled probability variables. If the function qsmm_node_asm loads an assembler program into the node, the assembler program specifies those initial values. If the function qsmm_node_profile_clone or qsmm_set_node_profile_source specifies a probability profile for the node, a source node provides those initial values.
  6. Rules for recomputing profile probabilities in cells of the state transition matrix and action emission matrix on changing the values of controlled probability variables. Every element of the list of controlled probability variables additionally contains an indication whether the value of a controlled probability variable set by the function qsmm_set_node_var_prob needs committing to the state transition matrix or action emission matrix by the function qsmm_node_var_realize according to those rules. See Controlled Variables.
  7. Optional names of node states corresponding to their indices. If the function qsmm_node_asm loads an assembler program into the node, the assembler program specifies those names. If the function qsmm_node_profile_clone or qsmm_set_node_profile_source specifies a probability profile for the node, a source node provides those names. The function qsmm_get_node_state_name retrieves the name of a node state by its index. The function qsmm_get_node_state_by_name retrieves the index of a node state by its name.
  8. An assembler program template for disassembling the node by the function qsmm_node_disasm. If the function qsmm_node_asm loads an assembler program with the flag QSMM_ASM_TEMPLATE, the assembler program becomes the template. If the function qsmm_node_profile_clone or qsmm_set_node_profile_source specifies a probability profile for the node, a source node provides the template.
  9. Rules for calculating the values of output probability variables and arrays. If the function qsmm_node_asm loads an assembler program into the node, the assembler program defines the output probability variables and arrays. If the function qsmm_node_profile_clone or qsmm_set_node_profile_source specifies a probability profile for the node, a source node defines the output probability variables and arrays. See Output Variables.
  10. The cache of calculated probabilities of output probability variables and the cache of calculated probabilities of choice alternatives. The function qsmm_get_node_var_prob_out caches the calculated value of an output probability variable. Additionally, that function and the function qsmm_get_node_array_prob_out cache the probabilities of all choice alternatives that include a choice alternative for a calculated output probability variable or array element. The function qsmm_node_var_out_forget called explicitly or implicitly in certain cases clears both caches.
  11. The number of times the function qsmm_node_call_default called the node and the number of times that function transferred control to the node but not yet returned control from it. The functions qsmm_get_node_fq and qsmm_get_node_recurs retrieve those numbers. The initial values are 0. See Calling a Node.

The node parameters tied to the model instance and listed above take the same initial values in case of creating the model instance after creating the node and in case of creating the node after creating the model instance.

The function qsmm_node_unload (see Unloading the Probability Profile) called for a node causes unsetting all node parameters tied to the model instance except for the parameters retrieved by the functions qsmm_get_node_fq and qsmm_get_node_recurs. The unset parameters take their initial values they have just after creating the model instance.


Next: , Previous: , Up: Creating a Multinode Model   [Contents][Index]

4.2.5 Creating Nodes

Use the following function to create a node belonging to a particular node class represented by an instruction class set.

Function: int qsmm_node_create_v2 (qsmm_t model, const char *node_class_name, int rez1, qsmm_sig_t *node_p)

This function creates a node of a multinode model. The node belongs to a node class represented by an instruction class set named node_class_name.

If node_p is NULL, or *node_p is QSMM_SIG_INVALID, the function finds the lowest unused node identifier for the new node; if node_p is not NULL, the function returns that identifier in *node_p. If node_p is not NULL, and *node_p is not QSMM_SIG_INVALID, *node_p specifies an unused identifier of a node to create; in this case, *node_p remains unchanged on function completion. The argument rez1 is for future use and must be equal to 0.

The node takes the initial values of basic parameters listed in Node Parameters. If the model instance exists, the node also takes the initial values of extended parameters listed in that section.

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 node_p is not NULL, and *node_p is not equal to QSMM_SIG_INVALID but is greater than QSMM_SIG_MAX.

QSMM_ERR_NOTFOUND

The instruction class set node_class_name does not exist.

QSMM_ERR_TYPE

An entity named node_class_name is not an instruction class set. The entity is an instruction meta-class.

QSMM_ERR_EXIST

The argument node_p is not NULL, *node_p is not equal to QSMM_SIG_INVALID, and a node with identifier *node_p already exists.

QSMM_ERR_VIOLAP

The model instance exists, and the identifier of a created node would be greater than the highest reserved node identifier (see the function qsmm_node_reserve).

QSMM_ERR_UNTIMELY

The identifier of a created node would exceed QSMM_SIG_MAX.

QSMM_ERR_NOMEM

There was not enough memory to create a node.

Use the following macro to create a node from within the event handler function of an instruction class set where the name of that event handler function is the name of this instruction class set.

Macro: QSMM_NODE_CREATE (node)

This macro expands to:

do {                                                       \
    qsmm_sig_t sig_node=(node);                            \
    qsmm_node_create_v2((qsmm),__FUNCTION__,0,&sig_node);  \
}                                                          \
while (0)

The macro is for creating a model node with identifier node from within the event handler function of an instruction class set representing the node class of this node. The name of that event handler function must be equal to the name of this instruction class set. The variable qsmm holding the handle of a multinode model must be accessible in the event handler function. Normally, that variable is an event handler function argument.

The function qsmm_destroy destroys a multinode model and all its nodes. The following function destroys a specific node.

Function: int qsmm_node_destroy (qsmm_t model, qsmm_sig_t node)

This function destroys a node with identifier node contained in a multinode model. The identifier becomes the unused one. The function destroys all parameters of this node listed in Node Parameters.

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

QSMM_ERR_NOTFOUND

A node with identifier node does not exist.

QSMM_ERR_PROFSRCP

A node with identifier node is the source of a probability profile for other nodes. See Memory Efficient Cloning the Probability Profile, for more information on this mode.

QSMM_ERR_STORAGE

A failure of statistics storage of a large actor representing the environment state identification engine. This error can leave the node in inconsistent state. If after removing a reason of this error a repeated call to this function succeeds, it completely destroys the node.

QSMM_ERR_STATS

Inconsistent statistics on an action choice state or cycle type detected for a large actor representing the environment state identification engine. This error can leave the node in inconsistent state. If after removing a reason of this error a repeated call to this function succeeds, it completely destroys the node.

QSMM_ERR_ILSEQ

For a large actor representing the environment state identification engine, a statistics storage access function generated an error message but cannot convert it to a wide string according to a current locale, or a storage redirection function reported QSMM_ERR_ILSEQ. This error can leave the node in inconsistent state. If after removing a reason of this error a repeated call to this function succeeds, it completely destroys the node.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation. This error can leave the node in inconsistent state. If after removing a reason of this error a repeated call to this function succeeds, it completely destroys the node.

Use the function described below to get the name of node class of a node. You can also use this function to test whether a node with a particular identifier exists.

Function: const char * qsmm_get_node_class_name (qsmm_t model, qsmm_sig_t node)

This function returns the name of instruction class set of a node with identifier node contained in a multinode model. If the node does not exist, the function returns NULL.

At present, QSMM has the following limitation: after creating the model instance, the function qsmm_node_create_v2 and macro QSMM_NODE_CREATE cannot create nodes with identifiers greater than the highest reserved node identifier known before creating the model instance. That highest reserved identifier is a maximum number among the highest identifier of a node created by qsmm_node_create_v2 or QSMM_NODE_CREATE (before creating the model instance) and the highest identifier reserved by the function described below. The default highest reserved identifier is 0.

Currently, the highest reserved node identifier also defines whether tuples encoding the action choice states of the environment state identification engine and instruction emitting engine contain a node identifier: if the highest reserved identifier is positive, the tuples contain the node identifier, otherwise they do not contain the node identifier. If the highest reserved identifier is 0, the function qsmm_node_call_default never generates an assembler program to set a default uniform probability profile.

Function: int qsmm_node_reserve (qsmm_t model, int node)

This function ensures that after creating the instance of a multinode model the function qsmm_node_create_v2 and macro QSMM_NODE_CREATE are able to create nodes with identifiers up to node inclusively. The highest reserved node identifier is currently a parameter for creating the environment state identification engine and instruction emitting engine. If the model instance already exists, the function qsmm_node_reserve only checks that node does not exceed a known highest reserved identifier.

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 node is negative or greater than QSMM_SIG_MAX.

QSMM_ERR_UNTIMELY

The model instance already exists, and node is greater than the current highest reserved identifier.

Use the following function to get the number of existing nodes in a model.

Function: qsmm_sig_t qsmm_get_nnode (qsmm_t model)

This function returns the number of nodes in a multinode model.

A newly created node has the number of states equal to the maximum allowed number of node states specified for the instruction class set of this node. See Setting the Number of States, for the descriptions of qsmm_get_nstate_max and qsmm_set_nstate_max functions for retrieving and setting that maximum allowed number of states. If a small actor represents the environment state identification engine, or the highest reserved node identifier is positive, you can change the number of node states to a lesser value by the function qsmm_set_node_nstate. If a large actor represents the environment state identification engine or instruction emitting engine, the highest reserved node identifier is positive, and the function qsmm_node_call_default already called the node, that function loaded a default uniform probability profile into the node, so qsmm_set_node_nstate cannot change the number of node states to a lesser value.

Use the following functions to retrieve or set the number of node states.

Function: int qsmm_get_node_nstate_v2 (qsmm_t model, int rez1, unsigned int flags, qsmm_sig_t node, qsmm_sig_t *nstate_p)

This function retrieves the number of states of a node with identifier node contained in a multinode model.

The argument rez1 is for future use and must be equal to 0.

On success, the function returns a non-negative value and sets *nstate_p if nstate_p is not NULL. If the node exists, the function sets *nstate_p to the number of node states. If the node does not exist, and flags do not contain bitmask QSMM_EXCEPT_NOTFOUND, the function sets *nstate_p to QSMM_SIG_INVALID.

If the node does not exist, and flags contain QSMM_EXCEPT_NOTFOUND, the function returns negative error code QSMM_ERR_NOTFOUND.

Function: int qsmm_set_node_nstate (qsmm_t model, qsmm_sig_t node, qsmm_sig_t nstate)

This function sets to nstate the number of states of a node with identifier node contained in a multinode model.

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 nstate is less than 2 or greater than the maximum allowed number of states specified for the instruction class set of this node.

QSMM_ERR_NOTFOUND

A node with identifier node does not exist.

QSMM_ERR_NOSTATE

The node has a probability profile loaded, and nstate is less than the number of states occupied by the probability profile.

QSMM_ERR_PROFSRCU

The node is a user of a probability profile provided by another node. See Memory Efficient Cloning the Probability Profile, for more information on this mode.

QSMM_ERR_NOTSUP

A large actor represents the environment state identification engine, and the highest reserved node identifier is 0. Use the function qsmm_set_nstate_max to set the number of states of this node before creating it.


Next: , Previous: , Up: Creating a Multinode Model   [Contents][Index]

4.2.6 Creating the Model Instance

A multinode model can have an instance holding the parameters of this model specific to its single run against input data or its single course of interaction with external entities. That is, a model represents the structure of a system, and the model instance is this system created to carry out a particular process of interaction or computation—a process of model execution. After finishing the process of model execution, a program can accumulate learned model parameters and recreate the model instance for a new process of model execution. Multiple model runs would provide the average values of learned model parameters.

Creating the model instance includes creating the environment state identification engine and instruction emitting engine. The function qsmm_engine_create creates both engines with parameters complying with every registered instruction class set and every created node. The function qsmm_destroy implicitly destroys the model instance if it exists.

When the model instance exists, nodes have extended parameters listed in Node Parameters. A node takes the initial values of those extended parameters on creating the model instance after creating the node and on creating the node after creating the model instance. All nodes lose their extended parameters on destroying the model instance.

When the model instance exists, attempts to register instruction meta-classes, instruction classes, and instruction class sets and create nodes with identifiers greater than the highest reserved node identifier result in reporting QSMM_ERR_UNTIMELY. You can reserve the highest node identifier before creating the model instance—explicitly by the function qsmm_node_reserve or implicitly by creating a node with that identifier by the function qsmm_node_create_v2 or macro QSMM_NODE_CREATE.

Use the following function to create the model instance.

Function: int qsmm_engine_create (qsmm_t model)

This function creates the instance of a multinode model. A model instance holds parameters specific to a particular process of interaction or computation performed using a model with certain structure. If the model instance already exists, the function first destroys it.

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

QSMM_ERR_BIGMDL

The multinode model has too many variants of content of look-ahead signal segment or contains too many nodes or an instruction class set with a too large maximum allowed number of states or an instruction class set with too many instruction classes or outcomes of those instruction classes.

QSMM_ERR_NOIC

The multinode model contains an instruction class set without instruction classes.

QSMM_ERR_NOMEM

There was not enough memory to create the model instance.

Use the following function to destroy the model instance.

Function: void qsmm_engine_destroy (qsmm_t model)

This function destroys the instance of a multinode model. Destroying that instance includes destroying the environment state identification engine and instruction emitting engine and removing all statistics they might have collected. If the model instance does not exist, the function has no effect. The destruction of model instance removes restrictions on changing model structure imposed when creating the instance.

In the current implementation, an object called actor pair referred to by an actor pair handle is a container of the environment state identification engine and instruction emitting engine in the scope of model instance.

Data type: qsmm_actpair_t

This is a type for an actor pair handle. It is a pointer, so variables of this type can be NULL. The function qsmm_get_actpair returns the handle of an actor pair corresponding to the model instance. That handle is valid until destroying the model instance.

Use the following function to get an actor pair associated with the model instance.

Function: qsmm_actpair_t qsmm_get_actpair (qsmm_t model)

This function returns the handle of an actor pair associated with the instance of a multinode model. That handle is valid until destroying the model instance. If the model instance does not exist, the function returns NULL.

Use the functions described below to get the actors comprising an actor pair and representing the environment state identification engine and instruction emitting engine.

Function: qsmm_actor_t qsmm_get_actpair_actor_env (qsmm_actpair_t actpair)

This function returns the handle of an actor representing the environment state identification engine in an actor pair actpair. This function never returns NULL.

Function: qsmm_actor_t qsmm_get_actpair_actor_opt (qsmm_actpair_t actpair)

This function returns the handle of an actor representing the instruction emitting engine in an actor pair actpair. This function never returns NULL.

To be confident that all key parameters of the environment state identification engine and instruction emitting engine have expected values, explicitly set those parameters after creating the model instance. If the variable qsmm holds the handle of a multinode model, use the following lines of code to assign to the variable actor_env the handle of the environment state identification engine and assign to the variable actor_iee the handle of the instruction emitting engine:

const qsmm_actpair_t actpair=qsmm_get_actpair(qsmm);
const qsmm_actor_t actor_env=qsmm_get_actpair_actor_env(actpair),
    actor_iee=qsmm_get_actpair_actor_opt(actpair);

Some parameters are applicable to a small actor associated with a large actor representing the environment state identification engine. Use the following lines of code to assign the handle of this small actor to the variable actor_env_env:

const qsmm_actor_t actor_env_env=
    qsmm_get_actpair_actor_env(
        qsmm_get_actpair(qsmm_get_actor_large_model(actor_env)));

Some parameters are applicable to a small actor associated with a large actor representing the instruction emitting engine. Use the following lines of code to assign the handle of this small actor to the variable actor_iee_env:

const qsmm_actor_t actor_iee_env=
    qsmm_get_actpair_actor_env(
        qsmm_get_actpair(qsmm_get_actor_large_model(actor_iee)));

Consult with Example of Using the Storage API, for a list of parameters you can set for an actor. The table below summarizes parameters you can set for the aforementioned variables actor_env, actor_iee, actor_env_env, and actor_iee_env—an existing environment state identification engine and instruction emitting engine and their associated small actors if they exist. The table indicates initial parameter values for those actors. Consider explicit setting the initial value of a parameter if a corresponding cell contains “varies”.

Parameter and API function for setting itactor_envactor_ieeactor_
env_env
actor_
iee_env
The mode of behavior: adaptive or random
qsmm_set_actor_random
adaptiveadaptive
The index of a spur type for the automatic spur
qsmm_set_actor_auto_spur_type
0-1varies-1
Discrete time
qsmm_set_actor_discrete_time
0000
Continuous time
qsmm_actor_time_delta
0000
Temperature
qsmm_set_actor_ktemperature
11
Spur values
qsmm_actor_spur_delta
00
Spur weights
qsmm_set_actor_spur_weight
varies1
The way of spur perception: normal or inverse
qsmm_set_actor_spur_perception
normalnormal
The type of time for computing spur increment velocity: discrete or continuous
qsmm_set_actor_spur_time – small actor only
variescontinuousvariescontinuous
The type of a function returning the relative probability of an output signal and, for certain those types, a helper function for computing the relative probability of an output signal
qsmm_set_actor_relprob_type and
qsmm_set_actor_relprob_helper
variesvaries
A function for intercepting the updates of cycle type statistics
qsmm_set_storage_cycle_update_hook for a handle obtained by qsmm_get_actor_storage
NULLNULLNULLNULL

Previous: , Up: Creating a Multinode Model   [Contents][Index]

4.2.7 Associating Parameters with a Model

When creating a multinode model, you can declare the custom parameters of this model as global variables and access them from event handler functions. However, when you create multiple models existing concurrently and sharing the same event handler functions, you may need to associate a number of variables with a particular model.

You can associate a number of pointers with a multinode model. They can address statically or dynamically allocated memory blocks. Every pointer has a unique index. In the simplest case, you can associate a single pointer with index 0 addressing an instance of a structure holding variables specific to a model.

Use the following functions to get a pointer associated with a multinode model or associate a pointer with the model.

Function: void * qsmm_get_ptr (qsmm_t model, int ptr_idx)

This function returns a pointer with index ptr_idx associated with a multinode model. If the model does not have a pointer with this index, or the pointer is NULL, the function returns NULL.

Function: int qsmm_set_ptr (qsmm_t model, int ptr_idx, void *ptr_p)

This function associates a pointer ptr_p with a multinode model. You can fetch this pointer later by index ptr_idx. If a pointer with this index already exists, the function overwrites it.

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 ptr_idx is negative.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

It is possible to associate pointers not only with the entire multinode model but also with its particular nodes. Use the following functions to get a pointer associated with a node or associate a pointer with the node.

Function: void * qsmm_get_node_ptr (qsmm_t model, qsmm_sig_t node, int ptr_idx)

This function returns a pointer with index ptr_idx associated with a node of a multinode model. The argument node specifies the identifier of this node. If the node does not exist, or the node does not have a pointer with this index, or the pointer is NULL, the function returns NULL.

Function: int qsmm_set_node_ptr (qsmm_t model, qsmm_sig_t node, int ptr_idx, void *ptr_p)

This function associates a pointer ptr_p with a node of a multinode model. The argument node specifies the identifier of this node. You can fetch the pointer later by index ptr_idx. If a pointer with this index already exists, the function overwrites it.

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 ptr_idx is negative.

QSMM_ERR_NOTFOUND

A node with identifier node does not exist.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.


Next: , Previous: , Up: Multinode Model   [Contents][Index]

4.3 Executing a Multinode Model

Executing a multinode model is executing its nodes in a model instance scope. The function qsmm_node_call_default starts executing a node. An executed node can call other nodes or finish its own execution causing that function to return control. Executed nodes use a call stack similar to a function call stack. The frames of this stack can contain application-specific information usable in event handler functions.

The execution of a node consists of a series of assembler instruction invocations for the changing current state of this node. The event handler of an instruction meta-class processes the invocations of assembler instructions belonging to instruction classes derived from this instruction meta-class. An invoked instruction returns an outcome the environment state identification engine uses to select the next node state.

As a side effect of processing an instruction invocation, the event handler of an instruction meta-class can increment continuous time, change spur tracked by the environment state identification engine or instruction emitting engine, or modify look-ahead signals taking part in the selection of next node state. If the multinode model operates correctly, the state models of executed nodes are adapting to provide higher spur increment velocity.

To evaluate whether a model provides adaptive behavior, a developer can compare the efficiency of this model in adaptive mode of operation with the efficiency in random mode of operation.


Next: , Up: Executing a Multinode Model   [Contents][Index]

4.3.1 Incrementing Time and Spur

Use the following function to convey to the instance of a multinode model information about passing a continuous time period.

Function: int qsmm_time_delta (qsmm_t model, double time_delta)

This function increments by time_delta continuous time tracked by the environment state identification engine and instruction emitting engine of a multinode model.

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 time_delta is not finite, or incremented continuous time tracked by an engine would be negative.

QSMM_ERR_INFIN

Incremented continuous time tracked by an engine would be positive infinity.

QSMM_ERR_UNTIMELY

The model instance does not exist.

If the environment state identification engine is a small actor, spur types supported by a multinode model have zero-based indices. By default, spur type 0 is the automatic spur, and only the environment state identification engine (not the instruction emitting engine) uses it. Ordinarily, you do not increment the automatic spur directly.

If the environment state identification engine is a large actor, the model supports special spur type -1 for the automatic spur of a small actor associated with the large actor. Ordinarily, you do not increment that automatic spur directly.

Spur type i of a multinode model corresponds to spur type i of the environment state identification engine. The instruction emitting engine has the number of supported spur types equal to the number of spur types specified when creating the model minus 1. If i>0, spur type i of the model corresponds to spur type i-1 of the instruction emitting engine.

Use the following function to increment spur with a specific type for a model instance.

Function: int qsmm_spur_delta (qsmm_t model, int spur_type, double spur_delta)

This function increments by spur_delta spur with type spur_type associated with a multinode model. The argument spur_delta can be negative.

If spur_type is 0 or -1, the function only increments spur with type spur_type tracked by the environment state identification engine. If spur_type is equal to i>0, the function increments spur with type i tracked by the environment state identification engine and spur with type i-1 tracked by the instruction emitting engine.

Spur type 0 is for the automatic spur of the environment state identification engine. If it is a large actor (specified by the field is_large_env of qsmm_desc_s structure when creating the model), spur type -1 corresponds to the automatic spur of a small actor associated with the large actor. The function qsmm_get_nspur returns the number of spur types supported by a multinode model excluding that special spur type -1.

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

One of the following conditions is true:

  • – the environment state identification engine is the small actor, and spur_type is negative;
  • – the environment state identification engine is the large actor, and spur_type is less than -1;
  • spur_type is greater than or equal to the number of spur types specified in the field nspur of qsmm_desc_s structure when creating the multinode model;
  • spur_delta is not finite.
QSMM_ERR_INFIN

Incremented spur tracked by an engine would be infinite.

QSMM_ERR_UNTIMELY

The model instance does not exist.

Use the function qsmm_actor_time_delta to increment continuous time tracked by either the environment state identification engine or instruction emitting engine. Use the function qsmm_actor_spur_delta to increment spur with a specific type tracked by either the environment state identification engine or instruction emitting engine. You can obtain the handles of those engines by the functions qsmm_get_actpair_actor_env and qsmm_get_actpair_actor_opt.


Next: , Previous: , Up: Executing a Multinode Model   [Contents][Index]

4.3.2 Transferring Control between Nodes

The function qsmm_node_call_default transfers control to a node. That function exits when node execution finishes. The event handler of an instruction meta-class can call that function to transfer control to another node in a nested manner while processing an instruction invocation.

To finish the execution of a node, call the function qsmm_return_to_caller_node while handling an instruction invocation for the node.

To terminate the execution of a model, for example, after processing all input data, call the macro QSMM_TERMINATE or the function qsmm_set_continue with flag equal to 0 while processing an instruction invocation. They cause finishing the execution of all nodes in the node call stack. The event handlers of instruction meta-classes may need to analyze a flag returned by the function qsmm_get_continue after a call to qsmm_node_call_default to perform exit from the event handler as soon as possible on terminating model execution.


Next: , Up: Transferring Control between Nodes   [Contents][Index]

4.3.2.1 Calling a Node

Use the following function to call a node.

Function: int qsmm_node_call_default (qsmm_t model, qsmm_sig_t node, void *paramp)

This function transfers control to a node with identifier node in a multinode model, executes the node, and exits when node execution finishes. A just called node resets its current state to initial one. When processing instruction invocations for executed nodes, the event handlers of instruction meta-classes can call this function recursively, including multiple times for the same node.

Transferring control to the node begins with sending an event QSMM_EVT_NODE_ENTER to the event handler of instruction class set of that node with passing the parameter paramp to that event handler. If the node does not have a probability profile specified, the environment state identification engine or instruction emitting engine is a large actor, and the highest reserved node identifier is positive, the function loads a default uniform probability profile into the node. While executing the node, the function sends events QSMM_EVT_ACTIVATE to the event handlers of instruction meta-classes to process the invocations of emitted instructions. On finishing node execution, before returning control to a caller, the function sends an event QSMM_EVT_NODE_LEAVE to the instruction class set with passing the parameter paramp to the event handler.

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_UNTIMELY

The model instance does not exist.

QSMM_ERR_NOTFOUND

A node with identifier node does not exist.

QSMM_ERR_STACKOVR

The number of frames in the node call stack would exceed a value specified in the field stack_sz_max of qsmm_desc_s structure when creating the multinode model. The function qsmm_get_stack_sz_max returns this value.

QSMM_ERR_OUTCOME

While processing an instruction invocation, the event handler of an instruction meta-class set an invalid instruction outcome or did not set an instruction outcome when it was necessary to do so. This error leaves the multinode model in inconsistent state.

QSMM_ERR_CALLBACK

A helper function for computing the relative probability of an output signal assigned to the environment state identification engine or instruction emitting engine reported an error by returning NaN. The function qsmm_actor_calc_action_prob calls the helper function. This error leaves the multinode model in inconsistent state.

QSMM_ERR_INFIN

The function qsmm_actor_reg_sig_in or qsmm_get_actor_sig_action called for the environment state identification engine or instruction emitting engine reported QSMM_ERR_INFIN. This error leaves the multinode model in inconsistent state.

QSMM_ERR_MPROF

No room in the pool of probabilities lists in normal form for a large actor representing the environment state identification engine or instruction emitting engine when loading a default uniform probability profile into the node. The fields profile_pool_env_sz and profile_pool_opt_sz of qsmm_desc_s structure specify the pool sizes when creating the multinode model.

QSMM_ERR_NOPROF

The function cannot generate a uniform probability profile for the node, because the action emission matrices of all nodes have the restriction to define only deterministic action choices (field is_determ_opt of qsmm_desc_s structure specifies this mode), but the instruction class set of that node contains multiple instruction classes. It is necessary to load a probability profile into the node explicitly.

QSMM_ERR_UNSUPPLA

The function cannot load a default uniform probability profile into the node, because the multinode model has positive length of look-ahead signal segment. The field ngram_env_la_sz of qsmm_desc_s structure specifies this length when creating the multinode model.

QSMM_ERR_STORAGE

A Storage API function reported storage failure. This error can leave the multinode model in inconsistent state.

QSMM_ERR_STATS

Inconsistent statistics on an action choice state or cycle type detected. This error can leave the multinode model in inconsistent state.

QSMM_ERR_ILSEQ

Unable to convert a multibyte string to a wide string or vice versa according to a current locale. This error can leave the multinode model in inconsistent state.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation. This error can leave the multinode model in inconsistent state.

Use the following function to get the number of calls of a node since creating the model instance.

Function: int qsmm_get_node_fq (qsmm_t model, qsmm_sig_t node, long *fq_p)

This function retrieves the number of calls to a node with identifier node in a multinode model by the function qsmm_node_call_default since creating the model instance. If the model instance does not exist, the retrieved number of calls is 0. If fq_p is not NULL, the function sets *fq_p to the retrieved number of calls.

On success, the function returns a non-negative value. If the node does not exist, the function returns negative error code QSMM_ERR_NOTFOUND.

Use the function described below to get the number of nested calls to a node. You can use this function to prevent recursive calling a node if the model does not support recursive node calls.

Function: int qsmm_get_node_recurs (qsmm_t model, qsmm_sig_t node)

On success, this function returns a non-negative number of nested calls to a node with identifier node in a multinode model by the function qsmm_node_call_default. If the node does not exist, the function qsmm_get_node_recurs returns negative error code QSMM_ERR_NOTFOUND.


Next: , Previous: , Up: Transferring Control between Nodes   [Contents][Index]

4.3.2.2 Returning Control from a Node

Use the following function in an event handler to return from last nested call to qsmm_node_call_default.

Function: void qsmm_return_to_caller_node (qsmm_t model)

This function sets the flag associated with a multinode model causing the function qsmm_node_call_default to exit. The latter function resets that flag before sending an event QSMM_EVT_NODE_ENTER to the instruction class set and before sending an event QSMM_EVT_ACTIVATE to an instruction meta-class and checks the flag after processing these events. In case of calling the function qsmm_return_to_caller_node while processing the event QSMM_EVT_ACTIVATE by the instruction meta-class, qsmm_node_call_default ignores a set instruction outcome.


Previous: , Up: Transferring Control between Nodes   [Contents][Index]

4.3.2.3 Terminating Model Execution

Model execution terminates after processing all input data or performing a course of interaction with external entities—all nodes return control, and the node call stack becomes empty.

The model instance has a flag indicating whether or not to continue model execution: a non-zero flag indicates to continue model execution, and zero flag indicates to terminate model execution with reporting success. The function qsmm_engine_create initializes the flag to a non-zero value when creating the model instance.

Use the following functions to query or set the flag.

Function: int qsmm_get_continue (qsmm_t model)

This function returns the flag specifying whether or not to continue the execution of a multinode model. If the function returns a positive value, model execution continues. If the function returns zero, model execution terminates. If the model instance does not exist, the function returns negative error code QSMM_ERR_UNTIMELY.

Function: int qsmm_set_continue (qsmm_t model, int flag)

This function sets the flag specifying whether or not to continue the execution of a multinode model. If flag is non-zero, model execution continues. If flag is zero, model execution terminates.

On success, the function returns a non-negative value. If the model instance does not exist, the function returns negative error code QSMM_ERR_UNTIMELY.

Zero flag causes returning from all nested calls to the function qsmm_node_call_default as if after calling the function qsmm_return_to_caller_node in the event handlers of instruction meta-classes on processing an event QSMM_EVT_ACTIVATE for all nodes in the node call stack. The function qsmm_node_call_default checks the flag at the beginning of its execution, and, if the flag is zero, the function exits immediately. That function also checks the flag (and possibly exits) after sending an event QSMM_EVT_NODE_ENTER to the instruction class set and after sending an event QSMM_EVT_ACTIVATE to an instruction meta-class. The event handler of an instruction meta-class can analyze the flag explicitly by calling the function qsmm_get_continue after a call to qsmm_node_call_default while processing an event QSMM_EVT_ACTIVATE to perform immediate exit from the event handler in case of terminating model execution.

Use the following macro to set the flag to zero.

Macro: QSMM_TERMINATE ()

This macro expands to:

qsmm_set_continue((qsmm), 0)

You can use this macro to terminate the execution of a multinode model from within an event handler, where its argument qsmm is equal to the handle of this multinode model.

For example, you can call this macro in a block of code handling the invocation of an instruction (in the event handler of an instruction meta-class on processing an event QSMM_EVT_ACTIVATE) to terminate the execution of a multinode model when the instruction fetches all input data of this multinode model.


Next: , Previous: , Up: Executing a Multinode Model   [Contents][Index]

4.3.3 Handling Instruction Invocation

During the execution of a multinode model, its nodes execute instructions. When a node has to invoke an instruction, the node triggers an event QSMM_EVT_ACTIVATE of the instruction meta-class of this instruction.

On triggering the event QSMM_EVT_ACTIVATE, the function qsmm_node_call_default passes the identifier of that node to the event handler of that instruction meta-class via the argument qsmm_node. The event handler can fetch the binary parameters of the instruction class of this instruction by calling the function qsmm_get_eh_instr_param. The function qsmm_get_eh_instr_class_set_name retrieves the name of an instruction class set containing the instruction class. To fetch from the current frame of node call stack (see Working with the Node Call Stack) index idx that uniquely identifies the instruction class in the instruction class set, use this call:

qsmm_get_stack_instr_class(qsmm,0,&idx);

While processing an event QSMM_EVT_ACTIVATE, the event handler of an instruction meta-class can make changes to an environment or:

  1. Set an instruction outcome by the function qsmm_set_instr_outcome. This operation is mandatory in certain cases.
  2. Increment the current values of time and spur by the functions qsmm_time_delta and qsmm_spur_delta. See Incrementing Time and Spur.
  3. Call nodes by the function qsmm_node_call_default. See Calling a Node.
  4. Return control to a caller node by the function qsmm_return_to_caller_node. See Returning Control from a Node.
  5. Terminate model execution by the function qsmm_set_continue or macro QSMM_TERMINATE. See Terminating Model Execution.
  6. Access user frames in the node call stack obtained by the function qsmm_get_stack_frame. See Working with the Node Call Stack.
  7. Change look-ahead signals by the function qsmm_set_la_sig. See Setting Look-ahead Signals.
  8. Change the weights of instruction classes by the functions qsmm_set_instr_class_weight, qsmm_set_instr_class_weight_by_name_f, and qsmm_set_instr_meta_class_weight. See Setting Instruction Classes Weights.

An instruction outcome affects the selection of next node state after an instruction invocation. Use the following functions to query or set an instruction outcome.

Function: void qsmm_get_instr_outcome (qsmm_t model, int *outcome_p)

This function retrieves an instruction outcome associated with a multinode model. If outcome_p is not NULL, the function sets *outcome_p to a retrieved outcome.

An instruction outcome associated with a multinode model is last instruction outcome set by the function qsmm_set_instr_outcome while processing an instruction invocation event. If there was no call to qsmm_set_instr_outcome, and the instruction class has a positive number of outcomes, instruction outcome returned is -1. If there was no call to qsmm_set_instr_outcome, and the instruction class has zero number of outcomes, instruction outcome returned is the outcome of previous instruction invoked by the node after transferring control to it or 0 if there was no such instruction.

Function: int qsmm_set_instr_outcome (qsmm_t model, int outcome)

This function sets to outcome the instruction outcome associated with a multinode model. The function performs only a preliminary check on the validity of that outcome. The function qsmm_node_call_default performs final checks after a return from the event handler of a corresponding instruction meta-class, and, if the outcome is invalid, that function reports QSMM_ERR_OUTCOME.

On success, the function returns a non-negative value. If outcome is less than -1, the function returns negative error code QSMM_ERR_INVAL.

The function qsmm_set_eh_noutcome specifies the number of instruction outcomes during instruction class initialization. The default number of instruction outcomes used in case of omitting a call to that function is equal to 1. The number of instruction outcomes equal to 0 has special meaning.

Before calling the event handler of an instruction meta-class to process an event QSMM_EVT_ACTIVATE, the function qsmm_node_call_default sets the instruction outcome associated with the multinode model to -1 if the instruction class has a positive number of outcomes. If the instruction class has zero number of outcomes, qsmm_node_call_default sets the instruction outcome associated with the multinode model to the outcome of previous instruction invoked by the node after transferring control to it or to 0 if there was no such instruction.

After calling the event handler of an instruction meta-class to process an event QSMM_EVT_ACTIVATE, if node execution continues, the instruction outcome associated with the multinode model is equal to -1, and the number of outcomes of an instruction class is equal to 1, qsmm_node_call_default uses outcome 0 to select the next node state. This behavior makes it possible to omit calls to the function qsmm_set_instr_outcome for instruction classes with only one possible instruction outcome.

If after calling the event handler node execution continues, the instruction outcome associated with the multinode model is equal to -1, and the number of outcomes of an invoked instruction class is not equal to 1, qsmm_node_call_default reports QSMM_ERR_OUTCOME. This check compels to set an instruction outcome by qsmm_set_instr_outcome if the number of outcomes of an invoked instruction class is greater than 1.

If the instruction class has zero number of outcomes, the event handler of a corresponding instruction meta-class can call the function qsmm_get_instr_outcome on processing an event QSMM_EVT_ACTIVATE to analyze the outcome of previous instruction invoked by the node after transferring control to it. The event handler can leave that outcome intact or change it to a non-negative value less than the maximum number among the numbers of outcomes of instruction classes in the instruction class set of that node.

The functions described below return the probability of last state transition for a currently executed node and the probability of last instruction emission in a current node state. The probabilities have the type QSMM_PROB_AGGR and are in cells of the state transition matrix and action emission matrix of this node. You can call these functions while processing an event QSMM_EVT_ACTIVATE by the event handler of an instruction meta-class, for example, to compute the time when an instruction has to take effect.

Function: double qsmm_get_prob_goto (qsmm_t model)

This function returns the probability of last state transition performed just before last instruction invocation by a node of a multinode model. That probability has the type QSMM_PROB_AGGR and is in a cell of state transition matrix of this node. If the nodes of this model did not yet invoke instructions, the function returns 0. A returned value is always in the range 0 to 1 inclusive.

Function: double qsmm_get_prob_action (qsmm_t model)

This function returns the probability of last instruction emission in the current state of a node of a multinode model just after performing last state transition. That probability has the type QSMM_PROB_AGGR and is in a cell of action emission matrix of this node. If the nodes of this model did not yet invoke instructions, the function returns 0. A returned value is always in the range 0 to 1 inclusive.


Next: , Previous: , Up: Executing a Multinode Model   [Contents][Index]

4.3.4 Setting Look-ahead Signals

Look-ahead signals are signals that along with an instruction class index and an instruction outcome take part in selecting the next node state after an instruction invocation. The adjective “look-ahead” indicates that in some situations those signals can convey look-ahead information. For example, when processing a sequence of symbols from left to right, a multinode model can analyze look-ahead symbols as look-ahead signals. In other situations, those signals can pass even look-back information to the model.

When creating a multinode model by the function qsmm_create, the fields ngram_env_la_sz, nsig_ngram_env_la, and range_sig_env_la_p of qsmm_desc_s structure specify the length of the look-ahead signal segment of this model and the ranges of signals assignable to the elements of that segment. You can retrieve those parameters later by the functions qsmm_get_ngram_env_la_sz and qsmm_get_nsig_ngram_env_la called for this multinode model and by the function qsmm_get_actor_range_sig called for the environment state identification engine.

An important limitation imposed on a multinode model when its look-ahead signal segment has positive length is that the function qsmm_node_asm cannot load assembler programs into the nodes of this model. This limitation also prevents loading default uniform probability profiles into the nodes of this model using implicitly generated assembler programs when the highest reserved node identifier is positive, and the environment state identification engine or instruction emitting engine is a large actor—in this case, the model is unusable. Therefore, if you need to use a look-ahead signal segment with positive length for a model with the environment state identification engine or instruction emitting engine represented by a large actor, use the model containing a single node with identifier 0.

Use the following functions to query or set signals in the look-ahead signal segment at specific positions.

Function: int qsmm_get_la_sig (qsmm_t model, int pos, qsmm_sig_t *sigp)

If sigp is not NULL, this function sets *sigp to an element of look-ahead signal segment of a multinode model at position pos.

On success, the function returns a non-negative value. If pos is negative or greater than or equal to the length of look-ahead signal segment, the function returns negative error code QSMM_ERR_INVAL.

Function: int qsmm_set_la_sig (qsmm_t model, int pos, qsmm_sig_t sig)

This function sets an element of look-ahead signal segment of a multinode model at position pos to sig.

On success, the function returns a non-negative value. If pos is negative or greater than or equal to the length of look-ahead signal segment, or sig does not belong to a range of allowed signal identifiers at position pos in the look-ahead signal segment, the function returns negative error code QSMM_ERR_INVAL.

You can call the functions qsmm_get_la_sig and qsmm_set_la_sig at any point after creating a multinode model. For example, you can call them while processing an event QSMM_EVT_NODE_ENTER by the event handler of an instruction class set or an event QSMM_EVT_ACTIVATE by the event handler of an instruction meta-class.

If the field range_sig_env_la_p of qsmm_desc_s structure is NULL, the function qsmm_create initializes the elements of look-ahead signal segment to 0. If that field is not NULL, qsmm_create initializes the elements of look-ahead signal segment to the values of first field in the corresponding elements of range_sig_env_la_p array.

See the file tests/lookup2.c for an example program that uses the look-ahead signal segment.


Next: , Previous: , Up: Executing a Multinode Model   [Contents][Index]

4.3.5 Setting Instruction Classes Weights

If the field dont_use_instr_class_weights of qsmm_desc_s structure passed to the function qsmm_create when creating a multinode model is zero, and the instruction emitting engine is a small actor, you can assign weights to instruction classes executed5 by a node of this model. The weights are multipliers for calculated probabilities of selection of those instruction classes by the instruction emitting engine assigned to its output signals by the function qsmm_set_actor_sig_weight. The function qsmm_node_create_v2 initializes to 1 the weights of all instruction classes executable by a node.

Warning: changing the weights of instruction classes leads to ill-defined behavior of built-in functions for computing the relative probability of an output signal by the instruction emitting engine. Therefore, avoid changing the weights of instruction classes if you use those built-in functions. See Number of Output Signals, for the explanation why the behavior becomes ill-defined.

You can use the following functions to query or set the weight of an instruction class specified by its index uniquely identifying the instruction class in an instruction class set.

Function: int qsmm_get_instr_class_weight (qsmm_t model, qsmm_sig_t node, qsmm_sig_t instr_class, double *weight_p)

This function retrieves the weight of an instruction class executable by a node of a multinode model. The argument node specifies the identifier of this node. The argument instr_class specifies the index of this instruction class in the instruction class set of this node. If weight_p is not NULL, the function sets *weight_p to retrieved weight.

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_NOTFOUND

A node with identifier node does not exist.

QSMM_ERR_INVAL

The argument instr_class is greater than or equal to the number of instruction classes in the instruction class set of the node.

QSMM_ERR_NOTSUP

The multinode model does not support assigning weights to instruction classes.

Function: int qsmm_set_instr_class_weight (qsmm_t model, qsmm_sig_t node, qsmm_sig_t instr_class, double weight)

This function sets to weight the weight of an instruction class executable by a node of a multinode model. The argument node specifies the identifier of this node. The argument instr_class specifies the index of this instruction class in the instruction class set of this node.

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_NOTFOUND

A node with identifier node does not exist.

QSMM_ERR_INVAL

The argument weight is negative or not finite, or instr_class is greater than or equal to the number of instruction classes in the instruction class set of the node.

QSMM_ERR_NOTSUP

The multinode model does not support assigning weights to instruction classes.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Use the following functions to query or set the weight of an instruction class specified by its name consisting of an instruction meta-class name and optional text parameters of this instruction class.

Function: int qsmm_get_instr_class_weight_by_name_f (qsmm_t model, qsmm_sig_t node, double *weight_p, const char *fmt, ...)
Function: int qsmm_set_instr_class_weight_by_name_f (qsmm_t model, qsmm_sig_t node, double weight, const char *fmt, ...)

The function qsmm_get_instr_class_weight_by_name_f retrieves the weight of an instruction class executable by a node of a multinode model. If weight_p is not NULL, the function sets *weight_p to retrieved weight. The function qsmm_set_instr_class_weight_by_name_f sets to weight the weight of an instruction class executable by a node of a multinode model.

The argument model specifies a multinode model handle. The argument node specifies a node identifier. The argument fmt and subsequent arguments interpreted as in the function printf specify an instruction class name: a sequence of zero or more whitespace characters, an instruction meta-class name optionally followed by a sequence of one or more whitespace characters and the text parameters of this instruction class, and a sequence of zero or more whitespace characters.

Before searching the instruction class in the instruction class set of this node, the functions convert the formatted name to the canonical form: the instruction meta-class name optionally followed by the space character and the text parameters of this instruction class converted to their canonical form according to rules described in Setting Text Instruction Parameters.

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

QSMM_ERR_NOTFOUND

A node with identifier node does not exist, or the instruction class not found in the instruction class set of this node.

QSMM_ERR_INVAL

The argument weight is negative or not finite, or an instruction class name has invalid format.

QSMM_ERR_NOTSUP

The multinode model does not support assigning weights to instruction classes.

QSMM_ERR_ILSEQ

Unable to convert an instruction class name to a wide string according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

For example, to set the weight of ‘move north’ instruction class to 0 to disable moving an agent in the north direction, use a line of code like this:

qsmm_set_instr_class_weight_by_name_f(qsmm,node,0,"move north");

Use the following function to set to the same value the weights of all instruction classes derived from an instruction meta-class for a node.

Function: int qsmm_set_instr_meta_class_weight (qsmm_t model, const char *instr_meta_class_name, qsmm_sig_t node, double weight)

This function sets the weights of all instruction classes derived from an instruction meta-class instr_meta_class_name and executable by a node of a multinode model to weight divided by the number of those instruction classes. The argument node specifies the identifier of this node.

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_NOTFOUND

The instruction meta-class instr_meta_class_name not found, or a node with identifier node does not exist, or there are no instruction classes derived from that instruction meta-class in the instruction class set of this node.

QSMM_ERR_INVAL

The argument weight is negative or not finite.

QSMM_ERR_TYPE

An entity named instr_meta_class_name is not an instruction meta-class. The entity is an instruction class set.

QSMM_ERR_NOTSUP

The multinode model does not support assigning weights to instruction classes.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

The function qsmm_node_call_default sets the weights of output signals of instruction emitting engine equal to the weights of instruction classes executable by a node on transferring control to it—calling the node or returning control to it from another node. The aforementioned functions for setting the weights of instruction classes immediately update the weights of corresponding output signals of instruction emitting engine if the model instance exists, the node call stack is not empty, and the identifier of a currently executed node is equal to node.


Next: , Previous: , Up: Executing a Multinode Model   [Contents][Index]

4.3.6 Working with the Node Call Stack

The node call stack contains information about nodes that received control but have not yet returned it. A node can occur in multiple stack frames if calls to the node are recursive. The field stack_sz_max of qsmm_desc_s structure specifies a limit on the number of frames in the stack. The function qsmm_get_stack_sz_max returns this limit. The following function returns the current number of frames in the stack.

Function: int qsmm_get_stack_sz (qsmm_t model)

This function returns the current number of frames in the node call stack of a multinode model. A returned value is always non-negative.

A system stack frame is the system part of a frame of node call stack. Each system stack frame contains the following information:

Use the following functions to fetch the aforementioned pieces of information from the system part of a node call stack frame at specified depth.

Function: int qsmm_get_stack_node (qsmm_t model, int depth)

This function returns the non-negative identifier of a called node stored in the system part of a frame of node call stack of a multinode model at depth. Depth 0 corresponds to the current stack frame, depth 1 corresponds to the previous stack frame, and so on.

On failure, the function returns a negative error code. Currently, the function can return the following error codes.

QSMM_ERR_UNTIMELY

The node call stack is empty.

QSMM_ERR_INVAL

The argument depth is negative or greater than or equal to the number of frames in the node call stack returned by the function qsmm_get_stack_sz.

Function: int qsmm_get_stack_state (qsmm_t model, int depth)

This function returns the non-negative index of a node state stored in the system part of a frame of node call stack of a multinode model at depth. The environment state identification engine has identified this node state. If the state is yet unknown (this is the case if the event handler of an instruction class set called this function on processing an event QSMM_EVT_NODE_ENTER), the function returns 0. Depth 0 corresponds to the current stack frame, depth 1 corresponds to the previous stack frame, and so on.

On failure, the function returns a negative error code. Currently, the function can return the following error codes.

QSMM_ERR_UNTIMELY

The node call stack is empty.

QSMM_ERR_INVAL

The argument depth is negative or greater than or equal to the number of frames in the node call stack returned by the function qsmm_get_stack_sz.

Function: int qsmm_get_stack_instr_class (qsmm_t model, int depth, int *idx_p)

This function retrieves the index of instruction class of last instruction invoked by a node of a multinode model. The function fetches that index from the system part of a frame of node call stack at depth. If idx_p is not NULL, the function sets *idx_p to a fetched index. If the node did not yet invoke any instructions since creating the frame in the node call stack, the fetched index is -1. Depth 0 corresponds to the current stack frame, depth 1 corresponds to the previous stack frame, and so on.

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_UNTIMELY

The node call stack is empty.

QSMM_ERR_INVAL

The argument depth is negative or greater than or equal to the number of frames in the node call stack returned by the function qsmm_get_stack_sz.

See Registering Instruction Classes, for the means of obtaining information about an instruction class specified by its index.

A user stack frame is the user part of a frame of node call stack. The user stack frame contains application-specific information associated with a called node for handling instruction invocations—the execution context of this node.

A user stack frame is typically an instance of a structure declared in an application program. The purpose of functions described below is to query or set the size of this frame. You should set the size of a user stack frame before creating the model instance by the function qsmm_engine_create.

Function: size_t qsmm_get_stack_frame_sz (qsmm_t model)

This function returns the size (in bytes) of the user part of each frame in the node call stack of a multinode model. If the model does not use that user part, the function returns 0.

Function: int qsmm_set_stack_frame_sz (qsmm_t model, size_t sz)

This function sets the size of the user part of each frame in the node call stack of a multinode model to sz bytes. Size 0 means that the model does not use the user part.

The function returns a non-negative value on success or negative error code QSMM_ERR_UNTIMELY if the model instance already exists.

The function qsmm_create initializes to 0 the size of the user part of each frame in the node call stack.

On calling a node, the function qsmm_node_call_default creates a new frame in the node call stack and initializes the user part of this frame with zero bytes. The new frame becomes the current stack frame. The function qsmm_get_stack_sz returns the total number of frames in the node call stack.

After creating the current stack frame, qsmm_node_call_default sends an event QSMM_EVT_NODE_ENTER to the instruction class set of a called node. The event handler of that instruction class set can process the event to perform application-specific initialization of that current frame. For example, the event handler may allocate dynamic arrays or copy the parameters of calling the node to the frame. A pointer to those parameters is an argument of qsmm_node_call_default, and this function passes this pointer to the event handler via its argument qsmm_param_p.

While executing the node, qsmm_node_call_default sends events QSMM_EVT_ACTIVATE to the instruction meta-classes of instructions selected for invocation by the instruction emitting engine. The event handler of an instruction meta-class can call the function qsmm_return_to_caller_node to return control from the node or the function qsmm_set_continue with flag equal to 0 or the macro QSMM_TERMINATE to return control from all nodes in the node call stack.

On returning control from the node, qsmm_node_call_default sends an event QSMM_EVT_NODE_LEAVE to the instruction class set of that node. The event handler of that instruction class set can use the content of the current stack frame to compute the results of node invocation and return those results via a memory block addressed by qsmm_param_p. If necessary, the event handler performs application-specific uninitialization of the current frame—for example, frees allocated dynamic arrays.

After sending the event QSMM_EVT_NODE_LEAVE, qsmm_node_call_default destroys the current stack frame and exits. If after this destruction the node call stack is not empty, the previous frame in the stack becomes the current frame.

Use the following function to get a pointer to the user part of a frame in the node call stack.

Function: int qsmm_get_stack_frame (qsmm_t model, int depth, void **frame_pp)

This function retrieves a pointer to the user part of a frame in the node call stack of a multinode model at depth. If frame_pp is not NULL, the function sets *frame_pp equal to this pointer. A program can access a memory block with size in bytes returned by the function qsmm_get_stack_frame_sz addressed by the pointer. Depth 0 corresponds to the current stack frame, depth 1 corresponds to the previous stack frame, and so on.

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_NOUSTACK

The model does not have user part in the frames of node call stack. Use the function qsmm_set_stack_frame_sz to specify positive size of that user part before creating the model instance.

QSMM_ERR_UNTIMELY

The node call stack is empty.

QSMM_ERR_INVAL

The argument depth is negative or greater than or equal to the number of frames in the node call stack returned by the function qsmm_get_stack_sz.

If the structure stack_frame_s holds a user stack frame, use the following call to set the size of this frame:

qsmm_set_stack_frame_sz(qsmm,sizeof(struct stack_frame_s));

To get a pointer to a current stack frame, use these lines:

struct stack_frame_s *stack_frame_p=0;
qsmm_get_stack_frame(qsmm,0,(void **) &stack_frame_p);

Next: , Previous: , Up: Executing a Multinode Model   [Contents][Index]

4.3.7 Switching Adaptive or Random Behavior

A multinode model has either a random number generator provided via the field rng of qsmm_desc_s structure when creating the multinode model or an instance of default random number generator allocated automatically if that field was NULL. The environment state identification engine and instruction emitting engine use that random number generator. The purpose of the following function is to obtain the random number generator of a multinode model.

Function: qsmm_rng_t qsmm_get_rng (qsmm_t model)

This function returns the handle of a random number generator used by the environment state identification engine and instruction emitting engine of a multinode model. The function never returns NULL.

You can use the returned handle of a random number generator to seed the generator after creating the multinode model or model instance. See Random Number Generators, for how to seed a random number generator and perform other operations on it.

A useful approach to determine the amount of contribution of optimization mechanism provided by QSMM to the optimality of behavior of a multinode model is comparing a measure of optimality for this multinode model behaving adaptively versus a measure of optimality for this model behaving randomly. The greater the difference is between those values the more contribution the optimization mechanism provided by QSMM makes to the optimality of behavior of this multinode model.

Use the following function to switch the model instance to random or adaptive (normal) behavior mode.

Function: int qsmm_set_random (qsmm_t model, int flag)

This function switches the current mode of behavior of instance of a multinode model to random or adaptive (normal) mode. If flag is non-zero, the function switches the current mode to random mode. If flag is zero, the function switches the current mode to adaptive mode.

The function is a short cut to setting the current mode of behavior for the environment state identification engine and instruction emitting engine of model instance by the function qsmm_set_actor_random.

On success, the function returns a non-negative value. If the model instance does not exist, the function returns negative error code QSMM_ERR_UNTIMELY.

The function qsmm_engine_create initializes the current mode of behavior of model instance to adaptive (normal) mode.


Previous: , Up: Executing a Multinode Model   [Contents][Index]

4.3.8 Tracing Model Execution

QSMM provides facilities for tracing events related to a multinode model. You can specify the types of events dumped to a trace log using a bitmask defined as a subset of the following macros merged by bitwise “or.”

Macro: QSMM_TRACE_API

Multinode model API calls entry and exit. API functions with a model handle argument dump a function name, the names and values of function arguments, and a returned value.

Macro: QSMM_TRACE_EVT

The beginning and end of processing every model event by event handlers with dumping event parameters.

Macro: QSMM_TRACE_CTRL

Calling nodes, returning control from nodes, instruction invocations, and the outcomes of those invocations.

Use the following functions to query or set a bitmask of types of events dumped to a trace log.

Function: unsigned int qsmm_get_trace_flags (qsmm_t model)

This function returns the bitmask of types of events dumped to the trace log of a multinode model. The model is the originator of those events. This function returns a bitmask set by the function qsmm_set_trace_flags or a default bitmask (see a remark below) if the latter function not yet called.

Function: void qsmm_set_trace_flags (qsmm_t model, unsigned int flags)

This function sets to flags the bitmask of types of events dumped to the trace log of a multinode model. The model is the originator of those events. The function does not check whether the bitmask is correct.

The function qsmm_create initializes the bitmask of types of events dumped to a trace log to 0.

A multinode model does not dump messages to a trace log unless the multinode model has an assigned stream for the trace log. Use the following functions to get or set the stream.

Function: FILE * qsmm_get_trace_stream (qsmm_t model)

This function returns a stream for the trace log of a multinode model. If the model does not have the stream assigned, the function returns NULL.

Function: void qsmm_set_trace_stream (qsmm_t model, FILE *filep)

This function sets to filep the stream for the trace log of a multinode model. The NULL stream disables dumping log messages.

Use the following functions to write a custom formatted message to the trace log.

Function: void qsmm_trace_f (qsmm_t model, const char *fmt, ...)
Function: void qsmm_trace_fv (qsmm_t model, const char *fmt, va_list ap)

These functions write a formatted message to the trace log of a multinode model. They append the character ‘\n’ to the message and flush the stream buffer. If the trace stream not set, the functions have no effect. The meaning of fmt argument and subsequent arguments of qsmm_trace_f function is the same as in the function printf. The meaning of fmt and ap arguments of qsmm_trace_fv function is the same as in the function vprintf.


Next: , Previous: , Up: Multinode Model   [Contents][Index]

4.4 Listing a Multinode Model

You can dump the state transition matrix and action emission matrix of a node or all nodes of a multinode model.

To enumerate instruction meta-classes, instruction class sets, and nodes existing in a multinode model, you use datatypes for entity references.


Next: , Up: Listing a Multinode Model   [Contents][Index]

4.4.1 Dumping the State Transition Matrix

The state transition matrix of a node contains transition probabilities of supported types along with other numeric information. The rows of that matrix biuniquely correspond to quadruples where each quadruple consists of a source transition state, a user or mixed-type instruction invoked in the source transition state, the outcome of this instruction, and the content of look-ahead signal segment. The columns of that matrix biuniquely correspond to target transition states. Use the following function to dump a state transition matrix to a stream.

Function: int qsmm_mat_goto_dump_v2 (qsmm_t model, int rez1, qsmm_sig_t node, struct qsmm_dump_mat_goto_desc_s *desc_p, FILE *filep)

This function dumps the state transition matrix of a node of a multinode model to a stream filep according to parameters specified in *desc_p. The argument node specifies the identifier of this node. If node is equal to QSMM_SIG_INVALID, the function dumps the state transition matrices of all nodes of this multinode model. If desc_p is NULL, the function uses default dumping parameters. The argument rez1 is for future use and must be equal to 0.

In the current implementation, the function does not modify *desc_p if desc_p is not NULL. However, in a future implementation, the function may modify *desc_p, for example, to store there statistics on the dumping process.

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_NOTFOUND

The argument node is not QSMM_SIG_INVALID, and a node with identifier node does not exist.

QSMM_ERR_INVAL

The argument desc_p is not NULL, and parameters in *desc_p are invalid.

QSMM_ERR_UNTIMELY

The model instance does not exist.

QSMM_ERR_CALLBACK

A helper function for computing the relative probability of an output signal assigned to the environment state identification engine reported an error by returning NaN. The function qsmm_actor_calc_action_prob calls the helper function.

QSMM_ERR_STORAGE

A Storage API function reported storage failure.

QSMM_ERR_STATS

Inconsistent statistics on an action choice state or cycle type detected.

QSMM_ERR_ILSEQ

Unable to convert a multibyte string to a wide string or vice versa according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Errors QSMM_ERR_STORAGE, QSMM_ERR_STATS, QSMM_ERR_ILSEQ, and QSMM_ERR_NOMEM can leave the model instance in inconsistent state.

The description of a structure specifying dumping parameters is below.

Structure: qsmm_dump_mat_goto_desc_s

This structure specifies the parameters of dumping the state transition matrix of a node. The structure contains the following fields.

Field: char do_print_prob[QSMM_PROB_COUNT]

An array specifying the types of probabilities to dump. The indices of this array are the elements of qsmm_prob_e enumeration (except for its last element QSMM_PROB_COUNT) described in Emitting an Output Signal. If an element of this array is non-zero, the function qsmm_mat_goto_dump_v2 dumps probabilities with a corresponding type. The default is to dump probabilities of all types.

Field: int indent

Left indent—the number of spaces to print at the beginning of each line of output. Must be a non-negative value. The default is to use indent 0.

Field: int prob_prec

The number of digits after the decimal point to print for probabilities. If that number is positive, use fixed-point notation. If that number is negative, use exponential notation with the number of digits after the decimal point equal to the absolute value of this field. If that number is zero, use exponential notation with 15 digits after the decimal point; this is the default mode.

Field: long fq_min

The minimum value of fq field of an instance of qsmm_cycle_s structure for a matrix cell. The function qsmm_mat_goto_dump_v2 does not output information on instances with lesser values of fq field (i.e. with lesser frequency). The default is to use minimum frequency 0.

To improve compatibility with future versions of QSMM library, zero by the function memset an instance of qsmm_dump_mat_goto_desc_s structure before setting the fields of this instance passed to the function qsmm_mat_goto_dump_v2.

Below there is an example fragment of a dump. When generating it, the element QSMM_PROB_LEARNED of do_print_prob field of qsmm_dump_mat_goto_desc_s structure passed to qsmm_mat_goto_dump_v2 was non-zero, and all other elements of this field were zero. The example contains truncated fractional parts of numbers in exponential notation to make lines shorter.

* State  83

  A0  |mn| O7 L0 : tmd0=183117, tmc0=6E+4, state_next=45,  spur[0].val0=-4E+5, spur[1].val0=4E+2

    S45  : pl=1.0E+00,  spur[0].ds=-3E+05, spur[1].ds=4E+02,  fq=376, ps_d=148416, ps_c=5E+04
    S79  : pl=4.2E-267, spur[0].ds=-4E+04, spur[1].ds=1E+01,  fq=3,   ps_d=23976,  ps_c=8E+03
    S92  : pl=9.1E-283, spur[0].ds=-2E+04, spur[1].ds=4E+00,  fq=2,   ps_d=9516,   ps_c=3E+03

  A0  |mn| O7 L1 : tmd0=183219, tmc0=6E+4, state_next=120, spur[0].val0=-4E+5, spur[1].val0=4E+2

    S63  : pl=2.2E-245, spur[0].ds=-4E+04, spur[1].ds=1E+01,  fq=5,   ps_d=22740,  ps_c=8E+03
    S87  : pl=2.0E-292, spur[0].ds=-3E+02, spur[1].ds=0E+00,  fq=1,   ps_d=156,    ps_c=5E+01
    S120 : pl=1.0E+00,  spur[0].ds=-3E+05, spur[1].ds=4E+02,  fq=119, ps_d=160185, ps_c=5E+04

Below there are descriptions of output pieces of information. See Structures for Accessing Storage, for details about referenced structure fields.

Ai

An instruction class invoked by the node in a source transition state. Index i uniquely identifies the instruction class in the instruction class set of the node. The name of the instruction class enclosed between the characters ‘|’ follows the token Ai.

Li

Look-ahead signal i that was in the look-ahead signal segment when the node was in a source transition state. The number of Li tokens is equal to look-ahead signal segment length. The positions of Li tokens are the positions of elements in the look-ahead signal segment.

Oi

Outcome i of an instruction class invoked by the node in a source transition state.

Si

The description of a transition to target state i. If the state has a name assigned by the argument of stt assembler instruction, the name enclosed in double quotes follows the token Si.

RST

This keyword can replace the tokens ‘Ax |name| Oy’ for source transition state 0. The keyword indicates that specified transitions to target states are initial transitions performed just after transferring control to the node. In this situation, the node did not yet invoke instructions, so values x and y are unknown.

fq

The value of fq field of qsmm_cycle_s structure.

pa

Probability of QSMM_PROB_AGGR type.

pf

Probability of QSMM_PROB_FQ type.

pl

Probability of QSMM_PROB_LEARNED type.

pp

Probability of QSMM_PROB_PROFILE type.

ps_c

The value of period_sum_c field of qsmm_cycle_s structure.

ps_d

The value of period_sum_d field of qsmm_cycle_s structure.

spur[i].ds

The value of delta_sum field of qsmm_cspur_s structure for spur type i. Spur type 0 is usually the automatic spur.

spur[i].val0

The value of val0 field of qsmm_sspur_s structure for spur type i. Spur type 0 is usually the automatic spur.

State

The index of a source transition state. If the state has a name assigned by the argument of stt assembler instruction, the name enclosed in double quotes follows that index.

state_next

The index of target state of last transition made from a source state. That index corresponds to the value of sig_cycle_next field of qsmm_state_s structure. The special value ‘N’ corresponds to the value QSMM_SIG_INVALID of this field.

tmc0

The value of tmc0 field of qsmm_state_s structure.

tmd0

The value of tmd0 field of qsmm_state_s structure.

The function qsmm_mat_goto_dump_v2 dumps only the descriptions of state transitions that have some information in statistics storage. This approach helps reduce the length of output when dumping a sparse state transition matrix.

When the descriptions of some state transitions are absent in the output because of a positive value of fq_min field of qsmm_dump_mat_goto_desc_s structure or because statistics storage does not contain information on some state transitions, the sum of state transition probabilities with a specific type may be less than 1 in a matrix row. If the field fq_min is zero, every not dumped transition has probability (1-p)/n, where p is the sum of probabilities of dumped transitions, and n is the number of not dumped transitions.


Next: , Previous: , Up: Listing a Multinode Model   [Contents][Index]

4.4.2 Dumping the Action Emission Matrix

The action emission matrix of a node contains the probabilities of emitting all instruction classes belonging to the instruction class set of this node in all states of this node. The rows of that matrix biuniquely correspond to node states. The columns of that matrix biuniquely correspond to instruction classes in the instruction class set. Use the following function to dump an action emission matrix to a stream.

Function: int qsmm_mat_action_dump_v2 (qsmm_t model, int rez1, qsmm_sig_t node, struct qsmm_dump_mat_action_desc_s *desc_p, FILE *filep)

This function dumps the action emission matrix of a node of a multinode model to a stream filep according to parameters specified in *desc_p. The argument node specifies the identifier of this node. If node is equal to QSMM_SIG_INVALID, the function dumps the action emission matrices of all nodes of this multinode model. If desc_p is NULL, the function uses default dumping parameters. The argument rez1 is for future use and must be equal to 0.

In the current implementation, the function does not modify *desc_p if desc_p is not NULL. However, in a future implementation, the function may modify *desc_p, for example, to store there statistics on the dumping process.

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_NOTFOUND

The argument node is not QSMM_SIG_INVALID, and a node with identifier node does not exist.

QSMM_ERR_INVAL

The argument desc_p is not NULL, and parameters in *desc_p are invalid.

QSMM_ERR_UNTIMELY

The model instance does not exist.

QSMM_ERR_CALLBACK

A helper function for computing the relative probability of an output signal assigned to the instruction emitting engine reported an error by returning NaN. The function qsmm_actor_calc_action_prob calls the helper function.

QSMM_ERR_STORAGE

A Storage API function reported storage failure.

QSMM_ERR_STATS

Inconsistent statistics on an action choice state or cycle type detected.

QSMM_ERR_ILSEQ

Unable to convert a multibyte string to a wide string or vice versa according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Errors QSMM_ERR_STORAGE, QSMM_ERR_STATS, QSMM_ERR_ILSEQ, and QSMM_ERR_NOMEM can leave the model instance in inconsistent state.

The description of a structure specifying dumping parameters is below.

Structure: qsmm_dump_mat_action_desc_s

This structure specifies the parameters of dumping the action emission matrix of a node. The structure contains the following fields.

Field: char do_print_prob[QSMM_PROB_COUNT]

An array specifying the types of probabilities to dump. The indices of this array are the elements of qsmm_prob_e enumeration (except for its last element QSMM_PROB_COUNT) described in Emitting an Output Signal. If an element of this array is non-zero, the function qsmm_mat_action_dump_v2 dumps probabilities with a corresponding type. The default is to dump probabilities of all types.

Field: int indent

Left indent—the number of spaces to print at the beginning of each line of output. Must be a non-negative value. The default is to use indent 0.

Field: int prob_prec

The number of digits after the decimal point to print for probabilities. If that number is positive, use fixed-point notation. If that number is negative, use exponential notation with the number of digits after the decimal point equal to the absolute value of this field. If that number is zero, use exponential notation with 15 digits after the decimal point; this is the default mode.

Field: long fq_min

The minimum value of fq field of an instance of qsmm_cycle_s structure for a matrix cell. The function qsmm_mat_action_dump_v2 does not output information on instances with lesser values of fq field (i.e. with lesser frequency). The default is to use minimum frequency 0.

To improve compatibility with future versions of QSMM library, zero by the function memset an instance of qsmm_dump_mat_action_desc_s structure before setting the fields of this instance passed to the function qsmm_mat_action_dump_v2.

Below there is an example fragment of a dump. When generating it, the element QSMM_PROB_LEARNED of do_print_prob field of qsmm_dump_mat_action_desc_s structure passed to qsmm_mat_action_dump_v2 was non-zero, and all other elements of this field were zero. The example contains truncated fractional parts of numbers in exponential notation to make lines shorter.

* State 1 : tmd0=2711, tmc0=1.205...E+03, action_next=0, spur[0].val0=4.000...E+00

  A0 |me| : pl=9.9306...E-01, spur[0].ds=4.0...E+00, fq=43, ps_d=1965, ps_c=8.22...E+02
  A1 |ms| : pl=3.4713...E-03, spur[0].ds=0.0...E+00, fq=49, ps_d=147,  ps_c=9.80...E+01
  A2 |mw| : pl=3.4713...E-03, spur[0].ds=0.0...E+00, fq=36, ps_d=108,  ps_c=7.20...E+01

Below there are descriptions of output pieces of information. See Structures for Accessing Storage, for details about referenced structure fields.

Ai

Information on an instruction class emitted in a node state. Index i uniquely identifies the instruction class in the instruction class set of the node. The name of the instruction class enclosed between the characters ‘|’ follows the token Ai.

action_next

The index of last instruction class emitted in a node state. That index corresponds to the value of sig_cycle_next field of qsmm_state_s structure. The special value ‘N’ corresponds to the value QSMM_SIG_INVALID of this field.

fq

The value of fq field of qsmm_cycle_s structure.

pa

Probability of QSMM_PROB_AGGR type.

pf

Probability of QSMM_PROB_FQ type.

pl

Probability of QSMM_PROB_LEARNED type.

pp

Probability of QSMM_PROB_PROFILE type.

ps_c

The value of period_sum_c field of qsmm_cycle_s structure.

ps_d

The value of period_sum_d field of qsmm_cycle_s structure.

spur[i].ds

The value of delta_sum field of qsmm_cspur_s structure for spur type i.

spur[i].val0

The value of val0 field of qsmm_sspur_s structure for spur type i.

State

The description of a state with a specific index. If the state has a name assigned by the argument of stt assembler instruction, the name enclosed in double quotes follows this index.

tmc0

The value of tmc0 field of qsmm_state_s structure.

tmd0

The value of tmd0 field of qsmm_state_s structure.

The function qsmm_mat_action_dump_v2 only dumps information on instruction classes contained in statistics storage. This approach helps reduce the length of output when dumping a sparse action emission matrix.

When information on some instruction classes is absent in the output because of a positive value of fq_min field of qsmm_dump_mat_action_desc_s structure or because statistics storage does not contain information on some instruction classes for some node states, the sum of action emission probabilities with a specific type may be less than 1 in a matrix row. If the field fq_min is zero, every not dumped instruction class has emission probability (1-p)/n, where p is the sum of probabilities of instruction classes dumped for a node state, and n is the number of instruction classes not dumped for the node state.


Next: , Previous: , Up: Listing a Multinode Model   [Contents][Index]

4.4.3 Entity References

Entity references identify entities existing in a multinode model. This identification is necessary when enumerating entities in the multinode model and when passing information about entities associated with an occurred error to a model error handler. See Error Handling for a Multinode Model, for information about the error handler of a multinode model. The header file refe.h contains declarations related to entity references. The notion of entity referred to by an entity reference has nothing to do with virtual or logical entities represented by the state models of nodes of a multinode model.

The basic type of an entity reference is local entity reference. A local entity reference identifies an entity within some known context. The following enumeration declares the types of local entity references.

Enumeration: qsmm_lref_e

This enumeration categorizes entities that are parts of a multinode model. The enumeration contains the following elements.

QSMM_LREF_INVALID

Invalid entity type. This element indicates unknown entity type or the type of a nonexistent entity.

QSMM_LREF_INSTR_CLASS_SET

An instruction class set.

QSMM_LREF_INSTR_META_CLASS

An instruction meta-class.

QSMM_LREF_NODE

A node.

QSMM_LREF_PROB_VAR_CTRL

A controlled probability variable. See Controlled Variables.

QSMM_LREF_PROB_VAR_OUT

An output probability variable. See Output Variables.

QSMM_LREF_PROB_ARR_OUT

An output probabilities array. See Output Arrays.

QSMM_LREF_INSTR_CLASS

An instruction class.

QSMM_LREF_COUNT

The number of supported types of local entity references.

The following union represents a local entity identifier for a local entity reference.

Union: qsmm_lref_u

This union holds a local entity identifier for a local entity reference with the type specified by an element of qsmm_lref_e enumeration. The union contains the following fields.

Field: char *name

An entity name. It is applicable to local entity references of QSMM_LREF_INSTR_CLASS_SET, QSMM_LREF_INSTR_META_CLASS, QSMM_LREF_PROB_VAR_CTRL, QSMM_LREF_PROB_VAR_OUT, and QSMM_LREF_PROB_ARR_OUT types.

Field: qsmm_sig_t sig

A local entity identifier represented by a signal. It is applicable to local entity references of QSMM_LREF_NODE type.

Field: struct qsmm_instr_class_s instr_class

An instruction class descriptor. It is applicable to local entity references of QSMM_LREF_INSTR_CLASS type.

The following structure holds an instruction class descriptor in the field instr_class of qsmm_lref_u union for local entity references of QSMM_LREF_INSTR_CLASS type.

Structure: qsmm_instr_class_s

This structure holds an instruction class descriptor identifying an instruction class. The structure contains the following fields.

Field: char *meta_class_name

An instruction meta-class name.

Field: char *param_str_p

Text instruction class parameters in the canonical form (see Setting Text Instruction Parameters). The empty string means empty text parameters. The NULL value means that the text parameters are unknown.

Field: qsmm_sig_t idx

An instruction class index. It uniquely identifies the instruction class in an instruction class set. The value QSMM_SIG_INVALID means that the index is unknown.

Field: size_t param_bin_sz

The size of binary instruction class parameters. If binary parameters are unknown, this field must be equal to 0.

Field: void *param_bin_p

Binary instruction class parameters. If this field is not NULL, it must address a memory block with size in bytes specified by the field param_bin_sz. If this field is NULL, then binary parameters are unknown, and the field param_bin_sz must be equal to 0.

The following structure represents a complete local entity reference.

Structure: qsmm_lref_s

This structure holds the type of a local entity reference along with a local entity identifier. The structure contains the following fields.

Field: enum qsmm_lref_e type

The type of a local entity reference.

Field: union qsmm_lref_u val

The value of a local entity reference depending on its type. For the type QSMM_LREF_INVALID, must be a block of zero bytes.

A global entity reference identifies an entity in the address space of a running process. The error handler of a multinode model receives global references to entities related to errors. The type of a global entity reference specifies a method of identifying an entity. The following enumeration declares the types of global entity references.

Enumeration: qsmm_gref_e

This enumeration specifies a method of identification of an entity in the address space of a running process. The enumeration contains the following elements.

QSMM_GREF_INVALID

Invalid global entity reference, including the absence of an entity to identify.

QSMM_GREF_HANDLE_LREF

An object handle and a local entity reference. This method of identification is applicable to local entity references of QSMM_LREF_INSTR_CLASS_SET, QSMM_LREF_INSTR_META_CLASS, and QSMM_LREF_NODE types. The object handle has the type QSMM_HANDLE_MODEL and refers to a multinode model containing an instruction class set, instruction meta-class, or node.

QSMM_GREF_HANDLE_LREF2

An object handle, the local entity reference of a container, and the local entity reference of a contained entity. This method of identification is applicable to local entity references of QSMM_LREF_PROB_VAR_CTRL, QSMM_LREF_PROB_VAR_OUT, QSMM_LREF_PROB_ARR_OUT, and QSMM_LREF_INSTR_CLASS types for contained entities. The object handle has the type QSMM_HANDLE_MODEL and refers to a multinode model with the container. The local entity reference of the container has the type QSMM_LREF_NODE for a controlled probability variable, output probability variable, or output probabilities array contained in a node or the type QSMM_LREF_INSTR_CLASS_SET for an instruction class contained in an instruction class set.

The following union represents a global entity identifier for a global entity reference.

Union: qsmm_gref_u

This union holds a global entity identifier for a global entity reference with the type specified by an element of qsmm_gref_e enumeration. The union contains the following fields.

Field: struct qsmm_handle_lref_s handle_lref

An object handle and a local entity reference. This field is for a global entity reference of QSMM_GREF_HANDLE_LREF type.

Field: struct qsmm_handle_lref2_s handle_lref2

An object handle, the local entity reference of a container, and the local entity reference of a contained entity. This field is for a global entity reference of QSMM_GREF_HANDLE_LREF2 type.

The following structure holds an object handle and local entity reference in the field handle_lref of qsmm_gref_u union for global entity references of QSMM_GREF_HANDLE_LREF type.

Structure: qsmm_handle_lref_s

This structure holds the handle of an object and a local entity reference for an entity contained in the object. The structure contains the following fields.

Field: struct qsmm_handle_s handle

The handle of a containing object. At present, can only be a handle of QSMM_HANDLE_MODEL type.

Field: struct qsmm_lref_s lref

A local entity reference for an entity contained in an object. At present, can be a local entity reference of QSMM_LREF_INSTR_CLASS_SET, QSMM_LREF_INSTR_META_CLASS, or QSMM_LREF_NODE type, where the containing object is a multinode model.

The following structure holds an object handle, the local entity reference of a container, and the local entity reference of a contained entity in the field handle_lref2 of qsmm_gref_u union for global entity references of QSMM_GREF_HANDLE_LREF2 type.

Structure: qsmm_handle_lref2_s

This structure holds the handle of an object, the local entity reference of a container in the object, and a local entity reference for an entity in the container. The structure contains the following fields.

Field: struct qsmm_handle_s handle

The handle of an object. At present, can only be a handle of QSMM_HANDLE_MODEL type.

Field: struct qsmm_lref_s container

The local entity reference of a container in an object. At present, can be a local entity reference of QSMM_LREF_NODE or QSMM_LREF_INSTR_CLASS_SET type, where the containing object is a multinode model.

Field: struct qsmm_lref_s lref

A local entity reference for an entity in a container. At present, can be:

  • – a local entity reference of QSMM_LREF_PROB_VAR_CTRL, QSMM_LREF_PROB_VAR_OUT, or QSMM_LREF_PROB_ARR_OUT type for the container specified by a local entity reference of QSMM_LREF_NODE type;
  • – a local entity reference of QSMM_LREF_INSTR_CLASS type for the container specified by a local entity reference of QSMM_LREF_INSTR_CLASS_SET type.

The following structure represents a complete global entity reference.

Structure: qsmm_gref_s

This structure holds the type of a global entity reference along with a global entity identifier. The structure contains the following fields.

Field: enum qsmm_gref_e type

The type of a global entity reference.

Field: union qsmm_gref_u val

The value of a global entity reference depending on its type. For the type QSMM_GREF_INVALID, must be a block of zero bytes.


Previous: , Up: Listing a Multinode Model   [Contents][Index]

4.4.4 Enumerating Entities

Instruction meta-classes and instruction class sets are entities a multinode model normally contains. Local entity references of QSMM_LREF_INSTR_META_CLASS and QSMM_LREF_INSTR_CLASS_SET types identify those entities by names. They share the same name space and cannot be duplicate, because those entities have event handler functions with names equal to entity names by default, and function names must be unique in certain scopes.

Use the following function to enumerate instruction meta-classes, instruction class sets, or nodes in a multinode model.

Function: int qsmm_enum_ent (qsmm_t model, enum qsmm_lref_e ent_type, qsmm_enum_ent_callback_func_t callback_func, void *paramp)

This function enumerates all entities of ent_type type stored in a multinode model. The process of enumeration is repeated calling a callback function callback_func receiving the type of a local entity reference, a local entity identifier, and a user parameter paramp. If the callback function returns a positive value, the function qsmm_enum_ent continues the enumeration. If the callback function returns zero, qsmm_enum_ent terminates the enumeration and reports success. If the callback function returns a negative value, qsmm_enum_ent terminates the enumeration and reports failure.

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 ent_type is not QSMM_LREF_INSTR_META_CLASS, QSMM_LREF_INSTR_CLASS_SET, and QSMM_LREF_NODE.

QSMM_ERR_CALLBACK

The callback function reported an error.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

The type of a pointer to a callback function called for every enumerated entity is below.

Data type: qsmm_enum_ent_callback_func_t

This is a type of a callback function pointer with the following declaration:

typedef int
(*qsmm_enum_ent_callback_func_t)(
    qsmm_t model,
    enum qsmm_lref_e lref_type,
    const union qsmm_lref_u *lref_p,
    void *paramp
);

An enumeration function calls the callback function for every enumerated entity of a multinode model. The argument lref_type specifies the type of an enumerated entity as the type of a local entity reference. The argument lref_p specifies the identifier of this entity as a local entity identifier. The argument paramp is a user parameter passed to the enumeration function.

The callback function shall return a positive value to continue the process of enumeration, zero to terminate the process of enumeration, or a negative value on error.

The function qsmm_enum_var_prob uses a callback function of qsmm_enum_ent_callback_func_t type for enumerating the controlled probability variables of an instruction class set. The function qsmm_enum_var_prob_out uses this callback function for enumerating the output probability variables of a node.

Use the following function to query the type of an entity by its name.

Function: enum qsmm_lref_e qsmm_get_ent_type_by_name (qsmm_t model, const char *ent_name)

This function returns the type of a local entity reference for an entity named ent_name stored in a multinode model. The function only supports local entity references of QSMM_LREF_INSTR_META_CLASS and QSMM_LREF_INSTR_CLASS_SET types. If the entity does not exist or is not an instruction meta-class and instruction class set, the function returns QSMM_LREF_INVALID.


Previous: , Up: Multinode Model   [Contents][Index]

4.5 Error Handling for a Multinode Model

A multinode model can have an error handler assigned to it. The error handler is a function called in the case of a failure in any QSMM API function that takes an argument of qsmm_t type and can return an error code of int type. The default error handler of a multinode model prints information on an occurred error to stderr and calls exit(2). The output consists of the name of that default error handler function followed by an indented description of an error as object content in JSON format. If a multinode model does not have an error handler assigned (including the default error handler), or an error handler assigned to the multinode model does not terminate program execution and returns, a failed API function returns a corresponding error code.

Use the following functions to query or set an error handler for a multinode model.

Function: void qsmm_get_err_handler (qsmm_t model, qsmm_err_handler_func_t *func_p, void **param_pp)

This function retrieves information on an error handler assigned to a multinode model. If func_p is not NULL, the function sets *func_p to the pointer to the error handler function or to NULL if the model does not have the error handler function assigned. If param_pp is not NULL, the function sets *param_pp to the user parameter of that error handler function.

Function: void qsmm_set_err_handler (qsmm_t model, qsmm_err_handler_func_t func, void *paramp)

This function assigns an error handler to a multinode model. The argument func specifies an error handler function. The argument paramp specifies the user parameter of this error handler function. If func is NULL, the model does not use an error handler.

An error handler function receives extended information on some types of errors. The header file err.h included in qsmm.h contains a declaration for the type of an error handler function. The Side API also uses this type for the error handler of an interaction side (see Error Handling for the Side API, for more information).

Data type: qsmm_err_handler_func_t

This is a type of an error handler function pointer with the following declaration:

typedef void
(*qsmm_err_handler_func_t)(
    void *rez1,
    struct qsmm_except_s *except_p,
    void *paramp
);

The argument except_p passes information on an occurred error. The argument paramp is a user parameter specified when setting the error handler function for a multinode model. You should not access the reserved argument rez1.

The description of a structure containing information on an occurred error is below. The header file err.h contains the declaration of this structure.

Structure: qsmm_except_s

This structure is for passing information about an occurred error to an error handler function. The structure contains the following fields.

Field: const char * func_name

The name of a QSMM library function where the error occurred. That name might be the name of an internal library function and not an API function.

Field: int code

An error code to return by a failed QSMM API function after returning from the error handler function.

Field: union qsmm_except_u ee

Extended information on the occurred error. A list of error codes with extended error information always provided in this field is in the description of qsmm_except_u union.

The description of a union containing extended error information depending on an error code is below. The header file err.h contains the declaration of this union.

Union: qsmm_except_u

This union contains fields corresponding to error codes that can have associated extended error information.

Field: char * noic

Extended information for error code QSMM_ERR_NOIC. The description of this error code is “instruction class set is empty.” This field contains the name of an instruction class set without instruction classes.

Field: int callback

Extended information for error code QSMM_ERR_CALLBACK. The description of this error code is “callback function reported an error.” This field contains an error code returned by a callback function.

Field: qsmm_sig_t noprof

Extended information for error code QSMM_ERR_NOPROF. The description of this error code is “node has no probability profile specified.” This field contains the identifier of a node without a probability profile specified.

Field: qsmm_sig_t violnode

Extended information for error code QSMM_ERR_VIOLNODE. The description of this error code is “change violates the parameters of an already created node.” This field contains the identifier of a node that prevents making a change because it would violate the parameters of this node.

Field: qsmm_msglist_t prg

Extended information for error code QSMM_ERR_PRG. The description of this error code is “invalid program.” This field contains a message list that hands over information on errors in an assembler program.

Field: qsmm_storage_t storage

Extended information for error code QSMM_ERR_STORAGE. The description of this error code is “storage failure.” This field refers to failed storage.

Field: size_t mprof

Extended information for error code QSMM_ERR_MPROF. The description of this error code is “too many probabilities lists in normal form.” This field contains the maximum number of elements in the pool of probabilities lists in normal form.

Field: struct qsmm_except_notfound_s notfound

Extended information for error code QSMM_ERR_NOTFOUND. The description of this error code is “entity not found.”

Field: struct qsmm_except_type_s type

Extended information for error code QSMM_ERR_TYPE. The description of this error code is “invalid entity type.”

Field: struct qsmm_except_exist_s exist

Extended information for error code QSMM_ERR_EXIST. The description of this error code is “entity already exists.”

Field: struct qsmm_except_outcome_s outcome

Extended information for error code QSMM_ERR_OUTCOME. The description of this error code is “invalid instruction outcome.”

Field: struct qsmm_except_evthndlr_s evthndlr

Extended information for error code QSMM_ERR_EVTHNDLR. The description of this error code is “event handler function reported an error.”

Field: struct qsmm_except_nostate_s nostate

Extended information for error code QSMM_ERR_NOSTATE. The description of this error code is “not enough node states to hold the probability profile.”

Field: struct qsmm_except_noeqclas_s noeqclas

Extended information for error code QSMM_ERR_NOEQCLAS. The description of this error code is “node classes are different.”

Field: struct qsmm_except_profsrcp_s profsrcp

Extended information for error code QSMM_ERR_PROFSRCP. The description of this error code is “node is a probability profile source for other nodes.”

Field: struct qsmm_except_profsrcu_s profsrcu

Extended information for error code QSMM_ERR_PROFSRCU. The description of this error code is “node is a user of a source probability profile provided by another node.”

Field: struct qsmm_except_psumgt1_s psumgt1

Extended information for error code QSMM_ERR_PSUMGT1. The description of this error code is “sum of probabilities would exceed 1.”

Use the following function to dump the content of qsmm_except_s structure to a stream in JSON format.

Function: void qsmm_except_dump (void *rez1, int indent, const struct qsmm_except_s *except_p, FILE *filep)

This function dumps error information in *except_p to a stream filep in JSON format as object content. The argument indent must be non-negative. It specifies left indent—the number of spaces to print at the beginning of each line of output. You should pass 0 for the reserved argument rez1.

The rest of this section describes the structures that are the fields of qsmm_except_u union. The header file err.h contains the declarations of those structures. Some of them have fields of enum qsmm_lref_e, struct qsmm_gref_s, and struct qsmm_instr_class_s types. See Entity References, for the descriptions of these types.

Structure: qsmm_except_notfound_s

This structure provides extended information for error code QSMM_ERR_NOTFOUND. The description of this error code is “entity not found.” The structure contains the following field.

Field: struct qsmm_gref_s gref

A reference to a not found entity.

Structure: qsmm_except_type_s

This structure provides extended information for error code QSMM_ERR_TYPE. The description of this error code is “invalid entity type.” The structure contains the following fields.

Field: enum qsmm_lref_e type_required

A required type for the entity.

Field: struct qsmm_gref_s gref

A reference to the entity that has an invalid type.

Structure: qsmm_except_exist_s

This structure provides extended information for error code QSMM_ERR_EXIST. The description of this error code is “entity already exists.” The structure contains the following field.

Field: struct qsmm_gref_s gref

A reference to an already existing entity.

Structure: qsmm_except_outcome_s

This structure provides extended information for error code QSMM_ERR_OUTCOME. The description of this error code is “invalid instruction outcome.” The structure contains the following fields.

Field: qsmm_sig_t node

The identifier of a node invoked the assembler instruction.

Field: qsmm_sig_t outcome

An invalid instruction outcome.

Field: qsmm_sig_t noutcome

The number of outcomes of the assembler instruction.

Field: qsmm_t model

A multinode model containing a node invoked the assembler instruction.

Field: struct qsmm_instr_class_s instr_class

The descriptor of an instruction class for the assembler instruction.

Structure: qsmm_except_evthndlr_s

This structure provides extended information for error code QSMM_ERR_EVTHNDLR. The description of this error code is “event handler function reported an error.” The structure contains the following fields.

Field: int rc

A negative return value of the event handler function.

Field: int evt

An event type passed to the event handler function—one of constants defined by the QSMM_EVT_* macros.

Field: int node

The identifier of a node associated with the event. A negative value means no node association.

Field: struct qsmm_gref_s gref

A reference to an entity emitting events processed by the event handler function.

Structure: qsmm_except_nostate_s

This structure provides extended information for error code QSMM_ERR_NOSTATE. The description of this error code is “not enough node states to hold the probability profile.” The structure contains the following fields.

Field: qsmm_sig_t node

The identifier of a node that has or would have the number of states less than it is necessary to hold the probability profile.

Field: qsmm_sig_t nstate_required

The minimum number of states the node must have to hold the probability profile.

Structure: qsmm_except_noeqclas_s

This structure provides extended information for error code QSMM_ERR_NOEQCLAS. The description of this error code is “node classes are different.” The structure contains the following fields.

Field: char * node_class_name_1

The name of the first node class, that is, the first instruction class set.

Field: char * node_class_name_2

The name of the second node class, that is, the second instruction class set.

Field: qsmm_sig_t node1

The identifier of a node belonging to the first node class. If that identifier is QSMM_SIG_INVALID, this parameter is not applicable.

Field: qsmm_sig_t node2

The identifier of a node belonging to the second node class. If that identifier is QSMM_SIG_INVALID, this parameter is not applicable.

Field: qsmm_t model

A multinode model containing the node classes.

Structure: qsmm_except_profsrcp_s

This structure provides extended information for error code QSMM_ERR_PROFSRCP. The description of this error code is “node is a probability profile source for other nodes.” The structure contains the following fields.

Field: qsmm_sig_t node_provider

The identifier of a node acting as a probability profile source for other nodes.

Field: qsmm_sig_t nnode_user

The number of nodes acting as probability profile users.

Field: qsmm_t model

A multinode model containing the nodes.

Structure: qsmm_except_profsrcu_s

This structure provides extended information for error code QSMM_ERR_PROFSRCU. The description of this error code is “node is a user of a source probability profile provided by another node.” The structure contains the following fields.

Field: qsmm_sig_t node_provider

The identifier of a node acting as a probability profile source.

Field: qsmm_sig_t node_user

The identifier of a node acting as a probability profile user.

Field: qsmm_t model

A multinode model containing the nodes.

Structure: qsmm_except_psumgt1_s

This structure provides extended information for error code QSMM_ERR_PSUMGT1. The description of this error code is “sum of probabilities would exceed 1.” The structure contains the following fields.

Field: char * var_name

The name of a controlled probability variable with an assigned value. This assignment causes the sum of probabilities of case instructions in a choice instruction block to exceed 1.

Field: qsmm_sig_t node

The identifier of a node containing a state corresponding to a choice instruction block.

Field: qsmm_sig_t state

The index of a node state corresponding to a choice instruction block.

Field: qsmm_t model

A multinode model containing the node.


Next: , Previous: , Up: Top   [Contents][Index]

5 Assembler Programs

QSMM assembler programs are the means of:

The use of assembler programs relies heavily on instruction meta-classes, instruction classes, and instruction class sets registered for a multinode model. The name of an instruction meta-class and the text parameters of an instruction class derived from the instruction meta-class identify assembler instructions belonging to this instruction class in assembler programs. Such assembler instructions fall into the category of user instructions with custom names. The other two categories of assembler instructions are built-in and mixed-type instructions with standard names.

A handle of qsmm_prg_t type refers to a memory representation of an assembler program. This memory representation is convertible to an assembler program text and vice versa. Information on assembler instructions is accessible by their indices in the memory representation.

Disassembling a node is converting its state model to an assembler program. Assembling a node is converting an assembler program to a probability profile for the state model of this node. A special mode of assembling a node is storing its assembler program as a template for a subsequent disassembling. In this case, a learned disassembled program is a template assembler program with learned probabilities replacing profile probabilities specified in the template assembler program.

An assembler program can contain probability variables along with their initial values specifying profile probabilities. A probability variable can be a controlled probability variable or an output probability variable. The instruction class set of a node specifies a set of allowed names of controlled probability variables. Changing the value of a controlled probability variable of a node results in changing one or more profile probabilities for the state model of this node. Output probability variables are the means of fetching specific probabilities from a learned state model of a node. Output probabilities arrays hand over learned probabilities for the case branches of choice instruction blocks.

Cloning a probability profile is helpful if multiple nodes have the same probability profile. It is faster to clone a probability profile from a node to other nodes than to assemble all those nodes using the same assembler program. A special cloning mode is deferred cloning a probability profile. This mode can decrease memory consumption by a multinode model.

Unloading the probability profile of a node additionally clears the learned state model of this node and breaks its correspondence with a node providing a source probability profile cloned in deferred mode.

The assembler preprocessor can preprocess an assembler program text before parsing it. The preprocessor provides capabilities for including other assembler source files in a preprocessed source file, defining and expanding basic macros, and generating unique location labels to produce a correct assembler program when expanding the same macro multiple times.


Next: , Up: Assembler Programs   [Contents][Index]

5.1 Basic Datatypes

A program handle refers to a memory representation of an assembler program.

Data type: qsmm_prg_t

This is a type for a program handle. It is a pointer, so variables of this type can be NULL. The functions qsmm_node_disasm, qsmm_parse_asm_source_buf, qsmm_parse_asm_source_stream, and qsmm_parse_asm_source_file allocate a new program handle. The function qsmm_prg_destroy frees an existing program handle. You can pass a program handle to API functions taking an argument of qsmm_prg_t type until freeing the handle.

Use the following function to destroy a memory representation of an assembler program.

Function: void qsmm_prg_destroy (qsmm_prg_t prg)

This function destroys a memory representation of an assembler program specified by a handle prg. You must not use the handle after the destruction of this memory representation. If prg is NULL, the function has no effect.

QSMM provides limited capabilities for working with assembler instructions contained in a memory representation of an assembler program. An instruction handle refers to an assembler instruction.

Data type: qsmm_instr_t

This is a type for an instruction handle. It is a pointer, so variables of this type can be NULL. The functions qsmm_get_prg_instr and qsmm_get_instr_nested (see Inspecting an Assembler Program) return the handle of an existing instruction.


Next: , Previous: , Up: Assembler Programs   [Contents][Index]

5.2 Assembler Program Syntax

An assembler program consists of lines. You can use empty lines to decorate the program. Comments are line characters starting with the first character ‘;’ outside a string literal; such literals can be parts of parameters of an assembler instruction (see Setting Text Instruction Parameters, for more information on string literals). For proper identification of continuation of multi-line comments, align the characters ‘;’ starting every line of a multi-line comment one beneath the another.

If the first character on a line is not a whitespace character and not ‘;’, then that first character must be the start of a label definition. There are two possible types of labels: location labels and data labels. The definitions of location labels end with the character ‘:’. The definitions of data labels do not end with that character. The first character of a label must be an English letter or the character ‘_’. Every subsequent character of the label (except for the last character ‘:’ in the definition of a location label) must be an English letter, digit, or ‘_’. The definition of a location label can be on a separate line, or at least one whitespace character and an assembler instruction can follow that definition. At least one whitespace character and the ‘prob’ keyword (see Variables in an Assembler Program, for more information on that keyword) must follow the definition of a data label.

If a line starts with at least one whitespace character, then an assembler instruction can follow these whitespace characters. The assembler instruction consists of an instruction name optionally followed by at least one whitespace character and instruction parameters. The assembler ignores whitespace characters in instruction parameters outside string literals.

A sample assembler program is below:

L1:     stt
        jprob   0.5, L2         ; jump with probability 0.5
        foo     4               ; user instruction
        jmp     L1

L2:     bar     r3, 5           ; user instruction
        jmp     L1

At present, an assembler program can contain “data” and “code” sections. The “data” sections can define probability variables using the ‘prob’ keyword following a data label and at least one whitespace character. The “code” sections can contain assembler instructions. The ‘.data’ and ‘.code’ directives mark the beginnings of blocks of “data” and “code” sections respectively. Those directives must be on lines of their own (after at least one whitespace character at the beginning of a line). If an assembler program contains multiple ‘.data’ and ‘.code’ directives, the assembler merges the corresponding blocks into a single “data” section and a single “code” section. By default, the assembler assumes that an assembler program starts with a ‘.code’ block.

The assembler supports the ‘line’ directive and uses information changed by it when printing error, warning, and note messages. You can put that directive in an assembler program explicitly, or the assembler preprocessor (see Using the Assembler Preprocessor) may generate it. The ‘line’ directive can change the current line number in the source file, the name of that source file, the stack of include locations, and the stack of macro expansion locations tracked by the assembler. This manual does not document changing the stack of include locations and the stack of macro expansion locations, because the corresponding syntax of ‘line’ directive will likely be different in future QSMM versions.

The directive must be on a separate line (after at least one whitespace character at the beginning of the line) and should have one of the following formats:

        line    line_number
        line    line_number, file_name

In the first case, the directive changes the tracked number of the next line in the current source file to line_number. In the second case, the directive changes the tracked number of the next line to line_number and the tracked name of the current source file to file_name. The parameter file_name must be a (quoted) string literal.


Next: , Previous: , Up: Assembler Programs   [Contents][Index]

5.3 Assembler Instructions

In QSMM, there are three categories of assembler instructions: built-in instructions, user instructions, and mixed-type instructions.

The built-in instructions are case, choice, end, jmp, joe, jprob, and stt. The assembler understands the built-in instructions without a prior definition of corresponding instruction classes and meta-classes. The built-in instructions do not necessarily induce code for execution by some kind of a machine; they can be the control words affecting the structure of a machine.

User instructions are assembler instructions with application-specific behavior. You declare a custom set of user instructions in an application program by registering instruction classes and meta-classes. You implement the execution of actions associated with the user instructions in the event handlers of instruction meta-classes.

The mixed-type instructions are abort, lookup, nop, and nop1. The disassembler can generate abort, lookup, and nop1 instructions, but assembling them requires defining the corresponding instruction classes and meta-classes. Their implementation can be specific to an application program. In certain cases, the assembler may implicitly generate nop instructions, but assembling them fails without a definition of the corresponding instruction class and meta-class.


Next: , Up: Assembler Instructions   [Contents][Index]

5.3.1 jmp Instruction

The instruction has the syntax

        jmp     loc_label

and specifies transferring control to a location label loc_label. The location label should have the following definition elsewhere in the assembler program:

loc_label:

Next: , Previous: , Up: Assembler Instructions   [Contents][Index]

5.3.2 jprob Instruction

This instruction has the following forms:

        jprob   number, loc_label
        jprob   var_name, loc_label

It specifies control transfer to a location label loc_label with probability number or with profile probability stored in a variable var_name. The parameter number must be in the range 0 to 1 inclusive. The assembler supports fixed-point and exponential notations for number.

The jprob instruction effectively sets a profile probability in the action emission matrix or at least one profile probability in the state transition matrix. If an stt instruction precedes a contiguous block of jprob instructions, these jprob instructions set profile probabilities in the action emission matrix. If an stt instruction does not precede a contiguous block of jprob instructions, these jprob instructions set profile probabilities in the state transition matrix. See stt Instruction, for more information.

If the assembler expects a user instruction at a particular location but encounters a contiguous block of jprob instructions at this location, the assembler implicitly inserts a nop instruction before the contiguous block and treats it as possible transitions to states made after the invocation of this nop instruction.

Let us consider a block of jprob instructions like this:

        jprob   prob1, L1
        jprob   prob2, L2
        jprob   prob3, L3

The probabilities of jumps to various destinations are the following:

Jump destinationProbability value
The location label L1prob1
The second jprob instruction1-prob1
The location label L2(1-prob1)*prob2
The third jprob instruction(1-prob1)*(1-prob2)
The location label L3(1-prob1)*(1-prob2)*prob3
An instruction following the third jprob instruction(1-prob1)*(1-prob2)*(1-prob3)

Next: , Previous: , Up: Assembler Instructions   [Contents][Index]

5.3.3 choice Instruction Block

This instruction block has the format

        choice
        case    ...
        case    ...
        ...
        end     choice

It consists of a choice instruction, at least one case instruction, and an end choice instruction. The instructions case and end choice must not have location labels assigned.

Each case instruction must have one of the following forms:

        case    number, loc_label
        case    var_name, loc_label

These case instructions specify control transfer to a location label loc_label with probability number or with profile probability stored in a variable var_name. The parameter number must be in the range 0 to 1 inclusive. The assembler supports fixed-point and exponential notations for number. If a choice instruction has a location label assigned, then you must not use this location label as the second argument of case instructions in the choice instruction block.

The choice instruction block effectively sets profile probabilities in the action emission matrix or state transition matrix. If an stt instruction precedes a particular choice instruction block, this instruction block sets profile probabilities in the action emission matrix. If an stt instruction does not precede a particular choice instruction block, this instruction block sets profile probabilities in the state transition matrix. See stt Instruction, for more information.

If the assembler expects a user instruction at a particular location but encounters a choice instruction block at this location, the assembler implicitly inserts a nop instruction before the choice instruction block and treats it as possible transitions to states made after the invocation of this nop instruction.

In contrast to a contiguous block of jprob instructions, a choice instruction block allows you to specify jump probabilities in a direct way. Let us consider a choice instruction block like this:

        choice
        case    prob1, L1
        case    prob2, L2
        case    prob3, L3
        end     choice

The probabilities of jumps to various destinations are the following:

Jump destinationProbability value
The location label L1prob1
The location label L2prob2
The location label L3prob3
An instruction following the choice instruction block1-prob1-prob2-prob3

Compare this example to the example with a block of jprob instructions in jprob Instruction.


Next: , Previous: , Up: Assembler Instructions   [Contents][Index]

5.3.4 joe Instruction

This instruction has the syntax

        joe     outcome, loc_label

and specifies control transfer to a location label loc_label if the outcome of last invoked user or mixed-type instruction is equal to outcome. The event handler of an instruction meta-class sets the number of outcomes of instructions belonging to an instruction class derived from the instruction meta-class on initialization of this instruction class.

If the assembler expects a user or mixed-type instruction at a particular location but encounters a contiguous block of joe instructions at this location, the assembler implicitly inserts a nop instruction before the contiguous block. Normally, the nop instruction does not change the outcome of last invoked instruction. After assembling the nop instruction, the assembler treats the contiguous block as a place of analysis of that outcome.


Next: , Previous: , Up: Assembler Instructions   [Contents][Index]

5.3.5 stt Instruction

This instruction has the following forms:

        stt
        stt     state_name

They are equivalent to the notation

        stt     [state_name]

The instruction marks the beginning of a state of an assembler program. The state biuniquely corresponds to a state of a node with this assembler program loaded. Both states can have a name specified by a (quoted) string literal state_name. An assembler program must not contain states with duplicate names. See Loading a Parsed Program into a Node, for the description of qsmm_get_node_state_name and qsmm_get_node_state_by_name functions retrieving the name of a node state by its index and retrieving the index of a node state by its name.

The stt instruction chooses the action emission matrix to hold profile probabilities specified by certain other instructions in an assembler program. Without the stt instruction, those other instructions would specify profile probabilities held in the state transition matrix.

The action emission matrix can have the restriction to define only deterministic choices of user and mixed-type instructions in all node states. In this case, all jprob and case instructions in an assembler program specify profile probabilities held in the state transition matrix—if there is no need to assign a name to a state, you can omit an stt instruction marking the beginning of this state.

If the action emission matrix does not have the restriction to define only deterministic choices of user and mixed-type instructions in all node states, omitting an stt instruction in an assembler program causes an unprocessed instruction or a nop instruction implicitly inserted before the unprocessed instruction to become the beginning of the next state. To prevent this undesired behavior, the best practice is to specify stt instructions for all states in the assembler program to know exactly where each state begins. To support this approach, the assembler can generate a warning for every location where a state begins, but an stt instruction is missing there. Note that inserting stt instructions into an assembler program may require rearranging the assembler program.

There are three possible types of places where you can insert an stt instruction.

  1. Before a user instruction or mixed-type instruction:
            stt     [state_name]
            user or mixed-type instruction
    

    This instruction arrangement means that in a state marked by the stt instruction the instruction emitting engine emits a specified user or mixed-type instruction. The user or mixed-type instruction must not have a location label assigned on condition that a jump from elsewhere to this label exists.

    As a result of assembling this instruction arrangement, the action emission matrix defines deterministic choice of this user or mixed-type instruction in this state. The action emission matrix contains profile probability 1 for this state and this user or mixed-type instruction and profile probability 0 for this state and all other user and mixed-type instructions.

    If you need to mark the beginning of a state, but there is no effective user or mixed-type instruction to insert beneath the stt instruction, you may insert the nop or nop1 instruction instead of such user or mixed-type instruction.

  2. Before a block of jprob instructions:
            stt     [state_name]
            jprob   prob1, L1
            jprob   prob2, L2
            ...
            jprob   probN, LN
            user or mixed-type instruction 0
            ...
    
    L1:     user or mixed-type instruction 1
            ...
    L2:     user or mixed-type instruction 2
            ...
    LN:     user or mixed-type instruction N
            ...
    

    This instruction arrangement means that in a state marked by the stt instruction the instruction emitting engine emits one of specified user or mixed-type instructions. All those user and mixed-type instructions must belong to different instruction classes, that is, have different combinations of an instruction name and instruction parameters. None of jprob instructions just after the stt instruction must have location labels assigned on condition that jumps from elsewhere to these labels exist.

    As a result of assembling this instruction arrangement, the action emission matrix contains the profile probabilities of emitting all specified user or mixed-type instructions in the state and contains profile probability 0 of emitting all other user and mixed-type instructions in this state. However, in the general case, the profile probabilities of emitting the specified user and mixed-type instructions are different from profile probabilities indicated in the corresponding jprob instructions. For more information, see an example block of jprob instructions in jprob Instruction.

  3. Before a choice instruction block:
            stt     [state_name]
    
            choice
            case    prob1, L1
            case    prob2, L2
            ...
            case    probN, LN
            end     choice
    
            user or mixed-type instruction 0
            ...
    
    L1:     user or mixed-type instruction 1
            ...
    L2:     user or mixed-type instruction 2
            ...
    LN:     user or mixed-type instruction N
            ...
    

    This instruction arrangement means that in a state marked by the stt instruction the instruction emitting engine emits one of specified user or mixed-type instructions. All those user and mixed-type instructions must belong to different instruction classes, that is, have different combinations of an instruction name and instruction parameters. The choice instruction after the stt instruction must not have a location label assigned on condition that a jump from elsewhere to this label exists. Do not assign location labels to case instructions in the choice instruction block.

    As a result of assembling this instruction arrangement, the action emission matrix contains the profile probabilities of emitting all specified user or mixed-type instructions in the state and contains profile probability 0 of emitting all other user and mixed-type instructions in this state. The profile probabilities of emitting the specified user and mixed-type instructions excluding the profile probability of emitting a user or mixed-type instruction beneath the choice instruction block are equal to profile probabilities indicated in the corresponding case instructions.

Adhere to the following assembler program structure after every user or mixed-type instruction in the above three instruction arrangement schemes:

  1. The locations of joe instruction blocks. A contiguous block of joe instructions can follow a user or mixed-type instruction. Those joe instructions analyze the outcome of this user or mixed-type instruction.
  2. The jump targets of joe instructions. Every joe instruction specifies a (conditional) jump to a contiguous block of jprob instructions or to a choice instruction block or to the beginning of a state.
  3. Instructions after a joe instruction block. One of these assembler text fragments follows a contiguous block of joe instructions:
    1. A contiguous block of jprob instructions.
    2. A choice instruction block.
    3. A jmp instruction transferring control to a state.
    4. The beginning of another state.
  4. Specifying state transition probabilities. A contiguous block of jprob instructions or a choice instruction block with case instructions can be the jump target of a joe instruction or can follow a contiguous block of joe instructions. Those jprob or case instructions specify probabilities stored in the state transition matrix. The jump targets of those jprob or case instructions are the beginnings of states.
  5. What follows a specification of state transition probabilities. The beginning of a different state or a jmp instruction transferring control to a state follows a contiguous block of jprob instructions or a choice instruction block if they specify state transition probabilities.

The following example illustrates the described assembler program structure.

        user or mixed-type instruction X

        ; A contiguous block of `joe' instructions. They analyze the
        ; outcome of user or mixed-type instruction X.
        ;
        ; Each of L1, L2, ..., LN labels transfers control to the
        ; beginning of one of the following:
        ; - a contiguous block of `jprob' instructions;
        ; - a `choice' instruction block;
        ; - a state.

        joe     outcome1, L1
        joe     outcome2, L2
        ...
        joe     outcomeN, LN

        joe     outcomeN1, LN1          ; The conditional jump to a sample
                                        ; contiguous block of `jprob'
                                        ; instructions.

        joe     outcomeN2, LN2          ; The conditional jump to a sample
                                        ; `choice' instruction block.

        ; An optional contiguous block of `jprob' instructions (can also be
        ; a `choice' instruction block). They specify the probabilities of
        ; transitions to states for the source state, user or mixed-type
        ; instruction X emitted in that source state, and any outcome
        ; of user or mixed-type instruction X different from outcome1,
        ; outcome2, ..., outcomeN, outcomeN1, and outcomeN2.
        ;
        ; Labels SA1, SA2, ..., SAN, and SANN transfer control to the
        ; beginnings of states.

        jprob   probA1, SA1
        jprob   probA2, SA2
        ...
        jprob   probAN, SAN
        jmp     SANN

        ; A sample `choice' instruction block. It specifies the
        ; probabilities of transitions to states for the source state, user
        ; or mixed-type instruction X emitted in that source state, and
        ; outcome outcomeN2 of user or mixed-type instruction X.
        ;
        ; Labels SB1, SB2, ..., SBN, and SBNN transfer control to the
        ; beginnings of states.

LN2:    choice
        case    probB1, SB1
        case    probB2, SB2
        ...
        case    probBN, SBN
        end     choice

        jmp     SBNN

        ; A sample contiguous block of `jprob' instructions. They specify
        ; the probabilities of transitions to states for the source state,
        ; user or mixed-type instruction X emitted in that source state,
        ; and outcome outcomeN1 of user or mixed-type instruction X.
        ;
        ; Labels SC1, SC2, ..., SCN, and SCNN transfer control to the
        ; beginnings of states.

LN1:    jprob   probC1, SC1
        jprob   probC2, SC2
        ...
        jprob   probCN, SCN
        jmp     SCNN                    ; This instruction is not necessary
                                        ; if it specifies the jump to a
                                        ; state going just after this line.

        ; The beginning of another state.

After a user or mixed-type instruction there can be no joe instructions at all. In this case, one of these assembler text fragments should immediately follow this user or mixed-type instruction:

  1. A contiguous block of jprob instructions.
  2. A choice instruction block.
  3. A jmp instruction transferring control to a state.
  4. The beginning of another state.

The following example illustrates this instruction arrangement.

        user or mixed-type instruction Y

        ; An optional contiguous block of `jprob' instructions (can also be
        ; a `choice' instruction block). They specify the probabilities of
        ; transitions to states for the source state, user or mixed-type
        ; instruction Y emitted in that source state, and any possible
        ; outcome of user or mixed-type instruction Y.
        ;
        ; Labels S1, S2, ..., SN, and SNN transfer control to the
        ; beginnings of states.

        jprob   prob1, S1
        jprob   prob2, S2
        ...
        jprob   probN, SN
        jmp     SNN                     ; This instruction is not necessary
                                        ; if it specifies the jump to a
                                        ; state going just after this line.

        ; The beginning of another state.

Adherence to the described assembler program structure simplifies understanding how the assembler converts an assembler program to a probability profile stored in the state transition matrix and action emission matrix of a node. This understanding is necessary to develop an assembler program for a node capable of efficient training.


Next: , Previous: , Up: Assembler Instructions   [Contents][Index]

5.3.6 nop and nop1 Instructions

The mixed-type instructions nop and nop1 should have the corresponding instruction meta-classes registered for a multinode model.

The expected behavior of nop instruction is the absence of any effect except for the duplication of outcome of the previous instruction invoked by a node. You can define the instruction meta-class for the nop instruction by the following code block:

static QSMM_INSTR_META_CLASS(nop) {
    switch (qsmm_evt) {
        case QSMM_EVT_INSTR_CLASS_INIT:
            qsmm_set_eh_noutcome(qsmm,0);
            break;
    }
    return 0;
}

The assembler can implicitly generate nop instructions while assembling a program and produce warnings indicating the insertion locations of those instructions. Ideally, an assembler program should not have implicitly generated nop instructions.

The mixed-type instruction nop1 should have single outcome 0 the instruction always returns. Besides that, the instruction should not have any effect. You can define the instruction meta-class of nop1 instruction by the following code block:

static QSMM_INSTR_META_CLASS(nop1) {
    return 0;
}

You can insert a nop1 instruction after an stt instruction where it is not necessary to preserve the outcome of the previous instruction invoked by a node. The use of nop1 instruction instead of nop instruction reduces the number of profile probabilities written to the state transition matrix making it simpler and decreasing the amount of memory needed to store the matrix. The disassembler can generate the nop1 instruction at the beginning of an assembler program.


Next: , Previous: , Up: Assembler Instructions   [Contents][Index]

5.3.7 lookup Instruction

This instruction is a mixed-type instruction. The disassembler can generate lookup instructions when disassembling a node of a multinode model with positive length of look-ahead signal segment. The field ngram_env_la_sz of qsmm_desc_s structure passed to the function qsmm_create specifies this length when creating the multinode model. The function qsmm_get_ngram_env_la_sz fetches this length for an existing multinode model.

The instruction has the syntax

        lookup  position

and sets the outcome equal to a look-ahead signal at zero-based position in the look-ahead signal segment.

The assembler does not support loading assembler programs into the nodes of a multinode model with positive length of look-ahead signal segment. Therefore, if you need to assemble a program (e.g. generated by the disassembler) containing lookup instructions, you do the following:

  1. Create a multinode model with zero-length look-ahead signal segment.
  2. Register the instruction meta-class ‘lookup’.
  3. Register instruction classes derived from the instruction meta-class ‘lookup’ for possible values of position. Instructions belonging to those instruction classes fetch signals at specified positions from an array used as a substitute for the look-ahead signal segment.
  4. Modify the elements of this array where you would modify the elements of look-ahead signal segment.

Next: , Previous: , Up: Assembler Instructions   [Contents][Index]

5.3.8 abort Instruction

This instruction is a mixed-type instruction. The disassembler can generate it after a user instruction or another mixed-type instruction when there is no information about instructions following the user or mixed-type instruction. This is the case when the instruction emitting engine emitted the user or mixed-type instruction once and that instruction has not returned control, or when the disassembler discarded subsequent instructions according to disassembling parameters.

You can use the following approach to assemble programs generated by the disassembler containing abort instructions. First, make the disassembler generate a single abort instruction at the end of an assembler program by setting the field use_abort_1 of qsmm_disasm_desc_s structure to a non-zero value. In this case, the assembler program contains jumps to this abort instruction from other locations where the disassembler would insert abort instructions in default mode. The disassembler additionally generates a jump to the beginning of this assembler program beneath this abort instruction. Second, implement the abort instruction as the nop1 instruction (without any effect). After you have done these two things, the environment state identification engine transfers control to the beginning of this assembler program when the next instruction to execute is unknown. Such looping may be appropriate in your situation.


Previous: , Up: Assembler Instructions   [Contents][Index]

5.3.9 User Instructions

An assembler program can contain user instructions. They are application-specific and can perform operations listed in Handling Instruction Invocation. User instructions correspond to instruction classes in the instruction class set of a node containing the assembler program. To find an instruction class for a user instruction, the assembler first converts the parameters of this user instruction to canonical form according to the rules described in Setting Text Instruction Parameters.

You can split the parameters of a user instruction into multiple lines at positions of commas located outside of string literals. To indicate a continuation of instruction parameters on the next line, finish the previous line just after a comma following an instruction parameter.


Next: , Previous: , Up: Assembler Programs   [Contents][Index]

5.4 Disassembling a Node

You can convert the state transition matrix and action emission matrix of a node to an assembler program—disassemble the node.

You typically disassemble a node after executing or training it. Before executing the node, you can load into it an assembler program specifying a probability profile for the state transition matrix and action emission matrix. To simplify the analysis of results of training the node, it might be desirable to obtain a disassembled program which is an assembler program previously loaded into the node, but with profile probabilities in jprob and case instructions changed to probabilities learned while training the node. To turn on this mode—disassembling using an assembler program template,—pass the QSMM_ASM_TEMPLATE flag to the function qsmm_node_asm when loading an assembler program into a node you are going to disassemble later (see Loading a Parsed Program into a Node). If a node does not have an assembler program loaded, or the node has an assembler program loaded without specifying the QSMM_ASM_TEMPLATE flag, you can only disassemble the node in classic mode.

Use the following function to disassemble a node.

Function: int qsmm_node_disasm (qsmm_t model, qsmm_sig_t node, struct qsmm_disasm_desc_s *desc_p, qsmm_prg_t *prg_p)

This function disassembles a node of a multinode model and stores the allocated handle of a disassembled program in *prg_p if prg_p is not NULL. The argument node specifies the identifier of this node. If desc_p is not NULL, *desc_p specifies disassembling parameters. If desc_p is NULL, the function uses default disassembling parameters.

If the function qsmm_node_asm previously assembled the node with the QSMM_ASM_TEMPLATE flag, or the node uses a source probability profile provided by another node assembled with the QSMM_ASM_TEMPLATE flag, the disassembled program is a template assembler program with replaced probabilities in jprob and case instructions. If desc_p is not NULL, probabilities of desc_p->prob_type type replace profile probabilities in those jprob and case instructions. If desc_p is NULL, probabilities of QSMM_PROB_AGGR type replace the profile probabilities.

In the current implementation, the function does not modify *desc_p if desc_p is not NULL. However, in a future implementation, the function may modify *desc_p, for example, to store there statistics on the disassembling process.

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_NOTFOUND

A node with identifier node does not exist.

QSMM_ERR_INVAL

The argument desc_p is not NULL, and parameters in *desc_p are invalid.

QSMM_ERR_UNTIMELY

The model instance does not exist.

QSMM_ERR_CALLBACK

A helper function for computing the relative probability of an output signal reported an error by returning NaN. The function qsmm_actor_calc_action_prob calls the helper function.

QSMM_ERR_STORAGE

A Storage API function reported storage failure.

QSMM_ERR_STATS

Inconsistent statistics on an action choice state or cycle type detected.

QSMM_ERR_ILSEQ

Unable to convert a multibyte string to a wide string or vice versa according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Errors QSMM_ERR_STORAGE, QSMM_ERR_STATS, QSMM_ERR_ILSEQ, and QSMM_ERR_NOMEM can leave the model instance in inconsistent state.

The description of a structure passed to the function qsmm_node_disasm is below.

Structure: qsmm_disasm_desc_s

This structure specifies the parameters of disassembling. The structure contains the following fields.

Field: char use_stt_start

If not 0, generate an stt instruction at the beginning of an assembler program if it started with a lookup instruction, and generate stt and nop1 instructions at the beginning of an assembler program if it started with a jprob instruction or choice instruction block. The default is not to generate. The disassembler ignores this field when disassembling a node using an assembler program template.

Field: char use_stt_state

If not 0, generate stt instructions at the beginnings of states. The default is not to generate. The disassembler ignores this field when disassembling a node using an assembler program template.

Field: char use_stt_lookup

If not 0, generate stt instructions before lookup instructions. The default is not to generate. The disassembler ignores this field when disassembling a node using an assembler program template.

Field: char use_stt_abort

If not 0, generate stt instructions before abort instructions. This is not very useful unless there is not more than one abort instruction in an assembler program (the field use_abort_1 sets this mode). The default is not to generate. The disassembler ignores this field when disassembling a node using an assembler program template.

Field: char use_choice

If not 0, generate choice instruction blocks instead of contiguous blocks of jprob instructions when the number of jprob instructions in a block is greater than one. The default is to generate. The disassembler ignores this field when disassembling a node using an assembler program template.

Field: char use_abort_1

If is 0, and there is no information what to execute after a user or mixed-type instruction, generate an abort instruction after the user or mixed-type instruction. If not 0, generate a jump after this user or mixed-type instruction to a single abort instruction at the end of an assembler program and generate a jump to the start of this assembler program after this abort instruction. If not 0, and there are no jumps to the abort instruction at the program end, skip generating that abort instruction followed by a jump to the program start. The default is to generate an abort instruction after a user or mixed-type instruction. The disassembler ignores this field when disassembling a node using an assembler program template.

Field: char do_retain_goto_1

If not 0, retain the most probable transition to a target state for every quadruple consisting of a source state, a user or mixed-type instruction emitted in the source state, the outcome of this instruction, and the content of look-ahead signal segment when discarding transitions with probabilities less than specified in the field prob_goto_min. This retaining ensures that for every quadruple there remains at least one transition to a target state. The field prob_type specifies the type of analyzed probabilities. The default is not to retain the most probable transition. The disassembler ignores this field when disassembling a node using an assembler program template.

Field: char do_retain_action_1

If not 0, retain the most probable user or mixed-type instruction emittable in every state when discarding instructions with probabilities less than specified in the field prob_action_min. This retaining ensures that for every state there remains at least one emittable user or mixed-type instruction—the disassembler will not remove a state because the state is without emittable user and mixed-type instructions. The field prob_type specifies the type of analyzed probabilities. The default is not to retain the most probable user or mixed-type instruction. The disassembler ignores this field when disassembling a node using an assembler program template.

Field: char do_calc_prob[QSMM_PROB_COUNT]

An array specifying additional types of probabilities to calculate for jprob and case instructions optionally printed in comments for those instructions. The indices of this array are the elements of qsmm_prob_e enumeration (except for its last element) described in Emitting an Output Signal. If an element of this array is non-zero, the disassembler calculates probabilities of a corresponding type and stores them in the instructions. The disassembler calculates probabilities of a type specified in the field prob_type regardless of do_calc_prob field. The default is not to calculate probabilities of additional types.

Field: long fq_goto_min

The minimum frequency of a transition to a target state for a quadruple consisting of a source state, a user or mixed-type instruction emitted in the source state, the outcome of this instruction, and the content of look-ahead signal segment. The disassembler discards transitions performed lesser numbers of times. The default minimum frequency is 0. The disassembler ignores this field when disassembling a node using an assembler program template.

Field: long fq_action_min

The minimum frequency of emitting a user or mixed-type instruction in a state. The disassembler discards instructions emitted lesser numbers of times. The default minimum frequency is 0. The disassembler ignores this field when disassembling a node using an assembler program template.

Field: double prob_goto_min

When disassembling a node using an assembler program template, this field specifies a minimum probability for jprob and case instructions corresponding to the state transition matrix. The disassembler removes instructions containing lesser probabilities from a disassembled program, although those instructions were in the assembler program template.

When disassembling a node without using an assembler program template, this field specifies the minimum probability of a transition to a target state for a quadruple consisting of a source state, a user or mixed-type instruction emitted in the source state, the outcome of this instruction, and the content of look-ahead signal segment. The disassembler discards transitions with lesser probabilities after discarding transitions with frequencies less than a frequency specified in the field fq_goto_min and after renormalizing transition probabilities. When discarding transitions with lesser probabilities, if do_retain_goto_1 is not 0, the disassembler retains most probable transitions.

The field prob_type specifies the type of analyzed probabilities. The default minimum probability is 0.

Field: double prob_action_min

When disassembling a node using an assembler program template, this field specifies a minimum probability for jprob and case instructions corresponding to the action emission matrix. The disassembler removes instructions containing lesser probabilities from a disassembled program, although those instructions were in the assembler program template.

When disassembling a node without using an assembler program template, this field specifies the minimum probability of emitting a user or mixed-type instruction in a state. The disassembler discards instructions with lesser emitting probabilities after discarding instructions with frequencies less than a frequency specified in the field fq_action_min and after renormalizing emitting probabilities. When discarding instructions with lesser emitting probabilities, if do_retain_action_1 is not 0, the disassembler retains most probable instructions.

The field prob_type specifies the type of analyzed probabilities. The default minimum probability is 0.

Field: enum qsmm_prob_e prob_type

The type of probabilities to calculate for jprob and case instructions.

When disassembling a node using an assembler program template, the disassembler compares those probabilities with probabilities in the fields prob_goto_min and prob_action_min to determine whether to discard specific jprob and case instructions.

When disassembling a node without using an assembler program template, this field specifies the type of probabilities for sorting jprob and case instructions in descending order within corresponding instruction blocks. This field also specifies the type of state transition probabilities and instruction emission probabilities for comparing with probabilities in the fields prob_goto_min and prob_action_min.

See Emitting an Output Signal, for the description of elements of qsmm_prob_e enumeration. The default type of probabilities is QSMM_PROB_AGGR.

Zero by the function memset an instance of qsmm_disasm_desc_s structure before setting the fields of this instance passed to the function qsmm_node_disasm.

When disassembling a node without using an assembler program template, the disassembler generates the following comments for instructions in a disassembled program:

Note the following regarding the frequencies that include the numbers of transfers of control to states, the numbers of instruction invocations, and the numbers of jumps performed:

To generate the most probable completely deterministic program when disassembling a node without using an assembler program template, set to 1 the fields prob_goto_min, prob_action_min, do_retain_goto_1, and do_retain_action_1 of qsmm_disasm_desc_s structure.

Below there is an example of calling the function qsmm_node_disasm to generate a program for subsequent assembling. A disassembled node does not have an assembler program loaded.

qsmm_prg_t prg=0;
struct qsmm_disasm_desc_s disasm_desc;
memset(&disasm_desc,0,sizeof(disasm_desc));
// Insert `stt' instructions at appropriate places.
disasm_desc.use_stt_start=1;
disasm_desc.use_stt_state=1;
disasm_desc.use_stt_lookup=1;
disasm_desc.use_stt_abort=1;
// Improve the readability of probabilistic jumps.
disasm_desc.use_choice=1;
// Simplify handling unexplored control paths.
disasm_desc.use_abort_1=1;
// Do not generate never executed code.
disasm_desc.fq_goto_min=1;
disasm_desc.fq_action_min=1;
// Do not generate probabilistic jumps for
// rounded probabilities less than 1%.
disasm_desc.prob_goto_min=0.005;
disasm_desc.prob_action_min=0.005;
qsmm_node_disasm(qsmm,node,&disasm_desc,&prg);

An example of calling the function qsmm_node_disasm for a node assembled with the QSMM_ASM_TEMPLATE flag occupies a lesser number of lines because the disassembler uses a small subset of fields of qsmm_disasm_desc_s structure in this mode.

qsmm_prg_t prg=0;
struct qsmm_disasm_desc_s disasm_desc;
memset(&disasm_desc,0,sizeof(disasm_desc));
// Remove `jprob' and `case' instructions with
// rounded probabilities less than 1%.
disasm_desc.prob_goto_min=0.005;
disasm_desc.prob_action_min=0.005;
qsmm_node_disasm(qsmm,node,&disasm_desc,&prg);

Refer to the files tests/disasm2.c and tests/lookup2.c for the methods of assembling a previously disassembled program.


Next: , Previous: , Up: Assembler Programs   [Contents][Index]

5.5 Inspecting an Assembler Program

Use the following function to get the number of instructions contained in an assembler program.

Function: int qsmm_get_prg_ninstr (qsmm_prg_t prg)

This function returns the number of instructions contained in a program prg. A returned value is always non-negative.

Use the following function to get an instruction contained in an assembler program.

Function: qsmm_instr_t qsmm_get_prg_instr (qsmm_prg_t prg, int instr_idx)

This function returns an instruction contained in a program prg at zero-based index instr_idx.

If instr_idx is negative or greater than or equal to the number of instructions in the program, the function returns NULL.

The following enumeration specifies the type of an assembler instruction.

Enumeration: qsmm_instr_e

This enumeration represents the type of an assembler instruction. The enumeration contains the following elements.

QSMM_INSTR_USER

A user or mixed-type instruction.

QSMM_INSTR_JMP

A jmp instruction.

QSMM_INSTR_JPROB

A jprob instruction.

QSMM_INSTR_CASE

A case instruction (in a choice instruction block).

QSMM_INSTR_CHOICE

A choice instruction.

QSMM_INSTR_JOE

A joe instruction.

QSMM_INSTR_STT

An stt instruction.

QSMM_INSTR_END

An end choice instruction (at the end of a choice instruction block).

Use the following function to get the type of an assembler instruction.

Function: enum qsmm_instr_e qsmm_get_instr_type (qsmm_instr_t instr)

This function returns the type of an instruction instr.

The function qsmm_get_prg_instr does not return instructions with the types QSMM_INSTR_CASE and QSMM_INSTR_END. Instead, it can return an instruction with the type QSMM_INSTR_CHOICE representing a choice instruction block containing nested case instructions and a nested end choice instruction. Use the following function to get the number of instructions nested in a choice instruction block.

Function: size_t qsmm_get_instr_nnested (qsmm_instr_t instr)

This function returns the number of instructions nested in an instruction instr with the type QSMM_INSTR_CHOICE. For instructions with other types, the function returns 0.

Use the following function to get a nested case or end choice instruction.

Function: qsmm_instr_t qsmm_get_instr_nested (qsmm_instr_t instr, size_t nested_idx)

This function returns an instruction nested in an instruction instr with the type QSMM_INSTR_CHOICE. The argument nested_idx specifies zero-based index of a nested instruction.

If the instruction instr does not have the type QSMM_INSTR_CHOICE, or nested_idx is greater than or equal to the number of instructions nested in the instruction instr, the function returns NULL.

An instruction can have location labels placed to the left of this instruction or before it. You can use a location label assigned to a choice instruction block to refer to an output probabilities array containing elements corresponding to case instructions in the block (see Output Arrays). Use the following function to get the number of location labels assigned to an instruction.

Function: size_t qsmm_get_instr_nlabel (qsmm_instr_t instr)

This function returns the number of location labels assigned to an instruction instr normally placed to the left of this instruction or before it.

Use the following function to get a location label by its index.

Function: const char * qsmm_get_instr_label (qsmm_instr_t instr, size_t label_idx)

This function returns a location label at zero-based index label_idx assigned to an instruction instr. If label_idx is greater than or equal to the number of location labels assigned to the instruction, the function returns NULL.


Next: , Previous: , Up: Assembler Programs   [Contents][Index]

5.6 Printing an Assembler Program

Use the following function to get a string representation of an assembler instruction.

Function: int qsmm_instr_str (char *bufp, size_t bufsz, qsmm_instr_t instr, struct qsmm_dump_instr_desc_s *desc_p)

This function stores in a buffer bufp with size bufsz bytes a string representation of an instruction instr. If desc_p is not NULL, the function generates the string representation according to parameters in *desc_p. If desc_p is NULL, the function generates the string representation according to default parameters. The function may change either *desc_p or those default parameters.

On success, the function returns a non-negative number of bytes required to store the string representation not counting finalizing byte 0. If bufsz is less than INT_MAX, a returned value greater than or equal to bufsz indicates the truncation of a string representation. In this case, if bufsz is positive, the function stores in bufp a truncated string representation with length bufsz–1 bytes and terminates a stored string with byte 0. The function supports passing 0 for both bufp and bufsz to determine the length of a string representation.

On failure, the function returns a negative error code. Currently, the function can return the following error codes.

QSMM_ERR_INVAL

The argument bufsz is positive, but bufp is NULL.

QSMM_ERR_ILSEQ

Unable to convert a multibyte string to a wide string or vice versa according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

The QSMM library contains an instance of qsmm_dump_instr_desc_s structure holding the default parameters of generating string representations of assembler instructions. Use the following function to get a pointer to this instance.

Function: struct qsmm_dump_instr_desc_s * qsmm_get_default_dump_instr_desc ()

This function returns a pointer to the default parameters of generating string representations of assembler instructions. You can change those parameters via this pointer. The function never returns NULL.

The description of a structure specifying the parameters of generating string representations of instructions is below.

Structure: qsmm_dump_instr_desc_s

This structure specifies the parameters of generating a string representation of an assembler instruction. The structure contains the following fields.

Field: char is_line_after_comment_above

If this field is not 0, the field do_print_comment_above is not 0, and the instruction has a comment above itself, insert an empty line after the comment and before the instruction. The function qsmm_prg_dump uses this field in a similar way to determine whether to insert an empty line after a comment preceding a definition of a probability variable. The default is to insert an empty line.

Field: char is_line_after_multiline_comment_right

If this field is not 0, and the field do_print_comment_right is not 0, insert an empty line after an instruction with a multi-line comment to the right or after a definition of a probability variable with a multi-line comment to the right if the next line in the assembler program contains a comment to the right. If an instruction name or instruction parameters are too long, the function qsmm_instr_str may put this multi-line comment below the instruction. The default is to insert an empty line.

Field: char is_space_after_comma

If not 0, insert a space after every comma outside string literals in instruction parameters. The default is to insert a space.

Field: char do_print_label

If not 0 and the instruction has a location label assigned, print the location label to the left of the instruction. If the instruction has multiple location labels assigned, print all those labels except for the last one on separate lines. If there is no room between the last label and an instruction name, print the last label on a separate line too. The default is to print location labels.

Field: char do_print_name

If not 0, print an instruction name. The default is to print.

Field: char do_print_param

If not 0, print instruction parameters. The default is to print.

Field: char do_print_comment_above

If not 0 and the instruction has a comment above itself, print this comment. The function qsmm_prg_dump uses this field in a similar way to determine whether to print comments above the definitions of probability variables. The default is to print the comments.

Field: char do_print_comment_right

If not 0 and the instruction has a comment to the right, print this comment. The function qsmm_prg_dump uses this field in a similar way to determine whether to print comments to the right of definitions of probability variables. The default is to print the comments.

Field: char do_print_comment_below

[New in QSMM 1.17] If not 0, the instruction has a comment to the right, and an instruction name or instruction parameters are too long, put this comment below the instruction. The function qsmm_instr_str considers the instruction name or parameters too long if the comment to the right is going to start at a column greater than specified in the field col_comment, and that field is positive. The function qsmm_instr_str indents the comment below the instruction at column col_comment. The default is not to move below an instruction a comment to the right of this instruction.

Warning: QSMM 1.18 does not correctly assign the comments below instructions to these instructions while parsing an assembler program.

Field: char do_print_var

If not 0, a jprob or case instruction uses the name of a probability variable, and the field prob_type is equal to QSMM_PROB_PROFILE, print that name in the instruction. Otherwise, print a probability. The default is to print the names of probability variables when possible.

Field: char do_print_state_name

If this field is not 0, the field do_print_param is not 0, and an stt instruction has a state name, print the state name in the instruction. The default is to print state names.

Field: char do_print_prob[QSMM_PROB_COUNT]

An array specifying additional types of probabilities to print in a comment for a jprob or case instruction to the right. If an instruction name or instruction parameters are too long, the function qsmm_instr_str may put this comment below the instruction. The indices of this array are the elements of qsmm_prob_e enumeration (except for its last element) described in Emitting an Output Signal. If the field do_print_comment_right is not 0, an element of this array is not 0, and the index of this element is not equal to the field prob_type, qsmm_instr_str prints a probability of a corresponding type in the comment. When printing an instruction of a program disassembled using an assembler program template, if the instruction has ambiguous context in the template, qsmm_instr_str prints ‘?’ for the probabilities in the comment. The default is not to print probabilities in the comments.

Field: int prob_prec

The number of digits after the decimal point to print for a probability in a jprob or case instruction according to the field prob_type and for probabilities in a comment to the right of this instruction according to the field do_print_prob. If an instruction name or instruction parameters are too long, the function qsmm_instr_str may put this comment below the instruction. The field prob_prec also specifies the number of digits after the decimal point printed by the function qsmm_prg_dump for probabilities in the definitions of probability variables. If this field is non-negative, use fixed-point notation. If this field is negative, use exponential notation with the number of digits after the decimal point equal to the absolute value of this field. The default number of digits to print after the decimal point is 2.

Field: long col_name

If this field is positive, it specifies alignment column for an instruction name. If this field is not positive, do not align the instruction name. This field also specifies a column for the function qsmm_prg_dump to indent ‘.data’ and ‘.code’ directives, comments above instructions and above the definitions of probability variables, and a tail comment in an assembler program. If this field is not positive, do not indent ‘.data’ and ‘.code’ directives and the comments (start them at column 1). The default alignment column is 9.

Field: long col_param

If this field is positive, it specifies alignment column for instruction parameters and, if the parameters occupy multiple lines, a column to indent them on the following lines. If this field is not positive, do not align or indent the instruction parameters. The default alignment column is 17.

Field: long col_comment

If this field is positive, it specifies alignment column for a comment to the right of an instruction. If an instruction name or instruction parameters are too long, the function qsmm_instr_str may put this comment below the instruction. If this field is not positive, do not align the comment. The default alignment column is 33.

Field: long margin_right

If this field is positive, it specifies a right margin column for comments. The functions qsmm_instr_str and qsmm_prg_dump split longer comments into multiple lines. If this field is not positive, do not split comments into multiple lines based on a right margin column. The default is not to split.

Field: long margin_right_param

If this field is positive, it specifies a right margin column for the parameters of a user instruction. The function qsmm_instr_str splits long parameters into multiple lines and uses the positions of commas outside string literals as allowed split positions. If this field is not positive, do not split the parameters into multiple lines based on a right margin column. The default right margin column is 30.

Field: long nline_comment_right

Output parameter. The function qsmm_instr_str stores here the number of lines in a comment to the right of an instruction. If an instruction name or instruction parameters are too long, qsmm_instr_str may put this comment below the instruction. If the field do_print_comment_right is 0, the instruction does not have the comment, or it occupies the number of lines less than the number of lines occupied by instruction parameters, qsmm_instr_str stores 0 here. If do_print_comment_right is not 0, the instruction has this comment possibly split into multiple lines according to the field margin_right, and the number of lines occupied by the comment is greater than or equal to the number of lines occupied by the instruction parameters, qsmm_instr_str stores a positive value here. The function qsmm_prg_dump reads this field to insert an empty line after an instruction with a multi-line comment to the right if the next instruction has a comment to the right.

Field: long nline_param

Output parameter. The function qsmm_instr_str stores here the number of printed lines of instruction parameters. The function qsmm_prg_dump reads this field to determine whether to insert empty lines around multi-line instructions.

Field: size_t out_sz

Output parameter. [New in QSMM 1.17] The number of bytes occupied by a string representation printed by the function qsmm_instr_str not counting finalizing byte 0. That number does not depend on buffer size passed to qsmm_instr_str.

Field: enum qsmm_prob_e prob_type

The type of a probability to print in a jprob or case instruction. See Emitting an Output Signal, for the description of elements of qsmm_prob_e enumeration. When printing an instruction of a program disassembled using an assembler program template, if the instruction has ambiguous context in the template, the function qsmm_instr_str prints ‘?’ for the probability. The default type of probabilities is QSMM_PROB_AGGR.

Note: when converting a disassembled program or its specific instructions to a string representation, be sure to set the fields do_print_prob and prob_type of qsmm_dump_instr_desc_s structure to values consistent with the fields do_calc_prob and prob_type of qsmm_disasm_desc_s structure used when disassembling the program. Otherwise, the function qsmm_instr_str or qsmm_prg_dump may print zero probabilities.

Use the following function to dump a program to a stream.

Function: int qsmm_prg_dump (qsmm_prg_t prg, struct qsmm_dump_prg_desc_s *desc_p, FILE *filep)

This function dumps a program prg to a stream filep. If desc_p is not NULL, the function dumps the program according to parameters in *desc_p. If desc_p is NULL, the function dumps the program according to default parameters.

In the current implementation, the function does not modify *desc_p or those default parameters. However, in a future implementation, the function may modify them, for example, to store there statistics on the dumping process.

This function calls the function qsmm_instr_str to obtain string representations of individual assembler instructions and passes to the latter function the field dump_instr_desc_p of qsmm_dump_prg_desc_s structure as the parameters of generating those string representations.

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_ILSEQ

Unable to convert a multibyte string to a wide string or vice versa according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

The QSMM library contains an instance of qsmm_dump_prg_desc_s structure holding the default parameters of dumping a program. Use the following function to get a pointer to this instance.

Function: struct qsmm_dump_prg_desc_s * qsmm_get_default_dump_prg_desc ()

This function returns a pointer to the default parameters of dumping an assembler program. You can change those parameters via this pointer. The function never returns NULL.

The description of a structure specifying the parameters of dumping a program is below.

Structure: qsmm_dump_prg_desc_s

This structure specifies the parameters of dumping an assembler program. The structure contains the following fields.

Field: char do_print_vars

If not 0 and the program contains the definitions of probability variables, dump a “data” section with those definitions. The default is to dump.

Field: char is_line_before_label

If not 0, insert an empty line before a line with a location label definition. If an instruction has multiple location labels assigned (dumped on separate lines), the function qsmm_prg_dump inserts an empty line only before a line with the first location label definition. The default is to insert.

Field: char is_line_before_isolated_comment

If not 0, insert an empty line before a comment above an instruction or the definition of a probability variable, and insert an empty line before a comment at the program end if the field do_print_comment_tail is not 0. The default is to insert.

Field: char are_lines_around_choice

If not 0, insert empty lines before and after choice instruction blocks. The default is to insert.

Field: char are_lines_around_multiline_param

If not 0, insert empty lines before and after multi-line user instructions. The default is to insert.

Field: char do_print_comment_tail

If not 0 and the program contains a comment at its end, dump this comment. The default is to dump.

Field: int col_var_type

If this field is positive, it specifies alignment column for ‘prob’ keywords. If this field is not positive, do not align those keywords. The default alignment column is 17.

Field: int col_var_val

If this field is positive, it specifies alignment column for the values of probability variables. If this field is not positive, do not align those values. The default alignment column is 25.

Field: int col_var_comment

If this field is positive, it specifies alignment column for comments to the right of definitions of probability variables. If this field is not positive, do not align those comments. The default alignment column is 33.

Field: struct qsmm_dump_instr_desc_s * dump_instr_desc_p

If this field is not NULL, it specifies the parameters of dumping assembler instructions by the function qsmm_instr_str. If this field is NULL, qsmm_instr_str uses default parameters returned by the function qsmm_get_default_dump_instr_desc.


Next: , Previous: , Up: Assembler Programs   [Contents][Index]

5.7 Parsing an Assembler Program

QSMM supports parsing an assembler program provided in an input stream, string buffer, or file. The result of this parsing is a memory representation of this assembler program you can inspect, print, or load into a node.

Function: int qsmm_parse_asm_source_buf (const char *in_p, const char *cwd_p, unsigned int flags, void *rez1, void *rez2, qsmm_msglist_t msglist, qsmm_prg_t *prg_p)
Function: int qsmm_parse_asm_source_stream (FILE *filep, const char *cwd_p, unsigned int flags, void *rez1, void *rez2, qsmm_msglist_t msglist, qsmm_prg_t *prg_p)

The function qsmm_parse_asm_source_buf parses an assembler program with source text in a string in_p. The function qsmm_parse_asm_source_stream parses an assembler program with source text read from a stream filep. Both functions store the allocated handle of a parsed program in *prg_p. The arguments rez1 and rez2 are for future use and must be equal to 0.

If msglist is not NULL, the functions add to a message list msglist error, warning, and note messages generated while parsing the source text. If flags has a bit specified by the mask QSMM_PARSE_ASM_PREPROCESS set, the functions first preprocess the source text by the assembler preprocessor. If cwd_p is not NULL, the preprocessor uses cwd_p as the name of a current working directory when resolving ‘include’ directives. If cwd_p is NULL, the preprocessor uses an actual current working directory when resolving ‘include’ directives.

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

QSMM_ERR_INVAL

The argument prg_p is NULL.

QSMM_ERR_PRG

The source program text has at least one error. If msglist is not NULL, the message list msglist contains at least one error message.

QSMM_ERR_ILSEQ

Unable to convert a multibyte string to a wide string or vice versa according to a current locale, including the inability to convert the source program text to a wide string.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Function: int qsmm_parse_asm_source_file (const char *fln, unsigned int flags, void *rez1, void *rez2, qsmm_msglist_t msglist, qsmm_prg_t *prg_p)

This function parses an assembler program with source text in a file fln. The function stores the allocated handle of a parsed program in *prg_p. If msglist is not NULL, the function adds to a message list msglist error, warning, and note messages generated while parsing the source text. If flags has a bit specified by the mask QSMM_PARSE_ASM_PREPROCESS set, the function first preprocesses the source text by the assembler preprocessor. The arguments rez1 and rez2 are for future use and must be equal to 0.

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 prg_p is NULL.

QSMM_ERR_LIBC

The operating system reported a file access error. The variable errno holds the error code.

QSMM_ERR_PRG

The source program text has at least one error. If msglist is not NULL, the message list msglist contains at least one error message.

QSMM_ERR_ILSEQ

Unable to convert a multibyte string to a wide string or vice versa according to a current locale, including the inability to convert the source program text to a wide string.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

See Creating a Message List, for the description of a function for creating an empty message list for passing it to the functions parsing an assembler program and the description of a function for destroying the message list afterwards. See Printing Messages, for the description of a function for dumping to a stream the message list possibly filled with error, warning, and note messages generated while parsing the assembler program.


Next: , Previous: , Up: Assembler Programs   [Contents][Index]

5.8 Loading a Parsed Program into a Node

An assembler program specifies a probability profile loadable into the nodes of a multinode model. Assembling a node is loading into it a probability profile specified by a memory representation of an assembler program. The instruction class set of this node contains instruction classes for all user and mixed-type instructions used in the assembler program. The assembler supports loading assembler programs into the nodes of a multinode model with zero-length look-ahead signal segment only.

Warning: if the environment state identification engine is a small actor (the field is_large_env of qsmm_desc_s structure passed to the function qsmm_create is zero), and it uses a built-in function for computing the relative probability of an output signal, the adaptive behavior of assembler programs specifying nondeterministic state transitions is generally ill-defined. Similarly, if the instruction emitting engine is a small actor (the field is_large_opt of qsmm_desc_s is zero), and it uses a built-in function for computing the relative probability of an output signal, the adaptive behavior of assembler programs specifying nondeterministic instruction emissions is also generally ill-defined. Therefore, tend to using large actors for the environment state identification engine and instruction emitting engine in these cases. The behavior is ill-defined, because profile probabilities act as output signal weights, and the explanation in Number of Output Signals applies.

The functions qsmm_node_asm and qsmm_get_prg_nstate_v2 described further on in this section take the argument flags specifying the modes of processing a memory representation of an assembler program. That argument is a bitmask defined as a subset of macros described below merged by bitwise “or.”

Macro: QSMM_ASM_DETERM_OPT

Impose the following restriction on a probability profile for the action emission matrix: for every node state, the probability profile must define deterministic choice of an instruction class emitted in the node state. Setting the field is_determ_opt of qsmm_desc_s structure to a non-zero value when creating a multinode model also turns on this mode but for all nodes in the multinode model. In this mode, the assembler considers that states begin just before user and mixed-type instructions, and there is no need to mark unnamed states by stt instructions. If you use stt instructions in this mode, you cannot place them just before jprob instructions and choice instruction blocks.

Macro: QSMM_ASM_TEMPLATE

Store the memory representation of an assembler program in the node as a template. The function qsmm_node_disasm automatically uses the template when disassembling the node: a disassembled program is the template program with profile probabilities in jprob and case instructions replaced with probabilities that have a type specified in the field prob_type of qsmm_disasm_desc_s structure passed to qsmm_node_disasm or the type QSMM_PROB_AGGR when using default disassembling parameters. The field prob_goto_min of qsmm_disasm_desc_s specifies a minimum probability in jprob and case instructions corresponding to the state transition matrix. The field prob_action_min of qsmm_disasm_desc_s specifies a minimum probability in jprob and case instructions corresponding to the action emission matrix. The disassembler removes jprob and case instructions containing lesser probabilities from the disassembled program, although those instructions were in the template program. The disassembler can calculate additional probabilities with types specified by the field do_calc_prob of qsmm_disasm_desc_s for subsequent adding to comments for jprob and case instructions.

Macro: QSMM_ASM_VAR_OUT

Collect information on output probability variables and output probabilities arrays in the assembler program. You use them to fetch probabilities learned while executing or training the node. Output probability variables contain probabilities for jprob and case instructions. Output probabilities arrays contain probabilities for choice instruction blocks. See Output Variables, and Output Arrays, for more information.

Macro: QSMM_ASM_VAR_AUX

Allow using auxiliary probability variables in the assembler program. Those variables act as constants and are neither controlled nor output variables. The disassembler merely replaces the occurrences of auxiliary probability variables in jprob and case instructions with the values of those variables specified by ‘prob’ keywords. See Auxiliary Variables, for more information.

Use the following function to load a parsed assembler program into a node.

Function: int qsmm_node_asm (qsmm_t model, qsmm_sig_t node, unsigned int flags, qsmm_prg_t prg, qsmm_msglist_t msglist)

This function assembles a node of a multinode model—loads a probability profile specified by a program prg into the node. The argument node specifies the identifier of this node. The argument flags specifies assembling modes (see above for the description of macros corresponding to the bits of this bitmask taken into account). If msglist is not NULL, the function adds to a message list msglist warning messages generated while assembling.

The function clears event history statistics collected for the node. If the node already has a probability profile loaded, the function first unloads the profile. To clear the event history statistics and unload the profile, this function calls the function qsmm_node_unload.

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_NOTFOUND

A node with identifier node does not exist.

QSMM_ERR_PRG

The program prg has an error. If the multinode model has an error handler assigned, it receives a message list with at least one error message.

QSMM_ERR_UNTIMELY

The model instance does not exist.

QSMM_ERR_PROFSRCP

The node is a probability profile source for other nodes. See Memory Efficient Cloning the Probability Profile, for more information on this mode.

QSMM_ERR_NOSTATE

The node does not have enough states.

QSMM_ERR_MPROF

No room in the pool of probabilities lists in normal form for a large actor representing the environment state identification engine or instruction emitting engine. The fields profile_pool_env_sz and profile_pool_opt_sz of qsmm_desc_s structure passed to the function qsmm_create specify the sizes of those pools.

QSMM_ERR_UNSUPPLA

The multinode model has positive length of look-ahead signal segment.

QSMM_ERR_STORAGE

A Storage API function reported storage failure.

QSMM_ERR_STATS

Inconsistent statistics on an action choice state or cycle type detected.

QSMM_ERR_ILSEQ

Unable to convert a multibyte string to a wide string or vice versa according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Errors QSMM_ERR_MPROF, QSMM_ERR_STORAGE, QSMM_ERR_STATS, QSMM_ERR_ILSEQ, and QSMM_ERR_NOMEM can leave the probability profile of this node in inconsistent state. If after removing a reason of this error a repeated call to this function succeeds, the probability profile becomes consistent.

In the current implementation, to load an assembler program into a node, it must have a sufficient number of states. Otherwise, the function qsmm_node_asm reports QSMM_ERR_NOSTATE. The function qsmm_set_node_nstate can set the number of states of a node. That number may not exceed the maximum number of states specified by the function qsmm_set_nstate_max for the instruction class set of this node. Use the following function to determine the number of states for passing to qsmm_set_node_nstate and qsmm_set_nstate_max.

Function: int qsmm_get_prg_nstate_v2 (qsmm_t model, const char *instr_class_set_name, int rez1, unsigned int flags, qsmm_prg_t prg, qsmm_msglist_t msglist, qsmm_sig_t *nstate_p)

This function calculates the minimum number of states required for nodes of a multinode model to load a program prg into them. The argument instr_class_set_name specifies the name of instruction class set of those nodes. If msglist is not NULL, the function adds to a message list msglist warning messages generated during the calculation.

The argument flags specifies assembling modes (see the beginning of this section for the description of macros corresponding to the bits of this bitmask taken into account). Additionally, flags can contain bitmask QSMM_EXCEPT_NOTFOUND or QSMM_EXCEPT_TYPE (or QSMM_EXCEPT_ALL including both of them). If flags contain bitmask QSMM_EXCEPT_NOTFOUND, and the instruction class set does not exist, the function reports QSMM_ERR_NOTFOUND. If flags contain bitmask QSMM_EXCEPT_TYPE, and an entity named instr_class_set_name is not an instruction class set, the function reports QSMM_ERR_TYPE. For certainty, the argument flags passed to this function should be equal to the argument flags passed to the function qsmm_node_asm when loading the program prg into particular nodes of this model.

On success, the function returns a non-negative value and sets *nstate_p if nstate_p is not NULL. If an entity named instr_class_set_name exists and is an instruction class set, the function sets *nstate_p to a calculated number of states. If the entity does not exist, and flags does not contain QSMM_EXCEPT_NOTFOUND, the function sets *nstate_p to QSMM_SIG_INVALID. If the entity exists but is not an instruction class set, and flags does not contain QSMM_EXCEPT_TYPE, the function sets *nstate_p to QSMM_SIG_INVALID.

On failure, the function returns a negative error code. Currently, the function can return the following error codes.

QSMM_ERR_NOTFOUND

The instruction class set instr_class_set_name does not exist. The function reports this error if flags include bitmask QSMM_EXCEPT_NOTFOUND. Otherwise, the function sets *nstate_p to QSMM_SIG_INVALID (if nstate_p is not NULL) and returns 0.

QSMM_ERR_TYPE

An entity named instr_class_set_name is not an instruction class set. The entity is an instruction meta-class. The function reports this error if flags include bitmask QSMM_EXCEPT_TYPE. Otherwise, the function sets *nstate_p to QSMM_SIG_INVALID (if nstate_p is not NULL) and returns 0.

QSMM_ERR_PRG

The program prg has an error. If the multinode model has an error handler assigned, it receives a message list with at least one error message.

QSMM_ERR_UNSUPPLA

The multinode model has positive length of look-ahead signal segment.

QSMM_ERR_ILSEQ

Unable to convert a multibyte string to a wide string or vice versa according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

The functions qsmm_node_asm and qsmm_get_prg_nstate_v2 can generate the following warning messages.

‘nop’ instruction inserted

The assembler inserted a nop instruction at the beginning of an implicitly defined state because the state does not start with a user or mixed-type instruction.

‘stt’ instruction expected

The assembler expects the beginning of a state in the assembler program, but there is no stt instruction at that place. The assembler defines the state implicitly. If the place has the definitions of location labels, the assembler may expect the beginning of a state at that place based on the structure of assembler program fragments containing jumps to those location labels. The assembler does not generate this warning if the field is_determ_opt of qsmm_desc_s structure passed to the function qsmm_create is non-zero, or the function qsmm_node_asm receives QSMM_ASM_DETERM_OPT in flags.

all valid outcomes already tested

Control never reaches an instruction after a joe instruction block because the block contains tests for all possible outcomes of a user or mixed-type instruction.

ignoring the test for outcome num because such test already exists

The assembler ignores the joe instruction performing a jump on outcome num because there was an earlier joe instruction also performing a jump on outcome num.

ignoring the test for outcome num because the outcome is out of range

The assembler ignores the joe instruction performing a jump on outcome num because that joe instruction tests the outcome of a user or mixed-type instruction with the number of possible outcomes less than or equal to num.

instruction has no effect because jump probability is 0

The assembler ignores this jprob or case instruction because it specifies a jump with probability 0.

instruction has no effect because of a jump beneath the ‘choice’ block

The assembler ignores this case instruction because it specifies a jump beneath a containing choice instruction block.

instruction has no effect because of a jump to the next instruction

The assembler ignores this jprob or joe instruction because it specifies a jump to the next instruction.

instruction has no effect because of a possible jump to itself

The assembler ignores this jprob instruction because it specifies a jump to itself with probability less than 1.

instruction is replaceable with a ‘jmp’ instruction

Beneath the jprob instruction with jump probability greater than 0 there is a jmp instruction transferring control to that jprob instruction. The jprob instruction does not specify a possible jump to this jmp instruction. The assembler replaces the jprob instruction with a nop instruction and sets its next instruction address equal to the jump location of that jprob instruction. Simply put, you can replace the jprob and jmp instructions with a single jmp instruction.

unreachable state

Control never reaches the state. The assembler generates this warning only when an stt instruction marks the beginning of that state, the field is_determ_opt of qsmm_desc_s structure passed to the function qsmm_create is non-zero, or the function qsmm_node_asm receives QSMM_ASM_DETERM_OPT in flags.

An assembler program can have names assigned to its states by the arguments of stt instructions. Use the following function to retrieve the index of a state of a node by the name of this state after loading an assembler program into the node.

Function: int qsmm_get_node_state_by_name (qsmm_t model, const char *state_name, qsmm_sig_t node, qsmm_sig_t *state_p)

This function retrieves the index of a state of a node of a multinode model by the name of this state. The argument state_name specifies that name assigned by an stt instruction marking the beginning of this state in an assembler program loaded into the node. The argument node specifies the identifier of this node.

On success, the function returns a non-negative value and sets *state_p if state_p is not NULL. If the state exists, the function sets *state_p to the index of that state. If the node does not have an assembler program loaded, or the assembler program does not define a state named state_name, the function sets *state_p to QSMM_SIG_INVALID.

If the node uses a source probability profile provided by another node, the function retrieves the index of a node state defined in an assembler program loaded into the latter node. See Memory Efficient Cloning the Probability Profile, for a detailed description of this mode.

On failure, the function returns a negative error code. Currently, the function can return the following error codes.

QSMM_ERR_NOTFOUND

A node with identifier node does not exist.

QSMM_ERR_ILSEQ

Unable to convert state_name to a wide string according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Use the following function to retrieve the name of a node state by its index.

Function: int qsmm_get_node_state_name (qsmm_t model, qsmm_sig_t node, qsmm_sig_t state, const char **state_name_pp)

This function retrieves the name of a state of a node of a multinode model by the index of this state. An stt instruction in an assembler program loaded into the node assigns that name to the state. The argument node specifies the identifier of this node. The argument state specifies the index of this state.

On success, the function returns a non-negative value and sets *state_name_pp if state_name_pp is not NULL. If the state has a name assigned by the argument of an stt instruction, the function sets *state_name_pp to this name. If the state does not have an assigned name, the function sets *state_name_pp to NULL.

If the node uses a source probability profile provided by another node, the function retrieves a state name specified in an assembler program loaded into the latter node. See Memory Efficient Cloning the Probability Profile, for a detailed description of this mode.

On failure, the function returns a negative error code. Currently, the function can return the following error codes.

QSMM_ERR_INVAL

The argument state is greater than or equal to the number of node states.

QSMM_ERR_NOTFOUND

A node with identifier node does not exist.

QSMM_ERR_ILSEQ

Unable to convert a state name to a multibyte string according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.


Next: , Previous: , Up: Assembler Programs   [Contents][Index]

5.9 Using Probability Variables

The ‘prob’ keyword in an assembler program defines a probability variable with a specific name. A jprob or case instruction can contain the name of a probability variable instead of a numeric probability value. There are three supported types of probability variables:

A controlled probability variable can simultaneously be an output probability variable.

An output probabilities array is the means of fetching probabilities learned for case instructions in a choice instruction block by their indices. A location label assigned to the choice instruction block is the name of this array.


Next: , Up: Using Probability Variables   [Contents][Index]

5.9.1 Variables in an Assembler Program

The “data” section of an assembler program can contain the definitions of probability variables. Every definition of a probability variable must be on a separate line. The line begins with a data label followed by at least one whitespace character, the ‘prob’ keyword, at least one whitespace character, and the initial value of a probability variable in the range 0 to 1 inclusive. The data label is the name of this probability variable. The assembler supports fixed-point and exponential notations for specifying the initial values of probability variables. The “data” section followed by the “code” section may look like this:

        .data

var_name_1      prob    val1
var_name_2      prob    val2
...
var_name_N      prob    valN

        .code

An assembler program can contain multiple ‘.data’ and ‘.code’ blocks, for example, within macros later expanded by the assembler preprocessor. The parser of an assembler program merges those blocks into a single “data” section and a single “code” section.

You can replace numeric probability values in jprob and case instructions with the names of probability variables previously defined in the “data” section:

        jprob   var_name, loc_label
        case    var_name, loc_label

A choice instruction block might look like this:

        choice
        case    var1, L1
        case    var2, L2
        case    0.25, L3
        case    var1, L4
        end     choice

After parsing an assembler program, you can obtain the number of probability variables defined in the assembler program by the following function.

Function: int qsmm_get_prg_nvar (qsmm_prg_t prg)

This function returns the number of probability variables defined in a program prg using ‘prob’ keywords. A returned value is always non-negative.

Use the following function to get the name of a probability variable by its index.

Function: const char * qsmm_get_prg_var_name (qsmm_prg_t prg, int var_idx)

This function returns the name of a probability variable with index var_idx in a program prg. If var_idx is negative or greater than or equal to the number of probability variables defined in the program using ‘prob’ keywords, the function returns NULL.

See Output Arrays, for how to define output probabilities arrays in an assembler program.


Next: , Previous: , Up: Using Probability Variables   [Contents][Index]

5.9.2 Controlled Variables

Controlled probability variables are the means of changing a probability profile loaded into a node, for example, as a result of reasoning or self-programming.

An assembler program can contain controlled probability variables for profile probabilities in the state transition matrix only if the environment state identification engine is a small actor—if the field is_large_env of qsmm_desc_s structure passed to the function qsmm_create is zero. An assembler program can contain controlled probability variables for profile probabilities in the action emission matrix only if the instruction emitting engine is a small actor—if the field is_large_opt of qsmm_desc_s is zero.

You have to register controlled probability variables in the instruction class set of a node. After registering the variables, you can load into the node an assembler program referencing a subset of those variables. Later, you can change their values for the node, thereby changing its probability profile (e.g. while processing instruction invocations by the event handlers of instruction meta-classes). Changing the value of a controlled probability variable updates profile probabilities in the state transition matrix and/or action emission matrix for the occurrences of jprob and case instructions containing this variable as a probability.

Use the following function to register a controlled probability variable in an instruction class set.

Function: int qsmm_reg_var_prob (qsmm_t model, const char *instr_class_set_name, const char *var_name, size_t *var_idx_p)

This function registers a controlled probability variable var_name in the instruction class set instr_class_set_name of a multinode model. If var_idx_p is not NULL, the function sets *var_idx_p to the index of this variable in the instruction class set.

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_NOTFOUND

The instruction class set instr_class_set_name does not exist.

QSMM_ERR_TYPE

An entity named instr_class_set_name is not an instruction class set. The entity is an instruction meta-class.

QSMM_ERR_EXIST

The instruction class set already has a controlled probability variable var_name registered.

QSMM_ERR_VIOLNODE

There exist nodes belonging to a node class represented by the instruction class set instr_class_set_name—cannot change its structure.

QSMM_ERR_UNSUPPLA

The multinode model has positive length of look-ahead signal segment.

QSMM_ERR_NOTSUP

The environment state identification engine and instruction emitting engine are large actors.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Currently, there are no API functions taking as an argument the index of a controlled probability variable returned by the function qsmm_reg_var_prob. Instead, functions that query and set the values of controlled probability variables take the name of a variable as an argument. To speed up querying and setting the values, future QSMM versions may include counterpart functions taking the index of a variable instead of its name.

Use the following macro to register a controlled probability variable on processing an event QSMM_EVT_ENT_INIT by the event handler of an instruction class set.

Macro: QSMM_REG_VAR_PROB (var_name)

This macro registers a controlled probability variable var_name. The macro expands to:

qsmm_reg_var_prob((qsmm), __FUNCTION__, (var_name), 0)

This macro is for expansion from the event handler of an instruction class set. The macro expects that the name of the event handler function is equal to the name of the instruction class set and the variable qsmm holding the handle of a multinode model is accessible in the event handler function. Normally, that variable is an event handler function argument.

Use the following function to get the names of controlled probability variables registered in an instruction class set.

Function: int qsmm_enum_var_prob (qsmm_t model, const char *instr_class_set_name, qsmm_enum_ent_callback_func_t callback_func, void *paramp)

This function enumerates controlled probability variables registered in the instruction class set instr_class_set_name of a multinode model. The process of enumeration is repeated calling a callback function callback_func receiving QSMM_LREF_PROB_VAR_CTRL as the type of a local entity reference, the name of a controlled probability variable in a local entity identifier, and a user parameter paramp. See Enumerating Entities, for the description of callback function type.

If the callback function returns a positive value, the function qsmm_enum_var_prob continues the enumeration. If the callback function returns zero, qsmm_enum_var_prob terminates the enumeration and reports success. If the callback function returns a negative value, qsmm_enum_var_prob terminates the enumeration and reports failure.

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_NOTFOUND

The instruction class set instr_class_set_name does not exist.

QSMM_ERR_TYPE

An entity named instr_class_set_name is not an instruction class set. The entity is an instruction meta-class.

QSMM_ERR_CALLBACK

The callback function reported an error.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Use the following functions to query or set the value of a controlled probability variable.

Function: int qsmm_get_node_var_prob (qsmm_t model, const char *var_name, qsmm_sig_t node, double *valp)

This function retrieves the value of the controlled probability variable var_name of a node of a multinode model. The argument node specifies the identifier of this node. If valp is not NULL, the function sets *valp to a retrieved value.

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_NOTFOUND

A node with identifier node or a controlled probability variable named var_name does not exist.

QSMM_ERR_UNSUPPLA

The multinode model has positive length of look-ahead signal segment.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Function: int qsmm_set_node_var_prob (qsmm_t model, const char *var_name, qsmm_sig_t node, double val)

This function sets to val the value of the controlled probability variable var_name of a node of a multinode model. The argument node specifies the identifier of this node. However, corresponding profile probabilities in the state transition matrix and/or action emission matrix of this node remain unchanged until calling the function qsmm_node_var_realize (described further on in this subsection).

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 val is not finite or is negative or greater than 1.

QSMM_ERR_NOTFOUND

A node with identifier node or a controlled probability variable named var_name does not exist.

QSMM_ERR_UNSUPPLA

The multinode model has positive length of look-ahead signal segment.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

After loading an assembler program into a node, controlled probability variables associated with the node take on initial values defined in the assembler program.

Assignments to controlled probability variables declared in an instruction class set but not defined in the assembler program have no effect on profile probabilities in the state transition matrix and action emission matrix of a node. Assignments to the controlled probability variables of a node without a loaded assembler program also have no effect on the profile probabilities.

After assigning values to controlled probability variables by the function qsmm_set_node_var_prob, call the following function to actually update profile probabilities in the state transition matrix and action emission matrix.

Function: int qsmm_node_var_realize (qsmm_t model, qsmm_sig_t node, int rez1)

This function updates profile probabilities in the state transition matrix and/or action emission matrix of a node of a multinode model according to assignments to controlled probability variables of this node previously made by calling the function qsmm_set_node_var_prob and clears the queue of pending updates. The argument node specifies the identifier of this node. The argument rez1 is for future use and must be equal to 0.

For affected action choice states, the function updates the fields nsig_pos and nsig_ctrl of qsmm_state_s structure. For affected cycle types, the function updates the field profile of qsmm_cycle_s structure.

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_NOTFOUND

A node with identifier node does not exist.

QSMM_ERR_PROFSRCP

The node is a probability profile source for other nodes. See Memory Efficient Cloning the Probability Profile, for more information on this mode.

QSMM_ERR_UNTIMELY

The model instance does not exist.

QSMM_ERR_UNSUPPLA

The multinode model has positive length of look-ahead signal segment.

QSMM_ERR_PSUMGT1

The sum of probabilities of case instructions in a choice instruction block would exceed 1.

QSMM_ERR_STORAGE

A Storage API function reported storage failure.

QSMM_ERR_STATS

Inconsistent statistics on an action choice state or cycle type detected.

QSMM_ERR_ILSEQ

Unable to convert a multibyte string to a wide string or vice versa according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Errors QSMM_ERR_PSUMGT1, QSMM_ERR_STORAGE, QSMM_ERR_STATS, QSMM_ERR_ILSEQ, and QSMM_ERR_NOMEM can leave the probability profile of this node in inconsistent state. If after removing a reason of this error a repeated call to this function succeeds, the probability profile becomes consistent.


Next: , Previous: , Up: Using Probability Variables   [Contents][Index]

5.9.3 Output Variables

The purpose of output probability variables is to retrieve probabilities learned while executing or training a node. You do not register variables of this kind in an instruction class set. The function qsmm_node_asm called with the QSMM_ASM_VAR_OUT flag automatically collects information on output probability variables in a memory representation of an assembler program while loading it into a node. An output probability variable can be a controlled probability variable.

Not every probability variable in an assembler program becomes an output probability variable. The first restriction is that the variable must occur in only one jprob or case instruction. The second restriction is that the variable must have unambiguous context. If a probability variable violates at least one of these restrictions, but the function qsmm_reg_var_prob or macro QSMM_REG_VAR_PROB has registered it as a controlled probability variable, it becomes only a controlled probability variable. If qsmm_node_asm receives the QSMM_ASM_VAR_AUX flag, a probability variable violates at least one of these restrictions and is not a controlled probability variable, that function treats the probability variable as an auxiliary variable. If qsmm_node_asm does not receive QSMM_ASM_VAR_AUX, a probability variable violates at least one of these restrictions and is not a controlled probability variable, that function reports an error.

Every output probability variable corresponds to either the state transition matrix or action emission matrix. The enumeration described below represents a matrix type.

Enumeration: qsmm_mat_e

This enumeration specifies a matrix type. The enumeration contains the following elements.

QSMM_MAT_GOTO

The state transition matrix.

QSMM_MAT_ACTION

The action emission matrix.

QSMM_MAT_COUNT

The number of supported matrix types.

Use the function described below to get the type of a matrix corresponding to an output probability variable.

Function: int qsmm_get_node_var_prob_mat (qsmm_t model, const char *var_name, qsmm_sig_t node, enum qsmm_mat_e *mat_p)

This function retrieves the type of a matrix corresponding to the output probability variable var_name of a node of a multinode model. The argument node specifies the identifier of this node. If mat_p is not NULL, the function sets *mat_p to a retrieved type.

If the node uses a source probability profile provided by another node, the function retrieves the type of the matrix of the output probability variable of the latter node. See Memory Efficient Cloning the Probability Profile, for a detailed description of this mode.

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_NOTFOUND

A node with identifier node or an output probability variable named var_name does not exist.

QSMM_ERR_UNTIMELY

The model instance does not exist.

QSMM_ERR_UNSUPPLA

The multinode model has positive length of look-ahead signal segment.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Fetching the value of an output probability variable requires calculating the relative probabilities of all choice alternatives that include an alternative corresponding to the output probability variable. The cache of calculated probabilities of choice alternatives speeds up fetching the values of output probability variables for other choice alternatives later. Along with the cache of calculated probabilities of choice alternatives, a node keeps the cache of calculated values of output probability variables. To free memory, you can clear both caches by the function qsmm_node_var_out_forget described further on in this subsection.

An output probability variable can correspond to multiple cells of a state transition matrix. The following fragment of an assembler program illustrates this situation.

        stt     "s0"
        test                    ; user instruction with multiple
                                ; outcomes (e.g. 3)
        jprob   var0, L2
        stt     "s1"
        ...
L2:     stt     "s2"

The above fragment of an assembler program does not condition on specific outcomes of ‘test’ instruction (i.e. handles them in the same way). The state transition matrix has rows for all three outcomes of this instruction and columns for the states ‘s0’, ‘s1’, and ‘s2’. The fragment of that state transition matrix is in Figure 5.1. There ν  denotes a frequency of state transition, and pp denotes a profile probability.

a state transition matrix fragment with multiple cells for a jprob instruction

Figure 5.1: a state transition matrix fragment with multiple cells for a jprob instruction

The function qsmm_get_node_var_prob_out described further on in this subsection supports calculating probabilities of QSMM_PROB_PROFILE and QSMM_PROB_FQ types for output probability variables corresponding to individual and multiple cells of state transition matrix and corresponding to individual cells of action emission matrix. That function supports calculating probabilities of QSMM_PROB_AGGR and QSMM_PROB_LEARNED types for output probability variables corresponding to individual cells only.

If an output probability variable corresponds to multiple cells of state transition matrix, profile probabilities in those multiple cells are equal, and qsmm_get_node_var_prob_out returns them as a QSMM_PROB_PROFILE probability. For the above example, qsmm_get_node_var_prob_out returns value var0 as the probability QSMM_PROB_PROFILE of ‘var0’ output probability variable. That function does not support calculating probabilities of QSMM_PROB_AGGR and QSMM_PROB_LEARNED types for this output probability variable.

To calculate a QSMM_PROB_FQ probability, qsmm_get_node_var_prob_out takes the sums of frequencies of transitions to target states for relative probabilities. For example, to calculate the probability QSMM_PROB_FQ of ‘var0’ output probability variable, qsmm_get_node_var_prob_out calculates the sums ν0,11,12,1  and ν0,21,22,2  and takes the ratio 0,21,22,2)/(ν0,11,12,10,21,22,2)  for that probability.

As already mentioned, a probability variable used in multiple jprob and case instructions cannot be an output probability variable. The following fragment of an assembler program illustrates this situation.

L1:     user    0               ; user instruction
        jprob   var0, L1        ; first occurrence of `var0' variable

L2:     user    1               ; user instruction
        jprob   var0, L2        ; second occurrence of `var0' variable;
                                ; encountering this occurrence means that
                                ; `var0' cannot be an output
                                ; probability variable
        jmp     L1

A probability variable used once but in ambiguous context cannot be an output probability variable too. At present, only jprob instructions can have ambiguous context. The context of a jprob instruction is ambiguous if the blocks of jprob instructions with different start addresses include this jprob instruction. The following fragment of an assembler program illustrates this situation.

L1:     user    0
        jprob   0.5, L3

L2:     jprob   var0, L1
        user    1

L3:     user    2
        jmp     L2

After invoking the ‘user 0’ instruction, the block consisting of ‘jprob 0.5, L3’ and ‘jprob var0, L1’ instructions selects the next instruction to execute. However, after invoking the ‘user 2’ instruction, only the last instruction of that block selects the next instruction to execute. In the first case, the block begins with the ‘jprob 0.5, L3’ instruction, and, in the second case, the block begins with the ‘jprob var0, L1’ instruction and contains only this instruction. That is, the blocks have different start addresses, the ‘jprob var0, L1’ instruction those blocks contain has ambiguous context, and, therefore, the variable ‘var0’ cannot be an output probability variable.

If the function qsmm_node_asm has not generated any warnings for an assembler program it loaded into a node, the assembler program does not contain instructions in ambiguous context. If qsmm_node_asm received the QSMM_ASM_VAR_OUT flag, all probability variables that occurred only once in this assembler program became output probability variables.

Use the following function to get the names of output probability variables of a node.

Function: int qsmm_enum_var_prob_out (qsmm_t model, qsmm_sig_t node, qsmm_enum_ent_callback_func_t callback_func, void *paramp)

This function enumerates output probability variables defined in an assembler program loaded into a node of a multinode model. The argument node specifies the identifier of this node.

The process of enumeration is repeated calling a callback function callback_func receiving QSMM_LREF_PROB_VAR_OUT as the type of a local entity reference, the name of an output probability variable in a local entity identifier, and a user parameter paramp. See Enumerating Entities, for the description of callback function type.

If the callback function returns a positive value, the function qsmm_enum_var_prob_out continues the enumeration. If the callback function returns zero, qsmm_enum_var_prob_out terminates the enumeration and reports success. If the callback function returns a negative value, qsmm_enum_var_prob_out terminates the enumeration and reports failure.

If the node uses a source probability profile provided by another node, the function enumerates the output probability variables of the latter node. See Memory Efficient Cloning the Probability Profile, for a detailed description of this mode.

The function qsmm_enum_var_prob_out does not enumerate the output probabilities arrays of a node. See Output Arrays, for an example program that enumerates those arrays and prints their content.

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_NOTFOUND

A node with identifier node does not exist.

QSMM_ERR_CALLBACK

The callback function reported an error.

Use the function described below to retrieve the value of an output probability variable.

Function: int qsmm_get_node_var_prob_out (qsmm_t model, const char *var_name, qsmm_sig_t node, enum qsmm_prob_e prob_type, double *valp)

This function retrieves the value of the output probability variable var_name of a node of a multinode model. The argument node specifies the identifier of this node.

The argument prob_type specifies the type of a probability to retrieve. See Emitting an Output Signal, for the description of elements of qsmm_prob_e enumeration. If valp is not NULL, the function sets *valp to a retrieved probability.

If the node uses a source probability profile provided by another node, the function obtains information how to calculate the output probability variable from the latter node. See Memory Efficient Cloning the Probability Profile, for a detailed description of this mode.

If the function is able to retrieve the value of that output probability variable, the function sets *valp to that value (if valp is not NULL) and returns 2. If prob_type is QSMM_PROB_AGGR or QSMM_PROB_LEARNED, and the output probability variable corresponds to multiple cells of state transition matrix, the function sets *valp to -2 (if valp is not NULL) and returns 1. If var_name is a controlled or auxiliary probability variable that occurs more than once in an assembler program loaded into the node or has ambiguous context in the assembler program, the function sets *valp to -1 (if valp is not NULL) and returns 0.

On failure, the function returns a negative error code. Currently, the function can return the following error codes.

QSMM_ERR_INVAL

The argument prob_type is invalid.

QSMM_ERR_NOTFOUND

A node with identifier node does not exist, or the node does not have an assembler program loaded, or the assembler program does not define a probability variable named var_name.

QSMM_ERR_UNTIMELY

The model instance does not exist.

QSMM_ERR_UNSUPPLA

The multinode model has positive length of look-ahead signal segment.

QSMM_ERR_CALLBACK

A helper function for computing the relative probability of an output signal reported an error by returning NaN. The function qsmm_actor_calc_action_prob calls the helper function.

QSMM_ERR_STORAGE

A Storage API function reported storage failure.

QSMM_ERR_STATS

Inconsistent statistics on an action choice state or cycle type detected.

QSMM_ERR_ILSEQ

Unable to convert a multibyte string to a wide string or vice versa according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Errors QSMM_ERR_STORAGE, QSMM_ERR_STATS, QSMM_ERR_ILSEQ, and QSMM_ERR_NOMEM can leave the model instance in inconsistent state.

You can retrieve output probabilities for case instructions in choice instruction blocks via output probability variables in the case instructions or via output probabilities arrays referred to by location labels assigned to the choice instruction blocks. Use the function qsmm_get_node_array_prob_out described in Output Arrays to retrieve an output probabilities array for a choice instruction block.

QSMM supports fetching aggregate statistics on cycle types for output probability variables and the elements of output probabilities arrays. The statistics are aggregate in the sense that if an output probability variable or an element of an output probabilities array corresponds to multiple cells of state transition matrix, the statistics includes statistics on cycle types in all those cells. If an output probability variable or an element of an output probabilities array corresponds to the action emission matrix, aggregate statistics are simply statistics on a cycle type in an individual cell.

Use the function described below to fetch aggregate statistics on cycle types associated with an output probability variable. Use the function qsmm_get_node_array_prob_cycle described in Output Arrays to fetch aggregate statistics on cycle types associated with an element of an output probabilities array.

Function: int qsmm_get_node_var_prob_cycle (qsmm_t model, const char *var_name, qsmm_sig_t node, struct qsmm_cycle_s *cycle_p, struct qsmm_cspur_s *cspur_p)

This function retrieves aggregate statistics on cycle types for the output probability variable var_name of a node of a multinode model. The argument node specifies the identifier of this node. If cycle_p is not NULL, the function sets *cycle_p to aggregate statistics on the cycle types. If cspur_p is not NULL, the function sets *cspur_p to aggregate statistics on spur types for the cycle types. See Structures for Accessing Storage, for the descriptions of qsmm_cycle_s and qsmm_cspur_s structures.

If cspur_p is not NULL, and the output probability variable corresponds to the state transition matrix, the array cspur_p must be capable of holding the number of elements returned by the function qsmm_get_nspur. If cspur_p is not NULL, and the output probability variable corresponds to the action emission matrix, the array cspur_p must be capable of holding the number of elements returned by qsmm_get_nspur minus 1. The function qsmm_get_node_var_prob_mat described earlier in this subsection retrieves the type of a matrix corresponding to an output probability variable.

The aggregate statistics composes from statistics on individual cycle types in the following way. The fields fq, period_sum_d, and period_sum_c of *cycle_p are the sums of those fields for all cycle types associated with the output probability variable. The field cycle_p->profile is equal to that field for last cycle type associated with the output probability variable, as all such cycle types have the same value of profile field. The fields delta_sum in the elements of cspur_p array are the sums of corresponding fields for all cycle types associated with the output probability variable.

If the node uses a source probability profile provided by another node, the function obtains information how to calculate aggregate statistics from the latter node. See Memory Efficient Cloning the Probability Profile, for a detailed description of this mode.

On success, the function returns a non-negative number of cycle types making up the aggregate statistics. If this number is greater than INT_MAX, the function returns INT_MAX. On failure, the function returns a negative error code. Currently, the function can return the following error codes.

QSMM_ERR_NOTFOUND

A node with identifier node or an output probability variable named var_name does not exist.

QSMM_ERR_UNTIMELY

The model instance does not exist.

QSMM_ERR_UNSUPPLA

The multinode model has positive length of look-ahead signal segment.

QSMM_ERR_STORAGE

A Storage API function reported storage failure.

QSMM_ERR_STATS

Inconsistent statistics on an action choice state or cycle type detected.

QSMM_ERR_ILSEQ

Unable to convert a multibyte string to a wide string or vice versa according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

The function qsmm_get_node_var_prob_out stores all values of output probability variables calculated for a node in a cache within the node. The functions qsmm_node_call_default (see Calling a Node), qsmm_node_unload (see Unloading the Probability Profile), and qsmm_engine_destroy (see Creating the Model Instance) and the function qsmm_node_disasm called to disassemble a node assembled with the QSMM_ASM_TEMPLATE flag automatically clear this cache along with the cache of calculated probabilities of choice alternatives mentioned earlier. To free memory, you can manually clear both caches by the following function.

Function: int qsmm_node_var_out_forget (qsmm_t model, qsmm_sig_t node)

This function clears a cache of calculated probabilities of output probability variables and a cache of calculated probabilities of choice alternatives both stored in a node of a multinode model. The argument node specifies the identifier of this node. The function qsmm_get_node_var_prob_out uses both caches to speed up retrieving the output probability variables of this node. The function qsmm_get_node_array_prob_out uses the second cache to speed up retrieving the output probabilities arrays of this node.

On success, the function returns a non-negative value. If a node with identifier node does not exist, the function returns negative error code QSMM_ERR_NOTFOUND.


Next: , Previous: , Up: Using Probability Variables   [Contents][Index]

5.9.4 Output Arrays

A location label assigned to a choice instruction block refers to an output probabilities array for this choice instruction block. The choice instruction block might look like this:

ARR:    choice
        case    0.15, L1
        case    0.05, L2
        case    0.10, L3
        case    0.20, L4
        end     choice

This example defines the output probabilities array ‘ARR’ with four elements corresponding to case instructions in the choice instruction block. The element with index 0 corresponds to the ‘case 0.15, L1’ instruction, and the element with index 3 corresponds to the ‘case 0.20, L4’ instruction.

An output probabilities array corresponds to either the state transition matrix or action emission matrix. Use the function described below to get a matrix type.

Function: int qsmm_get_node_array_prob_mat (qsmm_t model, const char *label, qsmm_sig_t node, enum qsmm_mat_e *mat_p)

This function retrieves the type of a matrix corresponding to an output probabilities array of a node of a multinode model. The argument node specifies the identifier of this node. A location label assigned to a choice instruction block in an assembler program loaded into the node identifies the array. If mat_p is not NULL, the function sets *mat_p to a retrieved type. See Output Variables, for the description of elements of qsmm_mat_e enumeration.

If the node uses a source probability profile provided by another node, the function retrieves the type of the matrix of the output probabilities array of the latter node. See Memory Efficient Cloning the Probability Profile, for a detailed description of this mode.

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_NOTFOUND

A node with identifier node or an output probabilities array label does not exist.

QSMM_ERR_UNTIMELY

The model instance does not exist.

QSMM_ERR_UNSUPPLA

The multinode model has positive length of look-ahead signal segment.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Use the function described below to get a segment of an output probabilities array.

Function: int qsmm_get_node_array_prob_out (qsmm_t model, const char *label, qsmm_sig_t node, size_t from, size_t to, enum qsmm_prob_e prob_type, double *prob_p)

This function retrieves a segment of an output probabilities array of a node of a multinode model. The argument node specifies the identifier of this node. A location label assigned to a choice instruction block in an assembler program loaded into the node identifies the array. If prob_p is not NULL, the function copies output probabilities from the array to a buffer prob_p starting at offset 0.

The argument prob_type specifies the type of probabilities to retrieve. See Emitting an Output Signal, for the description of elements of qsmm_prob_e enumeration. If prob_type is QSMM_PROB_AGGR or QSMM_PROB_LEARNED, and each array element corresponds to multiple cells of state transition matrix, the function retrieves all array elements equal to -2.

The arguments from and to specify the index of first element and the index of last element (exclusive) for the retrieved array segment. If to is 0, the function uses array length as the index of last element. The number of elements copied to prob_p is equal to the index of last element minus from.

A special element of an output probabilities array at index equal to array length corresponds to a choice alternative beneath the choice instruction block. This choice alternative receives control if none of case instructions in the choice instruction block transferred control elsewhere. To retrieve this special element, specify to equal to array length plus 1.

If the node uses a source probability profile provided by another node, the function obtains information how to calculate the array elements from the latter node. See Memory Efficient Cloning the Probability Profile, for a detailed description of this mode.

On success, the function returns a positive number of elements to store in prob_p starting at offset 0 as if prob_p is never NULL. If this number is greater than INT_MAX, the function returns INT_MAX. On failure, the function returns a negative error code. Currently, the function can return the following error codes.

QSMM_ERR_INVAL

The argument prob_type is invalid, or from is greater than or equal to the index of last element, or to is greater than array length plus 1.

QSMM_ERR_NOTFOUND

A node with identifier node or an output probabilities array label does not exist.

QSMM_ERR_UNTIMELY

The model instance does not exist.

QSMM_ERR_UNSUPPLA

The multinode model has positive length of look-ahead signal segment.

QSMM_ERR_CALLBACK

A helper function for computing the relative probability of an output signal reported an error by returning NaN. The function qsmm_actor_calc_action_prob calls the helper function.

QSMM_ERR_STORAGE

A Storage API function reported storage failure.

QSMM_ERR_STATS

Inconsistent statistics on an action choice state or cycle type detected.

QSMM_ERR_ILSEQ

Unable to convert a multibyte string to a wide string or vice versa according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Errors QSMM_ERR_STORAGE, QSMM_ERR_STATS, QSMM_ERR_ILSEQ, and QSMM_ERR_NOMEM can leave the model instance in inconsistent state.

When calculating a segment of an output probabilities array of a node, the function qsmm_get_node_array_prob_out stores in a cache within the node the calculated probabilities of all choice alternatives corresponding to the output probabilities array. The cache speeds up retrieving the elements of this output probabilities array later. Call the function qsmm_node_var_out_forget to manually clear the cache. See Output Variables, for more information on the cache and functions that clear it automatically.

Use the function described below to fetch aggregate statistics on cycle types associated with an element of an output probabilities array. See Output Variables, for the description of a counterpart function fetching aggregate statistics on cycle types associated with an output probability variable and for additional information on the concept of aggregate statistics.

Function: int qsmm_get_node_array_prob_cycle (qsmm_t model, const char *label, qsmm_sig_t node, size_t offs, struct qsmm_cycle_s *cycle_p, struct qsmm_cspur_s *cspur_p)

This function retrieves aggregate statistics on cycle types for an element of an output probabilities array of a node of a multinode model. The argument node specifies the identifier of this node. A location label assigned to a choice instruction block in an assembler program loaded into the node identifies the array.

The argument offs specifies the index of this array element. A special element of an output probabilities array at index equal to array length corresponds to a choice alternative beneath the choice instruction block. This choice alternative receives control if none of case instructions in the choice instruction block transferred control elsewhere.

If cycle_p is not NULL, the function sets *cycle_p to aggregate statistics on the cycle types. If cspur_p is not NULL, the function sets *cspur_p to aggregate statistics on spur types for the cycle types. See Structures for Accessing Storage, for the descriptions of qsmm_cycle_s and qsmm_cspur_s structures.

If cspur_p is not NULL, and the output probabilities array corresponds to the state transition matrix, the array cspur_p must be capable of holding the number of elements returned by the function qsmm_get_nspur. If cspur_p is not NULL, and the output probabilities array corresponds to the action emission matrix, the array cspur_p must be capable of holding the number of elements returned by qsmm_get_nspur minus 1. The function qsmm_get_node_array_prob_mat described earlier in this subsection retrieves the type of a matrix corresponding to an output probabilities array.

The aggregate statistics composes from statistics on individual cycle types in the following way. The fields fq, period_sum_d, and period_sum_c of *cycle_p are the sums of those fields for all cycle types associated with the element of the output probabilities array. The field cycle_p->profile is equal to that field for last cycle type associated with the element of the output probabilities array, as all such cycle types have the same value of profile field. The fields delta_sum in the elements of cspur_p array are the sums of corresponding fields for all cycle types associated with the element of the output probabilities array.

If the node uses a source probability profile provided by another node, the function obtains information how to calculate aggregate statistics from the latter node. See Memory Efficient Cloning the Probability Profile, for a detailed description of this mode.

On success, the function returns a non-negative number of cycle types making up the aggregate statistics. If this number is greater than INT_MAX, the function returns INT_MAX. On failure, the function returns a negative error code. Currently, the function can return the following error codes.

QSMM_ERR_INVAL

The argument offs is greater than the length of the output probabilities array.

QSMM_ERR_NOTFOUND

A node with identifier node or an output probabilities array label does not exist.

QSMM_ERR_UNTIMELY

The model instance does not exist.

QSMM_ERR_UNSUPPLA

The multinode model has positive length of look-ahead signal segment.

QSMM_ERR_STORAGE

A Storage API function reported storage failure.

QSMM_ERR_STATS

Inconsistent statistics on an action choice state or cycle type detected.

QSMM_ERR_ILSEQ

Unable to convert a multibyte string to a wide string or vice versa according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

To dump the contents of all output probabilities arrays defined in an assembler program, consider only instructions with the type QSMM_INSTR_CHOICE. Use the function qsmm_get_instr_type to obtain the type of an assembler instruction by its handle. If an instruction with the type QSMM_INSTR_CHOICE has at least one location label assigned, the instruction has an associated output probabilities array. The call qsmm_get_instr_label(instr,0), where instr is an instruction handle, returns the first location label identifying the output probabilities array. If that call returns NULL, the instruction does not have location labels assigned and, therefore, does not have an associated output probabilities array. The length of an associated output probabilities array is equal to the return value of qsmm_get_instr_nnested function minus 1, as the last nested instruction is the ‘end choice’ instruction.

Below there is an example function that dumps the contents of all output probabilities arrays of a node containing an assembler program prg. The function returns 0 on success or -1 on out of memory error.

#include <stdlib.h>
#include <qsmm/qsmm.h>

static int
dump_arr_prob_out(
    qsmm_t qsmm,
    qsmm_sig_t node,
    qsmm_prg_t prg,
    enum qsmm_prob_e prob_type
) {
    int result=-1;
    double *probp=0;
    size_t prob_allo=0;
    const size_t ninstr=qsmm_get_prg_ninstr(prg);
    for (size_t iinstr=0; iinstr<ninstr; iinstr++) {
        const qsmm_instr_t instr=qsmm_get_prg_instr(prg,iinstr);
        const char *const labelp=qsmm_get_instr_label(instr,0);
        if (!labelp) continue;
        if (qsmm_get_instr_type(instr)!=QSMM_INSTR_CHOICE) continue;
        const size_t nprob=qsmm_get_instr_nnested(instr)-1;
        if (prob_allo<nprob) {
            double *const newp=realloc(probp,nprob*sizeof(*newp));
            if (!newp) goto Exit;
            prob_allo=nprob;
            probp=newp;
        }
        qsmm_get_node_array_prob_out(qsmm, labelp, node, 0, nprob,
                                     prob_type, probp);
        for (size_t iprob=0; iprob<nprob; iprob++)
            printf("%s[%zu]=%.15E\n",labelp,iprob,probp[iprob]);
    }
    result=0;

Exit:
    if (probp) free(probp);
    return result;
}

Previous: , Up: Using Probability Variables   [Contents][Index]

5.9.5 Auxiliary Variables

Auxiliary probability variables act as constants. A controlled or output probability variable can never simultaneously be an auxiliary probability variable. The function qsmm_node_asm replaces the occurrences of auxiliary probability variables in jprob and case instructions with the values of those variables specified using ‘prob’ keywords. You cannot access auxiliary probability variables after loading an assembler program into a node.

You pass the QSMM_ASM_VAR_AUX flag to qsmm_node_asm to load an assembler program containing auxiliary probability variables. An occurrence of a probability variable in an assembler program is valid if the probability variable is a controlled or output probability variable, or if qsmm_node_asm received the QSMM_ASM_VAR_AUX flag. Note that you first register controlled probability variables in an instruction class set, and you pass the QSMM_ASM_VAR_OUT flag to qsmm_node_asm to collect information on output probability variables.


Next: , Previous: , Up: Assembler Programs   [Contents][Index]

5.10 Cloning the Probability Profile

To load the same probability profile into multiple nodes of a multinode model, you can load an assembler program into one node and copy its probability profile to other nodes—clone a probability profile. Cloning a probability profile from a node to other nodes is faster than loading the same assembler program into them.

Use the function described below to clone a probability profile.

Function: int qsmm_node_profile_clone (qsmm_t model, qsmm_sig_t node_from, qsmm_sig_t node_to, unsigned int flags)

This function copies a probability profile from a node of a multinode model to another node of this model. The argument node_from specifies the identifier of a source node. The argument node_to specifies the identifier of a destination node. The function clears event history statistics collected for the destination node. If the destination node already has a probability profile loaded, the function first unloads the profile from this node along with additional information the function can copy (see the description of flags argument below). To clear the event history statistics and unload the profile, this function calls the function qsmm_node_unload described in Unloading the Probability Profile. The function qsmm_node_profile_clone cannot copy probability profiles manually written to storage without prior calling the function qsmm_node_asm.

The argument flags is a bitmask specifying the types of information to copy from the source node to the destination node along with the probability profile. The following macros specify the bits of this bitmask taken into account.

Macro: QSMM_NODE_CLONE_VARS

Copy the definitions of controlled and output probability variables and arrays. This copying makes it possible to modify the controlled probability variables of the destination node and to retrieve the output probability variables and arrays of that node, as you can modify and retrieve them for the source node. Before copying the definitions of controlled probability variables, this function calls the function qsmm_node_var_realize for the source node if that node has uncommitted assignments to controlled probability variables.

Macro: QSMM_NODE_CLONE_STATE_NAMES

Copy names assigned to node states by the arguments of stt instructions. The functions qsmm_get_node_state_name and qsmm_get_node_state_by_name can retrieve this information from the destination node. The function qsmm_node_disasm can use this information when disassembling the destination node. The function qsmm_mat_goto_dump_v2 uses this information when dumping the state transition matrix of that node. The function qsmm_mat_action_dump_v2 uses this information when dumping the action emission matrix of that node.

Macro: QSMM_NODE_CLONE_TEMPLATE

If the source node has an associated assembler program template, copy the template. The function qsmm_node_disasm uses this template when disassembling the destination node.

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 node_from is equal to the argument node_to.

QSMM_ERR_NOTFOUND

The source or destination node does not exist.

QSMM_ERR_NOPROF

The source node does not have a loaded probability profile.

QSMM_ERR_NOEQCLAS

The instruction class set of the source node and the instruction class set of the destination node are different.

QSMM_ERR_NOSTATE

The destination node has the number of states less than it is necessary to hold the probability profile of the source node.

QSMM_ERR_UNTIMELY

The model instance does not exist.

QSMM_ERR_UNSUPPLA

The multinode model has positive length of look-ahead signal segment.

QSMM_ERR_PROFSRCU

The source node is a user of a source probability profile provided by another node.

QSMM_ERR_PROFSRCP

One of the following conditions is true:

  • – destination node is a probability profile source for other nodes;
  • – function qsmm_node_profile_clone called the function qsmm_node_var_realize for the source node, and the latter function has failed because that node is a probability profile source for other nodes.

This error can leave the probability profile of the destination node in inconsistent state. If after removing a reason of this error a repeated call to this function succeeds, the probability profile becomes consistent.

QSMM_ERR_PSUMGT1

The function qsmm_node_profile_clone called the function qsmm_node_var_realize for the source node, and the latter function failed because the sum of probabilities of case instructions in a choice instruction block would exceed 1.

QSMM_ERR_STORAGE

A Storage API function reported storage failure.

QSMM_ERR_STATS

Inconsistent statistics on an action choice state or cycle type detected.

QSMM_ERR_ILSEQ

Unable to convert a multibyte string to a wide string or vice versa according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Errors QSMM_ERR_PSUMGT1, QSMM_ERR_STORAGE, QSMM_ERR_STATS, QSMM_ERR_ILSEQ, and QSMM_ERR_NOMEM can leave the probability profile of the source or destination node in inconsistent state. If after removing a reason of this error a repeated call to this function succeeds, the probability profile becomes consistent.


Next: , Previous: , Up: Assembler Programs   [Contents][Index]

5.11 Memory Efficient Cloning the Probability Profile

QSMM supports a mechanism of deferred copying a probability profile from a source node to a destination node, where a copying operation itself only sets a correspondence between the two nodes—the source node becomes a probability profile source, and the destination node becomes a probability profile user. A node can be a probability profile source for multiple other nodes. Storage redirection functions described in Providing Initial Statistics provide read-only access for the destination node to the probability profile held in the source node.

A deferred copying operation provides copy-on-write behavior for the instances of qsmm_state_s and qsmm_cycle_s structures described in Structures for Accessing Storage. Those instances hold a probability profile along with statistics on the event history. The first operation of writing statistics to such an instance for the destination node causes allocating the instance and copying there a piece of information on the probability profile from the source node.

You can change the values of controlled probability variables for the destination node in the normal way. An assembler program loaded into the source node provides information on how to update the state transition matrix and action emission matrix of the destination node when changing the values of controlled probability variables for the destination node. Updating the state transition matrix and action emission matrix causes the allocation of instances of qsmm_state_s and qsmm_cycle_s for the destination node if they do not yet exist.

The following information held in a source node becomes automatically available for a destination node:

You cannot perform the following operations on a node acting as a probability profile source for other nodes:

You cannot perform the following operations on a node acting as a user of a probability profile provided by another node:

Applying deferred copying operations makes sense when a multinode model allocates storage dynamically—uses map storage for holding statistics on the event history.

When dumping the state transition matrix or action emission matrix of a node acting as a probability profile user or disassembling such node, keep in mind that its set of probabilities of QSMM_PROB_PROFILE type can be incomplete, as some instances of qsmm_state_s structure from a source node might not yet be available for the destination node. Therefore, avoid calculating probabilities of QSMM_PROB_PROFILE type for a node acting as a probability profile user.

Using the deferred copying mechanism for nodes of a multinode model slows down all access operations to storage used by the multinode model approximately twice (even for other nodes of this model).

Use the following function to set a correspondence between two nodes of a multinode model where one node becomes a probability profile source and the other node becomes a probability profile user.

Function: int qsmm_set_node_profile_source (qsmm_t model, qsmm_sig_t node_from, qsmm_sig_t node_to, int rez1)

This function sets a node of a multinode model as the source of a probability profile and sets another node of this model as a user of this probability profile. The argument node_from specifies the identifier of the source node. The argument node_to specifies the identifier of the destination node. The argument rez1 is for future use and must be equal to 0.

The function clears event history statistics collected for the destination node. If the destination node has a probability profile loaded, the function unloads the profile along with information dependent on it. To clear the event history statistics and unload the profile, this function calls the function qsmm_node_unload described in Unloading the Probability Profile.

If the source node has uncommitted assignments to controlled probability variables, the function qsmm_set_node_profile_source calls the function qsmm_node_var_realize for that node.

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 node_from is equal to the argument node_to.

QSMM_ERR_NOTFOUND

The source or destination node does not exist.

QSMM_ERR_NOPROF

The source node does not have a loaded probability profile.

QSMM_ERR_NOEQCLAS

The instruction class set of the source node and the instruction class set of the destination node are different.

QSMM_ERR_NOSTATE

The destination node has the number of states less than it is necessary to hold the probability profile of the source node.

QSMM_ERR_UNTIMELY

The model instance does not exist.

QSMM_ERR_UNSUPPLA

The multinode model has positive length of look-ahead signal segment.

QSMM_ERR_PROFSRCU

The source node is a user of a source probability profile provided by another node.

QSMM_ERR_PROFSRCP

One of the following conditions is true:

  • – destination node is a probability profile source for other nodes;
  • – function qsmm_set_node_profile_source called the function qsmm_node_var_realize for the source node, and the latter function has failed because that node is a probability profile source for other nodes.

This error can leave the probability profile of the destination node in inconsistent state. If after removing a reason of this error a repeated call to this function succeeds, the probability profile becomes consistent.

QSMM_ERR_PSUMGT1

The function qsmm_set_node_profile_source called the function qsmm_node_var_realize for the source node, and the latter function failed because the sum of probabilities of case instructions in a choice instruction block would exceed 1.

QSMM_ERR_STORAGE

A Storage API function reported storage failure.

QSMM_ERR_STATS

Inconsistent statistics on an action choice state or cycle type detected.

QSMM_ERR_ILSEQ

Unable to convert a multibyte string to a wide string or vice versa according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Errors QSMM_ERR_PSUMGT1, QSMM_ERR_STORAGE, QSMM_ERR_STATS, QSMM_ERR_ILSEQ, and QSMM_ERR_NOMEM can leave the probability profile of the source or destination node in inconsistent state. If after removing a reason of this error a repeated call to this function succeeds, the probability profile becomes consistent.

The function qsmm_node_unload described in the next section can break off a correspondence between a node acting as a probability profile source and a node acting as a probability profile user.


Next: , Previous: , Up: Assembler Programs   [Contents][Index]

5.12 Unloading the Probability Profile

Use the function described below to unload statistics and a probability profile from a node.

Function: int qsmm_node_unload (qsmm_t model, qsmm_sig_t node)

This function performs the following operations on a node of a multinode model:

The argument node specifies the identifier of this node.

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_NOTFOUND

A node with identifier node does not exist.

QSMM_ERR_PROFSRCP

The node is a probability profile source for other nodes. See Memory Efficient Cloning the Probability Profile, for more information on this mode.

QSMM_ERR_UNTIMELY

The model instance does not exist.

QSMM_ERR_STORAGE

A Storage API function reported storage failure.

QSMM_ERR_STATS

Inconsistent statistics on an action choice state or cycle type detected.

QSMM_ERR_ILSEQ

Unable to convert a multibyte string to a wide string or vice versa according to a current locale.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Errors QSMM_ERR_STORAGE, QSMM_ERR_STATS, QSMM_ERR_ILSEQ, and QSMM_ERR_NOMEM can leave the probability profile of this node or its statistics in inconsistent state. If after removing a reason of this error a repeated call to this function succeeds, the probability profile and statistics become unloaded.


Next: , Previous: , Up: Assembler Programs   [Contents][Index]

5.13 Using the Assembler Preprocessor

In QSMM, the assembler preprocessor provides the means of encapsulating similar blocks of source code in macros reusable in an assembler program. Those macros can define nested control transfer structures and produce unique location labels when expanded. The preprocessor also provides the means of including other files in an assembler source file.

The assembler preprocessor returns a single output buffer with a preprocessed program text for an assembler program and all included source files. The preprocessed output might contain ‘line’ directives describing the locations of preprocessed text fragments in source files. The preprocessor includes this information in error and note messages. The assembler includes this information in error, warning, and note messages. The preprocessor also merges (quoted) string literals on a line going one after another and delimited by zero or more whitespace characters into a single string literal.

When performing transformations of a source text, the assembler preprocessor may break the alignment of multi-line comments. This broken alignment may prevent proper detection by the assembler whether a multi-line comment continues on the next line, and the assembler may assign comments to some instructions incorrectly. At present, you cannot generally avoid this shortcoming.

The assembler preprocessor provides only basic features necessary to work with symbols and macros. If you need more sophisticated features to generate the source text of an assembler program, either produce input to the preprocessor using an auxiliary function, program, or script or generate an assembler program that does not require preprocessing by those means directly.


Next: , Up: Using the Assembler Preprocessor   [Contents][Index]

5.13.1 Changing Line Number and File Name

Use the ‘line’ directive of the assembler preprocessor to change current line number and, possibly, the logical name of a preprocessed source file tracked by the preprocessor with emitting a corresponding ‘line’ directive to preprocessed output for subsequent interpreting by the assembler. Additionally, the assembler preprocessor uses information changed by the ‘line’ directive when generating error and note messages.

The directive must be on a line of its own (after at least one whitespace character at the beginning of the line) and must have one of the following formats:

        line    line_number
        line    line_number, file_name

In the first case, the directive changes the logical number of the next line in a current source file to line_number. In the second case, the directive changes the logical number of the next line to line_number and the logical name of the current source file to file_name. The parameter file_name must be a (quoted) string literal.


Next: , Previous: , Up: Using the Assembler Preprocessor   [Contents][Index]

5.13.2 Including Other Source Files

To include another source file in an assembler source file, use the ‘include’ directive:

        include string_literal

The argument string_literal specifies a (quoted) absolute or relative path to an included file. The base directory for the relative path is:

The directive must be on a line of its own after at least one whitespace character at the beginning of the line. The directive must not occur within a macro definition. The maximum nesting level of ‘include’ directives is 100.


Next: , Previous: , Up: Using the Assembler Preprocessor   [Contents][Index]

5.13.3 Defining Symbols

To define or redefine a symbol, use the ‘def’ directive:

name    def     value

This statement defines or redefines a symbol name to a value. A symbol name must start at the beginning of a line. A symbol value must not contain commas outside of string literals.

There are two possible scopes of a symbol: global and local. Defining a symbol outside of macros makes the symbol global. If a symbol is global one, a ‘def’ directive used for this symbol inside a macro redefines the global symbol to a new value.

Defining a symbol inside a macro makes the symbol local. Macro arguments are also local symbols. Local symbols are not visible outside of macros containing their definitions. If a symbol is local one, a ‘def’ directive used for this symbol inside a macro (containing the definition of this symbol) redefines the local symbol to a new value.

The assembler preprocessor replaces with a symbol value every occurrence of a symbol name as a token in the scope of this symbol (after its definition or redefinition). To concatenate the symbol value with adjacent tokens, prepend and/or append the characters ‘##’ to the symbol name token.

For example, the source text

st      def     01

        choice
        case    a##st##_00, l##st##_00
        case    a##st##_01, l##st##_01
        end     choice

        jmp     l##st##_02

preprocesses to the text

        choice
        case    a01_00, l01_00
        case    a01_01, l01_01
        end     choice

        jmp     l01_02

If a symbol value is not a (quoted) string literal, prepend the character ‘#’ to the symbol name token to convert the symbol value to a string literal. For example, the source text

id       def     5

s##id:   stt     #id

preprocesses to the text

s5:   stt     "5"

The value of a defined or redefined symbol can contain symbol names. After expanding those symbol names, the value of this symbol must reduce to either a string literal or other text without string literals, spaces, and commas.

The assembler preprocessor supports the predefined symbol ‘__UNIQUE__’ expanded to the next number from the sequence of natural numbers. You can use that symbol to generate unique location labels in macros.


Next: , Previous: , Up: Using the Assembler Preprocessor   [Contents][Index]

5.13.4 Defining Macros

A macro definition looks like this:

name    macro   arg1, arg2, ...
        text
        end     macro

The above code block defines a macro name with arguments arg1, arg2, ... A macro may have no arguments at all. The names of macro arguments work as the names of local symbols usable within the macro.

If a macro has a long list of arguments, you can split the list into multiple lines. To indicate that a line of a list of arguments continues on the next line, terminate a continued line with a comma after the name of an argument. The following example demonstrates this:

mac1    macro   arg1, arg2, arg3, arg4,
                arg5, arg6, arg7, arg8
        ...
        end     macro

You may not define nested macros. However, a macro can expand another macro expanding another macro and so on. The maximum supported nesting level of macro expansions is 65535.

To expand a macro name defined earlier in a source text and use arg1, arg2, … for the values of macro arguments, write a line like this:

        name    arg1, arg2, ...

The name of an expanded macro must be on a line of its own. The line must begin with either at least one whitespace character followed by that name or a location label definition followed by at least one whitespace character and that name.

The assembler preprocessor does not perform the substitutions of symbol names with symbol values in the names of expanded macros. However, the preprocessor performs such substitutions in the values of macro arguments. After substituting, the value of every macro argument must reduce to either a string literal or other text without string literals, spaces, and commas.

If you are expanding a macro using a long list of arguments, you can split the list into multiple lines. To indicate that a line of a list of arguments continues on the next line, terminate a continued line with a comma after the value of an argument. The following example demonstrates this:

        mac1    "alpha", 0.1, "beta",  0.2,
                "gamma", 0.3, "delta", 0.4

Next: , Previous: , Up: Using the Assembler Preprocessor   [Contents][Index]

5.13.5 Generating Unique Location Labels

Macros often contain the definitions of location labels that must not duplicate when expanding a macro multiple times. To define a number of location labels in the local scope of a macro, you can define local symbols for them using lines of code like these:

lu0     def     u##__UNIQUE__
lu1     def     u##__UNIQUE__
lu2     def     u##__UNIQUE__

The above directives define the symbols lu0, lu1, and lu2 with values that have the form ui, where i is an increasing integer number. When expanding the macro the first time, the symbols lu0, lu1, and lu2 take the values u1, u2, u3 (if there are no definitions of other symbols using the predefined symbol ‘__UNIQUE__’). When expanding the macro the second time, the symbols lu0, lu1, and lu2 take the values u4, u5, u6, and so on. Thus, the values of the symbols lu0, lu1, and lu2 are always unique, and you can use them for location labels within macros expanded multiple times. The following example of a macro illustrates this:

emit_ch macro

lu0     def     u##__UNIQUE__
lu1     def     u##__UNIQUE__
lu2     def     u##__UNIQUE__

        choice
        case    0.33, lu0
        case    0.33, lu1
        end     choice

        emit    "A"
        jmp     lu2

lu0:    emit    "B"
        jmp     lu2

lu1:    emit    "C"

lu2:
        end     macro

This macro emits the character ‘A’, ‘B’, or ‘C’ by the corresponding user instruction emit. You can safely expand the macro an arbitrary number of times—location labels are unique in every expansion. For example, to emit a sequence of two characters, expand the macro twice:

        ...
        emit_ch
        emit_ch
        ...

Previous: , Up: Using the Assembler Preprocessor   [Contents][Index]

5.13.6 Getting Preprocessed Output

The functions qsmm_parse_asm_source_buf, qsmm_parse_asm_source_stream, and qsmm_parse_asm_source_file described in Parsing an Assembler Program can automatically call the assembler preprocessor to preprocess a source program text if they receive the QSMM_PARSE_ASM_PREPROCESS flag. However, sometimes it might be necessary to obtain a preprocessed source text directly. Use the following functions to accomplish this task.

Function: int qsmm_preprocess_asm_source_buf (const char *in_p, const char *cwd_p, int rez1, void *rez2, void *rez3, qsmm_msglist_t msglist, char **out_pp)
Function: int qsmm_preprocess_asm_source_stream (FILE *filep, const char *cwd_p, int rez1, void *rez2, void *rez3, qsmm_msglist_t msglist, char **out_pp)

The function qsmm_preprocess_asm_source_buf preprocesses a source program text provided via the argument in_p as a string. The function qsmm_preprocess_asm_source_stream preprocesses a source program text read from a stream filep.

If out_pp is not NULL, both functions set *out_pp to an allocated string containing preprocessed output. If the preprocessor produces zero-length output, both functions set *out_pp to NULL. If *out_pp is not NULL, free by the function free a memory block addressed by *out_pp after use.

If msglist is not NULL, both functions add to a message list msglist error and note messages generated while preprocessing the source program text. If cwd_p is not NULL, both functions use a string cwd_p as the name of a current working directory when resolving ‘include’ directives. If cwd_p is NULL, both functions use an actual current working directory when resolving ‘include’ directives. The arguments rez1, rez2, and rez3 are for future use and must be equal to 0.

On success, both functions return a non-negative number of bytes in the preprocessed output or INT_MAX if this number is greater than INT_MAX. If out_pp is not NULL, and this number is greater than 0 and less than INT_MAX, it is the length of a string *out_pp. On failure, both functions return a negative error code. Currently, the functions can return the following error codes.

QSMM_ERR_PRG

The source program text has at least one error. If msglist is not NULL, the message list msglist contains at least one error message.

QSMM_ERR_ILSEQ

Unable to convert a multibyte string to a wide string or vice versa according to a current locale, including the inability to convert the source program text to a wide string and the inability to convert the preprocessed output to a multibyte string.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.

Function: int qsmm_preprocess_asm_source_file (const char *fln, int rez1, void *rez2, void *rez3, qsmm_msglist_t msglist, char **out_pp)

This function preprocesses a source program text read from a file fln. If out_pp is not NULL, the function sets *out_pp to an allocated string containing preprocessed output. If the preprocessor produces zero-length output, the function sets *out_pp to NULL. If *out_pp is not NULL, free by the function free a memory block addressed by *out_pp after use.

If msglist is not NULL, the function adds to a message list msglist error and note messages generated while preprocessing the source program text. The arguments rez1, rez2, and rez3 are for future use and must be equal to 0.

On success, the function returns a non-negative number of bytes in the preprocessed output or INT_MAX if this number is greater than INT_MAX. If out_pp is not NULL, and this number is greater than 0 and less than INT_MAX, it is the length of a string *out_pp. On failure, the function returns a negative error code. Currently, the function can return the following error codes.

QSMM_ERR_LIBC

The operating system reported a file access error. The variable errno holds the error code.

QSMM_ERR_PRG

The source program text has at least one error. If msglist is not NULL, the message list msglist contains at least one error message.

QSMM_ERR_ILSEQ

Unable to convert a multibyte string to a wide string or vice versa according to a current locale, including the inability to convert the source program text to a wide string and the inability to convert the preprocessed output to a multibyte string.

QSMM_ERR_NOMEM

There was not enough memory to perform the operation.


Previous: , Up: Assembler Programs   [Contents][Index]

5.14 Example of Working with an Assembler Program

In the example of working with an assembler program, an agent controlled by the sample program has to find a path to the gold in a labyrinth and then to an exit from the labyrinth. As in the sample program samples/labyr2.c described in Example of Using the Actor API, the C source code contains the picture of this labyrinth encoded using a subset of ASCII characters resembling pseudographics. You can change that picture to test agent behavior for various labyrinth configurations.

To learn a labyrinth configuration, the agent visits the labyrinth the number of times defined by the macro NVISIT. Moving the agent to a cell designated as a labyrinth exit finishes a labyrinth visit.

The picture of a labyrinth cell is in Figure 2.8. See the description of a labyrinth cell and the macros MAX_X, MAX_Y, ENTRY_X and ENTRY_Y around that figure.

The agent does not know its precise location in the labyrinth in the default mode of program operation—the agent receives a limited amount of information about a current location. This information includes an indication whether a current cell is an exit from the labyrinth and, if the current cell is not an exit from the labyrinth, the union of the following pieces of information:

The macro NSTATE specifies the number of tracked environment states in the default mode of program operation. Defining that macro to a lesser value may result in infinite looping.

Just after its invocation, the sample program prints the number of tracked environment states. After every labyrinth visit, the sample program prints the following information:

  1. The ordinal number of a labyrinth visit.
  2. The number of times the agent found the gold since the beginning of program execution.
  3. The length of last visiting path.
  4. The length of all traversed visiting paths.
  5. The average amount of gold found per one move in the labyrinth.

In the default mode of program operation, the agent visits the labyrinth a number of times without taking the gold until at some point the agent usually “understands” how to take the gold and then finds the gold at almost every labyrinth visit.

At last labyrinth visit, the sample program switches the terminal to full-screen mode and shows a labyrinth picture. After pressing SPACE, the sample program shows movements of the agent in the labyrinth and prints the current length of visiting path and an indication whether or not the agent took the gold. After the agent finds an exit from the labyrinth, pressing Q turns off full-screen terminal mode and quits the sample program.

You can specify a random seed by the first program argument. If the random seed is non-negative, the agent operates adaptively (normally). If the random seed is negative, the agent operates randomly. You can compare agent behavior and program output for these two modes of program execution.

The special mode of program operation is the use of a profile assembler program helping the agent to do its job more efficiently. The second program argument turns on that special mode and specifies the name of a file with the profile assembler program.

Note: when using a custom profile assembler program, you may need to increase the sizes of the pools of probabilities lists in normal form, that is, increase values assigned to desc.profile_pool_env_sz and desc.profile_pool_opt_sz in the function main.

The file samples/maze.asm in the package distribution contains the source text of a profile assembler program for use with labyrinths that have up to 10 cells in width and height. This assembler program actually provides tracking a precise location of the agent in the labyrinth—the agent finds the gold at almost all labyrinth visits. The final visiting path shown in full-screen terminal mode does not have vacillations taking place in the default mode of program operation.

The content of that file is below.

        ; RELOCate.
        ;
        ; Analyze the outcome of an `mv' instruction for performing the
        ; next move.
        ;
        ; l_repeat - jump label for repeating an attempt to perform the
        ;            move if the `mv' instruction moved the
        ;            agent to an obstacle.
        ;
        ; new_row  - new row index for the agent if the movement
        ;            was successful.

        ; new_col  - new column index for the agent if the movement
        ;            was successful.

reloc   macro   l_repeat, new_row, new_col

l_g0    def     g0_r##new_row##_c##new_col
l_g1    def     g1_r##new_row##_c##new_col

        joe     0, l_g0
        joe     1, l_g0
        joe     2, l_g0
        joe     3, l_g0
        joe     4, l_g0
        joe     5, l_g0
        joe     6, l_g0
        joe     7, l_g0
        joe     8, l_g0
        joe     9, l_g0
        joe     10, l_g0
        joe     11, l_g0
        joe     12, l_g0
        joe     13, l_g0
        joe     14, l_g0
        joe     15, l_g0
        joe     32, l_g1
        joe     33, l_g1
        joe     34, l_g1
        joe     35, l_g1
        joe     36, l_g1
        joe     37, l_g1
        joe     38, l_g1
        joe     39, l_g1
        joe     40, l_g1
        joe     41, l_g1
        joe     42, l_g1
        joe     43, l_g1
        joe     44, l_g1
        joe     45, l_g1
        joe     46, l_g1
        joe     47, l_g1
        jmp     l_repeat

        end     macro


        ; Select a movement direction and analyze a movement outcome.
        ;
        ; is_gf     - indication whether the agent has found gold:
        ;             1 = has found;
        ;             0 = not yet found.
        ;
        ; row       - current row index for the agent.
        ; col       - current column index for the agent.
        ;
        ; row_north - new row index for the agent if it moves one step in
        ;             the north direction.
        ;
        ; row_south - new row index for the agent if it moves one step in
        ;             the south direction.
        ;
        ; col_west  - new column index for the agent if it moves one step
        ;             in the west direction.
        ;
        ; col_east  - new column index for the agent if it moves one step
        ;             in the east direction.

state   macro   is_gf, row, col,
                row_north, row_south, col_west, col_east

repeat  def     u##__UNIQUE__
m_north def     u##__UNIQUE__
m_east  def     u##__UNIQUE__
m_south def     u##__UNIQUE__

g##is_gf##_r##row##_c##col:
repeat: stt

        choice
        case    0.25, m_north
        case    0.25, m_east
        case    0.25, m_south
        end     choice

        mv      west
        reloc   repeat, row, col_west

m_south:
        mv      south
        reloc   repeat, row_south, col

m_east: mv      east
        reloc   repeat, row, col_east

m_north:
        mv      north
        reloc   repeat, row_north, col

        end     macro


        ; STates for a ROW.
        ;
        ; Movement selection states for a specific agent location row.
        ;
        ; is_gf     - indication whether the agent has found gold:
        ;             1 = has found;
        ;             0 = not yet found.
        ;
        ; row       - current row index for the agent.
        ;
        ; row_north - new row index for the agent if it moves one step in
        ;             the north direction.
        ;
        ; row_south - new row index for the agent if it moves one step in
        ;             the south direction.


strow   macro   is_gf, row, row_north, row_south

        state   is_gf, row, 0, row_north, row_south, 9, 1
        state   is_gf, row, 1, row_north, row_south, 0, 2
        state   is_gf, row, 2, row_north, row_south, 1, 3
        state   is_gf, row, 3, row_north, row_south, 2, 4
        state   is_gf, row, 4, row_north, row_south, 3, 5
        state   is_gf, row, 5, row_north, row_south, 4, 6
        state   is_gf, row, 6, row_north, row_south, 5, 7
        state   is_gf, row, 7, row_north, row_south, 6, 8
        state   is_gf, row, 8, row_north, row_south, 7, 9
        state   is_gf, row, 9, row_north, row_south, 8, 0

        end     macro


        ; STates for all ROWS.
        ;
        ; Movement selection states for all agent location rows.
        ;
        ; is_gf - indication whether the agent has found gold:
        ;         1 = has found;
        ;         0 = not yet found.

strows  macro   is_gf

        strow   is_gf, 0, 9, 1
        strow   is_gf, 1, 0, 2
        strow   is_gf, 2, 1, 3
        strow   is_gf, 3, 2, 4
        strow   is_gf, 4, 3, 5
        strow   is_gf, 5, 4, 6
        strow   is_gf, 6, 5, 7
        strow   is_gf, 7, 6, 8
        strow   is_gf, 8, 7, 9
        strow   is_gf, 9, 8, 0

        end     macro


        ; Generate movement selection states for the case when the agent
        ; has not yet found gold and the case when the agent has
        ; found the gold.

        strows  0
        strows  1

The file samples/maze_asm.c in the package distribution provides the source code of the sample program. A copy of that source code is below. The command make builds the sample program if the configure script has configured QSMM to use the ncurses library. See the file INSTALL in the root of the package distribution for information on the configure script.

#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#if defined(HAVE_CURSES_H)
#   include <curses.h>
#elif defined(HAVE_NCURSES_CURSES_H)
#   include <ncurses/curses.h>
#endif

#include <qsmm/qsmm.h>

#define NVISIT  200
#define NSTATE  512
#define MAX_X   8
#define MAX_Y   8
#define ENTRY_X 1
#define ENTRY_Y 8


#define CHK_FAIL(func, ...)                                               \
    do {                                                                  \
        int rc=func(__VA_ARGS__);                                         \
        if (rc<0) ERREXIT( #func ": %s", qsmm_err_str(rc));               \
    }                                                                     \
    while (0)


#define ERREXIT(fmt, ...)                                                 \
    do {                                                                  \
        fprintf(stderr,fmt "\n", ## __VA_ARGS__);                         \
        goto Exit;                                                        \
    }                                                                     \
    while (0)


enum direct_e {
    DIRECT_NORTH=0,  // move one step up
    DIRECT_EAST =1,  // move one step right
    DIRECT_SOUTH=2,  // move one step down
    DIRECT_WEST =3   // move one step left
};


static char is_gold_found;
static int path_len_pass, n_gold_found=0, path_len_total=0;
static qsmm_prg_t prg_asm=0;
static qsmm_msglist_t msglist=0;


// Get the bitmask of allowed movement directions.

static unsigned char
get_percept(
    const char **picture_pp,
    int xx,
    int yy
) {
    unsigned char result=0;
    const int col=xx*3+1, row=yy*2+1;
    assert(picture_pp[row][col]==' ' && picture_pp[row][col+1]==' ');
    assert((picture_pp[row-1][col]==' ' &&
            picture_pp[row-1][col+1]==' ') ||
           (picture_pp[row-1][col]!=' ' &&
            picture_pp[row-1][col+1]!=' '));
    assert((picture_pp[row+1][col]==' ' &&
            picture_pp[row+1][col+1]==' ') ||
           (picture_pp[row+1][col]!=' ' &&
            picture_pp[row+1][col+1]!=' '));
    if (picture_pp[row-1][col]==' ' && picture_pp[row-1][col+1]==' ')
        result|=1 << DIRECT_NORTH;
    if (picture_pp[row][col+2]==' ') result|=1 << DIRECT_EAST;
    if (picture_pp[row+1][col]==' ' && picture_pp[row+1][col+1]==' ')
        result|=1 << DIRECT_SOUTH;
    if (picture_pp[row][col-1]==' ') result|=1 << DIRECT_WEST;
    return result;
}


// Make a movement in the labyrinth in a specified direction possibly
// showing the movement on the screen.
// Returns: 3 = movement resulted in exiting the labyrinth;
//          2 = movement resulted in taking the gold;
//          1 = movement made successfully;
//          0 = cannot make the movement because a new location cell of the
//              agent is not empty.

static int
opaque_maze(
    enum direct_e direct,
    unsigned char *percept_p
) {
    static const char *picture[]={
        // 0  1  2  3  4  5  6  7  8
        "+-----+--+--#..#--+--------+",
        "|     |  |        |        |",  // 0
        "+--+  |  |  #--#  |  +  +  |",
        "|     |  |     |  |  |  |  |",  // 1
        "|  +--+  |  +--+  +--+  *  *",
        "|        |     |  |     |  |",  // 2
        "+--+  +--+-----+  +--+  *--*",
        "|     |  |        |        |",  // 3
        "|  +--+  +  +  +  |  +--+  |",
        "|           |  |  |     |  |",  // 4
        "|  +--+  +--+  |  |  +--+  |",
        "|  |     |     |  |     |  |",  // 5
        "+--+  +--+--+  +--+-----+  |",
        "|     |  |        |        |",  // 6
        "+--+  +  |  +--+  +--+  +--+",
        "|     |  |     |           |",  // 7
        "|  +--+  |  +--+  +--+  +--+",
        "|        |     |  |        |",  // 8
        "+--+..+--+-----+--+--------+"
    };
    static char is_gf=0;
    static int path_len, visit=0, xx=-1, yy=-1;
    char ss[128];
    int col, row, result=1;
    if (xx<0 || yy<0) {
        if (visit==NVISIT-1) {
            if (!initscr()) exit(2);
            noecho();
            for (row=0; row<=(MAX_Y+1)*2+1; row++)
                mvaddstr(row,0,picture[row]);
            row=(MAX_Y+1)*2+3;
            mvaddstr(row,0,"Press [Space] to start moving");
            while (getch()!=' ') ;
            sprintf(ss,"%64s","");
            mvaddstr(row,0,ss);
        }
        xx=ENTRY_X;
        yy=ENTRY_Y;
        path_len=0;
    }
    assert(xx>=0 && xx<=MAX_X);
    assert(yy>=0 && yy<=MAX_Y);
    unsigned char percept;
    if (get_percept(picture,xx,yy) & (1 << direct)) {
        col=xx*3+1;
        row=yy*2+1;
        switch (direct) {
            case DIRECT_NORTH: yy--; break;
            case DIRECT_EAST:  xx++; break;
            case DIRECT_SOUTH: yy++; break;
            case DIRECT_WEST:  xx--; break;
            default: assert(0);
        }
        percept=get_percept(picture,xx,yy);
        path_len++;
        if (visit==NVISIT-1) mvaddstr(row,col,"  ");
        col=xx*3+1;
        row=yy*2+1;
        if (visit==NVISIT-1) {
            int picture_w=strlen(picture[0]);
            mvaddstr(row,col,"[]");
            sprintf(ss," Gold found: %d",is_gf);
            mvaddstr(1,picture_w+2,ss);
            sprintf(ss,"Path length: %d",path_len);
            mvaddstr(3,picture_w+2,ss);
            move((MAX_Y+1)*2+3,0);
            refresh();
            usleep(125000);
        }
        if (picture[row-1][col-1]=='*' && picture[row-1][col+2]=='*' &&
            picture[row+1][col-1]=='*' && picture[row+1][col+2]=='*') {
            if (!is_gf) {
                is_gf=1;
                result=2;
            }
        }
        else if (picture[row-1][col-1]=='#' && picture[row-1][col+2]=='#' &&
                 picture[row+1][col-1]=='#' && picture[row+1][col+2]=='#') {
            is_gf=0;
            result=3;
            xx=-1;
            yy=-1;
            if (visit==NVISIT-1) {
                row=(MAX_Y+1)*2+3;
                mvaddstr(row,0,"Press [Q] to exit");
                while (1) {
                    int key=getch();
                    if (key=='q' || key=='Q') break;
                }
                endwin();
            }
            else visit++;
        }
    }
    else {
        percept=get_percept(picture,xx,yy)+16;
        result=0;
    }
    if (is_gf) percept+=32;
    if (percept_p) *percept_p=percept;
    return result;
}


static QSMM_INSTR_META_CLASS(mv) {
    enum direct_e direct=0;
    if (QSMM_HAS_INSTR_CLASS(qsmm_evt))
        qsmm_get_eh_instr_param(qsmm,sizeof(direct),&direct);
    switch (qsmm_evt) {
        case QSMM_EVT_INSTR_CLASS_INIT: {
            const char *ccp;
            switch (direct) {
                case DIRECT_NORTH: ccp="north"; break;
                case DIRECT_EAST:  ccp="east";  break;
                case DIRECT_SOUTH: ccp="south"; break;
                case DIRECT_WEST:  ccp="west";  break;
                default: assert(0);
            }
            qsmm_set_eh_instr_param_str_f(qsmm,"%s",ccp);
            qsmm_set_eh_noutcome(qsmm,64);
            break;
        }
        case QSMM_EVT_ACTIVATE: {
            unsigned char percept=0;
            const int rc=opaque_maze(direct,&percept);
            qsmm_time_delta(qsmm,1);
            switch (rc) {
                case 0:
                case 1:
                    break;
                case 2:
                    is_gold_found=1;
                    n_gold_found++;
                    break;
                case 3:
                    if (is_gold_found) qsmm_spur_delta(qsmm,1,1);
                    qsmm_return_to_caller_node(qsmm);
                    break;
                default:
                    assert(0);
            }
            if (rc!=3) {
                if (rc) {
                    path_len_pass++;
                    path_len_total++;
                }
                qsmm_set_instr_outcome(qsmm,percept);
            }
            break;
        }
    }
    return 0;
}


static QSMM_INSTR_CLASS_SET(walker) {
    switch (qsmm_evt) {
        case QSMM_EVT_ENT_INIT: {
            enum direct_e direct;
            direct=DIRECT_NORTH, QSMM_REG_INSTR_CLASS_PARAM(mv,direct);
            direct=DIRECT_EAST,  QSMM_REG_INSTR_CLASS_PARAM(mv,direct);
            direct=DIRECT_SOUTH, QSMM_REG_INSTR_CLASS_PARAM(mv,direct);
            direct=DIRECT_WEST,  QSMM_REG_INSTR_CLASS_PARAM(mv,direct);
            qsmm_sig_t nstate=0;
            if (prg_asm)
                qsmm_get_prg_nstate_v2(qsmm, __FUNCTION__, 0,
                                       QSMM_EXCEPT_ALL, prg_asm, 0,
                                       &nstate);
            else nstate=NSTATE;
            printf("nstate %d\n",nstate);
            qsmm_set_nstate_max(qsmm,__FUNCTION__,nstate);
            QSMM_NODE_CREATE(0);
            break;
        }
        case QSMM_EVT_ENGINE_INIT:
            if (prg_asm) qsmm_node_asm(qsmm,0,0,prg_asm,msglist);
            break;
        case QSMM_EVT_NODE_ENTER: {
            unsigned char percept=0;
            is_gold_found=0;
            opaque_maze(DIRECT_NORTH,&percept);
            break;
        }
    }
    return 0;
}


// Find a path to gold in the labyrinth and then to its exit possibly
// using a node probability profile specified by an assembler program.

int
main(
    int argc,
    char **argv
) {
    int seed=0, exit_code=1;
    qsmm_t qsmm=0;
    qsmm_msglist_t msglist_dump=0;
    if (argc>2) {
        CHK_FAIL(qsmm_msglist_create,&msglist);
        CHK_FAIL(qsmm_parse_asm_source_file, argv[2],
                 QSMM_PARSE_ASM_PREPROCESS, 0, 0, msglist, &prg_asm);
    }
    struct qsmm_desc_s desc;
    memset(&desc,0,sizeof(desc));
    desc.dont_use_instr_class_weights=1;
    desc.is_large_env=1;
    desc.is_large_opt=1;
    desc.nspur=2;
    desc.stack_sz_max=1;
    desc.profile_pool_env_sz=2;
    desc.profile_pool_opt_sz=2;
    desc.compat=1;
    desc.sparse_fill_max=0.2;
    CHK_FAIL(qsmm_create,&desc,&qsmm);
    QSMM_REG_INSTR_META_CLASS(qsmm,mv,0);
    QSMM_REG_INSTR_CLASS_SET(qsmm,walker,0);
    qsmm_engine_create(qsmm);
    if (argc>1 && (seed=atoi(argv[1]))<0) {
        qsmm_set_random(qsmm,1);
        seed=-seed;
    }
    qsmm_rng_seed(qsmm_get_rng(qsmm),seed);
    for (int visit=0; visit<NVISIT; visit++) {
        path_len_pass=0;
        qsmm_node_call_default(qsmm,0,0);
        printf(
    "visit %d: ngf %d, path_pass %d, path_total %d, ngf/path_total %.8f\n",
               visit+1, n_gold_found, path_len_pass, path_len_total,
               (double) n_gold_found/path_len_total);
    }
    exit_code=0;

Exit:
    qsmm_prg_destroy(prg_asm);
    qsmm_destroy(qsmm);
    if (msglist) {
        msglist_dump=msglist;
        msglist=0;
        CHK_FAIL(qsmm_msglist_dump,msglist_dump,0,"BUFFER",0,stderr);
    }
    qsmm_msglist_destroy(msglist_dump);
    return exit_code;
}

Sample program output is below.

$ ./maze-asm -1
nstate 512
visit 1: ngf 0, path_pass 94, path_total 94, ngf/path_total 0.00000000
visit 2: ngf 0, path_pass 706, path_total 800, ngf/path_total 0.00000000
...
visit 101: ngf 19, path_pass 640, path_total 87374, ngf/path_total 0.00021746
visit 102: ngf 19, path_pass 962, path_total 88336, ngf/path_total 0.00021509
...
visit 199: ngf 37, path_pass 90, path_total 178714, ngf/path_total 0.00020703
visit 200: ngf 37, path_pass 726, path_total 179440, ngf/path_total 0.00020620
$ ./maze-asm 1
nstate 512
visit 1: ngf 0, path_pass 632, path_total 632, ngf/path_total 0.00000000
visit 2: ngf 1, path_pass 2712, path_total 3344, ngf/path_total 0.00029904
...
visit 101: ngf 84, path_pass 570, path_total 115834, ngf/path_total 0.00072518
visit 102: ngf 85, path_pass 290, path_total 116124, ngf/path_total 0.00073198
...
visit 199: ngf 182, path_pass 370, path_total 150890, ngf/path_total 0.00120618
visit 200: ngf 183, path_pass 360, path_total 151250, ngf/path_total 0.00120992

The above pieces of output show that the average amount of gold found per one move in the labyrinth in the adaptive mode of program operation with random seed 1 and without using the profile assembler program is about 6 times greater than in the random mode of program operation.

$ ./maze-asm -1 maze.asm 
nstate 200
visit 1: ngf 1, path_pass 3086, path_total 3086, ngf/path_total 0.00032404
visit 2: ngf 1, path_pass 274, path_total 3360, ngf/path_total 0.00029762
...
visit 100: ngf 17, path_pass 430, path_total 91868, ngf/path_total 0.00018505
visit 101: ngf 17, path_pass 768, path_total 92636, ngf/path_total 0.00018351
...
visit 199: ngf 43, path_pass 132, path_total 192766, ngf/path_total 0.00022307
visit 200: ngf 43, path_pass 118, path_total 192884, ngf/path_total 0.00022293
./maze-asm 1 maze.asm
nstate 200
visit 1: ngf 1, path_pass 3086, path_total 3086, ngf/path_total 0.00032404
visit 2: ngf 2, path_pass 52, path_total 3138, ngf/path_total 0.00063735
...
visit 100: ngf 100, path_pass 52, path_total 8234, ngf/path_total 0.01214477
visit 101: ngf 101, path_pass 52, path_total 8286, ngf/path_total 0.01218923
...
visit 199: ngf 199, path_pass 52, path_total 13382, ngf/path_total 0.01487072
visit 200: ngf 200, path_pass 52, path_total 13434, ngf/path_total 0.01488760

The above pieces of output show that the average amount of gold found per one move in the labyrinth in the adaptive mode of program operation with random seed 1 and the use of the profile assembler program is about 67 times greater than in the random mode of program operation.


Next: , Previous: , Up: Top   [Contents][Index]

6 Miscellaneous Topics

This chapter covers secondary topics not covered in other chapters of this manual.


Next: , Up: Miscellaneous Topics   [Contents][Index]

6.1 Random Number Generators

An actor uses a random number generator as a source of randomness to stochastically emit output signals according to their probabilities.

A standard random number generator used in QSMM is actually a pseudo-random number generator. By default, the GNU Scientific Library provides the pseudo-random number generator. A developer can provide a custom random number generator for using by QSMM. Such custom random number generator may actually be a pseudo-random number generator or may provide real random numbers obtained using some physical process.

Whereas using a random (not pseudo-random) number generator adds a sense of “free will” to a system, improper application of the random number generator in the system might be comparable with a brain injury. The selection of a method of interfacing a physical process with a system via a random number generator might affect whether the system behaves as an integral or separate part of the environment. Currently, QSMM might not support developing systems behaving as integral parts of the environment.


Next: , Up: Random Number Generators   [Contents][Index]

6.1.1 Creating a Random Number Generator

A random number generator handle refers to a random number generator.

Data type: qsmm_rng_t

This is a type for the handle of a random number generator. The handle is a pointer, so variables of this type can be NULL. The functions qsmm_rng_create and qsmm_rng_create_custom allocate a new handle. The function qsmm_rng_destroy frees an existing handle.

You can pass an allocated handle to API functions taking an argument of qsmm_rng_t type until freeing the handle. You can also set an allocated handle as the value of rng field of qsmm_actor_desc_s or qsmm_desc_s structure specifying the parameters of creating an actor or multinode model respectively. The lifetime of an allocated handle should be longer than the lifetime of an actor or multinode model.

The function qsmm_get_actor_rng returns the handle of a random number generator specified in the field rng of qsmm_actor_desc_s structure when creating an actor by the function qsmm_actor_create or returns the handle of an instance of default random number generator allocated automatically if that field was NULL. The function qsmm_get_rng returns the handle of a random number generator specified in the field rng of qsmm_desc_s structure when creating a multinode model by the function qsmm_create or returns the handle of an instance of default random number generator allocated automatically if t