Browse Source
			
			
			Initial commit.
			
				
		Initial commit.
	
		
	
			
				The basic Implementation compiles. No tests yet.
Former-commit-id: 60b6d0f892
			
			
				main
			
			
		
				 9 changed files with 637 additions and 1 deletions
			
			
		- 
					2resources/3rdparty/CMakeLists.txt
- 
					18resources/3rdparty/sylvan/CMakeLists.txt
- 
					6resources/3rdparty/sylvan/examples/CMakeLists.txt
- 
					127resources/3rdparty/sylvan/examples/storm.cpp
- 
					9resources/3rdparty/sylvan/src/CMakeLists.txt
- 
					116resources/3rdparty/sylvan/src/storm_function_wrapper.cpp
- 
					33resources/3rdparty/sylvan/src/storm_function_wrapper.h
- 
					240resources/3rdparty/sylvan/src/sylvan_storm_rational_function.c
- 
					87resources/3rdparty/sylvan/src/sylvan_storm_rational_function.h
| @ -0,0 +1,127 @@ | |||
| #ifdef NDEBUG
 | |||
| #undef NDEBUG
 | |||
| #endif
 | |||
| 
 | |||
| #include <assert.h>
 | |||
| #include <stdio.h>
 | |||
| #include <stdint.h>
 | |||
| 
 | |||
| #include <sylvan.h>
 | |||
| #include <sylvan_obj.hpp>
 | |||
| #include <storm_function_wrapper.h>
 | |||
| #include <sylvan_storm_rational_function.h>
 | |||
| 
 | |||
| using namespace sylvan; | |||
| 
 | |||
| VOID_TASK_0(storm_rf) | |||
| { | |||
|     Bdd one = Bdd::bddOne(); // the True terminal
 | |||
|     Bdd zero = Bdd::bddZero(); // the False terminal
 | |||
| 
 | |||
|     // check if they really are the True/False terminal
 | |||
|     assert(one.GetBDD() == sylvan_true); | |||
|     assert(zero.GetBDD() == sylvan_false); | |||
| 
 | |||
|     Bdd a = Bdd::bddVar(0); // create a BDD variable x_0
 | |||
|     Bdd b = Bdd::bddVar(1); // create a BDD variable x_1
 | |||
| 
 | |||
|     // check if a really is the Boolean formula "x_0"
 | |||
|     assert(!a.isConstant()); | |||
|     assert(a.TopVar() == 0); | |||
|     assert(a.Then() == one); | |||
|     assert(a.Else() == zero); | |||
| 
 | |||
|     // check if b really is the Boolean formula "x_1"
 | |||
|     assert(!b.isConstant()); | |||
|     assert(b.TopVar() == 1); | |||
|     assert(b.Then() == one); | |||
|     assert(b.Else() == zero); | |||
| 
 | |||
|     // compute !a
 | |||
|     Bdd not_a = !a; | |||
| 
 | |||
|     // check if !!a is really a
 | |||
|     assert((!not_a) == a); | |||
| 
 | |||
|     // compute a * b and !(!a + !b) and check if they are equivalent
 | |||
|     Bdd a_and_b = a * b; | |||
|     Bdd not_not_a_or_not_b = !(!a + !b); | |||
|     assert(a_and_b == not_not_a_or_not_b); | |||
| 
 | |||
|     // perform some simple quantification and check the results
 | |||
|     Bdd ex = a_and_b.ExistAbstract(a); // \exists a . a * b
 | |||
|     assert(ex == b); | |||
|     Bdd andabs = a.AndAbstract(b, a); // \exists a . a * b using AndAbstract
 | |||
|     assert(ex == andabs); | |||
|     Bdd univ = a_and_b.UnivAbstract(a); // \forall a . a * b
 | |||
|     assert(univ == zero); | |||
| 
 | |||
|     // alternative method to get the cube "ab" using bddCube
 | |||
|     BddSet variables = a * b; | |||
|     std::vector<unsigned char> vec = {1, 1}; | |||
|     assert(a_and_b == Bdd::bddCube(variables, vec)); | |||
| 
 | |||
|     // test the bddCube method for all combinations
 | |||
|     assert((!a * !b) == Bdd::bddCube(variables, std::vector<uint8_t>({0, 0}))); | |||
|     assert((!a * b)  == Bdd::bddCube(variables, std::vector<uint8_t>({0, 1}))); | |||
|     assert((!a)      == Bdd::bddCube(variables, std::vector<uint8_t>({0, 2}))); | |||
|     assert((a * !b)  == Bdd::bddCube(variables, std::vector<uint8_t>({1, 0}))); | |||
|     assert((a * b)   == Bdd::bddCube(variables, std::vector<uint8_t>({1, 1}))); | |||
|     assert((a)       == Bdd::bddCube(variables, std::vector<uint8_t>({1, 2}))); | |||
|     assert((!b)      == Bdd::bddCube(variables, std::vector<uint8_t>({2, 0}))); | |||
|     assert((b)       == Bdd::bddCube(variables, std::vector<uint8_t>({2, 1}))); | |||
|     assert(one       == Bdd::bddCube(variables, std::vector<uint8_t>({2, 2}))); | |||
| } | |||
| 
 | |||
