Page 1 of 1

Including/excluding no-choice alternative

PostPosted: Wed Aug 10, 2022 12:10 am
by ljpu
Dear users and moderators,

Currently I'm designing a DCE for measuring citizens' preferences for public participation along the policy cycle. The participation moment (in the policy cycle) is fixed in the two alternatives to enable a comprehensible comparison for respondents. The attribute `E' represents price, and the rest of the attribute levels are effects coded because they are not continuous but describe certain characteristics of a participation process.

I'm still not sure whether to include an opt-out alternative (i.e. no public participation), but an issue arose here. When I do not specify a third alternative `alt3' Ngene will not generate a design and report:
Warning: No valid design has been found after 1000 evaluations. There may be a problem with the specification of the design. A common problem is that the choice probabilities are too extreme (close to 1 and 0), perhaps because some or all of the prior values are too large. Also, it is generally a good idea to start with a simple design (MNL, non-Bayesian), then add complexity. If you press stop, a design will be reported, which may assist in diagnosing the problem.

However, if I do include a third alternative `alt3', Ngene does generate a design, but an opt-out option is not visible in the (formatted) scenarios. It also does not show if I specify `alt3' and include another utility function `U(alt3) = asc'.
So, my question is why does it not generate a design if I only specify two alternatives, and why does an opt-out alternative not show in the design if I specify one? Furthermore, I don't have knowledge about prior-values, so I did not specify any, and specified them as zero for the effects coding.

Thanks in advance!


Code: Select all
Design

;alts = alt1, alt2

