The Ronseal Anti Condensation Paint adds a layer of insulation to help prevent condensation which leads to mould. Once it’s dry that’s it, job done. Unless you want to add some colour. Then you can paint over it any colour your want. I...

Set of 3 bristle paint brushes that are the perfect size for cutting in, skirtings and door and window frames. Theyre easy to clean, with no loss of bristles and split bristle tips for a smooth and even finish. Theres also a comfort rubber grip and handy paint tin opening tool on the end. Comprises a 1.5, 2 and unique 1 triangular brush.

Plastikote Super Spray Paints 400ml - PlastiKote 440.0011107.076, This white super spray paint from Plastikote is an excellent multi-purpose spray paint which is tough, hard wearing and resistant to scratches. The spray paint is very UV absorbent, water resistant, and will not fade or yellow, while protecting against rust and is fast-drying. Suitable for any decorative project inside or outside of

When its hot, you need comfort - and thats what the Beach Slide sandal is all about. Sleek in its monoblock design, with no lines visible at all when wearing it, and with a luxuriously cushioned footbed. Here in a very cool White Matt.

Dulux Paint Matt 2.5L White Cotton on USA sites

Create Paint is a waterborne urethane based whiteboard/ dry erase paint that transforms normal surfaces into creative surfaces. Create Paint is best applied using a standard paint roller and paint tray. Colors/finish: White Materials: There are 2 components: C and P Mixing: Add P to C and mix vigorously in the C container for 90 seconds to 3 minutes until a workable viscosity is achieved

The DeLonghi ICMI211.BK Distinta Filter Coffee Maker in Matt White is a sophisticated coffee machine with sleek lines and chromed details that will add a stylish look to any kitchen or office. The 1.25L capacity will produce 10 cups of filter coffee in one time. The Distincta features a permanent filter, a premium glass carafe and keep warm plate with an Eco function that will turn off

Uppercut matt clay pomade. This product is an all round knock out. It grips and slicks short or long hair and effortlessly shapes just about any style. Its almost too easy. Best used to create short textured looks, or longer sweeping styles where ultimate control and precision are required. Imported. Hold - Strong but reworkable Finish - Dry, matt look Style Guide - Perfect for controlling

If your little puddle-hunter is after something a little more understated then these rain boot wellies will fit the bill. Built from hardwearing rubber that has a matt finish and complete with an embossed Joules logo to the front.

\Dual thermostats regulate the temperature in this unique Thermal pet bed. The heater keeps the surface temperature of the bed approximately 12 to 15 degrees above ambient air temperature. When the pet lies down it warms to a comfortable 102 degrees . The heater easily removes for washing, which makes the bed useable year round. UL and CUL listed. This bed is recommended for indoor use. A great


#include "moar.h"

/* This representation's function pointer table. */
static const MVMREPROps CUnion_this_repr;

/* Locates all of the attributes. Puts them onto a flattened, ordered
 * list of attributes (populating the passed flat_list). Also builds
 * the index mapping for doing named lookups. Note index is not related
 * to the storage position. */
static MVMObject * index_mapping_and_flat_list(MVMThreadContext *tc, MVMObject *mro, MVMCUnionREPRData *repr_data) {
    MVMInstance *instance  = tc->instance;
    MVMObject *flat_list, *class_list, *attr_map_list;
    MVMint32  num_classes, i, current_slot = 0;
    MVMCUnionNameMap *result;

    MVMint32 mro_idx = MVM_repr_elems(tc, mro);
    flat_list = MVM_repr_alloc_init(tc, MVM_hll_current(tc)->slurpy_array_type);
    class_list = MVM_repr_alloc_init(tc, MVM_hll_current(tc)->slurpy_array_type);
    attr_map_list = MVM_repr_alloc_init(tc, MVM_hll_current(tc)->slurpy_array_type);

    /* Walk through the parents list. */
    while (mro_idx)
    {
        /* Get current class in MRO. */
        MVMObject *type_info     = MVM_repr_at_pos_o(tc, mro, --mro_idx);
        MVMObject *current_class = MVM_repr_at_pos_o(tc, type_info, 0);

        /* Get its local parents; make sure we're not doing MI. */
        MVMObject *parents     = MVM_repr_at_pos_o(tc, type_info, 2);
        MVMint32  num_parents = MVM_repr_elems(tc, parents);
        if (num_parents <= 1) {
            /* Get attributes and iterate over them. */
            MVMObject *attributes     = MVM_repr_at_pos_o(tc, type_info, 1);
            MVMIter * const attr_iter = (MVMIter *)MVM_iter(tc, attributes);
            MVMObject *attr_map = NULL;

            if (MVM_iter_istrue(tc, attr_iter))
                attr_map = MVM_repr_alloc_init(tc, MVM_hll_current(tc)->slurpy_hash_type);

            while (MVM_iter_istrue(tc, attr_iter)) {
                MVMObject *current_slot_obj = MVM_repr_box_int(tc, MVM_hll_current(tc)->int_box_type, current_slot);
                MVMObject *attr, *name_obj;
                MVMString *name;

                MVM_repr_shift_o(tc, (MVMObject *)attr_iter);

                /* Get attribute. */
                attr = MVM_iterval(tc, attr_iter);

                /* Get its name. */
                name_obj = MVM_repr_at_key_o(tc, attr, instance->str_consts.name);
                name     = MVM_repr_get_str(tc, name_obj);

                MVM_repr_bind_key_o(tc, attr_map, name, current_slot_obj);

                current_slot++;

                /* Push attr onto the flat list. */
                MVM_repr_push_o(tc, flat_list, attr);
            }

            /* Add to class list and map list. */
            MVM_repr_push_o(tc, class_list, current_class);
            MVM_repr_push_o(tc, attr_map_list, attr_map);
        }
        else {
            MVM_gc_allocate_gen2_default_clear(tc);
            MVM_exception_throw_adhoc(tc,
                "CUnion representation does not support multiple inheritance");
        }
    }

    /* We can now form the name map. */
    num_classes = MVM_repr_elems(tc, class_list);
    result = (MVMCUnionNameMap *) MVM_malloc(sizeof(MVMCUnionNameMap) * (1 + num_classes));

    for (i = 0; i < num_classes; i++) {
        result[i].class_key = MVM_repr_at_pos_o(tc, class_list, i);
        result[i].name_map  = MVM_repr_at_pos_o(tc, attr_map_list, i);
    }

    /* set the end to be NULL, it's useful for iteration. */
    result[i].class_key = NULL;

    repr_data->name_to_index_mapping = result;

    return flat_list;
}

/* This works out an allocation strategy for the object. It takes care of
 * "inlining" storage of attributes that are natively typed, as well as
 * noting unbox targets. */
static void compute_allocation_strategy(MVMThreadContext *tc, MVMObject *repr_info, MVMCUnionREPRData *repr_data) {
    /* Compute index mapping table and get flat list of attributes. */
    MVMObject *flat_list = index_mapping_and_flat_list(tc, repr_info, repr_data);

    /* If we have no attributes in the index mapping, then just the header. */
    if (repr_data->name_to_index_mapping[0].class_key == NULL) {
        repr_data->struct_size = 1; /* avoid 0-byte malloc */
        repr_data->struct_align = ALIGNOF(void *);
    }

    /* Otherwise, we need to compute the allocation strategy.  */
    else {
        /* The structure itself will as big as the biggest element.
         * So we keep track of that biggest element. */
        MVMint32 total_size = 0;

        /* Get number of attributes and set up various counters. */
        MVMint32 num_attrs        = MVM_repr_elems(tc, flat_list);
        MVMint32 info_alloc       = num_attrs == 0 ? 1 : num_attrs;
        MVMint32 cur_obj_attr     = 0;
        MVMint32 cur_init_slot    = 0;
        MVMint32 i;

        /* Allocate location/offset arrays and GC mark info arrays. */
        repr_data->num_attributes      = num_attrs;
        repr_data->attribute_locations = (MVMint32 *)   MVM_malloc(info_alloc * sizeof(MVMint32));
        repr_data->struct_offsets      = (MVMint32 *)   MVM_malloc(info_alloc * sizeof(MVMint32));
        repr_data->flattened_stables   = (MVMSTable **) MVM_calloc(info_alloc, sizeof(MVMObject *));
        repr_data->member_types        = (MVMObject **) MVM_calloc(info_alloc, sizeof(MVMObject *));
        repr_data->struct_align        = 0;

        /* Go over the attributes and arrange their allocation. */
        for (i = 0; i < num_attrs; i++) {
            /* Fetch its type; see if it's some kind of unboxed type. */
            MVMObject *attr  = MVM_repr_at_pos_o(tc, flat_list, i);
            MVMObject *type  = MVM_repr_at_key_o(tc, attr, tc->instance->str_consts.type);
            MVMObject *inlined_val = MVM_repr_at_key_o(tc, attr, tc->instance->str_consts.inlined);
            MVMint64 inlined = !MVM_is_null(tc, inlined_val) && MVM_repr_get_int(tc, inlined_val);
            MVMint32   bits  = sizeof(void *) * 8;
            MVMint32   align = ALIGNOF(void *);

            if (!MVM_is_null(tc, type)) {
                /* See if it's a type that we know how to handle in a C struct. */
                const MVMStorageSpec *spec = REPR(type)->get_storage_spec(tc, STABLE(type));
                MVMint32  type_id    = REPR(type)->ID;
                if (spec->inlineable == MVM_STORAGE_SPEC_INLINED &&
                        (spec->boxed_primitive == MVM_STORAGE_SPEC_BP_INT ||
                         spec->boxed_primitive == MVM_STORAGE_SPEC_BP_NUM)) {
                    /* It's a boxed int or num; pretty easy. It'll just live in the
                     * body of the struct. Instead of masking in i here (which
                     * would be the parallel to how we handle boxed types) we
                     * repurpose it to store the bit-width of the type, so
                     * that get_attribute_ref can find it later. */
                    bits = spec->bits;
                    align = spec->align;

                    repr_data->attribute_locations[i] = (bits << MVM_CUNION_ATTR_SHIFT) | MVM_CUNION_ATTR_IN_STRUCT;
                    repr_data->flattened_stables[i] = STABLE(type);
                    if (REPR(type)->initialize) {
                        if (!repr_data->initialize_slots)
                            repr_data->initialize_slots = (MVMint32 *) MVM_calloc(info_alloc + 1, sizeof(MVMint32));
                        repr_data->initialize_slots[cur_init_slot] = i;
                        cur_init_slot++;
                    }
                }
                else if (spec->can_box & MVM_STORAGE_SPEC_CAN_BOX_STR) {
                    /* It's a string of some kind.  */
                    repr_data->num_child_objs++;
                    repr_data->attribute_locations[i] = (cur_obj_attr++ << MVM_CUNION_ATTR_SHIFT) | MVM_CUNION_ATTR_STRING;
                    repr_data->member_types[i] = type;
                    repr_data->flattened_stables[i] = STABLE(type);
                    if (REPR(type)->initialize) {
                        if (!repr_data->initialize_slots)
                            repr_data->initialize_slots = (MVMint32 *) MVM_calloc(info_alloc + 1, sizeof(MVMint32));
                        repr_data->initialize_slots[cur_init_slot] = i;
                        cur_init_slot++;
                    }
                }
                else if (type_id == MVM_REPR_ID_MVMCArray) {
                    /* It's a CArray of some kind.  */
                    repr_data->num_child_objs++;
                    repr_data->attribute_locations[i] = (cur_obj_attr++ << MVM_CUNION_ATTR_SHIFT) | MVM_CUNION_ATTR_CARRAY;
                    repr_data->member_types[i] = type;
                }
                else if (type_id == MVM_REPR_ID_MVMCStruct) {
                    /* It's a CStruct. */
                    repr_data->num_child_objs++;
                    repr_data->attribute_locations[i] = (cur_obj_attr++ << MVM_CUNION_ATTR_SHIFT) | MVM_CUNION_ATTR_CSTRUCT;
                    repr_data->member_types[i] = type;
                    if (inlined) {
                        MVMCStructREPRData *cstruct_repr_data = (MVMCStructREPRData *)STABLE(type)->REPR_data;
                        if (!cstruct_repr_data) {
                            MVM_gc_allocate_gen2_default_clear(tc);
                            MVM_exception_throw_adhoc(tc,
                                "CUnion: can't inline a CStruct attribute before its type's definition");
                        }
                        bits                                  = cstruct_repr_data->struct_size * 8;
                        align                                 = cstruct_repr_data->struct_align;
                        repr_data->attribute_locations[i]    |= MVM_CUNION_ATTR_INLINED;
                    }
                }
                else if (type_id == MVM_REPR_ID_MVMCPPStruct) {
                    /* It's a CPPStruct. */
                    repr_data->num_child_objs++;
                    repr_data->attribute_locations[i] = (cur_obj_attr++ << MVM_CUNION_ATTR_SHIFT) | MVM_CUNION_ATTR_CPPSTRUCT;
                    repr_data->member_types[i] = type;
                    if (inlined) {
                        MVMCPPStructREPRData *cppstruct_repr_data = (MVMCPPStructREPRData *)STABLE(type)->REPR_data;
                        if (!cppstruct_repr_data) {
                            MVM_gc_allocate_gen2_default_clear(tc);
                            MVM_exception_throw_adhoc(tc,
                                "CUnion: can't inline a CPPStruct attribute before its type's definition");
                        }
                        bits                                      = cppstruct_repr_data->struct_size * 8;
                        align                                     = cppstruct_repr_data->struct_align;
                        repr_data->attribute_locations[i]        |= MVM_CUNION_ATTR_INLINED;
                    }
                }
                else if (type_id == MVM_REPR_ID_MVMCUnion) {
                    /* It's a CUnion. */
                    repr_data->num_child_objs++;
                    repr_data->attribute_locations[i] = (cur_obj_attr++ << MVM_CUNION_ATTR_SHIFT) | MVM_CUNION_ATTR_CUNION;
                    repr_data->member_types[i] = type;
                    if (inlined) {
                        MVMCUnionREPRData *cunion_repr_data = (MVMCUnionREPRData *)STABLE(type)->REPR_data;
                        if (!cunion_repr_data) {
                            MVM_gc_allocate_gen2_default_clear(tc);
                            MVM_exception_throw_adhoc(tc,
                                "CUnion: can't inline a CUnion attribute before its type's definition");
                        }
                        bits                                = cunion_repr_data->struct_size * 8;
                        align                               = cunion_repr_data->struct_align;
                        repr_data->attribute_locations[i]  |= MVM_CUNION_ATTR_INLINED;
                    }
                }
                else if (type_id == MVM_REPR_ID_MVMCPointer) {
                    /* It's a CPointer. */
                    repr_data->num_child_objs++;
                    repr_data->attribute_locations[i] = (cur_obj_attr++ << MVM_CUNION_ATTR_SHIFT) | MVM_CUNION_ATTR_CPTR;
                    repr_data->member_types[i] = type;
                }
                else {
                    MVM_gc_allocate_gen2_default_clear(tc);
                    MVM_exception_throw_adhoc(tc,
                        "CUnion representation only handles attributes of type:\n"
                        "  (u)int8, (u)int16, (u)int32, (u)int64, (u)long, (u)longlong, num32, num64, (s)size_t, bool, Str\n"
                        "  and types with representation: CArray, CPointer, CStruct, CPPStruct and CUnion");
                }
            }
            else {
                MVM_gc_allocate_gen2_default_clear(tc);
                MVM_exception_throw_adhoc(tc,
                    "CUnion representation requires the types of all attributes to be specified");
            }

            if (bits % 8) {
                MVM_gc_allocate_gen2_default_clear(tc);
                MVM_exception_throw_adhoc(tc,
                    "CUnion only supports native types that are a multiple of 8 bits wide (was passed: %"PRId32")", bits);
            }

            if (align > repr_data->struct_align)
                repr_data->struct_align = align;

            repr_data->struct_offsets[i] = 0;
            if (bits / 8 > total_size)
                total_size = bits / 8;
        }

        /* Finally, put computed allocation size in place; it's body size plus
         * header size. Also number of markables and sentinels. */
        repr_data->struct_size = total_size;
        if (repr_data->initialize_slots)
            repr_data->initialize_slots[cur_init_slot] = -1;
    }
}