| VOID_TASK_1(_main, void*, arg) | |||
| { | |||
|     // Initialize Sylvan
 | |||
|     // With starting size of the nodes table 1 << 21, and maximum size 1 << 27.
 | |||
|     // With starting size of the cache table 1 << 20, and maximum size 1 << 20.
 | |||
|     // Memory usage: 24 bytes per node, and 36 bytes per cache bucket
 | |||
|     // - 1<<24 nodes: 384 MB
 | |||
|     // - 1<<25 nodes: 768 MB
 | |||
|     // - 1<<26 nodes: 1536 MB
 | |||
|     // - 1<<27 nodes: 3072 MB
 | |||
|     // - 1<<24 cache: 576 MB
 | |||
|     // - 1<<25 cache: 1152 MB
 | |||
|     // - 1<<26 cache: 2304 MB
 | |||
|     // - 1<<27 cache: 4608 MB
 | |||
|     sylvan_init_package(1LL<<22, 1LL<<26, 1LL<<22, 1LL<<26); | |||
| 
 | |||
|     // Initialize the BDD module with granularity 1 (cache every operation)
 | |||
|     // A higher granularity (e.g. 6) often results in better performance in practice
 | |||
|     sylvan_init_bdd(1); | |||
| 
 | |||
|     // Now we can do some simple stuff using the C++ objects.
 | |||
|     CALL(storm_rf); | |||
| 
 | |||
|     // Report statistics (if SYLVAN_STATS is 1 in the configuration)
 | |||
|     sylvan_stats_report(stdout, 1); | |||
| 
 | |||
|     // And quit, freeing memory
 | |||
|     sylvan_quit(); | |||
| 
 | |||
|     // We didn't use arg
 | |||
|     (void)arg; | |||
| } | |||
| 
 | |||
| int | |||
| main (int argc, char *argv[]) | |||
| { | |||
|     int n_workers = 0; // automatically detect number of workers
 | |||
|     size_t deque_size = 0; // default value for the size of task deques for the workers
 | |||
|     size_t program_stack_size = 0; // default value for the program stack of each pthread
 | |||
| 
 | |||
|     // Initialize the Lace framework for <n_workers> workers.
 | |||
|     lace_init(n_workers, deque_size); | |||
| 
 | |||
|     // Spawn and start all worker pthreads; suspends current thread until done.
 | |||
|     lace_startup(program_stack_size, TASK(_main), NULL); | |||
| 
 | |||
|     // The lace_startup command also exits Lace after _main is completed.
 | |||
| 
 | |||
|     return 0; | |||
|     (void)argc; // unused variable
 | |||
|     (void)argv; // unused variable
 | |||
| } | |||
| @ -0,0 +1,116 @@ | |||
| #include "storm_function_wrapper.h"
 | |||
