diff --git a/src/storage/ppg/ProgramAction.cpp b/src/storage/ppg/ProgramAction.cpp
new file mode 100644
index 000000000..9f3d8a66f
--- /dev/null
+++ b/src/storage/ppg/ProgramAction.cpp
@@ -0,0 +1,15 @@
+#include "ProgramAction.h"
+#include "ProgramGraph.h"
+
+namespace storm {
+    namespace ppg {
+        
+        ProbabilisticProgramAction::ProbabilisticProgramAction(ProgramGraph* graph, ProgramActionIdentifier actId, int64_t from, int64_t to) : ProgramAction(graph, actId) {
+            assert(from <= to);
+            storm::expressions::Expression prob = graph->getExpressionManager()->integer(1) / graph->getExpressionManager()->integer(to - from + 1);
+            for(int64_t i = from; i <= to; ++i) {
+                values.emplace_back(i, prob);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/storage/ppg/ProgramAction.h b/src/storage/ppg/ProgramAction.h
new file mode 100644
index 000000000..5b44030ff
--- /dev/null
+++ b/src/storage/ppg/ProgramAction.h
@@ -0,0 +1,158 @@
+#pragma once
+#include "defines.h"
+#include "src/storage/expressions/Expression.h"
+#include "src/storage/expressions/Variable.h"
+#include "src/storage/expressions/ExpressionManager.h"
+
+namespace storm {
+    namespace ppg {
+        
+        class ProgramAction {
+        public:
+            ProgramAction(ProgramGraph* graph, ProgramActionIdentifier id) : graph(graph), actId(id) {
+                
+            }
+            
+            ProgramActionIdentifier id() const {
+                return actId;
+            }
+            
+            ProgramGraph const& getProgramGraph() const {
+                return *graph;
+            }
+            
+            virtual bool isProbabilistic() const = 0;
+        private:
+            ProgramGraph* graph;
+            ProgramActionIdentifier actId;
+        };
+        
+        
+        struct ValueProbabilityPair {
+            ValueProbabilityPair(int64_t value, storm::expressions::Expression const& probability) : value(value), probability(probability) {
+                // Intentionally left empty.
+            }
+            
+            int64_t value;
+            storm::expressions::Expression probability;
+        };
+        
+        class ProbabilisticProgramAction : public ProgramAction {
+        public:
+            // TODO in the long run, we probably need own iterators for this.
+            using iterator = std::vector<ValueProbabilityPair>::iterator;
+            using const_iterator = std::vector<ValueProbabilityPair>::const_iterator;
+            
+            
+            
+            /**
+             * Constructs a uniform assignment operation to a variable;
+             * Action assigns a variable according to a uniform distribution [from, to]
+             */
+            ProbabilisticProgramAction(ProgramGraph* graph, ProgramActionIdentifier actId, int64_t from, int64_t to);
+            
+            bool isProbabilistic() const override{
+                return true;
+            }
+            
+            iterator begin() {
+                return values.begin();
+            }
+            
+            iterator end() {
+                return values.end();
+            }
+            
+            const_iterator begin() const {
+                return values.begin();
+            }
+            
+            const_iterator end() const {
+                return values.end();
+            }
+            
+        private:
+            // TODO not the smartest representation (but at least it is internal!)
+            std::vector<ValueProbabilityPair> values;
+            
+        };
+        
+        
+        struct AssignmentGroup {
+            using iterator = std::unordered_map<uint64_t, storm::expressions::Expression>::iterator;
+            using const_iterator = std::unordered_map<uint64_t, storm::expressions::Expression>::const_iterator;
+            
+            storm::expressions::Expression& operator[](uint64_t varIndex) {
+                return map[varIndex];
+            }
+            
+            bool hasVariable(uint64_t varIndex) const {
+                return map.count(varIndex) > 0;
+            }
+            
+            iterator begin() {
+                return map.begin();
+            }
+            
+            iterator end() {
+                return map.end();
+            }
+            
+            const_iterator begin() const {
+                return map.begin();
+            }
+            
+            const_iterator end() const {
+                return map.end();
+            }
+            
+        private:
+            std::unordered_map<uint64_t, storm::expressions::Expression> map;
+        };
+        
+        class DeterministicProgramAction : public ProgramAction {
+            
+        public:
+            using iterator = std::vector<AssignmentGroup>::iterator;
+            using const_iterator = std::vector<AssignmentGroup>::const_iterator;
+            
+            DeterministicProgramAction(ProgramGraph* graph, ProgramActionIdentifier actId) : ProgramAction(graph, actId) {
+                
+            }
+            
+            
+            
+            void addAssignment(uint64_t varIndex, storm::expressions::Expression const& expr, uint64_t level=0) {
+                if(assignments.size() <= level) {
+                    assignments.resize(level+1);
+                }
+                assert(!assignments[level].hasVariable(varIndex));
+                assignments[level][varIndex] = expr;
+            }
+            
+            iterator begin() {
+                return assignments.begin();
+            }
+            
+            iterator end() {
+                return assignments.end();
+            }
+            
+            const_iterator begin() const {
+                return assignments.begin();
+            }
+            
+            const_iterator end() const {
+                return assignments.end();
+            }
+            
+            bool isProbabilistic() const override{
+                return false;
+            }
+            
+        protected:
+            std::vector<AssignmentGroup> assignments;
+        };
+        
+    }
+}
\ No newline at end of file
diff --git a/src/storage/ppg/ProgramEdge.cpp b/src/storage/ppg/ProgramEdge.cpp
index 608da964d..4b5647d34 100644
--- a/src/storage/ppg/ProgramEdge.cpp
+++ b/src/storage/ppg/ProgramEdge.cpp
@@ -1,9 +1,11 @@
-//
-//  ProgramEdge.cpp
-//  storm
-//
-//  Created by Sebastian Junges on 09/09/16.
-//
-//
-
 #include "ProgramEdge.h"
+#include "ProgramGraph.h"
+
+namespace storm {
+    namespace ppg {
+        
+        ProgramAction const& ProgramEdge::getAction() const {
+            return group->getGraph().getAction(action);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/storage/ppg/ProgramEdge.h b/src/storage/ppg/ProgramEdge.h
index fa9d3b3db..0cbef21a9 100644
--- a/src/storage/ppg/ProgramEdge.h
+++ b/src/storage/ppg/ProgramEdge.h
@@ -5,6 +5,8 @@
 
 namespace storm {
     namespace ppg {
+        class ProgramAction;
+        
         class ProgramEdge {
         public:
             ProgramEdge(ProgramEdgeGroup* group, ProgramEdgeIdentifier id, ProgramActionIdentifier action, storm::expressions::Expression const& condition, ProgramLocationIdentifier targetId)
@@ -13,6 +15,17 @@ namespace storm {
                 // Intentionally left empty.
             }
             
+            
+            ProgramLocationIdentifier getTargetId() const {
+                return target;
+            }
+            
+            storm::expressions::Expression const& getCondition() const {
+                return condition;
+            }
+            
+            ProgramAction const& getAction() const;
+            
             virtual ~ProgramEdge() {
                 // Intentionally left empty.
             }
diff --git a/src/storage/ppg/ProgramEdgeGroup.h b/src/storage/ppg/ProgramEdgeGroup.h
index 0c215de31..9736c658f 100644
--- a/src/storage/ppg/ProgramEdgeGroup.h
+++ b/src/storage/ppg/ProgramEdgeGroup.h
@@ -8,6 +8,8 @@ namespace storm {
         
         class ProgramEdgeGroup {
         public:
+            using const_iterator = std::vector<ProgramEdge*>::const_iterator;
+            
             ProgramEdgeGroup(ProgramGraph* graph, ProgramEdgeGroupIdentifier id, ProgramLocationIdentifier sourceId, storm::expressions::Expression const& probability)
             : graph(graph), groupId(id), sourceId(sourceId), probability(probability)
             {
@@ -31,6 +33,26 @@ namespace storm {
                 return edges.back();
             }
             
+            const_iterator begin() const {
+                return edges.begin();
+            }
+            
+            const_iterator end() const {
+                return edges.end();
+            }
+            
+            size_t nrEdges() const {
+                return edges.size();
+            }
+            
+            storm::expressions::Expression const& getProbability() const {
+                return probability;
+            }
+            
+            ProgramGraph const& getGraph() const {
+                return *graph;
+            }
+            
         private:
             /// Pointer to the graph; not owned.
             ProgramGraph* graph;
diff --git a/src/storage/ppg/ProgramGraph.h b/src/storage/ppg/ProgramGraph.h
index 0dec3e610..7dc505298 100644
--- a/src/storage/ppg/ProgramGraph.h
+++ b/src/storage/ppg/ProgramGraph.h
@@ -8,19 +8,10 @@
 #include "ProgramLocation.h"
 #include "ProgramEdge.h"
 #include "ProgramEdgeGroup.h"
+#include "ProgramAction.h"
 
 namespace storm {
     namespace ppg {
-        struct ProgramAction {
-            ProgramAction(ProgramGraph* graph, ProgramActionIdentifier actId) : graph(graph), actId(actId) {
-                
-            }
-            
-            ProgramGraph* graph;
-            ProgramActionIdentifier actId;
-        };
-        
-         
         /**
          *  Program graph as based on Principles of Model Checking, Def 2.13
          *  Action effects are part of the action.
@@ -34,15 +25,15 @@ namespace storm {
                 
             }
             
+            ProgramGraph(ProgramGraph const&) = delete;
+            
             virtual ~ProgramGraph() {
-                std::cout << "remove graph" << std::endl;
             }
             
-            ProgramActionIdentifier addAction() {
+            DeterministicProgramAction* addDeterministicAction() {
                 ProgramActionIdentifier newId = freeActionIndex();
                 assert(!hasAction(newId));
-                actions.emplace(newId, ProgramAction(this, newId));
-                return newId;
+                return &(deterministicActions.emplace(newId, DeterministicProgramAction(this, newId)).first->second);
             }
             
             ProgramLocation* addLocation(bool isInitial = false) {
@@ -101,12 +92,51 @@ namespace storm {
             }
 
             
+            ProgramVariableIdentifier getVariableId(std::string const& varName) const {
+                // TODO consider holding a map for this.
+                uint64_t res = 0;
+                for(auto const& v : variables) {
+                    if(v.getName() == varName) {
+                        return res;
+                    }
+                    ++res;
+                }
+                assert(false);
+            }
+            
+            std::string const& getVariableName(ProgramVariableIdentifier id) const {
+                return variables.at(id).getName();
+            }
+            
+            bool hasVariable(std::string const& varName) const {
+                for(auto const& v : variables) {
+                    if(v.getName() == varName) {
+                        return true;
+                    }
+                }
+                return false;
+            }
+            
             bool hasLocation(ProgramLocationIdentifier id) const {
                 return locations.count(id) == 1;
             }
             
             bool hasAction(ProgramActionIdentifier id) const {
-                return actions.count(id) == 1;
+                return deterministicActions.count(id) == 1 || probabilisticActions.count(id);
+            }
+            
+            ProgramAction const& getAction(ProgramActionIdentifier id) const {
+                assert(hasAction(id));
+                if(isDeterministicAction(id)) {
+                    return deterministicActions.at(id);
+                } else {
+                    return probabilisticActions.at(id);
+                }
+            }
+            
+            bool isDeterministicAction(ProgramActionIdentifier id) const {
+                assert(hasAction(id));
+                return probabilisticActions.count(id) == 0;
             }
             
             size_t nrLocations() const {
@@ -117,6 +147,10 @@ namespace storm {
                 return variables.size();
             }
             
+            size_t nrActions() const {
+                return variables.size();
+            }
+            
             
             ConstLocationIterator locationBegin() const {
                 return locations.begin();
@@ -141,6 +175,7 @@ namespace storm {
             void printInfo(std::ostream& os) const {
                 os << "Number of variables: " << nrVariables() << std::endl;
                 os << "Number of locations: " << nrLocations() << std::endl;
+                os << "Number of actions: " << nrActions() << std::endl;
             }
             
         protected:
@@ -168,7 +203,8 @@ namespace storm {
                 return newEdgeGroupId++;
             }
             
-            std::unordered_map<ProgramActionIdentifier, ProgramAction> actions;
+            std::unordered_map<ProgramActionIdentifier, DeterministicProgramAction> deterministicActions;
+            std::unordered_map<ProgramActionIdentifier, ProbabilisticProgramAction> probabilisticActions;
             std::unordered_map<ProgramLocationIdentifier, ProgramLocation> locations;
             storm::expressions::Expression initialValueRestriction;
             std::vector<storm::expressions::Variable> variables;
diff --git a/src/storage/ppg/ProgramLocation.h b/src/storage/ppg/ProgramLocation.h
index 8efde84c8..e88f0e85d 100644
--- a/src/storage/ppg/ProgramLocation.h
+++ b/src/storage/ppg/ProgramLocation.h
@@ -8,6 +8,7 @@ namespace storm {
         class ProgramLocation {
         public:
             using EdgeGroupIterator = std::vector<ProgramEdgeGroup*>::iterator;
+            using const_iterator = std::vector<ProgramEdgeGroup*>::const_iterator;
             
             ProgramLocation(ProgramGraph* graph, ProgramLocationIdentifier id, bool initial) : graph(graph), locId(id), init(initial){
                 // Intentionally left empty
@@ -38,10 +39,27 @@ namespace storm {
                 return edgeGroups.size();
             }
             
+            bool hasNonDeterminism() const {
+                for(auto const& eg : edgeGroups) {
+                    if(eg->nrEdges() > 1) return true;
+                }
+                return false;
+            }
+            
+            const_iterator begin() const {
+                return edgeGroups.begin();
+            }
+            
+            const_iterator end() const {
+                return edgeGroups.end();
+            }
+            
+            // Todo rename?
             EdgeGroupIterator getOutgoingEdgeGroupBegin() {
                 return edgeGroups.begin();
             }
             
+            // Todo rename?
             EdgeGroupIterator getOutgoingEdgeGroupEnd() {
                 return edgeGroups.end();
             }
diff --git a/src/storage/ppg/defines.h b/src/storage/ppg/defines.h
index 6f64e9cfe..548160ba9 100644
--- a/src/storage/ppg/defines.h
+++ b/src/storage/ppg/defines.h
@@ -10,6 +10,7 @@ namespace storm {
         using ProgramActionIdentifier = uint64_t;
         using ProgramEdgeGroupIdentifier =  uint64_t;
         using ProgramEdgeIdentifier = uint64_t;
+        using ProgramVariableIdentifier = uint64_t;
         
     }
 }
\ No newline at end of file