- Added '--extend-trivial' switch. This is not a complete '--extend'
algorithm, as it is pretty dumb, but it works in most cases. Use with care.
This commit is contained in:
parent
44bc36edc5
commit
cb315aafc8
112
src/arachne.c
112
src/arachne.c
@ -3484,3 +3484,115 @@ arachne ()
|
|||||||
cl = cl->next;
|
cl = cl->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Construct knowledge set at some event, based on a semitrace.
|
||||||
|
/**
|
||||||
|
* This is a very 'stupid' algorithm; it is just there because GijsH
|
||||||
|
* requested it. It does in no way guarantee that this is the actual
|
||||||
|
* knowledge set at the given point. It simply gives an underapproximation,
|
||||||
|
* that will be correct in most cases. The main reason for this is that it
|
||||||
|
* completely ignores any information on unbound variables, and regards them
|
||||||
|
* as bound constants.
|
||||||
|
*
|
||||||
|
* Because everything is supposed to be bound, we conclude that even 'read'
|
||||||
|
* events imply a certain knowledge.
|
||||||
|
*
|
||||||
|
* If aftercomplete is 0 or false, we actually check the ordering; otherwise we
|
||||||
|
* just assume the trace has finished.
|
||||||
|
*
|
||||||
|
* Use knowledgeDelete later to clean up.
|
||||||
|
*/
|
||||||
|
Knowledge
|
||||||
|
knowledgeAtArachne (const System sys, const int myrun, const int myindex,
|
||||||
|
const int aftercomplete)
|
||||||
|
{
|
||||||
|
Knowledge know;
|
||||||
|
int run;
|
||||||
|
|
||||||
|
goal_graph_create (); // ensure a valid ordering graph
|
||||||
|
know = knowledgeDuplicate (sys->know); // duplicate initial knowledge
|
||||||
|
run = 0;
|
||||||
|
while (run < sys->maxruns)
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
int maxstep;
|
||||||
|
Roledef rd;
|
||||||
|
|
||||||
|
index = 0;
|
||||||
|
rd = sys->runs[run].start;
|
||||||
|
maxstep = sys->runs[run].step;
|
||||||
|
if (run == myrun && myindex > maxstep)
|
||||||
|
{
|
||||||
|
// local run index can override real step
|
||||||
|
maxstep = myindex;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (rd != NULL && index < maxstep)
|
||||||
|
{
|
||||||
|
// Check whether this event precedes myevent
|
||||||
|
if (aftercomplete || isOrderedBefore (run, index, myrun, myindex))
|
||||||
|
{
|
||||||
|
// If it is a send (trivial) or a read (remarkable, but true
|
||||||
|
// because of bindings) we can add the message and the agents to
|
||||||
|
// the knowledge.
|
||||||
|
if (rd->type == SEND || rd->type == READ)
|
||||||
|
{
|
||||||
|
knowledgeAddTerm (know, rd->message);
|
||||||
|
if (rd->from != NULL)
|
||||||
|
knowledgeAddTerm (know, rd->from);
|
||||||
|
if (rd->to != NULL)
|
||||||
|
knowledgeAddTerm (know, rd->to);
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
rd = rd->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Not ordered before anymore, so we skip to the next run.
|
||||||
|
rd = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
run++;
|
||||||
|
}
|
||||||
|
return know;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Determine whether a term is trivially known at some event in a partially ordered structure.
|
||||||
|
/**
|
||||||
|
* Important: read disclaimer at knowledgeAtArachne()
|
||||||
|
*
|
||||||
|
* Returns true iff the term is certainly known at that point in the
|
||||||
|
* semitrace.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
isTriviallyKnownAtArachne (const System sys, const Term t, const int run,
|
||||||
|
const int index)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
Knowledge knowset;
|
||||||
|
|
||||||
|
knowset = knowledgeAtArachne (sys, run, index, false);
|
||||||
|
result = inKnowledge (knowset, t);
|
||||||
|
knowledgeDelete (knowset);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Determine whether a term is trivially known after execution of some partially ordered structure.
|
||||||
|
/**
|
||||||
|
* Important: read disclaimer at knowledgeAtArachne()
|
||||||
|
*
|
||||||
|
* Returns true iff the term is certainly known after all events in the
|
||||||
|
* semitrace.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
isTriviallyKnownAfterArachne (const System sys, const Term t, const int run,
|
||||||
|
const int index)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
Knowledge knowset;
|
||||||
|
|
||||||
|
knowset = knowledgeAtArachne (sys, run, index, true);
|
||||||
|
result = inKnowledge (knowset, t);
|
||||||
|
knowledgeDelete (knowset);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@ -8,5 +8,9 @@ void arachneDone ();
|
|||||||
int arachne ();
|
int arachne ();
|
||||||
int get_semitrace_length ();
|
int get_semitrace_length ();
|
||||||
void indentPrint ();
|
void indentPrint ();
|
||||||
|
int isTriviallyKnownAtArachne (const System sys, const Term t, const int run,
|
||||||
|
const int index);
|
||||||
|
int isTriviallyKnownAfterArachne (const System sys, const Term t,
|
||||||
|
const int run, const int index);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -66,6 +66,17 @@ binding_destroy (Binding b)
|
|||||||
memFree (b, sizeof (struct binding));
|
memFree (b, sizeof (struct binding));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Test whether one event is ordered before another
|
||||||
|
/**
|
||||||
|
* Is only guaranteed to yield trustworthy results after a new graph is created, using
|
||||||
|
* goal_graph_create ()
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
isOrderedBefore (const int run1, const int ev1, const int run2, const int ev2)
|
||||||
|
{
|
||||||
|
return graph[graph_nodes (nodes, run2, ev2, run2, ev2)];
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Main
|
* Main
|
||||||
|
@ -36,6 +36,10 @@ int node_count ();
|
|||||||
int node_number (int run, int ev);
|
int node_number (int run, int ev);
|
||||||
__inline__ int graph_nodes (const int nodes, const int run1, const int ev1,
|
__inline__ int graph_nodes (const int nodes, const int run1, const int ev1,
|
||||||
const int run2, const int ev2);
|
const int run2, const int ev2);
|
||||||
|
|
||||||
|
int isOrderedBefore (const int run1, const int ev1, const int run2,
|
||||||
|
const int ev2);
|
||||||
|
|
||||||
void goal_graph_create ();
|
void goal_graph_create ();
|
||||||
|
|
||||||
|
|
||||||
|
@ -78,6 +78,7 @@ switchesInit (int argc, char **argv)
|
|||||||
switches.reportTime = 0;
|
switches.reportTime = 0;
|
||||||
switches.reportStates = 0;
|
switches.reportStates = 0;
|
||||||
switches.extendNonReads = 0; // default off
|
switches.extendNonReads = 0; // default off
|
||||||
|
switches.extendTrivial = 0; // default off
|
||||||
|
|
||||||
// Obsolete
|
// Obsolete
|
||||||
switches.latex = 0; // latex output?
|
switches.latex = 0; // latex output?
|
||||||
@ -481,6 +482,20 @@ switcher (const int process, int index)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (detect (' ', "extend-trivial", 0))
|
||||||
|
{
|
||||||
|
if (!process)
|
||||||
|
{
|
||||||
|
/* discourage: hide
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switches.extendTrivial = 1;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ==================
|
/* ==================
|
||||||
* External options
|
* External options
|
||||||
*/
|
*/
|
||||||
|
@ -57,6 +57,7 @@ struct switchdata
|
|||||||
int reportTime; //!< Time display switch.
|
int reportTime; //!< Time display switch.
|
||||||
int reportStates; //!< Progress display switch. (traversed states)
|
int reportStates; //!< Progress display switch. (traversed states)
|
||||||
int extendNonReads; //!< Show further events in arachne xml output.
|
int extendNonReads; //!< Show further events in arachne xml output.
|
||||||
|
int extendTrivial; //!< Show further events in arachne xml output, based on knowledge underapproximation. (Includes at least the events of the nonreads extension)
|
||||||
|
|
||||||
//! Latex output switch.
|
//! Latex output switch.
|
||||||
/**
|
/**
|
||||||
|
40
src/xmlout.c
40
src/xmlout.c
@ -872,12 +872,50 @@ xmlOutRuns (const System sys)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (switches.extendNonReads)
|
if (switches.extendTrivial || switches.extendNonReads)
|
||||||
{
|
{
|
||||||
if (rd->type != READ)
|
if (rd->type != READ)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (switches.extendTrivial)
|
||||||
|
{
|
||||||
|
/* This is a read, and we don't know whether to
|
||||||
|
* include it. Default behaviour would be to jump
|
||||||
|
* out of the conditions, and return false.
|
||||||
|
* Instead, we check whether it can be trivially
|
||||||
|
* satisfied by the knowledge from the preceding
|
||||||
|
* events.
|
||||||
|
*/
|
||||||
|
if (isTriviallyKnownAtArachne (sys,
|
||||||
|
rd->message,
|
||||||
|
run, index))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We cannot extend it trivially, based on
|
||||||
|
* the preceding events, but maybe we can
|
||||||
|
* base it on another (*all*) event. That
|
||||||
|
* would in fact introduce another implicit
|
||||||
|
* binding. Currently, we do not explicitly
|
||||||
|
* introduce this binding, but just allow
|
||||||
|
* displaying the event.
|
||||||
|
*
|
||||||
|
* TODO consider what it means to leave out
|
||||||
|
* this binding.
|
||||||
|
*/
|
||||||
|
if (isTriviallyKnownAfterArachne
|
||||||
|
(sys, rd->message, run, index))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user