| 
 | |||
| #include <cstring>
 | |||
| #include "src/adapters/CarlAdapter.h"
 | |||
| 
 | |||
| void storm_rational_function_init(storm_rational_function_ptr* a) { | |||
| 	storm_rational_function_ptr srf_ptr = static_cast<storm_rational_function_ptr>(malloc(sizeof(storm_rational_function_ptr_struct))); | |||
| 	 | |||
| 	if (srf_ptr == nullptr) { | |||
| 		return; | |||
| 	} | |||
| 	 | |||
| 	srf_ptr->storm_rational_function = new storm::RationalFunction(*(storm::RationalFunction*)((*a)->storm_rational_function)); | |||
| 
 | |||
| 	*a = srf_ptr; | |||
| } | |||
| 
 | |||
| void storm_rational_function_destroy(storm_rational_function_ptr a) { | |||
| 	delete (storm::RationalFunction*)a->storm_rational_function; | |||
| 	a->storm_rational_function = nullptr; | |||
| 	free((void*)a); | |||
| } | |||
| 
 | |||
| int storm_rational_function_equals(storm_rational_function_ptr a, storm_rational_function_ptr b) { | |||
| 	storm::RationalFunction* srf_a = (storm::RationalFunction*)a->storm_rational_function; | |||
| 	storm::RationalFunction* srf_b = (storm::RationalFunction*)b->storm_rational_function; | |||
| 
 | |||
| 	if (*srf_a == *srf_b) { | |||
| 		return 0; | |||
| 	} | |||
| 
 | |||
| 	return -1; | |||
| } | |||
| 
 | |||
| storm_rational_function_ptr storm_rational_function_plus(storm_rational_function_ptr a, storm_rational_function_ptr b) { | |||
| 	storm::RationalFunction& srf_a = *(storm::RationalFunction*)a->storm_rational_function; | |||
| 	storm::RationalFunction& srf_b = *(storm::RationalFunction*)b->storm_rational_function; | |||
| 
 | |||
| 	storm::RationalFunction* result_srf = new storm::RationalFunction(srf_a); | |||
| 	*result_srf += srf_b; | |||
| 
 | |||
| 	storm_rational_function_ptr result = (storm_rational_function_ptr)malloc(sizeof(storm_rational_function_ptr_struct)); | |||
| 	result->storm_rational_function = (void*)result_srf; | |||
| 
 | |||
| 	return result; | |||
| } | |||
| 
 | |||
| storm_rational_function_ptr storm_rational_function_minus(storm_rational_function_ptr a, storm_rational_function_ptr b) { | |||
| 	storm::RationalFunction& srf_a = *(storm::RationalFunction*)a->storm_rational_function; | |||
| 	storm::RationalFunction& srf_b = *(storm::RationalFunction*)b->storm_rational_function; | |||
| 
 | |||
| 	storm::RationalFunction* result_srf = new storm::RationalFunction(srf_a); | |||
| 	*result_srf -= srf_b; | |||
| 
 | |||
| 	storm_rational_function_ptr result = (storm_rational_function_ptr)malloc(sizeof(storm_rational_function_ptr_struct)); | |||
| 	result->storm_rational_function = (void*)result_srf; | |||
| 
 | |||
| 	return result; | |||
| } | |||
| 
 | |||
| storm_rational_function_ptr storm_rational_function_times(storm_rational_function_ptr a, storm_rational_function_ptr b) { | |||
| 	storm::RationalFunction& srf_a = *(storm::RationalFunction*)a->storm_rational_function; | |||
| 	storm::RationalFunction& srf_b = *(storm::RationalFunction*)b->storm_rational_function; | |||
| 
 | |||
| 	storm::RationalFunction* result_srf = new storm::RationalFunction(srf_a); | |||
| 	*result_srf *= srf_b; | |||
| 
 | |||
| 	storm_rational_function_ptr result = (storm_rational_function_ptr)malloc(sizeof(storm_rational_function_ptr_struct)); | |||
| 	result->storm_rational_function = (void*)result_srf; | |||
| 
 | |||
| 	return result; | |||
| } | |||
| 
 | |||