/* Helper for reading an int at the specified offset. */
static MVMint32 get_int_at_offset(void *data, MVMint32 offset) {
    void *location = (char *)data + offset;
    return *((MVMint32 *)location);
}

/* Helper for writing an int at the specified offset. */
static void set_int_at_offset(void *data, MVMint32 offset, MVMint32 value) {
    void *location = (char *)data + offset;
    *((MVMint32 *)location) = value;
}

/* Helper for reading a num at the specified offset. */
static MVMnum32 get_num_at_offset(void *data, MVMint32 offset) {
    void *location = (char *)data + offset;
    return *((MVMnum32 *)location);
}

/* Helper for writing a num at the specified offset. */
static void set_num_at_offset(void *data, MVMint32 offset, MVMnum32 value) {
    void *location = (char *)data + offset;
    *((MVMnum32 *)location) = value;
}

/* Helper for reading a pointer at the specified offset. */
static void * get_ptr_at_offset(void *data, MVMint32 offset) {
    void *location = (char *)data + offset;
    return *((void **)location);
}

/* Helper for writing a pointer at the specified offset. */
static void set_ptr_at_offset(void *data, MVMint32 offset, void *value) {
    void *location = (char *)data + offset;
    *((void **)location) = value;
}

/* Helper for finding a slot number. */
static MVMint32 try_get_slot(MVMThreadContext *tc, MVMCUnionREPRData *repr_data, MVMObject *class_key, MVMString *name) {
    if (repr_data->name_to_index_mapping) {
        MVMCUnionNameMap *cur_map_entry = repr_data->name_to_index_mapping;
        while (cur_map_entry->class_key != NULL) {
            if (cur_map_entry->class_key == class_key) {
                MVMObject *slot_obj = MVM_repr_at_key_o(tc, cur_map_entry->name_map, name);
                if (IS_CONCRETE(slot_obj))
                    return MVM_repr_get_int(tc, slot_obj);
                break;
            }
            cur_map_entry++;
        }
    }
    return -1;
}

/* Creates a new type object of this representation, and associates it with
 * the given HOW. */
static MVMObject * type_object_for(MVMThreadContext *tc, MVMObject *HOW) {
    MVMSTable *st  = MVM_gc_allocate_stable(tc, &CUnion_this_repr, HOW);

    MVMROOT(tc, st, {
        MVMObject *obj = MVM_gc_allocate_type_object(tc, st);
        MVM_ASSIGN_REF(tc, &(st->header), st->WHAT, obj);
        st->size = sizeof(MVMCUnion);
    });

    return st->WHAT;
}

/* Composes the representation. */
static void compose(MVMThreadContext *tc, MVMSTable *st, MVMObject *repr_info) {
    /* Compute allocation strategy. */
    MVMCUnionREPRData *repr_data = MVM_calloc(1, sizeof(MVMCUnionREPRData));
    MVMObject *attr_info = MVM_repr_at_key_o(tc, repr_info, tc->instance->str_consts.attribute);
    MVM_gc_allocate_gen2_default_set(tc);
    compute_allocation_strategy(tc, attr_info, repr_data);
    MVM_gc_allocate_gen2_default_clear(tc);
    st->REPR_data = repr_data;
}

/* Initialize a new instance. */
static void initialize(MVMThreadContext *tc, MVMSTable *st, MVMObject *root, void *data) {
    MVMCUnionREPRData * repr_data = (MVMCUnionREPRData *)st->REPR_data;

    /* Allocate object body. */
    MVMCUnionBody *body = (MVMCUnionBody *)data;
    body->cunion = MVM_calloc(1, repr_data->struct_size > 0 ? repr_data->struct_size : 1);

    /* Allocate child obj array. */
    if (repr_data->num_child_objs > 0)
        body->child_objs = (MVMObject **)MVM_calloc(repr_data->num_child_objs,
            sizeof(MVMObject *));

    /* Initialize the slots. */
    if (repr_data->initialize_slots) {
        MVMint32 i;
        for (i = 0; repr_data->initialize_slots[i] >= 0; i++) {
            MVMint32  offset = repr_data->struct_offsets[repr_data->initialize_slots[i]];
            MVMSTable *st     = repr_data->flattened_stables[repr_data->initialize_slots[i]];
            st->REPR->initialize(tc, st, root, (char *)body->cunion + offset);
        }
    }
}

/* Copies to the body of one object to another. */
static void copy_to(MVMThreadContext *tc, MVMSTable *st, void *src, MVMObject *dest_root, void *dest) {
    MVM_exception_throw_adhoc(tc, "cloning a CUnion is NYI");
}

/* Helper for complaining about attribute access errors. */
MVM_NO_RETURN static void no_such_attribute(MVMThreadContext *tc, const char *action, MVMObject *class_handle, MVMString *name) MVM_NO_RETURN_ATTRIBUTE;
static void no_such_attribute(MVMThreadContext *tc, const char *action, MVMObject *class_handle, MVMString *name) {
    char *c_name = MVM_string_utf8_encode_C_string(tc, name);
    char *waste[] = { c_name, NULL };
    MVM_exception_throw_adhoc_free(tc, waste, "Can not %s non-existent attribute '%s'",
        action, c_name);
}

/* Helper to die because this type doesn't support attributes. */
MVM_NO_RETURN static void die_no_attrs(MVMThreadContext *tc) MVM_NO_RETURN_ATTRIBUTE;
static void die_no_attrs(MVMThreadContext *tc) {
    MVM_exception_throw_adhoc(tc,
        "CUnion representation attribute not yet fully implemented");
}

static void get_attribute(MVMThreadContext *tc, MVMSTable *st, MVMObject *root,
        void *data, MVMObject *class_handle, MVMString *name, MVMint64 hint,
        MVMRegister *result_reg, MVMuint16 kind) {
    MVMCUnionREPRData *repr_data = (MVMCUnionREPRData *)st->REPR_data;
    MVMCUnionBody *body = (MVMCUnionBody *)data;
    MVMint64 slot;

    if (!repr_data)
        MVM_exception_throw_adhoc(tc, "CUnion: must compose before using get_attribute");

    slot = hint >= 0 ? hint : try_get_slot(tc, repr_data, class_handle, name);
    if (slot >= 0) {
        MVMSTable *attr_st = repr_data->flattened_stables[slot];
        switch (kind) {
        case MVM_reg_obj: {
            MVMint32 type      = repr_data->attribute_locations[slot] & MVM_CUNION_ATTR_MASK;
            MVMint32 real_slot = repr_data->attribute_locations[slot] >> MVM_CUNION_ATTR_SHIFT;

            if (type == MVM_CUNION_ATTR_IN_STRUCT) {
                MVM_exception_throw_adhoc(tc,
                    "CUnion can't perform boxed get on flattened attributes yet");
            }
            else {
                MVMObject *typeobj = repr_data->member_types[slot];
                MVMObject *obj     = body->child_objs[real_slot];
                if (!obj) {
                    /* No cached object. */
                    MVMROOT(tc, root, {
                        if (repr_data->attribute_locations[slot] & MVM_CUNION_ATTR_INLINED) {
                            if (type == MVM_CUNION_ATTR_CSTRUCT) {
                                obj = MVM_nativecall_make_cstruct(tc, typeobj,
                                    (char *)body->cunion + repr_data->struct_offsets[slot]);
                            }
                            else if (type == MVM_CUNION_ATTR_CPPSTRUCT) {
                                obj = MVM_nativecall_make_cppstruct(tc, typeobj,
                                    (char *)body->cunion + repr_data->struct_offsets[slot]);
                            }
                            else if (type == MVM_CUNION_ATTR_CUNION) {
                                obj = MVM_nativecall_make_cunion(tc, typeobj,
                                    (char *)body->cunion + repr_data->struct_offsets[slot]);
                            }
                        }
                        else {
                            void *cobj = get_ptr_at_offset(body->cunion, repr_data->struct_offsets[slot]);
                            if (cobj) {
                                if (type == MVM_CUNION_ATTR_CARRAY) {
                                    obj = MVM_nativecall_make_carray(tc, typeobj, cobj);
                                }
                                else if(type == MVM_CUNION_ATTR_CSTRUCT) {
                                    obj = MVM_nativecall_make_cstruct(tc, typeobj, cobj);
                                }
                                else if(type == MVM_CUNION_ATTR_CPPSTRUCT) {
                                    obj = MVM_nativecall_make_cppstruct(tc, typeobj, cobj);
                                }
                                else if(type == MVM_CUNION_ATTR_CUNION) {
                                    obj = MVM_nativecall_make_cunion(tc, typeobj, cobj);
                                }
                                else if(type == MVM_CUNION_ATTR_CPTR) {
                                    obj = MVM_nativecall_make_cpointer(tc, typeobj, cobj);
                                }
                                else if(type == MVM_CUNION_ATTR_STRING) {
                                    MVMROOT(tc, typeobj, {
                                        MVMString *str = MVM_string_utf8_decode(tc, tc->instance->VMString,
                                            cobj, strlen(cobj));
                                        obj = MVM_repr_box_str(tc, typeobj, str);
                                    });
                                }
                            }
                            else {
                                obj = typeobj;
                            }
                        }
                    });
                    MVM_ASSIGN_REF(tc, &(root->header), body->child_objs[real_slot], obj);
                }
                result_reg->o = obj;
            }
            break;
        }
        case MVM_reg_int64: {
            if (attr_st)
                result_reg->i64 = attr_st->REPR->box_funcs.get_int(tc, attr_st, root,
                    ((char *)body->cunion) + repr_data->struct_offsets[slot]);
            else
                MVM_exception_throw_adhoc(tc, "CUnion: invalid native get of object attribute");
            break;
        }
        case MVM_reg_num64: {
            if (attr_st)
                result_reg->n64 = attr_st->REPR->box_funcs.get_num(tc, attr_st, root,
                    ((char *)body->cunion) + repr_data->struct_offsets[slot]);
            else
                MVM_exception_throw_adhoc(tc, "CUnion: invalid native get of object attribute");
            break;
        }
        case MVM_reg_str: {
            if (attr_st)
                result_reg->s = attr_st->REPR->box_funcs.get_str(tc, attr_st, root,
                    ((char *)body->cunion) + repr_data->struct_offsets[slot]);
            else
                MVM_exception_throw_adhoc(tc, "CUnion: invalid native get of object attribute");
            if (!result_reg->s)
                result_reg->s = tc->instance->str_consts.empty;
            break;
        }
        default:
            MVM_exception_throw_adhoc(tc, "CUnion: invalid kind in attribute get");
        }
    }
    else {
        no_such_attribute(tc, "bind", class_handle, name);
    }
}

