Пример #1
0
int SmartState::getState(const PetriNet& net, MarkVal* marking, VarVal* valuation) const{
	if(stored()){
		memcpy(marking, _marking, sizeof(MarkVal) * net.numberOfPlaces());
		memcpy(valuation, _valuation, sizeof(VarVal) * net.numberOfVariables());
		return 0;
	}
	int depth = parent()->getState(net, marking, valuation);
	net.fireWithoutCheck(transition(), marking, valuation, marking, valuation, multiplicity());
	return depth + 1;
}
Пример #2
0
int StateConstraints::fireVectorSize(const PetriNet& net,
									 const MarkVal* m0,
									 const VarVal*) const{
	assert(nPlaces == net.numberOfPlaces());
	assert(nVars == net.numberOfVariables());

	// Create linary problem
	lprec* lp;
	lp = make_lp(0, net.numberOfTransitions());	// One variable for each entry in the firing vector
	assert(lp);
	if(!lp) return false;

	// Set verbosity
	set_verbose(lp, IMPORTANT);

	// Set transition names (not strictly needed)
	for(size_t i = 0; i < net.numberOfTransitions(); i++)
		set_col_name(lp, i+1, const_cast<char*>(net.transitionNames()[i].c_str()));

	// Start adding rows
	set_add_rowmode(lp, TRUE);

	REAL row[net.numberOfTransitions() + 1];
	for(size_t p = 0; p < nPlaces; p++){
		// Set row zero
		memset(row, 0, sizeof(REAL) * net.numberOfTransitions() + 1);
		for(size_t t = 0; t < net.numberOfTransitions(); t++){
			int d = net.outArc(t, p) - net.inArc(p, t);
			row[1+t] = d;
		}

		if(pcs[p].min == pcs[p].max &&
		   pcs[p].max != CONSTRAINT_INFTY){
			double target = pcs[p].min - m0[p];
			add_constraint(lp, row, EQ,  target);
		}else{
			// There's always a min, even zero is interesting
			double target = pcs[p].min - m0[p];
			add_constraint(lp, row, GE,  target);
			if(pcs[p].max != CONSTRAINT_INFTY){
				double target = pcs[p].max - m0[p];
				add_constraint(lp, row, LE,  target);
			}
		}
	}

	// Finished adding rows
	set_add_rowmode(lp, FALSE);

	// Create objective
	memset(row, 0, sizeof(REAL) * net.numberOfTransitions() + 1);
	for(size_t t = 0; t < net.numberOfTransitions(); t++)
		row[1+t] = 1;	// The sum the components in the firing vector

	// Set objective
	set_obj_fn(lp, row);

	// Minimize the objective
	set_minim(lp);

	// Set variables as integer variables
	for(size_t i = 0; i < net.numberOfTransitions(); i++)
		set_int(lp, 1+i, TRUE);

	// Attempt to solve the problem
	int result = solve(lp);

	// Limit on traps to test
	size_t traplimit = nPlaces * OVER_APPROX_TRAP_FACTOR;
	// Try to add a minimal trap constraint
	while((result == OPTIMAL) && traplimit-- < 0){
		memset(row, 0, sizeof(REAL) * net.numberOfTransitions() + 1);
		// Get the firing vector
		get_variables(lp, row);
		// Compute the resulting marking
		MarkVal rMark[net.numberOfPlaces()];
		for(size_t p = 0; p < nPlaces; p++){
			rMark[p] = m0[p];
			for(size_t t = 0; t < net.numberOfTransitions(); t++)
				rMark[p] += (net.outArc(t, p) - net.inArc(p, t)) * (int)row[t];
		}

		// Find an M-trap
		BitField trap(minimalTrap(net, m0, rMark));

		//Break if there's no trap
		if(trap.none()) break;

		// Compute the new equation
		for(size_t t = 0; t < net.numberOfTransitions(); t++){
			row[1+t] = 0;
			for(size_t p = 0; p < nPlaces; p++)
				if(trap.test(p))
					row[1+t] += net.outArc(t, p) - net.inArc(p, t);
		}

		// Add a new row with target as greater than equal to 1
		set_add_rowmode(lp, TRUE);
		add_constraint(lp, row, GE,  1);
		set_add_rowmode(lp, FALSE);

		// Attempt to solve the again
		result = solve(lp);
	}

	int retval = 0;

	if(result != INFEASIBLE){
		get_variables(lp, row);
		for(size_t t = 0; t < net.numberOfTransitions(); t++)
			retval += (int)row[t];
	}

	// Delete the linear problem
	delete_lp(lp);
	lp = NULL;

	// Return true, if it was infeasible
	return retval;
}
Пример #3
0
bool KarpMillerL1SearchStrategy::reachable(const PetriNet &net,
										   const MarkVal *initialMarking,
										   const VarVal*,
										   PQL::Condition *query){
	assert(net.numberOfVariables() == 0);
	if(net.numberOfVariables() > 0){
		//TODO: Return unknown, or could not be found
		return false;
	}

	const unsigned int nTransitions = net.numberOfTransitions(),
					   nPlaces = net.numberOfPlaces();
	MarkVal old_m[nPlaces];
	MarkVal new_m[nPlaces];
	memcpy(old_m, initialMarking, nPlaces * sizeof(MarkVal));
	size_t depth = 1;
	uint8_t* stack = new uint8_t[MAX_DEPTH];
	stack[0] = 0;
	uint8_t t = 0;
	while(true){
		// Invariant:
		// old_m is the current marking
		// stack[depth] is where the next transtion goes
		// t is the next transition to fire

		while(!fire(net, t, old_m, new_m)){
			while(++t == nTransitions){
				if(--depth == 0)	//Pop the stack
					return false;	//Terminate algorithm, we're done now
				// Reverse transition on the stack
				t = stack[depth];
				for(size_t i = 0; i < nPlaces; i++)
					old_m[i] -= net.transitionVector(t)[i];
			}
		}

		//Test if query is satisfied
		if(query->evaluate(PQL::EvaluationContext(new_m, NULL)))
			return true;

		//Check if it's seen
		bool seen = false;
		size_t d = depth;
		while(--d > 0){
			seen = true;
			const MarkVal* tv = net.transitionVector(stack[d]);
			for(size_t i = 0; i < nPlaces; i++){
				old_m[i] -= tv[i];
				seen &= old_m[i] == new_m[i];
				if(!seen) break;
			}
			if(seen) break;
		}
		if(seen)
			printf("|");
		else
			printf("%i", (int)t);
		fflush(stdout);
		memcpy(old_m, new_m, nPlaces * sizeof(MarkVal));
		if(!seen){
			stack[depth++] = t;
			t = 0;
		}else{
			for(size_t i = 0; i < nPlaces; i++)
				old_m[i] -= net.transitionVector(t)[i];
			//Pop if needed as long as needed
			while(++t == nTransitions){
				if(--depth == 0)	//Pop the stack
					return false;	//Terminate algorithm, we're done now
				// Reverse transition on the stack
				t = stack[depth];
				for(size_t i = 0; i < nPlaces; i++)
					old_m[i] -= net.transitionVector(t)[i];
			}
		}
	}
}
Пример #4
0
ReachabilityResult MagicSearch::reachable(const PetriNet &net,
										  const MarkVal *m0,
										  const VarVal *v0,
										  PQL::Condition *query){
	SmartStateAllocator<MEMORY_BOUND> allocator(net);
	SmartStateSet states(net);
	EnhancedPriorityQueue<Step> queue;

	_dm = new Structures::DistanceMatrix(net);
	{	//Compute constraints
		ConstraintAnalysisContext context(net);
		query->findConstraints(context);
		if(context.canAnalyze)
			contraints = context.retval;
	}

	//Create s0
	SmartState* s0 = allocator.createStoredState();
	memcpy(s0->marking(), m0, sizeof(MarkVal) * net.numberOfPlaces());
	memcpy(s0->valuation(), v0, sizeof(VarVal) * net.numberOfVariables());
	states.add(s0, s0->marking(), s0->valuation());
	Step step0;
	step0.depth = 0;
	step0.lastApprox = INT_MAX;
	step0.lastStored = 0;
	step0.state = s0;
	queue.push(0, step0);

	//Temporary marking and valuation to work with
	MarkVal tmpM[net.numberOfPlaces()];
	VarVal tmpV[net.numberOfVariables()];
	SmartState* ns = allocator.createStoredState();
	SmartState* ls = allocator.createState();

	//Statistics
	int lastReport = 0;
	BigInt expanded = 0, explored = 0;
	size_t max = 1;

	//Main loop
	while(!queue.empty()){
		// Report progress if needed
		if(lastReport++ & 1<<17){
			lastReport = 0;
			if(queue.size() > max)
				max = queue.size();
			this->reportProgress((double)(max - queue.size()) / ((double)(max)));
			if(this->abortRequested())
				return ReachabilityResult(ReachabilityResult::Unknown,
										  "Query aborted!");
		}

		//Pop stuff of the queue
		Step step = queue.pop(depthFirst);
		expanded++; //Cound expanded states

		// Get current state
		const MarkVal* m;
		const VarVal* v;
		if(step.state->stored()){
			m = step.state->marking();
			v = step.state->valuation();
		}else{
			step.state->getState(net, tmpM, tmpV);
			m = tmpM;
			v = tmpV;
		}

		//Attempt to exclude by over-approx
		if(step.lastApprox >= approxScale(step.depth)){
			if(canExcludeByOverApprox(net, m, v))
				continue;
			step.lastApprox = 0;
		}

		for(unsigned int t = 0; t < net.numberOfTransitions(); t++){
			//Fire the transition
			if(net.fire(t, m, v, ns->marking(), ns->valuation())){
				//Determine whether or not to store the entire state
				bool storeCurrentState = step.lastStored >= storeScale(allocator.percentMemoryUsed());// storeScale(allocator.percentMemoryUsed());
				SmartState* storeState;
				if(storeCurrentState)
					storeState = ns;
				else
					storeState = ls;
				storeState->setParent(step.state);
				storeState->setTransition(t);

				//Add it to the state set
				if(states.add(storeState, ns->marking(), ns->valuation())){
					explored++; //Count explored states

					//Test the query
					if(query->evaluate(EvaluationContext(ns->marking(), ns->valuation()))){
						printf("\nmemory usage: %f\n",allocator.percentMemoryUsed());
						return ReachabilityResult(ReachabilityResult::Satisfied,
												  "Query was satified!",
												  expanded,
												  explored,
												  storeState->pathLength(),
												  storeState->trace());
					}

					//Make the next step
					Step nextstep;
					nextstep.depth = step.depth + 1;
					nextstep.lastApprox = step.lastApprox + 1;
					if(storeState == ns)
						nextstep.lastStored = 0;
					else
						nextstep.lastStored = step.lastStored + 1;
					nextstep.state = storeState;

					//Push step on the queue
					double p = priority(ns->marking(), ns->valuation(), query, net);
					queue.push(p, nextstep);

					//Allocate new memory, depending on what was stored
					if(storeState == ns)
						ns = allocator.createStoredState();
					else
						ls = allocator.createState();
				}
			}
		}
	}
	return ReachabilityResult(ReachabilityResult::NotSatisfied,
							  "Query cannot be satisfied!",
							  expanded,
							  explored);
}