| storm_rational_function_ptr storm_rational_function_divide(storm_rational_function_ptr a, storm_rational_function_ptr b) { | |||
| 	storm::RationalFunction& srf_a = *(storm::RationalFunction*)a->storm_rational_function; | |||
| 	storm::RationalFunction& srf_b = *(storm::RationalFunction*)b->storm_rational_function; | |||
| 
 | |||
| 	storm::RationalFunction* result_srf = new storm::RationalFunction(srf_a); | |||
| 	*result_srf /= srf_b; | |||
| 
 | |||
| 	storm_rational_function_ptr result = (storm_rational_function_ptr)malloc(sizeof(storm_rational_function_ptr_struct)); | |||
| 	result->storm_rational_function = (void*)result_srf; | |||
| 
 | |||
| 	return result; | |||
| } | |||
| 
 | |||
| uint64_t storm_rational_function_hash(storm_rational_function_ptr const a, uint64_t const seed) { | |||
| 	storm::RationalFunction& srf_a = *(storm::RationalFunction*)a->storm_rational_function; | |||
| 
 | |||
| 	size_t hash = carl::hash_value(srf_a); | |||
| 	uint64_t result = hash ^ seed; | |||
| 
 | |||
| 	return result; | |||
| } | |||
| 
 | |||
| storm_rational_function_ptr storm_rational_function_negate(storm_rational_function_ptr a) { | |||
| 	storm::RationalFunction& srf_a = *(storm::RationalFunction*)a->storm_rational_function; | |||
| 
 | |||
| 	storm::RationalFunction* result_srf = new storm::RationalFunction(srf_a); | |||
| 	*result_srf = -srf_a; | |||
| 
 | |||
| 	storm_rational_function_ptr result = (storm_rational_function_ptr)malloc(sizeof(storm_rational_function_ptr_struct)); | |||
| 	result->storm_rational_function = (void*)result_srf; | |||
| 
 | |||
| 	return result; | |||
| } | |||
| 
 | |||
| int storm_rational_function_is_zero(storm_rational_function_ptr a) { | |||
| 	storm::RationalFunction& srf_a = *(storm::RationalFunction*)a->storm_rational_function; | |||
| 
 | |||
| 	if (srf_a.isZero()) { | |||
| 		return 1; | |||
| 	} else { | |||
| 		return 0; | |||
| 	} | |||
| } | |||
| @ -0,0 +1,33 @@ | |||
| #ifndef SYLVAN_STORM_FUNCTION_WRAPPER_H | |||
| #define SYLVAN_STORM_FUNCTION_WRAPPER_H | |||
| 
 | |||
| #include <stdint.h> | |||
| 
 | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| 
 | |||
| typedef struct { | |||
| 	void* storm_rational_function; | |||
| } storm_rational_function_ptr_struct; | |||
| typedef storm_rational_function_ptr_struct storm_rational_function_t[1]; | |||
| typedef storm_rational_function_ptr_struct* storm_rational_function_ptr; | |||
| 
 | |||
| 
 | |||
| // equals, plus, minus, divide, times, create, destroy | |||
| void storm_rational_function_init(storm_rational_function_ptr* a); | |||
| void storm_rational_function_destroy(storm_rational_function_ptr a); | |||
| int storm_rational_function_equals(storm_rational_function_ptr a, storm_rational_function_ptr b); | |||
| storm_rational_function_ptr storm_rational_function_plus(storm_rational_function_ptr a, storm_rational_function_ptr b); | |||
| storm_rational_function_ptr storm_rational_function_minus(storm_rational_function_ptr a, storm_rational_function_ptr b); | |||
| storm_rational_function_ptr storm_rational_function_times(storm_rational_function_ptr a, storm_rational_function_ptr b); | |||
| storm_rational_function_ptr storm_rational_function_divide(storm_rational_function_ptr a, storm_rational_function_ptr b); | |||
| storm_rational_function_ptr storm_rational_function_negate(storm_rational_function_ptr a); | |||
| uint64_t storm_rational_function_hash(storm_rational_function_ptr const a, uint64_t const seed); | |||
| int storm_rational_function_is_zero(storm_rational_function_ptr a); | |||
| 
 | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| 
 | |||