/* Binds the given value to the specified attribute. */
static void bind_attribute(MVMThreadContext *tc, MVMSTable *st, MVMObject *root,
        void *data, MVMObject *class_handle, MVMString *name, MVMint64 hint,
        MVMRegister value_reg, MVMuint16 kind) {
    MVMCUnionREPRData *repr_data = (MVMCUnionREPRData *)st->REPR_data;
    MVMCUnionBody *body = (MVMCUnionBody *)data;
    MVMint64 slot;

    if (!repr_data)
        MVM_exception_throw_adhoc(tc, "CUnion: must compose before using bind_attribute");

    slot = hint >= 0 ? hint : try_get_slot(tc, repr_data, class_handle, name);
    if (slot >= 0) {
        MVMSTable *attr_st = repr_data->flattened_stables[slot];
        switch (kind) {
        case MVM_reg_obj: {
            MVMObject *value = value_reg.o;
            MVMint32   type  = repr_data->attribute_locations[slot] & MVM_CUNION_ATTR_MASK;

            if (type == MVM_CUNION_ATTR_IN_STRUCT) {
                MVM_exception_throw_adhoc(tc,
                    "CUnion can't perform boxed bind on flattened attributes yet");
            }
            else {
                MVMint32   real_slot = repr_data->attribute_locations[slot] >> MVM_CUNION_ATTR_SHIFT;

                if (IS_CONCRETE(value)) {
                    void *cobj       = NULL;

                    MVM_ASSIGN_REF(tc, &(root->header), body->child_objs[real_slot], value);

                    /* Set cobj to correct pointer based on type of value. */
                    if (type == MVM_CUNION_ATTR_CARRAY) {
                        if (REPR(value)->ID != MVM_REPR_ID_MVMCArray)
                            MVM_exception_throw_adhoc(tc,
                                "Can only store CArray attribute in CArray slot in CUnion");
                        cobj = ((MVMCArray *)value)->body.storage;
                    }
                    else if (type == MVM_CUNION_ATTR_CSTRUCT) {
                        if (REPR(value)->ID != MVM_REPR_ID_MVMCStruct)
                            MVM_exception_throw_adhoc(tc,
                                "Can only store CStruct attribute in CStruct slot in CUnion");
                        cobj = ((MVMCStruct *)value)->body.cstruct;
                    }
                    else if (type == MVM_CUNION_ATTR_CPTR) {
                        if (REPR(value)->ID != MVM_REPR_ID_MVMCPointer)
                            MVM_exception_throw_adhoc(tc,
                                "Can only store CPointer attribute in CPointer slot in CUnion");
                        cobj = ((MVMCPointer *)value)->body.ptr;
                    }
                    else if (type == MVM_CUNION_ATTR_STRING) {
                        MVMString *str  = MVM_repr_get_str(tc, value);
                        cobj = MVM_string_utf8_encode_C_string(tc, str);
                    }

                    set_ptr_at_offset(body->cunion, repr_data->struct_offsets[slot], cobj);
                }
                else {
                    body->child_objs[real_slot] = NULL;
                    set_ptr_at_offset(body->cunion, repr_data->struct_offsets[slot], NULL);
                }
            }
            break;
        }
        case MVM_reg_int64: {
            if (attr_st)
                attr_st->REPR->box_funcs.set_int(tc, attr_st, root,
                    ((char *)body->cunion) + repr_data->struct_offsets[slot], value_reg.i64);
            else
                MVM_exception_throw_adhoc(tc, "CUnion: invalid native binding to object attribute");
            break;
        }
        case MVM_reg_num64: {
            if (attr_st)
                attr_st->REPR->box_funcs.set_num(tc, attr_st, root,
                    ((char *)body->cunion) + repr_data->struct_offsets[slot], value_reg.n64);
            else
                MVM_exception_throw_adhoc(tc, "CUnion: invalid native binding to object attribute");
            break;
        }
        case MVM_reg_str: {
            if (attr_st)
                attr_st->REPR->box_funcs.set_str(tc, attr_st, root,
                    ((char *)body->cunion) + repr_data->struct_offsets[slot], value_reg.s);
            else
                MVM_exception_throw_adhoc(tc, "CUnion: invalid native binding to object attribute");
            break;
        }
        default:
            MVM_exception_throw_adhoc(tc, "CUnion: invalid kind in attribute bind");
        }
    }
    else {
        no_such_attribute(tc, "bind", class_handle, name);
    }
}

/* Checks if an attribute has been initialized. */
static MVMint64 is_attribute_initialized(MVMThreadContext *tc, MVMSTable *st, void *data, MVMObject *class_handle, MVMString *name, MVMint64 hint) {
    die_no_attrs(tc);
}

/* Gets the hint for the given attribute ID. */
static MVMint64 hint_for(MVMThreadContext *tc, MVMSTable *st, MVMObject *class_handle, MVMString *name) {
    return MVM_NO_HINT;
}

/* Adds held objects to the GC worklist. */
static void gc_mark(MVMThreadContext *tc, MVMSTable *st, void *data, MVMGCWorklist *worklist) {
    MVMCUnionREPRData *repr_data = (MVMCUnionREPRData *) st->REPR_data;
    MVMCUnionBody *body = (MVMCUnionBody *)data;
    MVMint32 i;
    for (i = 0; i < repr_data->num_child_objs; i++)
        MVM_gc_worklist_add(tc, worklist, &body->child_objs[i]);
}

/* Marks the representation data in an STable.*/
static void gc_mark_repr_data(MVMThreadContext *tc, MVMSTable *st, MVMGCWorklist *worklist) {
    MVMCUnionREPRData *repr_data = (MVMCUnionREPRData *)st->REPR_data;
    if (repr_data) {
        MVMint32 i;
        if (repr_data->name_to_index_mapping) {
            MVMCUnionNameMap *map = repr_data->name_to_index_mapping;
            for (i = 0; map[i].class_key; i++) {
                MVM_gc_worklist_add(tc, worklist, &map[i].class_key);
                MVM_gc_worklist_add(tc, worklist, &map[i].name_map);
            }
        }

        if (repr_data->flattened_stables) {
            MVMSTable **flattened_stables = repr_data->flattened_stables;
            for (i = 0; i < repr_data->num_attributes; i++)
                MVM_gc_worklist_add(tc, worklist, &flattened_stables[i]);
        }

        if (repr_data->member_types) {
            MVMObject **member_types = repr_data->member_types;
            for (i = 0; i < repr_data->num_attributes; i++)
                MVM_gc_worklist_add(tc, worklist, &member_types[i]);
        }
    }
}

/* Free representation data. */
static void gc_free_repr_data(MVMThreadContext *tc, MVMSTable *st) {
    MVM_free(st->REPR_data);
}

/* This is called to do any cleanup of resources when an object gets
 * embedded inside another one. Never called on a top-level object. */
static void gc_cleanup(MVMThreadContext *tc, MVMSTable *st, void *data) {
    MVMCUnionBody *body = (MVMCUnionBody *)data;
    if (body->child_objs)
        MVM_free(body->child_objs);
    /* XXX For some reason, this causes crashes at the moment. Need to
     * work out why. */
    /*if (body->cunion)
        MVM_free(body->cunion);*/
}

/* Called by the VM in order to free memory associated with this object. */
static void gc_free(MVMThreadContext *tc, MVMObject *obj) {
    gc_cleanup(tc, STABLE(obj), OBJECT_BODY(obj));
}

static const MVMStorageSpec storage_spec = {
    MVM_STORAGE_SPEC_REFERENCE, /* inlineable */
    sizeof(void*) * 8,          /* bits */
    ALIGNOF(void*),             /* align */
    MVM_STORAGE_SPEC_BP_NONE,   /* boxed_primitive */
    0,                          /* can_box */
    0,                          /* is_unsigned */
};

/* Gets the storage specification for this representation. */
static const MVMStorageSpec * get_storage_spec(MVMThreadContext *tc, MVMSTable *st) {
    return &storage_spec;
}

/* Serializes the REPR data. */
static void serialize_repr_data(MVMThreadContext *tc, MVMSTable *st, MVMSerializationWriter *writer) {
    MVMCUnionREPRData *repr_data = (MVMCUnionREPRData *)st->REPR_data;
    MVMint32 i, num_classes, num_slots;

    MVM_serialization_write_int(tc, writer, repr_data->struct_size);
    MVM_serialization_write_int(tc, writer, repr_data->struct_align);
    MVM_serialization_write_int(tc, writer, repr_data->num_attributes);
    MVM_serialization_write_int(tc, writer, repr_data->num_child_objs);
    for(i = 0; i < repr_data->num_attributes; i++){
        MVM_serialization_write_int(tc, writer, repr_data->attribute_locations[i]);
        MVM_serialization_write_int(tc, writer, repr_data->struct_offsets[i]);

        MVM_serialization_write_int(tc, writer, repr_data->flattened_stables[i] != NULL);
        if (repr_data->flattened_stables[i])
            MVM_serialization_write_stable_ref(tc, writer, repr_data->flattened_stables[i]);

        MVM_serialization_write_ref(tc, writer, repr_data->member_types[i]);
    }

    i=0;
    while (repr_data->name_to_index_mapping[i].class_key)
        i++;
    num_classes = i;
    MVM_serialization_write_int(tc, writer, num_classes);
    for(i = 0; i < num_classes; i++){
        MVM_serialization_write_ref(tc, writer, repr_data->name_to_index_mapping[i].class_key);
        MVM_serialization_write_ref(tc, writer, repr_data->name_to_index_mapping[i].name_map);
    }

    i=0;
    while(repr_data->initialize_slots && repr_data->initialize_slots[i] != -1)
        i++;
    num_slots = i;
    MVM_serialization_write_int(tc, writer, num_slots);
    for(i = 0; i < num_slots; i++){
        MVM_serialization_write_int(tc, writer, repr_data->initialize_slots[i]);
    }
}

/* Deserializes the REPR data. */
static void deserialize_repr_data(MVMThreadContext *tc, MVMSTable *st, MVMSerializationReader *reader) {
    MVMCUnionREPRData *repr_data = (MVMCUnionREPRData *) MVM_malloc(sizeof(MVMCUnionREPRData));
    MVMint32 i, num_classes, num_slots;

    repr_data->struct_size = MVM_serialization_read_int(tc, reader);
    if (reader->root.version >= 17) {
        repr_data->struct_align = MVM_serialization_read_int(tc, reader);
    }
    repr_data->num_attributes = MVM_serialization_read_int(tc, reader);
    repr_data->num_child_objs = MVM_serialization_read_int(tc, reader);

    repr_data->attribute_locations = (MVMint32 *)MVM_malloc(sizeof(MVMint32) * repr_data->num_attributes);
    repr_data->struct_offsets      = (MVMint32 *)MVM_malloc(sizeof(MVMint32) * repr_data->num_attributes);
    repr_data->flattened_stables   = (MVMSTable **)MVM_malloc(repr_data->num_attributes * sizeof(MVMSTable *));
    repr_data->member_types        = (MVMObject **)MVM_malloc(repr_data->num_attributes * sizeof(MVMObject *));

    for(i = 0; i < repr_data->num_attributes; i++) {
        repr_data->attribute_locations[i] = MVM_serialization_read_int(tc, reader);
        repr_data->struct_offsets[i] = MVM_serialization_read_int(tc, reader);

        if(MVM_serialization_read_int(tc, reader)){
            MVM_ASSIGN_REF(tc, &(st->header), repr_data->flattened_stables[i], MVM_serialization_read_stable_ref(tc, reader));
        }
        else {
            repr_data->flattened_stables[i] = NULL;
        }

        repr_data->member_types[i] = MVM_serialization_read_ref(tc, reader);
    }

    num_classes = MVM_serialization_read_int(tc, reader);
    repr_data->name_to_index_mapping = (MVMCUnionNameMap *)MVM_malloc(sizeof(MVMCUnionNameMap) * (1 + num_classes));
    for(i = 0; i < num_classes; i++){
        repr_data->name_to_index_mapping[i].class_key = MVM_serialization_read_ref(tc, reader);
        repr_data->name_to_index_mapping[i].name_map = MVM_serialization_read_ref(tc, reader);
    }
    repr_data->name_to_index_mapping[i].class_key = NULL;
    repr_data->name_to_index_mapping[i].name_map = NULL;

    num_slots = MVM_serialization_read_int(tc, reader);
    repr_data->initialize_slots = (MVMint32 *)MVM_malloc(sizeof(MVMint32) * (1 + num_slots));
    for(i = 0; i < num_slots; i++){
        repr_data->initialize_slots[i] = MVM_serialization_read_int(tc, reader);
    }
    repr_data->initialize_slots[i] = -1;

    st->REPR_data = repr_data;
}

static void deserialize_stable_size(MVMThreadContext *tc, MVMSTable *st, MVMSerializationReader *reader) {
    st->size = sizeof(MVMCUnion);
}

/* Initializes the representation. */
const MVMREPROps * MVMCUnion_initialize(MVMThreadContext *tc) {
    return &CUnion_this_repr;
}

