|  |  | @ -93,7 +93,46 @@ namespace storm { | 
			
		
	
		
			
				
					|  |  |  |                         return h; | 
			
		
	
		
			
				
					|  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |                 return underApproximation->findSeparatingHalfspace(pointToBeSeparated); | 
			
		
	
		
			
				
					|  |  |  |                  | 
			
		
	
		
			
				
					|  |  |  |                 // We now use LP solving to find a seperating halfspace.
 | 
			
		
	
		
			
				
					|  |  |  |                 // Note that StoRM's LPSover does not support rational numbers. Hence, we optimize a polytope instead.
 | 
			
		
	
		
			
				
					|  |  |  |                 // The variables of the LP are the normalVector entries w_0 ... w_{n-1} and the minimal distance d between the halfspace and the paretoOptimalPoints
 | 
			
		
	
		
			
				
					|  |  |  |                 uint_fast64_t numVariables = pointToBeSeparated.size() + 1; | 
			
		
	
		
			
				
					|  |  |  |                 std::vector<storm::storage::geometry::Halfspace<RationalNumberType>> constraints; | 
			
		
	
		
			
				
					|  |  |  |                 constraints.reserve((numVariables-1) + 2 + paretoOptimalPoints.size()); | 
			
		
	
		
			
				
					|  |  |  |                 // w_i >= 0 and d>= 0   <==>  -w_i <= 0 and -d <= 0
 | 
			
		
	
		
			
				
					|  |  |  |                 for(uint_fast64_t i = 0; i<numVariables; ++i) { | 
			
		
	
		
			
				
					|  |  |  |                     WeightVector constraintCoefficients(numVariables, storm::utility::zero<RationalNumberType>()); | 
			
		
	
		
			
				
					|  |  |  |                     constraintCoefficients[i] = -storm::utility::one<RationalNumberType>(); | 
			
		
	
		
			
				
					|  |  |  |                     RationalNumberType constraintOffset = storm::utility::zero<RationalNumberType>(); | 
			
		
	
		
			
				
					|  |  |  |                     constraints.emplace_back(std::move(constraintCoefficients), std::move(constraintOffset)); | 
			
		
	
		
			
				
					|  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |                 // sum_i w_i == 1   <==>   sum_i w_i <=1 and sum_i -w_i <= -1
 | 
			
		
	
		
			
				
					|  |  |  |                 { | 
			
		
	
		
			
				
					|  |  |  |                     WeightVector constraintCoefficients(numVariables, storm::utility::one<RationalNumberType>()); | 
			
		
	
		
			
				
					|  |  |  |                     constraintCoefficients.back() = storm::utility::zero<RationalNumberType>(); | 
			
		
	
		
			
				
					|  |  |  |                     RationalNumberType constraintOffset = storm::utility::one<RationalNumberType>(); | 
			
		
	
		
			
				
					|  |  |  |                     constraints.emplace_back(constraintCoefficients, constraintOffset); | 
			
		
	
		
			
				
					|  |  |  |                     storm::utility::vector::scaleVectorInPlace(constraintCoefficients, -storm::utility::one<RationalNumberType>()); | 
			
		
	
		
			
				
					|  |  |  |                     constraintOffset = -storm::utility::one<RationalNumberType>(); | 
			
		
	
		
			
				
					|  |  |  |                     constraints.emplace_back(std::move(constraintCoefficients), std::move(constraintOffset)); | 
			
		
	
		
			
				
					|  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |                 // let q=pointToBeSeparated. For each paretoPoint x: q*w - x*w >= d  <==> (x-q) * w + d <= 0
 | 
			
		
	
		
			
				
					|  |  |  |                 for(auto const& paretoPoint : paretoOptimalPoints){ | 
			
		
	
		
			
				
					|  |  |  |                     WeightVector constraintCoefficients(numVariables-1); | 
			
		
	
		
			
				
					|  |  |  |                     storm::utility::vector::subtractVectors(paretoPoint.first, pointToBeSeparated, constraintCoefficients); | 
			
		
	
		
			
				
					|  |  |  |                     constraintCoefficients.push_back(storm::utility::one<RationalNumberType>()); | 
			
		
	
		
			
				
					|  |  |  |                     RationalNumberType constraintOffset = storm::utility::zero<RationalNumberType>(); | 
			
		
	
		
			
				
					|  |  |  |                     constraints.emplace_back(std::move(constraintCoefficients), std::move(constraintOffset)); | 
			
		
	
		
			
				
					|  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |                  | 
			
		
	
		
			
				
					|  |  |  |                 WeightVector optimizationVector(numVariables); | 
			
		
	
		
			
				
					|  |  |  |                 optimizationVector.back() = storm::utility::one<RationalNumberType>(); // maximize d
 | 
			
		
	
		
			
				
					|  |  |  |                 std::pair<WeightVector, bool> optimizeResult = storm::storage::geometry::Polytope<RationalNumberType>::create(constraints)->optimize(optimizationVector); | 
			
		
	
		
			
				
					|  |  |  |                 STORM_LOG_THROW(optimizeResult.second, storm::exceptions::UnexpectedException, "There seems to be no seperating halfspace."); | 
			
		
	
		
			
				
					|  |  |  |                 optimizeResult.first.pop_back(); //drop the distance
 | 
			
		
	
		
			
				
					|  |  |  |                 RationalNumberType offset = storm::utility::vector::dotProduct(optimizeResult.first, pointToBeSeparated); | 
			
		
	
		
			
				
					|  |  |  |                 return storm::storage::geometry::Halfspace<RationalNumberType>(std::move(optimizeResult.first), std::move(offset)); | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |             template <class SparseModelType, typename RationalNumberType> | 
			
		
	
	
		
			
				
					|  |  | 
 |