| #endif // SYLVAN_STORM_FUNCTION_WRAPPER_H | |||
| @ -0,0 +1,240 @@ | |||
| #include <sylvan_config.h> | |||
| 
 | |||
| #include <assert.h> | |||
| #include <inttypes.h> | |||
| #include <math.h> | |||
| #include <stdint.h> | |||
| #include <stdio.h> | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| 
 | |||
| #include <sylvan.h> | |||
| #include <sylvan_common.h> | |||
| /*#include <sylvan_mtbdd_int.h>*/ | |||
| #include <sylvan_storm_rational_function.h> | |||
| 
 | |||
| #include <storm_function_wrapper.h> | |||
| 
 | |||
| /** | |||
|  * helper function for hash | |||
|  */ | |||
| #ifndef rotl64 | |||
| static inline uint64_t | |||
| rotl64(uint64_t x, int8_t r) | |||
| { | |||
|     return ((x<<r) | (x>>(64-r))); | |||
| } | |||
| #endif | |||
| 
 | |||
| static uint64_t | |||
| sylvan_storm_rational_function_hash(const uint64_t v, const uint64_t seed) | |||
| { | |||
|     /* Hash the storm::RationalFunction in pointer v */ | |||
|      | |||
| 	storm_rational_function_ptr x = (storm_rational_function_ptr)(size_t)v; | |||
| 
 | |||
| 	return storm_rational_function_hash(x, seed); | |||
| } | |||
| 
 | |||
| static int | |||
| sylvan_storm_rational_function_equals(const uint64_t left, const uint64_t right) | |||
| { | |||
|     /* This function is called by the unique table when comparing a new | |||
|        leaf with an existing leaf */ | |||
| 	storm_rational_function_ptr a = (storm_rational_function_ptr)(size_t)left; | |||
| 	storm_rational_function_ptr b = (storm_rational_function_ptr)(size_t)right; | |||
| 
 | |||
|     /* Just compare x and y */ | |||
|     return (storm_rational_function_equals(a, b) == 0) ? 1 : 0; | |||
| } | |||
| 
 | |||
| static void | |||
| sylvan_storm_rational_function_create(uint64_t *val) | |||
| { | |||
|     /* This function is called by the unique table when a leaf does not yet exist. | |||
|        We make a copy, which will be stored in the hash table. */ | |||
| 	storm_rational_function_ptr* x = (storm_rational_function_ptr*)(size_t)val; | |||
| 	storm_rational_function_init(x); | |||
| } | |||
| 
 | |||
| static void | |||
| sylvan_storm_rational_function_destroy(uint64_t val) | |||
| { | |||
|     /* This function is called by the unique table | |||
|        when a leaf is removed during garbage collection. */ | |||
| 	storm_rational_function_ptr x = (storm_rational_function_ptr)(size_t)val; | |||
| 	storm_rational_function_destroy(x); | |||
| } | |||
| 
 | |||
| static uint32_t sylvan_storm_rational_function_type; | |||
| static uint64_t CACHE_STORM_RATIONAL_FUNCTION_AND_EXISTS; | |||
| 
 | |||
| /** | |||
|  * Initialize storm::RationalFunction custom leaves | |||
|  */ | |||
| void | |||
| sylvan_storm_rational_function_init() | |||
| { | |||
|     /* Register custom leaf 3 */ | |||
|     sylvan_storm_rational_function_type = mtbdd_register_custom_leaf(sylvan_storm_rational_function_hash, sylvan_storm_rational_function_equals, sylvan_storm_rational_function_create, sylvan_storm_rational_function_destroy); | |||
| 	CACHE_STORM_RATIONAL_FUNCTION_AND_EXISTS = cache_next_opid(); | |||
| } | |||
| 
 | |||