static const MVMREPROps CUnion_this_repr = {
    type_object_for,
    MVM_gc_allocate_object,
    initialize,
    copy_to,
    {
        get_attribute,
        bind_attribute,
        hint_for,
        is_attribute_initialized,
        MVM_REPR_DEFAULT_ATTRIBUTE_AS_ATOMIC
    },   /* attr_funcs */
    MVM_REPR_DEFAULT_BOX_FUNCS,
    MVM_REPR_DEFAULT_POS_FUNCS,
    MVM_REPR_DEFAULT_ASS_FUNCS,
    MVM_REPR_DEFAULT_ELEMS,
    get_storage_spec,
    NULL, /* change_type */
    NULL, /* serialize */
    NULL, /* deserialize */
    serialize_repr_data,
    deserialize_repr_data,
    deserialize_stable_size,
    gc_mark,
    gc_free,
    gc_cleanup,
    gc_mark_repr_data,
    gc_free_repr_data,
    compose,
    NULL, /* spesh */
    "CUnion", /* name */
    MVM_REPR_ID_MVMCUnion,
    NULL, /* unmanaged_size */
    NULL, /* describe_refs */
};


Q:

Changing DOMNode tag name creating anomalies within the saved HTML

In the process of making a Wordpress post parser for my personal website but hitting some behaviour I can't explain.
Here's the code:
// Wordpress uses

 sections for new lines
$sections = $doc->getElementsByTagName('p');

foreach ($sections as $section)
{
    $hasChilderen = $section->hasChildNodes();
    $contents = $section->nodeValue;

    // If we have text, assume we are a paragraph (for the time being)
    if (!empty($contents))
    {
        $section->setAttribute('class', 'post-inner-content-paragraph');
    }
    elseif ($hasChilderen)
    {
        $section->setAttribute('class', 'post-inner-content-media');
        $section = change_tag_name($section, 'div');

        $imgs = $section->getElementsByTagName('img');
        foreach ($imgs as $img)
        {
            $img->removeAttribute('class');
        }
    }
    else
    {
        $section->setAttribute('class', 'post-inner-content-empty');
    }
}

change_tag_name:
function change_tag_name($node, $name)
{
    $doc = $node->ownerDocument;

    $newnode = $doc->createElement($name);

    foreach ($node->childNodes as $child)
    {
        $child = $doc->importNode($child, true);
        $newnode->appendChild($child);
    }

    if ($node->hasAttributes())
    {
        foreach ($node->attributes as $attr)
            {
                $name = $attr->nodeName;
                $value = $attr->nodeValue;
                $newnode->setAttribute($name, $value);
            }
    }

    $node->parentNode->replaceChild($newnode, $node);

    return $newnode;
}

There's no way for a
 block to passed as a section and NOT get an attribute assigned to it, however:

The highlighted
 block doesn't have a class!
Here's the HTML loaded into the DOMDocument $dom: http://pastebin.com/biVSyWn9
Here's the HTML leaving my parse function: http://pastebin.com/RhzgeWAS
I can't detect any reason why this particular
 block isn't being set a class.

A:

Solution
You have to traverse the node list backwards in order to make the kind of changes I want to do. crnix's answer helped identify that the problem occured with replaceChild within the change_tag_name function. Changing my foreach loop to the following fixed my issue:
$sections = $doc->getElementsByTagName('p');
$i = $sections->length - 1;
while ($i > -1)
{
    $section = $sections->item($i);

    // Change tag name of section

    $i--;
}


---
abstract: 'Pro-social punishment is a key driver of harmonious and stable society. However, this institution is vulnerable to corruption since law-violators can avoid sanctioning by paying bribes to corrupt law-enforcers. Consequently, to understand how altruistic behavior survives in a corrupt environment is an open question. To reveal potential explanations here we introduce corrupt enforcers and violators into the public goods game with pool punishment, and assume that punishers, as corrupt enforcers, may select defectors probabilistically to take a bribe from, and meanwhile defectors, as corrupt violators, may select punishers stochastically to be corrupted. By means of mathematical analysis, we aim to study the necessary conditions for the evolution of cooperation in such corrupt environment. We find that cooperation can be maintained in the population in two distinct ways. First, cooperators, defectors, and punishers can coexist by all keeping a steady fraction of the population. Second, these three strategies can form a cyclic dominance that resembles a rock-scissors-paper cycle or a heteroclinic cycle. We theoretically identify conditions when the competing strategies coexist in a stationary way or they dominate each other in a cyclic way. These predictions are confirmed numerically.'
address:
- 'School of Mathematical Sciences, University of Electronic Science and Technology of China, Chengdu 611731, China'
- |
    School of Mathematical Sciences, University of Electronic Science and Technology of China, Chengdu 611731, China\
    xiaojiechen@uestc.edu.cn\
    $*$Corresponding author
- |
    Institute of Technical Physics and Materials Science, Centre for Energy Research, Hungarian Academy of Sciences, P.O. Box 49, H-1525 Budapest, Hungary\
    szolnoki.attila@energia.mta.hu
author:
- Linjie Liu
- 'Xiaojie Chen\*'
- Attila Szolnoki
title: Evolutionary dynamics of cooperation in a population with probabilistic corrupt enforcers and violators
---

Introduction
============

Understanding the emergence and persistence of altruistic behavior among selfish individuals has long been an enormous challenge for research community [@fehr2003nature; @Szolnoki2007Cooperation; @santos2008social; @santos2012role; @Dolfin14; @Perc2017Statistical; @Allen18; @chen18; @szolnokipre18]. This conundrum of collective behaviors has been often studied in social-economical systems where different mathematical tools including the kinetic theory of active particles and agent based modeling can be used [@Hamilton1963The; @Bellomo09; @Bellomo11; @Pareschi2013; @Herrero15; @Marsan16; @Burini16; @Bellomo16; @Dolfin17; @Bellomo17]. As an alternative approach, evolutionary game theory has also been applied to model individuals interactions at a microscopic scale for understanding the dynamics of collective actions of cooperation in large systems of interacting entities [@Tanimoto07; @Szolnoki2018; @Perc2008Social; @Perc2010Coevolutionary; @fu2010invasion; @Santos12; @Vasconcelos13; @Vasconcelos15]. Particularly, public goods game (PGG), as a standard metaphor of the mentioned social dilemma, has attracted a lot of attention from broad range of research disciplines [@milinski2002reputation; @hauert2002volunteering; @Szolnoki2009Resolving; @hilbe18; @he2018amc; @Wu18]. In the PGG, individuals decide whether to contribute to the common pool or not, and the accumulated and enhanced contribution are distributed to group members equally. Thus defectors who contribute nothing will obtain a higher payoff, no matter what other players do. If left controlled, each individual prefers to defect in the game leading to the collapse of cooperation [@hardin1968tragedy].

In order to solve the problem of cooperation in the game, an intensive research efforts have been carried out during the past few decades [@nowak2006five; @Fu2008Reputation; @santos2011risk; @Szolnoki2012Evolutionary; @chen2012risk; @Sasaki2012The]. One prominently discussed solution is the employment of pro-social punishment, that is, punishing uncooperative individuals by lowering their income [@rockenbach2006efficient; @Szolnoki2011Phase; @sasaki2013evolution; @Szolnoki2013Effectiveness; @chen2014probabilistic; @Chenxj2015; @Liu2017Competitions; @szolnoki2017alliance; @Liu2018Chaos; @Yang2018]. In particular, two different ways of punishment are studied, namely, peer punishment and pool punishment. The former refers to that group individuals can impose fines on the violators directly and its additional cost [@Fehr02; @Andreoni03; @rockenbach2006efficient]. The latter means that players can decide whether to contribute to a punishment pool before contributing to the common pool of the basic game and sanctioning defection is organized centrally [@Sigmund2010nature; @Szolnoki2011Phase]. This way of punishment is widespread and generally preferred in modern human societies [@Sigmund2010nature].

While punishment can solve the original dilemma of cooperation, the effectiveness of punishment in promoting cooperation has been challenged by recent theoretical research showing that the existence of corruption where defectors bribe corrupt officials to avoid punishment can destroy the positive consequence of costly punishment in cooperation [@Abdallah14; @Verma2015; @Lee2017; @Muthukrishna2017; @Huang2018]. For example, Muthukrishna et al. [@Muthukrishna2017] experimentally showed that the possibility of corruption can cause a significant fall in public good provisioning and make empowering leaders decrease cooperative contributions.

It is worth mentioning that in most of the studies involving corruption, it is always assumed that defectors bribe corrupt enforcers and meanwhile enforcers who are involved with corruption take the bribes permanently. Indeed this assumption is not always justified in realistic situations where officials who are involved in corruption do not accept all the offered bribes and meanwhile civilians who violate the rules are not always going to offer a bribe to the officials. In other words, corrupt officials and defective civilians may act stochastically and offer or take bribes occasionally.

Motivated by the above mentioned observations, in this work we thus introduce corrupt enforcers and violators into the PGG with pool punishment, and we assume that defectors bribe enforcers probabilistically to avoid punishment and meanwhile pool punishers accept a bribe from defectors also stochastically. By applying the replicator equation approach we assume infinite population where the evolutionary game dynamics is used. Our theoretical analysis reveals, which is also confirmed by numerical calculations, that the cooperative behavior can be maintained in the population in two different ways. First, cooperators, defectors, and punishers can coexist where the portions of all strategies are stable in time. Alternatively, the three strategies can dominate each other in a cyclic way similarly to the well known rock-scissors-paper cycle or the heteroclinic cycle.