? (Currently) 14 estimated parameters in utility-function, and 2 alternatives (alt3 is `opt out'). So, minimum of 14/2 = 7 choice tasks.
;rows = 14
;eff

;cond:

? If listen as a spectator, then only personal benefit possible
if(alt1.C = 1, alt1.D = 1),     
if(alt2.C = 1, alt2.D = 1),                             

? If aggregate & bargain or deliberate & negotiate, listen as spectator not possible
if(alt1.C = [3, 4], alt1.D = [1, 2, 3, 4]),
if(alt2.C = [3, 4], alt2.D = [1, 2, 3, 4]),

? Specify costs for scenarios

if(alt1.B = 0 and alt1.C = 0, alt1.E = 62500),
if(alt1.B = 0 and alt1.C = 1, alt1.E = 156250),
if(alt1.B = 0 and alt1.C = 2, alt1.E = 250000),
if(alt1.B = 0 and alt1.C = 3, alt1.E = 437500),
if(alt1.B = 0 and alt1.C = 4, alt1.E = 625000),
if(alt1.B = 1 and alt1.C = 0, alt1.E = 37500),
if(alt1.B = 1 and alt1.C = 1, alt1.E = 62500),
if(alt1.B = 1 and alt1.C = 2, alt1.E = 156250),
if(alt1.B = 1 and alt1.C = 3, alt1.E = 250000),
if(alt1.B = 1 and alt1.C = 4, alt1.E = 437500),
if(alt1.B = 2 and alt1.C = 0, alt1.E = 12500),
if(alt1.B = 2 and alt1.C = 1, alt1.E = 37500),
if(alt1.B = 2 and alt1.C = 2, alt1.E = 62500),
if(alt1.B = 2 and alt1.C = 3, alt1.E = 156250),
if(alt1.B = 2 and alt1.C = 4, alt1.E = 250000),

if(alt2.B = 0 and alt2.C = 0, alt2.E = 62500),
if(alt2.B = 0 and alt2.C = 1, alt2.E = 156250),
if(alt2.B = 0 and alt2.C = 2, alt2.E = 250000),
if(alt2.B = 0 and alt2.C = 3, alt2.E = 437500),
if(alt2.B = 0 and alt2.C = 4, alt2.E = 625000),
if(alt2.B = 1 and alt2.C = 0, alt2.E = 37500),
if(alt2.B = 1 and alt2.C = 1, alt2.E = 62500),
if(alt2.B = 1 and alt2.C = 2, alt2.E = 156250),
if(alt2.B = 1 and alt2.C = 3, alt2.E = 250000),
if(alt2.B = 1 and alt2.C = 4, alt2.E = 437500),
if(alt2.B = 2 and alt2.C = 0, alt2.E = 12500),
if(alt2.B = 2 and alt2.C = 1, alt2.E = 37500),
if(alt2.B = 2 and alt2.C = 2, alt2.E = 62500),
if(alt2.B = 2 and alt2.C = 3, alt2.E = 156250),
if(alt2.B = 2 and alt2.C = 4, alt2.E = 250000)

? Effects coding for individual level utility observance
? Effects coding instead of dummy because non-zero base-levels. Better for comparison with other attributes

;model:
U(alt1) =   A.effects[0|0|0]      * A[0,1,2,3]
          +    b2.effects[0|0]        * B[0,1,2]
          +    b3.effects[0|0|0|0] * C[0,1,2,3,4]
          +    b4.effects[0|0|0|0] * D[0,1,2,3,4]
          +    b5                           * E[12500, 37500, 62500, 156250, 250000, 437500, 625000]
         
/
? Fix `A' as same moment as in alt1 for understandable comparison.
U(alt2) = A                    * A[A]         
          +  b2                  * B       
          +  b3                  * C           
          +  b4                  * D
          +  b5                  * E               
$

Re: Including/excluding no-choice alternative

PostPosted: Wed Aug 10, 2022 12:26 am
by Michiel Bliemer
You have perfectly correlated alt1.A and alt2A, so there is never a trade-off between alt1 and alt2 with respect to attribute A, it is a constant and hence its parameters cannot be estimated. If you add an opt-out, then these parameters become identifiable since attribute A is no longer a constant across ALL alternatives.

If you want to include an attribute that is constant across alternatives, which is often referred to as a scenario variable, then there are only two ways to add them to the utility function to guarantee parameter identifiability in model estimation:

1. Add an opt-out alternative and add the scenario variable as a main effect in the other utility functions (as you have done), or
2. Interaction attribute A with other attributes to describe the impact of attribute A on the preferences towards other attributes.

You can also use a combination of approach 1 and 2.

An opt-out alternative does not have attributes, so it does not appear in the design matrix and hence also does not appear in the formatted choice tasks. You can add the opt-out manually in the formatted choice tasks by right-clicking with the mouse in the editor of the formatted scenarios and adding a column.

Using zero priors is fine. If you want Ngene to avoid dominant alternatives, you could add small positive/negative prior values to indicate the preference order of the attribute levels, e.g. something like

Code: Select all
;alts = alt1*, alt2*, optout
...
;model:
U(alt1) = A.effects[0.001|0.002|0.003] * A[1,2,3,0]  ? note that the LAST level is the base level
        + ...
        + b5[-0.00000081] * E[12500, 37500, 62500, 156250, 250000, 437500, 625000]


Michiel

Re: Including/excluding no-choice alternative

PostPosted: Wed Aug 10, 2022 1:12 am
by ljpu
Dear mr. Bliemer,

Thanks for your quick response, that's very clear! And it's a scenario variable indeed! As for option 2., if I understood the manual correctly, is it true one should then include an interaction-term for every level combination of attribute A with attributes B, C, and D? So,

Code: Select all
+ i1 *  A[1] * B[1] + i2 * A[1] * B[2] etc.
+ ix  * A[2] * B[1] + iy * A[2] * B[2] etc.
etc.
+ ik * A[1] * C[1] + ij  * A[2] * C[2] etc.
etc.


instead of e.g.

Code: Select all
+ A * (i1.effects[0,0] * B + i2.effects[0,0,0,0] * C + i3.effects[0,0,0,0] * D + i4 * E)

Re: Including/excluding no-choice alternative

PostPosted: Wed Aug 10, 2022 7:51 am
by Michiel Bliemer
You would get something like the syntax below. Note that if you include all interaction effects with A, you get a lot of parameters to estimate so you may want to select the most relevant interactions for your specific study.

Note that it is currently not possibly in Ngene to specify categorical variables only in interactions because they first need to be defined in a main effect. I applied a trick in Ngene that I first specify A as a main effect in model m1, and then once A is defined and known to Ngene, I can use it only in an interaction in model m2 that is being optimised on.

Code: Select all
Design

;alts(m1) = alt1*, alt2*
;alts(m2) = alt1*, alt2*

;rows = 50
;eff = m2(mnl,d)

;cond:
? A is scenario variable
if(alt1.A = 0, alt2.A = 0),
if(alt1.A = 1, alt2.A = 1),
if(alt1.A = 2, alt2.A = 2),
if(alt1.A = 3, alt2.A = 3),

? If listen as a spectator, then only personal benefit possible
if(alt1.C = 1, alt1.D = 1),     
if(alt2.C = 1, alt2.D = 1),                             

? If aggregate & bargain or deliberate & negotiate, listen as spectator not possible
if(alt1.C = [3, 4], alt1.D = [1, 2, 3, 4]),
if(alt2.C = [3, 4], alt2.D = [1, 2, 3, 4]),

? Specify costs for scenarios

if(alt1.B = 0 and alt1.C = 0, alt1.E = 62500),
if(alt1.B = 0 and alt1.C = 1, alt1.E = 156250),
if(alt1.B = 0 and alt1.C = 2, alt1.E = 250000),
if(alt1.B = 0 and alt1.C = 3, alt1.E = 437500),
if(alt1.B = 0 and alt1.C = 4, alt1.E = 625000),
if(alt1.B = 1 and alt1.C = 0, alt1.E = 37500),
if(alt1.B = 1 and alt1.C = 1, alt1.E = 62500),
if(alt1.B = 1 and alt1.C = 2, alt1.E = 156250),
if(alt1.B = 1 and alt1.C = 3, alt1.E = 250000),
if(alt1.B = 1 and alt1.C = 4, alt1.E = 437500),
if(alt1.B = 2 and alt1.C = 0, alt1.E = 12500),
if(alt1.B = 2 and alt1.C = 1, alt1.E = 37500),
if(alt1.B = 2 and alt1.C = 2, alt1.E = 62500),
if(alt1.B = 2 and alt1.C = 3, alt1.E = 156250),
if(alt1.B = 2 and alt1.C = 4, alt1.E = 250000),

if(alt2.B = 0 and alt2.C = 0, alt2.E = 62500),
if(alt2.B = 0 and alt2.C = 1, alt2.E = 156250),
if(alt2.B = 0 and alt2.C = 2, alt2.E = 250000),
if(alt2.B = 0 and alt2.C = 3, alt2.E = 437500),
if(alt2.B = 0 and alt2.C = 4, alt2.E = 625000),
if(alt2.B = 1 and alt2.C = 0, alt2.E = 37500),
if(alt2.B = 1 and alt2.C = 1, alt2.E = 62500),
if(alt2.B = 1 and alt2.C = 2, alt2.E = 156250),
if(alt2.B = 1 and alt2.C = 3, alt2.E = 250000),
if(alt2.B = 1 and alt2.C = 4, alt2.E = 437500),
if(alt2.B = 2 and alt2.C = 0, alt2.E = 12500),
if(alt2.B = 2 and alt2.C = 1, alt2.E = 37500),
if(alt2.B = 2 and alt2.C = 2, alt2.E = 62500),
if(alt2.B = 2 and alt2.C = 3, alt2.E = 156250),
if(alt2.B = 2 and alt2.C = 4, alt2.E = 250000)


;model(m1): ? in this model I define attribute A
U(alt1) =   b1.effects[0|0|0]      * A[0,1,2,3]         
          + b2.effects[0|0]        * B[0,1,2]
          + b3.effects[0|0|0|0]    * C[0,1,2,3,4]
          + b4.effects[0|0|0|0]    * D[0,1,2,3,4]
          + b5                     * E[12500, 37500, 62500, 156250, 250000, 437500, 625000]
          /
U(alt2) =   b1                     * A
          + b2                     * B
          + b3                     * C           
          + b4                     * D
          + b5                     * E         

;model(m2): ? this is the model that is being optimised for, where A only appears in the interaction
U(alt1) =   b2                     * B
          + b3                     * C           
          + b4                     * D
          + b5                     * E     
          + i1                     * A.effects[0] * B.effects[0]
          + i2                     * A.effects[1] * B.effects[0]
          + i3                     * A.effects[2] * B.effects[0]
          + i4                     * A.effects[0] * B.effects[1]
          + i5                     * A.effects[1] * B.effects[1]
          + i6                     * A.effects[2] * B.effects[1]
          + i7                     * A.effects[0] * C.effects[0]
          + i8                     * A.effects[1] * C.effects[0]
          + i9                     * A.effects[2] * C.effects[0]
          + i10                    * A.effects[0] * C.effects[1]
          + i11                    * A.effects[1] * C.effects[1]
          + i12                    * A.effects[2] * C.effects[1]         
          + i13                    * A.effects[0] * C.effects[2]
          + i14                    * A.effects[1] * C.effects[2]
          + i15                    * A.effects[2] * C.effects[2]
          + i16                    * A.effects[0] * C.effects[3]
          + i17                    * A.effects[1] * C.effects[3]
          + i18                    * A.effects[2] * C.effects[3]
          + i19                    * A.effects[0] * D.effects[0]
          + i20                    * A.effects[1] * D.effects[0]
          + i21                    * A.effects[2] * D.effects[0]
          + i22                    * A.effects[0] * D.effects[1]
          + i23                    * A.effects[1] * D.effects[1]
          + i24                    * A.effects[2] * D.effects[1]         
          + i25                    * A.effects[0] * D.effects[2]
          + i26                    * A.effects[1] * D.effects[2]
          + i27                    * A.effects[2] * D.effects[2]
          + i28                    * A.effects[0] * D.effects[3]
          + i29                    * A.effects[1] * D.effects[3]
          + i30                    * A.effects[2] * D.effects[3]
          + i31                    * A.effects[0] * E
          + i32                    * A.effects[1] * E
          + i33                    * A.effects[2] * E
          /
U(alt2) =   b2                     * B
          + b3                     * C           
          + b4                     * D
          + b5                     * E     
          + i1                     * A.effects[0] * B.effects[0]
          + i2                     * A.effects[1] * B.effects[0]
          + i3                     * A.effects[2] * B.effects[0]
          + i4                     * A.effects[0] * B.effects[1]
          + i5                     * A.effects[1] * B.effects[1]
          + i6                     * A.effects[2] * B.effects[1]
          + i7                     * A.effects[0] * C.effects[0]
          + i8                     * A.effects[1] * C.effects[0]
          + i9                     * A.effects[2] * C.effects[0]
          + i10                    * A.effects[0] * C.effects[1]
          + i11                    * A.effects[1] * C.effects[1]
          + i12                    * A.effects[2] * C.effects[1]         
          + i13                    * A.effects[0] * C.effects[2]
          + i14                    * A.effects[1] * C.effects[2]
          + i15                    * A.effects[2] * C.effects[2]
          + i16                    * A.effects[0] * C.effects[3]
          + i17                    * A.effects[1] * C.effects[3]
          + i18                    * A.effects[2] * C.effects[3]
          + i19                    * A.effects[0] * D.effects[0]
          + i20                    * A.effects[1] * D.effects[0]
          + i21                    * A.effects[2] * D.effects[0]
          + i22                    * A.effects[0] * D.effects[1]
          + i23                    * A.effects[1] * D.effects[1]
          + i24                    * A.effects[2] * D.effects[1]         
          + i25                    * A.effects[0] * D.effects[2]
          + i26                    * A.effects[1] * D.effects[2]
          + i27                    * A.effects[2] * D.effects[2]
          + i28                    * A.effects[0] * D.effects[3]
          + i29                    * A.effects[1] * D.effects[3]
          + i30                    * A.effects[2] * D.effects[3]
          + i31                    * A.effects[0] * E
          + i32                    * A.effects[1] * E
          + i33                    * A.effects[2] * E
$


Michiel

Re: Including/excluding no-choice alternative

PostPosted: Thu Aug 11, 2022 11:19 pm
by ljpu
Thanks! That's really clear!