| /** | |||
|  * Create storm::RationalFunction leaf | |||
|  */ | |||
| MTBDD | |||
| mtbdd_storm_rational_function(storm_rational_function_t val) | |||
| { | |||
|     return mtbdd_makeleaf(sylvan_storm_rational_function_type, (size_t)val); | |||
| } | |||
| 
 | |||
| /** | |||
|  * Operation "plus" for two storm::RationalFunction MTBDDs | |||
|  * Interpret partial function as "0" | |||
|  */ | |||
| TASK_IMPL_2(MTBDD, sylvan_storm_rational_function_op_plus, MTBDD*, pa, MTBDD*, pb) | |||
| { | |||
|     MTBDD a = *pa, b = *pb; | |||
| 
 | |||
|     /* Check for partial functions */ | |||
|     if (a == mtbdd_false) return b; | |||
|     if (b == mtbdd_false) return a; | |||
| 
 | |||
|     /* If both leaves, compute plus */ | |||
|     if (mtbdd_isleaf(a) && mtbdd_isleaf(b)) { | |||
| 		storm_rational_function_ptr ma = (storm_rational_function_ptr)mtbdd_getvalue(a); | |||
| 		storm_rational_function_ptr mb = (storm_rational_function_ptr)mtbdd_getvalue(b); | |||
| 
 | |||
| 		storm_rational_function_ptr mres = storm_rational_function_plus(ma, mb); | |||
|         MTBDD res = mtbdd_storm_rational_function(mres); | |||
|          | |||
| 		// TODO: Delete mres? | |||
| 
 | |||
|         return res; | |||
|     } | |||
| 
 | |||
|     /* Commutative, so swap a,b for better cache performance */ | |||
|     if (a < b) { | |||
|         *pa = b; | |||
|         *pb = a; | |||
|     } | |||
| 
 | |||
|     return mtbdd_invalid; | |||
| } | |||
| 
 | |||
| /** | |||
|  * Operation "minus" for two storm::RationalFunction MTBDDs | |||
|  * Interpret partial function as "0" | |||
|  */ | |||
| TASK_IMPL_2(MTBDD, sylvan_storm_rational_function_op_minus, MTBDD*, pa, MTBDD*, pb) | |||
| { | |||
|     MTBDD a = *pa, b = *pb; | |||
| 
 | |||
|     /* Check for partial functions */ | |||
|     if (a == mtbdd_false) return sylvan_storm_rational_function_neg(b); | |||
|     if (b == mtbdd_false) return a; | |||
| 
 | |||
|     /* If both leaves, compute plus */ | |||
|     if (mtbdd_isleaf(a) && mtbdd_isleaf(b)) { | |||
| 		storm_rational_function_ptr ma = (storm_rational_function_ptr)mtbdd_getvalue(a); | |||
| 		storm_rational_function_ptr mb = (storm_rational_function_ptr)mtbdd_getvalue(b); | |||
| 
 | |||
| 		storm_rational_function_ptr mres = storm_rational_function_minus(ma, mb); | |||
| 		MTBDD res = mtbdd_storm_rational_function(mres); | |||
| 
 | |||
| 		// TODO: Delete mres? | |||
| 
 | |||
|         return res; | |||
|     } | |||
| 
 | |||
|     return mtbdd_invalid; | |||
| } | |||
| 
 | |||