Model and method {#section2}
================

Public goods game
-----------------

We consider the PGG played in an infinite well-mixed population. At each time step, $N$ individuals are randomly chosen to form a group to participate in the PGG. Each individual can choose to cooperate or defect. Cooperators ($C$) contribute to the common pool at a cost $c$, while defectors ($D$) contribute nothing. The sum of contributions is multiplied by a factor $r$ ($1<r<N$) and then the enhanced amount is divided equally among all group members.

We then introduce a third strategist, pool punishers ($P$), who contribute $G$ to the punishment pool before contributing $c$ to the common pool. They are responsible for monitoring the entire population and punishing those individuals who are unwilling to contribute to the common pool. Alternatively, some defectors might be tempted to bribe the enforcers, so as to enable them to avoid punishment. In the same way, some enforcers can choose to accept bribes and do not punish the bribers. Here we assume that punishers decide to accept the bribe $b$ from corrupt defectors with probability $p$. With $1-p$ probability they do not accept any bribes and punish defectors in the group. On the other hand, we assume that defector will pay the cost $h$ to bribe the corrupt punishers with probability $q$, while with $1-q$ probability they are unwilling to do this. Thus, a defector who does not bribe will receive a fine $B (B\geq h)$ from every punisher no matter whether he/she is willing to accept bribes.

As a result, the payoffs of cooperators, defectors, and punishers from one PGG can be respectively written as $$\begin{aligned}
\pi_{C}&=&\frac{rc(N_{C}+N_{P}+1)}{N}-c,  \\
\pi_{D}&=&\frac{rc(N_{C}+N_{P})}{N}-(1-pq)BN_{P}-pqN_{P}h,  \\
\pi_{P}&=&\frac{rc(N_{C}+N_{P}+1)}{N}-c-G+pqN_{D}b,\end{aligned}$$ where $N_{C}, N_{D}$, and $N_{P}$ respectively represent the number of cooperators, defectors, and pool punishers among the other $N-1$ group members, and $(1-pq)B$ denotes the expected fine from each punisher.

Replicator equation
-------------------

We apply replicator equations to study the evolutionary dynamics of strategies in our model [@Santos12; @Nowak04S; @hofbauer1998evolutionary; @wang2018]. We denote by $x, y,$ and $z$ the frequencies of $C, D$, and $P$, respectively. Thus, $x, y, z\geq0$ and $x+y+z=1$. The replicator equations are written as $$\begin{aligned}
\label{system1}
\left\{
\begin{aligned}
\dot{x}&=x(P_{C}-\bar{P}),  \\
\dot{y}&=y(P_{D}-\bar{P}),  \\
\dot{z}&=z(P_{P}-\bar{P}),
\end{aligned}
\right.\end{aligned}$$ where $P_{C}, P_{D}$, and $P_{P}$ denote the expected payoffs of $C, D,$ and $P$, respectively, and $\bar{P}=xP_{C}+yP_{D}+zP_{P}$ gives the average payoff of the entire population. Accordingly, the expected payoffs of the above three strategies can be written as $$\begin{aligned}
\label{equation2.5}
P_{i}=\sum_{N_{C}=0}^{N-1}\sum_{N_{D}=0}^{N-N_{C}-1}\binom{N-1}{N_{C}}\binom{N-N_{C}-1}{N_{D}}x^{N_{C}}y^{N_{D}}z^{N-N_{C}-N_{D}-1}\pi_{i},\end{aligned}$$ where $i=C, D,$ or $P$.

In the next section, we examine the evolutionary dynamics for the mentioned three strategies. Particulary, we analyze the distribution and stability of equilibrium points in the following section.

Theoretical analysis {#section3}
====================

Equilibrium points
------------------

We consider the replicator dynamics for cooperators ($C$), defectors ($D$), and pool punishers ($P$), with the frequencies $x, y$, and $z$, respectively. We can get the expected payoffs of these three strategies by simplifying the formula presented in Eq. (\[equation2.5\]) as follows: $$\begin{aligned}
P_{C}&=&\frac{rc}{N}(N-1)(x+z)+\frac{rc}{N}-c,  \\
P_{D}&=&\frac{rc}{N}(N-1)(x+z)-(1-pq)B(N-1)z-pq(N-1)zh,\\
P_{P}&=&\frac{rc}{N}(N-1)(x+z)+\frac{rc}{N}-c-G+pq(N-1)yb,\end{aligned}$$ where $(N-1)(x+z)$ denotes the expected numbers of contributors among the $N-1$ co-players, and $B(N-1)z$ gives the expected fine on a defector. The detailed analysis of the equilibrium points is shown in Theorem \[theorem3.1\].

\[theorem3.1\] The system described by (\[system1\]) has at most five equilibria $(x, y, z)=(1, 0, 0), (0, 1, 0), (0, 0, 1), (0, 1-\alpha, \alpha)$, and $(1-\beta-\mu, \mu, \beta)$. Here we introduce the abbreviation $\alpha=\frac{rc/N-c-G+pq(N-1)b}{(B+b-h)(N-1)pq-B(N-1)}$, $\beta=\frac{c-rc/N}{(1-pq)B(N-1)+pqh(N-1)}$, and $\mu=\frac{G}{pq(N-1)b}$ \[T3.1\].

It is easy to obtain the three vertex fixed points of the above system, namely, $(0, 0, 1), (1, 0, 0)$, and $(0, 1, 0)$. In the following, we analyze the boundary and interior equilibria of the system in detail.

We first investigate the interior equilibrium points in the simplex $S_{3}$. Solving $P_{C}=P_{D}$ results in $z=\beta$. Similarly, by solving $P_{C}=P_{P}$, we have $y=\mu$. Thus, there is an interior equilibrium point $(1-\beta-\mu, \mu, \beta)$ when $\mu<1$, $\beta<1$, and $1-\beta-\mu>0$.

Then we investigate the fixed points on each edge of the simplex $S_{3}$. On the edge $CD$ we have $z=0$, resulting in $\dot{y}=y(1-y)(P_{D}-P_{C})=y(1-y)(c-\frac{rc}{N})>0$. As a result, the system evolves from the $C$ state towards the $D$ state.

On the $CP$ edge we have $y=0$, resulting in $\dot{x}=x(1-x)(P_{C}-P_{P})=x(1-x)G>0$. Thus the direction of the dynamics goes from $P$ toward $C$ state.

On the $DP$ edge we have $y+z=1$, and the replicator system changes to $\dot{z}=z(1-z)(P_{P}-P_{D})$. Solving $P_{P}=P_{D}$ results in $z=\alpha$. Thus there exists a boundary equilibrium point $(0, 1-\alpha,\alpha)$ when $0<\alpha<1$.

Stability analysis of equilibria
--------------------------------

Here we set that $$\begin{aligned}
\left\{
\begin{aligned}\label{system2}
f(x,y)&=&x[(1-x)(P_{C}-P_{P})-y(P_{D}-P_{P})],\\
g(x,y)&=&y[(1-y)(P_{D}-P_{P})-x(P_{C}-P_{P})].
\end{aligned}
\right.\end{aligned}$$ Then the Jacobian of the system is $$J=\begin{bmatrix}
\frac{\partial{f(x,y)}}{\partial{x}} & \frac{\partial{f(x,y)}}{\partial{y}}\\
\frac{\partial{g(x,y)}}{\partial{x}} & \frac{\partial{g(x,y)}}{\partial{y}}
\end{bmatrix},$$ where $$\begin{aligned}
\left\{
\begin{aligned}
\frac{\partial{f(x,y)}}{\partial{x}}&=[(1-x)(P_{C}-P_{P})-y(P_{D}-P_{P})]+x[-(P_{C}-P_{P})\\
&+(1-x)\frac{\partial}{\partial{x}}(P_{C}-P_{P})-y\frac{\partial}{\partial{x}}(P_{D}-P_{P})],\\
\frac{\partial{f(x,y)}}{\partial{y}}&=x[(1-x)\frac{\partial}{\partial{y}}(P_{C}-P_{P})-(P_{D}-P_{P})-y\frac{\partial}{\partial{y}}(P_{D}-P_{P})],\\
\frac{\partial{g(x,y)}}{\partial{x}}&=y[(1-y)\frac{\partial}{\partial{x}}(P_{D}-P_{P})-(P_{C}-P_{P})-x\frac{\partial}{\partial{x}}(P_{C}-P_{P})],\\
\frac{\partial{g(x,y)}}{\partial{y}}&=[(1-y)(P_{D}-P_{P})-x(P_{C}-P_{P})]+y[-(P_{D}-P_{P})\\
&+(1-y)\frac{\partial}{\partial{y}}(P_{D}-P_{P})-x\frac{\partial}{\partial{y}}(P_{C}-P_{P})].
\end{aligned}
\right.\end{aligned}$$

In the following, we study the stabilities of equilibria based on whether the system has an interior equilibrium point.

### The system (\[system1\]) has an interior equilibrium point {#subsection3.2.1}

When $\beta<1$, $\mu<1$, and $\beta+\mu<1$, there exists an interior fixed point, namely, $(x, y, z)=(1-\beta-\mu, \mu, \beta)$. In the following we discuss the stability of this fixed point.

When $(1-pq)B+pqh-pqb<0$, the existing interior fixed point is stable.

\(1) For $0<\alpha<1$, there is a boundary equilibrium point with $z=\alpha$ on the $DP$ edge. Thus the system has five fixed points in the parameter space, namely, $(0, 0, 1), (1, 0, 0), (0, 1, 0), (0, 1-\alpha, \alpha)$, and $(1-\beta-\mu, \mu, \beta)$.

For $(x, y, z)=(0, 0, 1)$, the Jacobian is $$J=\begin{bmatrix}
G &&& 0\\
0 &&& -(1-pq)B(N-1)-pq(N-1)h-\frac{rc}{N}+c+G
\end{bmatrix},$$ thus the fixed equilibrium is unstable since $G>0$.

For $(x, y, z)=(1, 0, 0)$, the Jacobian is $$J=\begin{bmatrix}
-G &&& -(c+G-\frac{rc}{N})\\
0 &&& c-\frac{rc}{N}
\end{bmatrix},$$ thus the fixed equilibrium is unstable since $r<N$.

For $(x, y, z)=(0, 1, 0)$, the Jacobian is $$J=\begin{bmatrix}
\frac{rc}{N}-c &&& 0\\
-(G-pq(N-1)b) &&& \frac{rc}{N}-c-G+pq(N-1)b
\end{bmatrix},$$ thus the fixed equilibrium is a saddle point and unstable since $\frac{rc}{N}-c-G+pq(N-1)b>0$.

For $(x, y, z)=(0, 1-\alpha, \alpha)$, the Jacobian is $$J=\begin{bmatrix}
a_{11} & 0\\
a_{21} & a_{22}
\end{bmatrix},$$ where $a_{11}=G-pq(N-1)yb, a_{21}=y(1-y)[pq(N-1)h+(1-pq)(N-1)B]-y[G-pq(N-1)yb]$, and $a_{22}=y(1-y)(N-1)[(1-pq)B+pqh-pqb]$, thus the fixed equilibrium is unstable since $G-pq(N-1)yb>0$.

For $(x,y,z)=(1-\beta-\mu, \mu, \beta)$, we define the equilibrium point as $(x^{*}, y^{*}, z^{*})$ hereafter, thus the elements in the Jacobian matrix are written as $$\begin{aligned}
\left\{
\begin{aligned}
\frac{\partial{f}}{\partial{x}}(x^{*},y^{*})&=&x^{*}[(1-x^{*})\frac{\partial}{\partial{x}}(P_{C}-P_{P})-y^{*}\frac{\partial}{\partial{x}}(P_{D}-P_{P})],\\
\frac{\partial{f}}{\partial{y}}(x^{*},y^{*})&=&x^{*}[(1-x^{*})\frac{\partial}{\partial{y}}(P_{C}-P_{P})-y^{*}\frac{\partial}{\partial{y}}(P_{D}-P_{P})],\\
\frac{\partial{g}}{\partial{x}}(x^{*},y^{*})&=&y^{*}[(1-y^{*})\frac{\partial}{\partial{x}}(P_{D}-P_{P})-x^{*}\frac{\partial}{\partial{x}}(P_{C}-P_{P})],\\
\frac{\partial{g}}{\partial{y}}(x^{*},y^{*})&=&y^{*}[(1-y^{*})\frac{\partial}{\partial{y}}(P_{D}-P_{P})-x^{*}\frac{\partial}{\partial{y}}(P_{C}-P_{P})],
\end{aligned}
\right.\end{aligned}$$ where $$\begin{aligned}
\left\{
\begin{aligned}
\frac{\partial}{\partial{x}}(P_{C}-P_{P})&=0,\\
\frac{\partial}{\partial{y}}(P_{C}-P_{P})&=-pq(N-1)b,\\
\frac{\partial}{\partial{x}}(P_{D}-P_{P})&=(N-1)[pqh+(1-pq)B],\\
\frac{\partial}{\partial{y}}(P_{D}-P_{P})&=(N-1)[pqh+(1-pq)B-pqb].
\end{aligned}
\right.\end{aligned}$$ Then we define that $p=\frac{\partial{f}}{\partial{x}}(x^{*},y^{*})\frac{\partial{g}}{\partial{y}}(x^{*},y^{*})-\frac{\partial{f}}{\partial{y}}(x^{*},y^{*})\frac{\partial{g}}{\partial{x}}(x^{*},y^{*})$ and $q=\frac{\partial{f}}{\partial{x}}(x^{*},y^{*})+\frac{\partial{g}}{\partial{y}}(x^{*},y^{*})$. Thus we have $$\begin{aligned}
p&=&\frac{\partial{f}}{\partial{x}}(x^{*},y^{*})\frac{\partial{g}}{\partial{y}}(x^{*},y^{*})-\frac{\partial{f}}{\partial{y}}(x^{*},y^{*})\frac{\partial{g}}{\partial{x}}(x^{*},y^{*})\nonumber\\
&=&x^{*}y^{*}(1-x^{*}-y^{*})[\frac{\partial}{\partial{x}}(P_{C}-P_{P})\frac{\partial}{\partial{y}}(P_{D}-P_{P})\nonumber\\
&-&\frac{\partial}{\partial{y}}(P_{C}-P_{P})\frac{\partial}{\partial{x}}(P_{D}-P_{P})]\nonumber\\
&=&x^{*}y^{*}(1-x^{*}-y^{*})(N-1)^{2}pqb[pqh+(1-pq)B]\nonumber\\
&>&0,\end{aligned}$$ and $$\begin{aligned}
q&=&\frac{\partial{f}}{\partial{x}}(x^{*},y^{*})+\frac{\partial{g}}{\partial{y}}(x^{*},y^{*})\nonumber\\
&=&x^{*}(1-x^{*})\frac{\partial}{\partial{x}}(P_{C}-P_{P})+y^{*}(1-y^{*})\frac{\partial}{\partial{y}}(P_{D}-P_{P})\nonumber\\
&-&x^{*}y^{*}[\frac{\partial}{\partial{x}}(P_{D}-P_{P})+\frac{\partial}{\partial{y}}(P_{C}-P_{P})]\nonumber\\
&=&(N-1)[(1-pq)B+pqh-pqb]y^{*}(1-y^{*}-x^{*}).\end{aligned}$$

Consequently for $(1-pq)B+pqh-pqb<0$ the interior fixed point is stable.

\(2) For $\alpha\leq0$ or $\alpha\geq1$, the boundary equilibrium point of the $DP$ edge does not exist. Thus the system has four fixed points in the parameter space. The stability of $(0, 0, 1), (1, 0, 0),$ and $(1-\beta-\mu, \mu, \beta)$ will not change, compared with the case of $0<\alpha <1$. If $\alpha\geq1$, the fixed point $(0, 1, 0)$ is unstable since the largest eigenvalue of $J(0, 1, 0)$ is positive. If $\alpha<0$, the fixed point $(0, 1, 0)$ is stable. Particularly, for $\alpha=0$ we can prove that this fixed point is unstable by using the center manifold theorem [@Carr81; @Khalil96] (see Theorem.\[theorem3.3\]).

\[theorem3.3\] When $\frac{rc}{N}-c-G+pq(N-1)b=0$, the fixed point $(0, 1, 0)$ is unstable.

Because of $y = 1 - x - z$, the dynamic equations (\[system2\]) become $$\begin{aligned}
\label{system2.2}
\left\{
\begin{aligned}
\dot{x}&=x[(1-x)(P_{C}-P_{D})-z(P_{P}-P_{D})],\\
\dot{z}&=z[(1-z)(P_{P}-P_{D})-x(P_{C}-P_{D})],
\end{aligned}
\right.\label{2.3}\end{aligned}$$ where $$\begin{aligned}
P_{C}-P_{D}&=&\frac{rc}{N}-c+(1-pq)B(N-1)z+(N-1)pqzh,\\
P_{P}-P_{D}&=&\frac{rc}{N}-c-G+pq(N-1)(1-x-z)b\nonumber\\
&+&(1-pq)B(N-1)z+pq(N-1)zh.\end{aligned}$$

We know that $(x, z)=(0, 0)$ is an equilibrium point of the equation system (\[system2.2\]). Consequently the Jacobian is $$A=\begin{bmatrix}
\frac{rc}{N}-c & 0\\
0 & \frac{rc}{N}-c-G+pq(N-1)b
\end{bmatrix}.$$ When $\frac{rc}{N}-c-G+pq(N-1)b=0$, the eigenvalues of the Jacobian for the fixed point $(x, z)=(0, 0)$ are $0$ and $\frac{rc}{N}-c$. In this condition, we study the stability of the equilibrium point by further using the center manifold theorem [@Khalil96]. To do that, we construct a matrix $M$, whose column elements are the eigenvectors of the matrix $A$, given as $$M=\begin{bmatrix}
0 &&& 1\\
1 &&& 0
\end{bmatrix}.$$ Let $T=M^{-1}$, then we have $$TAT^{-1}=\begin{bmatrix}
0 &&& 0\\
0 &&& \frac{rc}{N}-c
\end{bmatrix}.$$ Using variable substitution, we have $$\begin{bmatrix}
v \\
u
\end{bmatrix}=T\begin{bmatrix}
x\\
z
\end{bmatrix}=\begin{bmatrix}
0 &&& 1\\
1 &&& 0
\end{bmatrix}\begin{bmatrix}
x\\
z
\end{bmatrix}=\begin{bmatrix}
z\\
x
\end{bmatrix}.$$ Therefore, the system (\[2.3\]) can be rewritten as $$\begin{aligned}
\left\{
\begin{aligned}
\dot{v}&=v(1-v)[\frac{rc}{N}-c-G+pq(N-1)(1-u-v)b+(1-pq)B(N-1)v\nonumber\\
&+pq(N-1)vh]-vu[\frac{rc}{N}-c+(1-pq)B(N-1)v+(N-1)pqvh],\\
\dot{u}&=u(1-u)[\frac{rc}{N}-c+(1-pq)B(N-1)v+(N-1)pqvh]-vu[\frac{rc}{N}-c\nonumber\\
&-G+pq(N-1)(1-u-v)b+(1-pq)B(N-1)v+pq(N-1)vh].
\end{aligned}
\right.\end{aligned}$$ Using the center manifold theorem [@Carr81; @Khalil96], we have that $u = e(v)$ is a center manifold for the above system. Then the dynamics on the center manifold, namely, the dynamics of $$\begin{aligned}
\label{A35}
\dot{v}&=&v(1-v)[\frac{rc}{N}-c-G+pq(N-1)(1-e(v)-v)b+(1-pq)B(N-1)v\nonumber\\
&+&pq(N-1)vh]-ve(v)[\frac{rc}{N}-c+(1-pq)B(N-1)v+(N-1)pqvh],\end{aligned}$$ determine the dynamics near the equilibrium point. Assuming that $e(v)=O(|v|^2)$, thus the system (\[A35\]) can be expressed as $$\begin{aligned}
\dot{v}=(v^{2}-v^{3})[-pq(N-1)b+(1-pq)(N-1)B+pq(N-1)h]+O(|v|^{4}).\end{aligned}$$ Since $-pq(N-1)b+(1-pq)(N-1)B+pq(N-1)h\neq0$, thus we obtain that $v=0$ is unstable. Accordingly, the fixed point $(0, 1, 0)$ is unstable in the equation system (\[system1\]).

Next we study the case when $(1-pq)B+pqh-pqb=0$. Here the eigenvalues of the Jacobian matrix for the interior equilibrium point are pure imaginary. Besides, the boundary equilibrium point of the $DP$ edge does not exist. Hence the system has four fixed points in the parameter space, namely, $(0, 0, 1), (1, 0, 0), (0, 1, 0)$, and $(1-\beta-\mu, \mu, \beta)$. The three vertexes are unstable since the largest eigenvalues of the Jacobian matrices of these three fixed points are all positive.\[case2\]

\[theorem3.2\] When $(1-pq)B+pqh-pqb=0$, the interior fixed point is a center surrounding by periodic closed orbits.

We introduce a new variable $\varepsilon=\frac{x}{x+y}$, which represents the fraction of cooperators among individuals who do not contribute to the punishment pool. This yields $$\begin{aligned}
\dot{\varepsilon}=\frac{xy}{(x+y)^{2}}(P_{C}-P_{D})=-\varepsilon(1-\varepsilon)(P_{D}-P_{C}).\end{aligned}$$ On the other hand, $\dot{z}=z(P_{P}-\bar{P})$, where $$\begin{aligned}
\bar{P}&=&xP_{C}+yP_{D}+zP_{P}\nonumber\\
&=&x(P_{C}-P_{D})+(1-z)(P_{D}-P_{P})+P_{P}.\end{aligned}$$ Thus we have $$\begin{aligned}
\dot{z}=z[x(P_{D}-P_{C})-(1-z)(P_{D}-P_{P})].\end{aligned}$$ Accordingly the equation system becomes $$\begin{aligned}
\left\{
\begin{aligned}
\dot{\varepsilon}&=\varepsilon(1-\varepsilon)[\frac{rc}{N}-c+(1-pq)B(N-1)z+(N-1)pqzh],\\
\dot{z}&=z(1-z)\{(1-\varepsilon)[\frac{rc}{N}-c+pq(N-1)(1-z)b\nonumber\\
&+(1-pq)B(N-1)z+pq(N-1)zh]-G\}.
\end{aligned}
\right.\end{aligned}$$ The separability of the factors allows us to write $$\begin{aligned}
\frac{dz}{d\varepsilon}=\frac{z(1-z)}{\frac{rc}{N}-c+(1-pq)B(N-1)z+(N-1)pqzh}\frac{(1-\varepsilon)[\frac{rc}{N}-c+pq(N-1)b]-G}{\varepsilon(1-\varepsilon)},\end{aligned}$$ such that $$\begin{aligned}
\int\frac{\frac{rc}{N}-c+(1-pq)B(N-1)z+(N-1)pqzh}{z(1-z)}dz\nonumber\\
=\int\frac{(1-\varepsilon)[\frac{rc}{N}-c+pq(N-1)b]-G}{\varepsilon(1-\varepsilon)}d\varepsilon.\end{aligned}$$ The integral of the right-hand side is $$\begin{aligned}
[\frac{rc}{N}-c+pq(N-1)b]\log(\varepsilon)-G[\log(\varepsilon)-\log(1-\varepsilon)].\end{aligned}$$ The integral of the left-hand side is $$\begin{aligned}
(\frac{rc}{N}-c)[\log(z)-\log(1-z)]-[(1-pq)B(N-1)\nonumber\\
+(N-1)pqh]\log(1-z).\end{aligned}$$

In this way, we identify the constant of motion $$\begin{aligned}
H(\varepsilon,z)&=&[\frac{rc}{N}-c+pq(N-1)b]\log(\varepsilon)-G[\log(\varepsilon)-\log(1-\varepsilon)]\nonumber\\
&+&(\frac{rc}{N}-c)[\log(z)-\log(1-z)]-[(1-pq)B(N-1)\nonumber\\
&+&(N-1)pqh]\log(1-z).\end{aligned}$$ Therefore, we have $$\begin{aligned}
\dot{H}=\frac{\partial{H}}{\partial{\varepsilon}}\dot{\varepsilon}+\frac{\partial{H}}{\partial{z}}\dot{z}=0.\end{aligned}$$ Accordingly, the system is conservative and all constant level sets of $H$ correspond to closed curves. Besides, the interior fixed point is neutrally stable surrounded by those closed and periodic orbits.

Last, when $(1-pq)B+pqh-pqb>0$, the existing interior fixed point is unstable.\[case3\]

\(1) For $0<\alpha<1$, there is a boundary equilibrium point on the $DP$ edge. Then the system has five fixed points in the parameter space, namely, $(0, 0, 1), (1, 0, 0), (0, 1, 0), (0, 1-\alpha, \alpha)$, and $(1-\beta-\mu, \mu, \beta)$.

The fixed points $(0, 0, 1), (1, 0, 0),$ and $(0, 1-\alpha, \alpha)$ are all unstable since the largest eigenvalues of the Jacobian matrices are all positive.

For $(x,y,z)=(0,1,0)$, the Jacobian is $$J=\begin{bmatrix}
\frac{rc}{N}-c &&& 0\\
-(G-pq(N-1)b) &&& \frac{rc}{N}-c-G+pq(N-1)b
\end{bmatrix},$$ thus this is a stable equilibrium point since $\frac{rc}{N}-c-G+pq(N-1)b<0$.

\(2) For $\alpha\leq0$ or $\alpha\geq1$, the boundary equilibrium point of the $DP$ edge does not exist. Thus the system has four fixed points in the mentioned parameter space. The stability of $(0, 0, 1), (1, 0, 0),$ and $(1-\beta-\mu, \mu, \beta)$ will not change, compared with the case of $0<\alpha<1$. If $\alpha\geq1$, the fixed point $(0, 1, 0)$ is stable since the largest eigenvalue of $J(0, 1, 0)$ is positive. If $\alpha\leq0$, the fixed point $(0, 1, 0)$ is unstable.

\[theorem3.4\] When $\frac{rc}{N}-c-G>\max\{-(N-1)[(1-pq)B+pqh],-pq(N-1)b\}$ and $r<N$, there is a stable heteroclinic cycle on the boundary of the simplex $S_{3}$.

When $\frac{rc}{N}-c-G>\max\{-(N-1)[(1-pq)B+pqh],-pq(N-1)b\}$ and $r<N$, we know that the three vertex equilibrium points ($C, D$, and $P$) are all saddle nodes, and the three edges ($CD, DP$, and $PC$) are the heteroclinic trajectories. All of these guarantee the existence of the heteroclinic cycle on the boundary $S_{3}$. In the following, we will prove that the heteroclinic cycle is asymptotically stable.

Based on the above analysis, we can get the eigenvalues of the Jacobian matrices of the three vertex equilibrium points, namely, $\lambda_{P}^{-}=-(N-1)[(1-pq)B+pqh]-(\frac{rc}{N}-c-G), \lambda_{P}^{+}=G, \lambda_{C}^{-}=-G, \lambda_{C}^{+}=c-\frac{rc}{N}, \lambda_{D}^{-}=\frac{rc}{N}-c,$ and $\lambda_{D}^{+}=\frac{rc}{N}-c-G+pq(N-1)b$, respectively. Then we respectively define that $\lambda_{P}=-\frac{\lambda_{P}^{-}}{\lambda_{P}^{+}}, \lambda_{C}=-\frac{\lambda_{C}^{-}}{\lambda_{C}^{+}},$ and $\lambda_{D}=-\frac{\lambda_{D}^{-}}{\lambda_{D}^{+}}$, and we have $\lambda=\lambda_{P}\lambda_{C}\lambda_{D}=\frac{\frac{rc}{N}-c-G+(N-1)[(1-pq)B+pqh]}{\frac{rc}{N}-c-G+pq(N-1)b}$. When $(1-pq)B+pq(h-b)>0$, we have $\lambda>1$. Therefore the heteroclinic cycle is asymptotically stable [@park18].

### There is no interior equilibrium point in the system (\[system1\]) {#subsection3.2.2}

When $\beta\geq1$, or $\mu\geq1$, or $\beta+\mu\geq1$, the interior fixed point does not exist.

\(1) For $0<\alpha<1$, there is a boundary equilibrium point on the $DP$ edge. Then the system has four fixed points in the parameter space, namely, $(0, 0, 1), (1, 0, 0), (0, 1, 0),$ and $(0, 1-\alpha, \alpha)$.

The fixed points $(0, 0, 1)$ and $(1, 0, 0)$ are both unstable since the largest eigenvalues of Jacobian matrices are both positive.

For $(x,y,z)=(0,1,0)$, the Jacobian is $$J=\begin{bmatrix}
\frac{rc}{N}-c &&& 0\\
-(G-pq(N-1)b) &&& \frac{rc}{N}-c-G+pq(N-1)b
\end{bmatrix},$$ thus the fixed equilibrium is a saddle point and unstable when $\frac{rc}{N}-c-G+pq(N-1)b>0$; while when $\frac{rc}{N}-c-G+pq(N-1)b<0$, it is stable.

For $(x, y, z)=(0, 1-\alpha, \alpha)$, the Jacobian is $$J=\begin{bmatrix}
a_{11} &&& 0\\
a_{21} &&& a_{22}
\end{bmatrix},$$ where $a_{11}=G-pq(N-1)(1-\alpha)b, a_{21}=\alpha(1-\alpha)[pq(N-1)h+(1-pq)(N-1)B]-(1-\alpha)[G-pq(N-1)(1-\alpha) b]$, and $a_{22}=\alpha(1-\alpha)(N-1)[(1-pq)B+pqh-pqb]$, thus the fixed equilibrium is stable when $pqb>\max\{\frac{G}{(N-1)(1-\alpha)}, (1-pq)B+pqh\}$, and it is unstable when $pqb<\max\{\frac{G}{(N-1)(1-\alpha)}, (1-pq)B+pqh\}$. Particularly, when $pqb=\max\{\frac{G}{(N-1)(1-\alpha)}, (1-pq)B+pqh\}$, we find that one eigenvalue of the Jacobian matrix at this fixed point is zero and the other one is negative. Accordingly, we study its stability by further using the center manifold theorem [@Khalil96] as follows.

For $0<\alpha<1$, we know $pqb\neq (1-pq)B+pqh$ and $\max\{\frac{G}{(N-1)y}, (1-pq)B+pqh\}=\frac{G}{(N-1)y}$. In order to use the center manifold theorem conveniently, we take $\xi =y-1+\alpha$, then the equation system becomes $$\begin{aligned}
\left\{
\begin{aligned}
\dot{x}&=x(1-x)[G-pq(N-1)(1+\xi-\alpha)b]-x(1+\xi-\alpha)[-(1-pq)\\
&B(N-1)(\alpha-x-\xi)-pq(N-1)(\alpha-x-\xi)h-rc/N+c\\
&+G-pq(N-1)b(1+\xi-\alpha)],\\
\dot{\xi}&=(1+\xi-\alpha)(\alpha-\xi)[-(1-pq)B(N-1)(\alpha-x-\xi)\\
&-pq(N-1)(\alpha-x-\xi)h-rc/N+c+G-pq(N-1)b(1+\xi-\alpha)]\\
&-x(1+\xi-\alpha)[G-pq(N-1)b(1+\xi-\alpha)].
\end{aligned}
\right.\end{aligned}$$ We further let $M$ be a matrix whose columns are the eigenvectors of $J(0, 1-\alpha, \alpha)$ which can be written as $$M=\begin{bmatrix}
\frac{a_{11}-a_{22}}{a_{21}} &&& 0\\
1 &&& 1
\end{bmatrix}.$$ Then we have $$M^{-1}J(0, 1-\alpha, \alpha)M=\begin{bmatrix}
0 &&& 0\\
0 &&& a_{22}
\end{bmatrix}.$$ We further take $[u \quad v]^{T} = M^{-1}[x \quad \xi]^{T}$, and thus we have $u = x / \theta$ and $v = \xi-x / \theta$ where we use the notation $\theta=\frac{a_{11}-a_{22}}{a_{21}}$. It leads to $$\begin{aligned}
\dot{u}&=&u(1-\theta u)[-(u+v)pq(N-1)b]-u(1+u+v-\alpha)\\
&\times&[-(1-pq)B(N-1)(\alpha-\theta u-u-v)-pq(N-1)(\alpha-\theta u-u-v)h\\
&-&rc/N+c-pq(N-1)b(u+v)].\end{aligned}$$ Using the center manifold theorem, we have that $v = e(u)$ is a center manifold. We assume that $e(u) = O(|u|^{2})$, which yields the reduced system $$\begin{aligned}
\dot{u}&=-u^{2}pq(N-1)b+\theta u^{3}pq(N-1)b+O(|u|^{4}).\end{aligned}$$ Since $-pq(N-1)b\neq0$, we know that the fixed point $(u, e(u))=(0, 0)$ is unstable for the reduced system. Accordingly, the fixed point $(0, 1-\alpha, \alpha)$ is unstable.

\(2) For $\alpha\leq0$ or $\alpha\geq1$, the boundary equilibrium point of the $DP$ edge does not exist. Then the system has only three fixed points in the parameter space, namely, $(0, 0, 1), (1, 0, 0),$ and $(0, 1, 0)$.

The fixed point $(0, 0, 1)$ and $(1, 0, 0)$ are both unstable since the largest eigenvalues of corresponding Jacobian matrices are both positive. If $\frac{rc}{N}-c-G+pq(N-1)b<0$, the fixed point $(0, 1, 0)$ is stable, while it is a saddle point and becomes unstable when $\frac{rc}{N}-c-G+pq(N-1)b>0$. Particulary, when $rc/N-c-G+pq(N-1)b=0$ and $(1-pq)B+pqh-pqb\neq0$, it is unstable.

Numerical examples
==================

![image](Fig1.pdf){width="5in"}

We now provide some numerical examples to confirm the above theoretical analysis. We use the simplex $S_{3}=\{(x, y, z): x, y, z\geq 0, x+y+z=1\}$ to depict the state space of above three strategies. Accordingly, the three homogeneous states $C$ ($x=1$), $D$ ($y=1$), and $P$ ($z=1$) correspond to three corners of the simplex $S_{3}$. All of these are equilibrium points of the system (\[system1\]). We first present numerical cases when the system (\[system1\]) has an interior equilibrium point. When $\beta<1, \mu<1$, and $\beta+\mu<1$, there is an interior fixed point. From the theoretical analysis we know that its stability is determined by the relationship between the expected loss $(1-pq)B+pqh$ of defectors and the expected bribe amount $pqb$ received by punishers.

Stable interior equilibrium point
---------------------------------

In the following we present a numerical example to confirm that the system can have a stable interior equilibrium point. As shown in Fig. \[fig1\](a), we see that there exist five equilibria in the simplex $S_{3}$. The existing interior equilibrium point is stable and all interior orbits converge to this point, irrespective of the initial conditions. Besides, a boundary equilibrium point between all defectors and all punishers appears on the edge $DP$, which is unstable. Furthermore, the direction of the evolution on the $CP$ edge is from $P$ to $C$, and from $C$ to $D$ on the $CD$ edge. Figure \[fig1\](b) depicts the time evolution of the frequencies of cooperators, defectors, and punishers. We can see that all mentioned strategists can coexist when the system reaches the steady state. Furthermore, the fraction of punishers is the highest, and the fraction of defectors is the lowest.

It is worth noting that all these results above are consistent with the theoretical results. In particular, when $(1-pq)B+pqh-pqb<0$, the interior equilibrium point is stable. And the boundary fixed point with $z=\alpha$ on $DP$ edge can appear when $0<\alpha<1$. According to our theoretical analysis, we know that it is unstable since $G-pq(N-1)(1-\alpha)b>0$ (see Theorem \[T3.1\] and Sec. \[subsection3.2.1\]).

Hamiltonian system
------------------

![image](Fig2.pdf){width="5in"}

In this section we provide a numerical example to confirm that the system can become a Hamiltonian system. In Fig. \[fig2\](a), we see that the existing interior equilibrium point is a center surrounded by periodic orbits and the strategy evolution trajectory displays a limit cycle. No boundary fixed points can be detected on the three edges. And the direction of evolution on the $DP$ edge is from $D$ to $P$, from $P$ to $C$ on the $PC$ edge, and from $C$ to $D$ on the $CD$ edge. Figure \[fig2\](b) depicts that the frequencies of these three strategies display periodic oscillations in dependence on time, which is corresponding to the limit cycle shown in Fig. \[fig2\](a). All these results are in agreement with the theoretical prediction, namely, when $(1-pq)B+pqh-pqb=0$ the interior fixed point is neutrally stable, and the dynamic system is Hamiltonian (see Theorem \[theorem3.2\] of Sec. \[section3\]).

The cyclical evolutionary scenario can be described as follows. If most players are cooperators in the group, it is better to become a defector due to the social dilemma. If defectors are prevalent, corrupt officials can get a lot of bribes from a group of defectors, and thus the number of punishers increases. If most players are punishers, the bribes from a few defectors are usually small enough to subvert cooperators dominance over punishers, and thus cooperators spread. If the number of cooperators increases sufficiently, then the original cooperation dilemma returns. It is worth noting that cooperative behavior can still emerge even in a completely corrupt environment. As we set that $p=q=1$, which means that all defectors are willing to offer a bribe to punishers, and all punishers are corrupt officials. It is inspiring to see that altruistic behavior can still be maintained due to the oscillations recurrent increase in cooperation.

Heteroclinic cycle
------------------

![image](Fig3.pdf){width="5in"}

We provide a numerical example to confirm that the heteroclinic cycle can exist in our equation system. Figure \[fig3\](a) shows that there are four unstable fixed points in the simple $S_{3}$, and all interior curves of state space converge to the boundary of $S_{3}$. Besides, the direction of the evolution on the $DP$ edge is from $D$ to $P$, on the $PC$ edge is from $P$ to $C$, while on the $CD$ edge is from $C$ to $D$. Figure \[fig3\](b) depicts that the frequencies of the three strategies are oscillating and the amplitudes are gradually growing, eventually forming periodic oscillations. This means that these three strategies can be cyclically dominant in the population and can thus avoid the collapse of cooperation. Note that these numerical results are in agreement with the theoretical analysis which predicts that the population converges to a stable heteroclinic cycle on the boundary of $S_3$ for $(1-pq)B+pqh-pqb>0$, $\frac{rc}{N}-c-G>\max\{-(N-1)[(1-pq)B+pqh],-pq(N-1)b\}$ and $r<N$ (Theorem \[theorem3.4\] of Sec. \[section3\]).

Global stability of all-D state
-------------------------------

![image](Fig4.pdf){width="5in"}

Next we provide a numerical example to confirm that the equation system can converge to the all-$D$ state with global stability when the interior equilibrium point is unstable. As shown in Fig. \[fig4\](a), there are five fixed points in the simplex $S_{3}$. All interior orbits coverage to the vertex $D$, which is a global stable equilibrium point. In the boundary case the unstable equilibrium point on the $DP$ edge reappears. Besides, defectors can always do better than cooperators on the $CD$ edge, and cooperators have more advantages than punishers on the remaining $CP$ edge. In Fig. \[fig4\](b), we show how the frequencies of the three strategies evolve with time when the initial fractions of cooperators, defectors, and punishers are $0.8$, $0.1$, and $0.1$, respectively. Finally the fraction of defectors reaches one. This numerical calculation is in agreement with our theoretical prediction that the system converges on the all-$D$ state for $\frac{rc}{N}-c-G+pq(N-1)b<0$ (Sec. \[subsection3.2.1\]).

Boundary equilibrium point with the coexistence of defectors and punishers
--------------------------------------------------------------------------

![image](Fig5.pdf){width="5in"}

Finally we present a numerical example to confirm that there exists a stable boundary equilibrium point with the coexistence of defectors and punishers. In Fig. \[fig5\](a), we show that the system converges to the stable boundary equilibrium point on the $DP$ edge, irrespective of the initial conditions, which means that defectors and punishers can coexist permanently in the population, while cooperators disappear. Besides, the evolutionary direction on $CD$ edge is from $C$ to $D$, while it is from $P$ to $C$ on the $CP$ edge. Figure \[fig5\](b) shows that the fraction of cooperators gradually reduces to zero, even though their initial frequency is relatively high. In parallel the fraction of punishers finally reaches about $0.8$, while the fraction of defectors converges to about $0.2$. These numerical results validate our theoretical analysis based on which as long as the interior equilibrium does not exist, the boundary fixed point on the $DP$ edge is globally stable (Sec. \[subsection3.2.2\]).

Conclusions
===========

In this paper, we have introduced probabilistic corrupt enforcers and violators into the PGG and investigated their consequence on the evolution of cooperation and punishment in infinite well-mixed populations. As a result, we have observed basically two different evolutionary scenarios. Namely, the competing strategies either coexist by forming stable time-dependent fractions or they dominate each other in a rock-scissors-paper game like manner. But for both cases the cooperative behavior can be well preserved. We have further identified the conditions in which the two dynamic behaviors can appear. We find that when the expected loss is less than the related bribe amount, a stable coexistence state among these three strategists can appear. In the alternative case, when these two quantity values are identical, the replicator dynamical system can be reduced to a Hamiltonian system. Here a center surrounded by closed orbits appears in the interior of the simplex $S_{3}$, which means that these three strategies are mutually restrained and exhibit periodic oscillations. When the expected loss is larger than the expected bribe amount, the interior fixed point is unstable, and two different evolutionary dynamic behaviors can emerge, namely, stable heteroclinic cycle and global attractor $D$. The former can guarantee that cooperators, defectors, and punishers are cyclically dominant in the population, while the latter will lead to the collapse of cooperation.

The key feature of our model is that corruption may emerge stochastically, either from the side of violators or from corrupt enforcers. This realistic assumption can be modeled in infinite well-mixed populations by using replicator equations. The study of such highly nonlinear equation systems is really challenging [@Hauert02], but we could manage a comprehensive and systematic theoretical analysis. We could identify all equilibrium points and characterize their stability by appropriately linearizing the equation system. In particular, when there are pure imaginary among the eigenvalues of the Jacobian we cannot determine the stability of an equilibrium point based only on the eigenvalues. Instead, we investigate its stability by utilizing the center manifold theorem [@Carr81; @Khalil96]. Furthermore, we not only prove that the system can exhibit the central limit cycle, but also theoretically confirm the existence and stability of heteroclinic cycle.

Recently, Huang et al. [@Huang2018] investigated the effect of corruption on the evolution of cooperation and punishment in a hierarchical society which is divided into civilians and cops. Our present work, however, focuses on the evolutionary dynamics of cooperation, defection, and punishment in an integrated society when corruption is possible. Importantly, we consider that defectors probabilistically bribe enforcers to avoid punishment and meanwhile pool punishers probabilistically accept a bribe from defectors, which can reflect a realistic behavior manner of individuals in human societies. This behavior was studied in a population where individuals play the PGG with pool punishment [@Sigmund2011Social], and thus provides an alternative, but reasonable route to study the effects of corruption on collective actions of cooperation. Rather unexpectedly, the introduction of corruption can stabilize cooperation, and more interesting dynamic behaviors can be derived which may provide some implications for designing sanctioning strategies to support the evolution of cooperation.

We point out that although cooperative behavior can occur in a corrupt environment, the long-term existence of corruption will seriously harm the economy and society as a whole. For example, one cross-cultural experiment involving thousands of people worldwide showed that corruption not only deprives people of economic prosperity and growth, but also jeopardizes their intrinsic honesty [@Salvi16]. We should stress that our present model does not explicitly consider a strategy chance of an anti-corruption control which could be an additional source of cooperation support. Such kind of extension could be the scope of future research. On the other hand, however, although powerful anti-corruption monitoring and sanctioning have been used to resolve the corruption problem, the effects of such measures are either transient or uncertain [@Abdallah14; @Lee2017; @Muthukrishna2017; @Verma2017; @Huang2018]. For example, Muthukrishna et al. [@Muthukrishna2017] found that anti-corruption strategies are effective under some conditions, but can further decrease public good provisioning when leaders are weak and the economic potential is poor even if these strategies are powerful. The failure of anti-corruption strategies is related to many independent factors, and the most important factor may be that the reason why enforcers are apt to fall into corruption is unclear. A recent experimental study has revealed the reason why the upper-class individuals behave more unethically than lower-class individuals is that they are more favorable attitudes toward greed [@piff2014pnas]. Consequently, the task how to design efficient anti-corruption strategies for resisting the occurrence of corruption from the source remains an open and challenging question.

Acknowledgments {#acknowledgments .unnumbered}
===============

This research was supported by the National Natural Science Foundation of China (Grant Nos. 61976048 and 61503062), and by the Hungarian National Research Fund (Grant K-120785), and by the Science Strength Promotion Programme of University of Electronic Science and Technology of China.

[00]{}

S. Abdallah, R. Sayed, I. Rahwan, B. L. LeVeck, M. Cebrian, A. Rutherford, and J. H. Fowler, Corruption drives the emergence of civil society, [*J. Roy. Soc. Interface*]{} [**11**]{} (2014) 20131044. G. Ajmone Marsan, N. Bellomo, and L. Gibelli, Stochastic evolutionary differential games toward a systems theory of behavioral social dynamics, [*Math. Models Methods Appl. Sci.*]{} [**26**]{} (2016), 1051-1093. J. M. Allen, A. C. Skeldon, and R. B. Hoyle, Social influence preserves cooperative strategies in the conditional cooperator public goods game on a multiplex network, [*Phys. Rev. E*]{} [**98** ]{}(2018) 062305. J. Andreoni, W. Harbaugh, and L. Vesterlund, The carrot or the stick: Rewards, punishments, and cooperation, [*Am. Econ. Rev.*]{} [**93**]{} (2003) 893–902.

N. Bellomo, H. Berestycki, F. Brezzi, and J. Nadal, Mathematics and complexity in life and human sciences, [*Math. Models Methods Appl. Sci.*]{} [**19**]{} (2009) 1385-1389.

N. Bellomo and F. Brezzi, Mathematics and complexity in biological sciences, [*Math. Models Methods Appl. Sci.*]{} [**21**]{} (2011) 819-824.

N. Bellomo, F. Brezzi, and M. Pulvirenti, Modeling behavioral social systems, [*Math. Models Methods Appl. Sci.*]{} [**27**]{} (2017) 1–11. N. Bellomo and S. Y. Ha, A quest toward a mathematical theory of the dynamics of swarms, [*Math. Models Methods Appl. Sci.*]{} [**27**]{} (2017) 745–770. D. Burini, S. De Lillo and L. Gibelli, Collective learning modeling based on the kinetic theory of active particles, [*Phys. Life Rev.*]{}, [**16**]{} (2016), 123-139. J. Carr, [*Applications of Center Manifold Theory*]{}, (Springer Verlag, New York, 1981) X. Chen, T. Sasaki, [Å]{}. Brännström, and U. Dieckmann, First carrot, then stick: how the adaptive hybridization of incentives promotes cooperation, [*J. Roy. Soc. Interface*]{} [**12**]{} (2014) 20140935.

X. Chen and A. Szolnoki, Punishment and inspection for governing the commons in a feedback-evolving game, [*PLOS Comp. Biol.*]{} [**14**]{} (2018) e1006347. X. Chen, A. Szolnoki, and M. Perc, Risk-driven migration and the collective-risk social dilemma, [*Phys. Rev. E*]{} [**86**]{} (2012) 036101.

X. Chen, A. Szolnoki, and M. Perc, Probabilistic sharing solves the problem of costly punishment, [*New J. Phys.*]{} [**16**]{} (2014) 083016.

M. Dolfin and M. Lachowicz, Modeling altruism and selfishness in welfare dynamics: The role of nonlinear interactions, [*Math. Models Methods Appl. Sci.*]{} [**24**]{} (2014) 2361-2381. M. Dolfin, L. Leonida, and N. Outada, Modelling human behaviour in economics and social science, Physics of Life Reviews, 22 (2017), 1-21. E. Fehr and U. Fischbacher, The nature of human altruism, [*Nature*]{} [**425**]{} (2003) 785–791. E. Fehr and S. Gächter, Altruistic punishment in humans, [*Nature*]{}, [**415**]{} (2002) 137. F. Fu, C. Hauert, M. A. Nowak, and L. Wang, Reputation-based partner choice promotes cooperation in social networks, [*Phys. Rev. E*]{} [**78**]{} (2008) 026117.

F. Fu, M. A. Nowak, and C. Hauert, Invasion and expansion of cooperators in lattice populations: Prisoner’s dilemma vs. snowdrift games, [*J. Theor. Biol.*]{} [**266**]{} (2010) 358–366 W. D. Hamilton, The evolution of altruistic behavior, [*Am. Nat.*]{} [**97**]{} (1963) 354-356. G. Hardin, The tragedy of the commons, [*Science*]{} [**162**]{} (1968) 1243–1248. C. Hauert, S. De Monte, J. Hofbauer, and K. Sigmund, Volunteering as red queen mechanism for cooperation in public goods games, [*Science*]{} [**296**]{} (2002) 1129–1132. C. Hauert, S. De Monte, J. Hofbauer, and K. Sigmund, Replicator dynamics for optional public good games, [*J. Theor. Biol.*]{} [**218**]{} (2002) 187–194. N. He, X. Chen, and A. Szolnoki. Central governance based on monitoring and reporting solves the collective-risk social dilemma, [*Appl. Math. Comput.*]{} [**347**]{} (2019) 334–341. M. A. Herrero and J. Soler, Cooperation, competition, organization: The dynamics of interacting living populations, [*Math. Models Methods Appl. Sci.*]{} [**25**]{} (2015) 2407–2415. C. Hilbe, L. Schmid, J. Tkadlec, K. Chatterjee, and M. A. Nowak, Indirect reciprocity with private, noisy, and incomplete information, [*Proc. Natl. Acad. Sci. USA*]{} [**115**]{} (2018) 12241-12246. J. Hofbauer and K. Sigmund, [*Evolutionary Games and Population Dynamics*]{}, (Cambridge University Press, 1998). F. Huang, X. Chen, and L. Wang, Evolution of cooperation in a hierarchical society with corruption control, [*J. Theor. Biol.*]{} [**449**]{} (2018) 60–72. H. K. Khalil, [*Noninear Systems*]{}, (Prentice-Hall, 1996) J. H. Lee, M. Jusup, and Y. Iwasa, Games of corruption in preventing the overuse of common-pool resources, [*J. Theor. Biol.*]{} [**428**]{} (2017) 76–86. L. Liu, X. Chen, and A. Szolnoki, Competitions between prosocial exclusions and punishments in finite populations, [*Sci. Rep.*]{} [**7**]{} (2017) 46634. L. Liu, S. Wang, X. Chen, and M. Perc, Evolutionary dynamics in the public goods games with switching between punishment and exclusion, [*Chaos*]{}, [**28**]{} (2018) 103105. M. Milinski, D. Semmann, and H. J. Krambeck, Reputation helps solve the ‘tragedy of the commons’, [*Nature*]{} [**415**]{} (2002) 424. M. Muthukrishna, P. Francois, S. Pourahmadi, and J. Henrich, Corrupting cooperation and how anti-corruption strategies may backfire, [*Nat. Hum. Behav.*]{} [**1**]{} (2017) 0138. M. A. Nowak, Five rules for the evolution of cooperation, [*Science*]{} [**314**]{} (2006) 1560–1563. M. A. Nowak and K. Sigmund, Evolutionary dynamics of biological games, [*Science*]{} [**303**]{} (2004) 793-799. L. Pareschi and G. Toscani, [*Interacting multiagent systems: kinetic equations and Monte Carlo methods*]{} (Oxford University Press, Oxford, 2013). J. Park, Balancedness among competitions for biodiversity in the cyclic structured three species system, [*Appl. Math. Comput.*]{} [**320**]{} (2018) 425–436. M. Perc, J. J. Jordan, D. G. Rand, and Z. Wang, S. Boccaletti, and A. Szolnoki, Statistical physics of human cooperation, [*Phys. Rep.*]{} [**687**]{} (2017) 1–51. M. Perc and A. Szolnoki, Social diversity and promotion of cooperation in the spatial prisoner’s dilemma game, [*Phys. Rev. E*]{} [**77**]{} (2008) 011904. M. Perc and A. Szolnoki, Coevolutionary games–a mini review, [*BioSystems*]{} [**99**]{} (2010) 109–125. P. K. Piff, D. M. Stancato, S. Côté, R. Mendoza-Denton, and D. Keltner, Higher social class predicts increased unethical behavior, [*Proc. Natl. Acad. Sci. USA*]{} [**109**]{} (2012) 4086-4091. B. Rockenbach and M. Milinski, The efficient interaction of indirect reciprocity and costly punishment, [*Nature*]{} [**444**]{} (2006) 718–723. S. Salvi, Corruption corrupts: Society-level rule violations affect individuals’ intrinsic honesty, [*Nature*]{} [**531**]{} (2016) 456–457. F. C. Santos, C. Francisco, and J. M. Pacheco, Risk of collective failure provides an escape from the tragedy of the commons, [*Proc. Natl. Acad. Sci. USA*]{} [**108**]{} (2011) 10421–10425.

F. C. Santos, F. L. Pinheiro, T. Lenaerts, and J. M. Pacheco, The role of diversity in the evolution of cooperation, [*J. Theor. Biol.*]{} [**299**]{} (2012) 88–96.

F. C. Santos, M. D. Santos, and J. M. Pacheco, Social diversity promotes the emergence of cooperation in public goods games, [*Nature*]{} [**454**]{} (2008) 213–216. F. C. Santos, V. V. Vasconcelos, M. D. Santos, P. N. B. Neves, and J. M. Pacheco, Evolutionary dynamics of climate change under collective-risk dilemmas, [*Math. Models Methods Appl. Sci.*]{} [**22**]{} (2012) 1140004.

T. Sasaki, A. Brännström, U. Dieckmann, and K. Sigmund, The take-it-or-leave-it option allows small penalties to overcome social dilemmas, [*Proc. Natl. Acad. Sci. USA*]{} [**109**]{} (2012) 1165–1169, T. Sasaki and S. Uchida, The evolution of cooperation by social exclusion, [*Proc. R. Soc. B*]{} [**280**]{} (2012) 20122498. K. Sigmund, H. De Silva, A. Traulsen, and C. Hauert, Social learning promotes institutions for governing the commons, [*Nature*]{} [**466**]{} (2010) 861–863. K. Sigmund, C. Hauert, A. Traulsen, and H. De Silva, Social Control and the Social Contract: The Emergence of Sanctioning Systems for Collective Action, [*Dyn. Games Appl.*]{} [**1**]{} (2011) 149–171. A. Szolnoki and X. Chen, Alliance formation with exclusion in the spatial public goods game, [*Phys. Rev. E*]{} [**95**]{} (2017) 052316. A. Szolnoki and X. Chen, Competition and partnership between conformity and payoff-based imitations in social dilemmas, [*New. J. Phys.*]{} [**20**]{} (2018) 093008.

A. Szolnoki and X. Chen, Reciprocity-based cooperative phalanx maintained by overconfident players, [*Phys. Rev. E*]{} [**98**]{} (2018) 022309.

A. Szolnoki and M. Perc, Resolving social dilemmas on evolving random networks, [*EPL*]{} [**86**]{} (2009) 30007. A. Szolnoki and M. Perc, Evolutionary advantages of adaptive rewarding, [*New J. Phys.*]{} [**14**]{} (2012) 93016. A. Szolnoki and M. Perc, Effectiveness of conditional punishment for the evolution of public cooperation, [*J. Theor. Biol.*]{} [**325**]{} (2013) 34–41. A. Szolnoki and G. Szab[ó]{}, Cooperation enhanced by inhomogeneous activity of teaching for evolutionary Prisoner’s Dilemma games, [*EPL*]{} [**77**]{} (2007) 30004. A. Szolnoki, G. Szab[ó]{}, and M. Perc, Phase diagrams for the spatial public goods game with pool punishment, [*Phys. Rev. E*]{} [**83**]{} (2011) 036101. J. Tanimoto and H. Sagara, Relationship between dilemma occurrence and the existence of a weakly dominant strategy in a two-player symmetric game, [*BioSystems*]{} [**90**]{} (2007) 105-114. V. V. Vasconcelos, F. C. Santos, and J. M. Pacheco, A bottom-up institutional approach to cooperative governance of risky commons, [*Nat. Clim. Change*]{} [**25**]{} (2013) 797. V. V. Vasconcelos, F. C. Santos, and J. M. Pacheco, Cooperation dynamics of polycentric climate governance, [*Math. Models Methods Appl. Sci.*]{} [**25**]{} (2015) 2503–2517. P. Verma, A. K. Nandi, and S. Sengupta, Bribery games on inter-dependent regular networks, [*Sci. Rep.*]{} [**7**]{} (2017) 42735. P. Verma and S. Sengupta, Bribe and punishment: An evolutionary game-theoretic analysis of bribery, [*PLoS ONE*]{} [**10**]{} (2015) e0133441. Q. Wang, N. He, and X. Chen, Replicator dynamics for public goods game with resource allocation in large populations, [*Appl. Math. Comput.*]{} [**328**]{} (2018) 162–170. T. Wu, F. Fu, and L. Wang, Coevolutionary dynamics of aspiration and strategy in spatial repeated public goods games, [*New J. Phys.* ]{} [**20**]{} (2018) 063007. H-X. Yang and X. Chen, Promoting cooperation by punishing minority, [*Appl. Math. Comput.*]{} [**316**]{} (2018) 460–466.