Design a method to select predicate branches based on exploration counts
authorweiyu <weiyuluo1232@gmail.com>
Fri, 11 Oct 2019 00:33:57 +0000 (17:33 -0700)
committerweiyu <weiyuluo1232@gmail.com>
Fri, 11 Oct 2019 00:33:57 +0000 (17:33 -0700)
funcinst.cc
funcinst.h
funcnode.cc
history.cc
newfuzzer.cc
newfuzzer.h
predicate.cc
predicate.h

index 4fcf0e7..44bb167 100644 (file)
@@ -4,7 +4,7 @@
 FuncInst::FuncInst(ModelAction *act, FuncNode *func_node) :
        single_location(true),
        execution_number(model->get_execution_number()),
-       marker(0)       /* The marker for FuncNode starts from 1 */
+       action_marker(0)        /* The marker for FuncNode starts from 1 */
 {
        ASSERT(act);
        ASSERT(func_node);
@@ -50,12 +50,12 @@ bool FuncInst::add_succ(FuncInst * other)
 void FuncInst::set_associated_act(ModelAction * act, uint32_t marker)
 {
        associated_act = act;
-       this->marker = marker;
+       action_marker = marker;
 }
 
 ModelAction * FuncInst::get_associated_act(uint32_t marker)
 {
-       if (marker == this->marker)
+       if (action_marker == marker)
                return associated_act;
        else
                return NULL;
index fe4adb4..98af6bc 100644 (file)
@@ -65,7 +65,7 @@ private:
        int execution_number;
 
        ModelAction * associated_act;
-       uint32_t marker;
+       uint32_t action_marker;
 
        /* Currently not in use. May remove this field later
         *
index 05974d7..75cb0cb 100644 (file)
@@ -306,6 +306,7 @@ void FuncNode::update_predicate_tree(action_list_t * act_list)
                        inst_id_map.put(next_inst, inst_counter++);
 
                it = it->getNext();
+               curr_pred->incr_count();
        }
 }
 
index 4fde914..34ec080 100644 (file)
@@ -341,7 +341,7 @@ void ModelHistory::check_waiting_write(ModelAction * write_act)
                /* Check if the written value satisfies every predicate expression */
                for (uint i = 0; i < concrete_exprs->size(); i++) {
                        struct concrete_pred_expr concrete = (*concrete_exprs)[i];
-                       bool equality;
+                       bool equality = false;
                        switch (concrete.token) {
                                case EQUALITY:
                                        equality = (value == concrete.value);
index 4863d47..e290db4 100644 (file)
@@ -77,6 +77,7 @@ int NewFuzzer::selectWrite(ModelAction *read, SnapVector<ModelAction *> * rf_set
                        return -1;
                } else {
                        Predicate * selected_branch = get_selected_child_branch(tid);
+//                     selected_branch->incr_count();
                        failed_predicates.put(selected_branch, true);
 
                        SnapVector<ModelAction *> * pruned_writes = thrd_pruned_writes[thread_id];
@@ -119,11 +120,16 @@ Predicate * NewFuzzer::selectBranch(thread_id_t tid, Predicate * curr_pred, Func
 
        ModelVector<Predicate *> * children = curr_pred->get_children();
        SnapVector<Predicate *> branches;
+       uint32_t numerator = 1;
 
        for (uint i = 0; i < children->size(); i++) {
                Predicate * child = (*children)[i];
                if (child->get_func_inst() == read_inst && !failed_predicates.contains(child)) {
                        branches.push_back(child);
+
+                       // max of (exploration counts + 1)
+                       if (child->get_count() + 1 > numerator)
+                               numerator = child->get_count() + 1;
                }
        }
 
@@ -134,13 +140,61 @@ Predicate * NewFuzzer::selectBranch(thread_id_t tid, Predicate * curr_pred, Func
        }
 
        // randomly select a branch
-       int random_index = random() % branches.size();
-       Predicate * random_branch = branches[ random_index ];
+       // int random_index = random() % branches.size();
+       // Predicate * random_branch = branches[ random_index ];
+
+       int index = choose_index(&branches, numerator);
+       Predicate * random_branch = branches[ index ];
        thrd_selected_child_branch[thread_id] = random_branch;
 
        return random_branch;
 }
 
+/**
+ * @brief Select a branch from the given predicate branches based
+ * on their exploration counts.
+ *
+ * Let b_1, ..., b_n be branches with exploration counts c_1, ..., c_n
+ * M := max(c_1, ..., c_n) + 1
+ * Factor f_i := M / (c_i + 1)
+ * The probability p_i that branch b_i is selected:
+ *     p_i := f_i / (f_1 + ... + f_n)
+ *          = \fraction{ 1/(c_i + 1) }{ 1/(c_1 + 1) + ... + 1/(c_n + 1) }
+ *
+ * Note: (1) c_i + 1 is used because counts may be 0.
+ *      (2) The numerator of f_i is chosen to reduce the effect of underflow
+ *     
+ * @param numerator is M defined above
+ */
+int NewFuzzer::choose_index(SnapVector<Predicate *> * branches, uint32_t numerator)
+{
+       if (branches->size() == 1)
+               return 0;
+
+       double total_factor = 0;
+       SnapVector<double> factors = SnapVector<double>( branches->size() );
+       for (uint i = 0; i < branches->size(); i++) {
+               Predicate * branch = (*branches)[i];
+               double factor = (double) numerator / (branch->get_count() + 1);
+               total_factor += factor;
+               factors[i] = factor;
+       }
+
+       double prob = (double) random() / RAND_MAX;
+       double prob_sum = 0;
+       int index = 0;
+
+       for (uint i = 0; i < factors.size(); i++) {
+               prob_sum += (double) factors[i] / total_factor;
+               if (prob_sum > prob) {
+                       index = i;
+                       break;
+               }
+       }
+
+       return index;
+}
+
 Predicate * NewFuzzer::get_selected_child_branch(thread_id_t tid)
 {
        int thread_id = id_to_int(tid);
index d1037a6..a4699bd 100644 (file)
@@ -35,6 +35,7 @@ private:
 
        bool prune_writes(thread_id_t tid, Predicate * pred, SnapVector<ModelAction *> * rf_set, inst_act_map_t * inst_act_map);
        Predicate * selectBranch(thread_id_t tid, Predicate * curr_pred, FuncInst * read_inst);
+       int choose_index(SnapVector<Predicate *> * branches, uint32_t numerator);
 
        /* The set of Threads put to sleep by NewFuzzer because no writes in rf_set satisfies the selected predicate. Only used by selectWrite.
         */
index 9e2f162..a64737e 100644 (file)
@@ -6,6 +6,7 @@ Predicate::Predicate(FuncInst * func_inst, bool is_entry) :
        func_inst(func_inst),
        entry_predicate(is_entry),
        does_write(false),
+       exploration_count(0),
        pred_expressions(16),
        children(),
        parent(NULL),
@@ -129,6 +130,7 @@ void Predicate::print_predicate()
        if (does_write) {
                model_print("Does write\n");
        }
+       model_print("Count: %d\n", exploration_count);
        model_print("\"];\n");
 }
 
index 4c26a9d..b85eab0 100644 (file)
@@ -37,6 +37,9 @@ public:
 
        ConcretePredicate * evaluate(inst_act_map_t * inst_act_map, thread_id_t tid);
 
+       uint32_t get_count() { return exploration_count; }
+       void incr_count() { exploration_count++; }
+
        void print_predicate();
        void print_pred_subtree();
 
@@ -45,6 +48,7 @@ private:
        FuncInst * func_inst;
        bool entry_predicate;
        bool does_write;
+       uint32_t exploration_count;
 
        /* May have multiple predicate expressions */
        PredExprSet pred_expressions;