| /** | |||
|  * Operation "times" for two storm::RationalFunction MTBDDs. | |||
|  * One of the parameters can be a BDD, then it is interpreted as a filter. | |||
|  * For partial functions, domain is intersection | |||
|  */ | |||
| TASK_IMPL_2(MTBDD, sylvan_storm_rational_function_op_times, MTBDD*, pa, MTBDD*, pb) | |||
| { | |||
|     MTBDD a = *pa, b = *pb; | |||
| 
 | |||
|     /* Check for partial functions and for Boolean (filter) */ | |||
|     if (a == mtbdd_false || b == mtbdd_false) return mtbdd_false; | |||
| 
 | |||
|     /* If one of Boolean, interpret as filter */ | |||
|     if (a == mtbdd_true) return b; | |||
|     if (b == mtbdd_true) return a; | |||
| 
 | |||
|     /* Handle multiplication of leaves */ | |||
|     if (mtbdd_isleaf(a) && mtbdd_isleaf(b)) { | |||
| 		storm_rational_function_ptr ma = (storm_rational_function_ptr)mtbdd_getvalue(a); | |||
| 		storm_rational_function_ptr mb = (storm_rational_function_ptr)mtbdd_getvalue(b); | |||
| 
 | |||
| 		storm_rational_function_ptr mres = storm_rational_function_times(ma, mb); | |||
| 		MTBDD res = mtbdd_storm_rational_function(mres); | |||
| 
 | |||
| 		// TODO: Delete mres? | |||
| 
 | |||
|         return res; | |||
|     } | |||
| 
 | |||
|     /* Commutative, so make "a" the lowest for better cache performance */ | |||
|     if (a < b) { | |||
|         *pa = b; | |||
|         *pb = a; | |||
|     } | |||
| 
 | |||
|     return mtbdd_invalid; | |||
| } | |||
| 
 | |||
| /** | |||
|  * Operation "divide" for two storm::RationalFunction MTBDDs. | |||
|  * For partial functions, domain is intersection | |||
|  */ | |||
| TASK_IMPL_2(MTBDD, sylvan_storm_rational_function_op_divide, MTBDD*, pa, MTBDD*, pb) | |||
| { | |||
|     MTBDD a = *pa, b = *pb; | |||
| 
 | |||
|     /* Check for partial functions */ | |||
|     if (a == mtbdd_false || b == mtbdd_false) return mtbdd_false; | |||
| 
 | |||
|     /* Handle division of leaves */ | |||
|     if (mtbdd_isleaf(a) && mtbdd_isleaf(b)) { | |||
| 		storm_rational_function_ptr ma = (storm_rational_function_ptr)mtbdd_getvalue(a); | |||
| 		storm_rational_function_ptr mb = (storm_rational_function_ptr)mtbdd_getvalue(b); | |||
| 
 | |||
| 		storm_rational_function_ptr mres = storm_rational_function_divide(ma, mb); | |||
| 		MTBDD res = mtbdd_storm_rational_function(mres); | |||
| 
 | |||
| 		// TODO: Delete mres? | |||
| 
 | |||
|         return res; | |||
|     } | |||
| 
 | |||
|     return mtbdd_invalid; | |||
| } | |||
| 
 | |||
| /** | |||
|  * Operation "neg" for one storm::RationalFunction MTBDD | |||
|  */ | |||
| TASK_IMPL_2(MTBDD, sylvan_storm_rational_function_op_neg, MTBDD, dd, size_t, p) | |||
| { | |||
|     /* Handle partial functions */ | |||
|     if (dd == mtbdd_false) return mtbdd_false; | |||
| 
 | |||
|     /* Compute result for leaf */ | |||
|     if (mtbdd_isleaf(dd)) { | |||
| 		storm_rational_function_ptr mdd = (storm_rational_function_ptr)mtbdd_getvalue(dd); | |||
| 
 | |||
| 		storm_rational_function_ptr mres = storm_rational_function_negate(mdd); | |||
| 		MTBDD res = mtbdd_storm_rational_function(mres); | |||
| 
 | |||
| 		// TODO: Delete mres? | |||
|         return res; | |||
|     } | |||
| 
 | |||
|     return mtbdd_invalid; | |||
|     (void)p; | |||
| } | |||
| @ -0,0 +1,87 @@ | |||
| /** | |||
|  * This is an implementation of storm::RationalFunction custom leaves of MTBDDs | |||
|  */ | |||
| 
 | |||
