Previous: Getting the Reason of a Storage Failure, Up: Statistics Storage [Contents][Index]
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:
wr_acstate
saves the following information:
wr_acstate
saves the following information:
The functions actor_save
and actor_load
do not save and load the following parameters:
qsmm_get_actor_relprob_type
queries that type.
The function qsmm_set_actor_relprob_type
sets that type.
qsmm_get_actor_relprob_helper
retrieves the helper function.
The function qsmm_set_actor_relprob_helper
sets the helper 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.
qsmm_actor_profile_add
adds a probabilities list to the pool.
qsmm_actor_profile_add
and qsmm_actor_permut_add
add a permutation of output signals to the pool.
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.
qsmm_get_actor_discrete_cycle_period_last
returns this cycle period.
qsmm_get_actor_discrete_cycle_period_mean
returns this cycle period.
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:
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; }
Previous: Getting the Reason of a Storage Failure, Up: Statistics Storage [Contents][Index]