| #ifndef SYLVAN_STORM_RATIONAL_FUNCTION_H | |||
| #define SYLVAN_STORM_RATIONAL_FUNCTION_H | |||
| 
 | |||
| #include <sylvan.h> | |||
| #include <storm_function_wrapper.h> | |||
| 
 | |||
| #define SYLVAN_HAVE_CARL 1 | |||
| 
 | |||
| #ifdef SYLVAN_HAVE_CARL | |||
| 
 | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif /* __cplusplus */ | |||
| 
 | |||
| /** | |||
|  * Initialize storm::RationalFunction custom leaves | |||
|  */ | |||
| void sylvan_storm_rational_function_init(); | |||
| 
 | |||
| /** | |||
|  * Create storm::RationalFunction leaf | |||
|  */ | |||
| MTBDD mtbdd_storm_rational_function(storm_rational_function_t val); | |||
| 
 | |||
| /** | |||
|  * Operation "plus" for two storm::RationalFunction MTBDDs | |||
|  */ | |||
| TASK_DECL_2(MTBDD, sylvan_storm_rational_function_op_plus, MTBDD*, MTBDD*); | |||
| TASK_DECL_3(MTBDD, sylvan_storm_rational_function_abstract_op_plus, MTBDD, MTBDD, int); | |||
| 
 | |||
| /** | |||
|  * Operation "minus" for two storm::RationalFunction MTBDDs | |||
|  */ | |||
| TASK_DECL_2(MTBDD, sylvan_storm_rational_function_op_minus, MTBDD*, MTBDD*); | |||
| 
 | |||
| /** | |||
|  * Operation "times" for two storm::RationalFunction MTBDDs | |||
|  */ | |||
| TASK_DECL_2(MTBDD, sylvan_storm_rational_function_op_times, MTBDD*, MTBDD*); | |||
| TASK_DECL_3(MTBDD, sylvan_storm_rational_function_abstract_op_times, MTBDD, MTBDD, int); | |||
| 
 | |||
| /** | |||
|  * Operation "divide" for two storm::RationalFunction MTBDDs | |||
|  */ | |||
| TASK_DECL_2(MTBDD, sylvan_storm_rational_function_op_divide, MTBDD*, MTBDD*); | |||
| 
 | |||
| /** | |||
|  * Operation "negate" for one storm::RationalFunction MTBDD | |||
|  */ | |||
| TASK_DECL_2(MTBDD, sylvan_storm_rational_function_op_neg, MTBDD, size_t); | |||
| 
 | |||
| /** | |||
|  * Compute a + b | |||
|  */ | |||
| #define sylvan_storm_rational_function_plus(a, b) mtbdd_apply(a, b, TASK(sylvan_storm_rational_function_op_plus)) | |||
| 
 | |||
| /** | |||
|  * Compute a - b | |||
|  */ | |||
| #define sylvan_storm_rational_function_minus(a, b) mtbdd_apply(a, b, TASK(sylvan_storm_rational_function_op_minus)) | |||
| 
 | |||
| /** | |||
|  * Compute a * b | |||
|  */ | |||
| #define sylvan_storm_rational_function_times(a, b) mtbdd_apply(a, b, TASK(sylvan_storm_rational_function_op_times)) | |||
| 
 | |||
| /** | |||
|  * Compute a / b | |||
|  */ | |||
| #define sylvan_storm_rational_function_divide(a, b) mtbdd_apply(a, b, TASK(sylvan_storm_rational_function_op_divide)) | |||
| 
 | |||
| /** | |||
|  * Compute -a | |||
|  */ | |||
| #define sylvan_storm_rational_function_neg(a) mtbdd_uapply(a, TASK(sylvan_storm_rational_function_op_neg), 0); | |||
| 
 | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif /* __cplusplus */ | |||
| 
 | |||
| #endif // SYLVAN_HAVE_CARL | |||
| 
 | |||
| #endif // SYLVAN_STORM_RATIONAL_FUNCTION_H | |||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue