Labeled Pivot Design

This forum is for posts that specifically focus on Ngene.

Moderators: Andrew Collins, Michiel Bliemer, johnr

Labeled Pivot Design

Postby jamalm » Thu Feb 13, 2025 8:41 am

Dear ChoiceMetrics Team,

I’m designing a labeled choice experiment with vehicle-specific constraints and pivot-based cost attributes. Despite multiple attempts, I’m stuck with errors and would appreciate your guidance. I have four different types of vehicles (ICT, BEV, PHEV, & FCH), with each taking certain attribute levels (aka many constraints!).

Design Requirements
Alternatives: ICT, BEV, PHEV, FCH, Opt-out.

My constraints are:
ICT: RT=0, FSA=100%, MC[6,8,10], FC[7,10].
BEV: RT[20,40,60], FSA[10,40,70,100], MC[3,6], FC[1,3].
PHEV: RT[0,20], FSA[70,100], FC[3,7].
FCH: RT=0, FSA=10%.
Pivot Cost: Percentage changes (-10,0,10,20,30,40) applied to a respondent-specific base price.

Below is my current code and the issues I’m facing:
Code: Select all
Design
    ;alts = ICT*, BEV*, PHEV*, FCH*, none
    ;rows = 24
    ;block = 3, minsum
    ;eff = (mnl,d)
    ;alg = mfederov
   
;model:

    ? ICE (ICT)
    U(ICT) =
        b1_ICT[0] * FS[1] ? ICE fuel source (fixed)
        + b2_ICT * DR[200,300,400,500]
        + b3_ICT[0] * RT[0] ? RT fixed at 0
        + b4_ICT[0] * FSA[100] ? FSA fixed at 100%
        + b5_ICT.dummy[0|0] * MC[6,8,10] ? Maintenance cost for ICE
        + b6_ICT.dummy[0] * FC[7,10] ? Fuel cost for ICE
        + b7_ICT[-0.01] * C.piv[-10,0,10,20,30,40] ? Pivot cost (% change os stated value - reference will be given by the respondent)
    /

    ? BEV
    U(BEV) =
        b1_BEV.dummy[0|0|0] * FS[2,3,4,5] ? BEV fuel source (4 levels)
        + b2_BEV * DR[200,300,400,500]
        + b3_BEV.dummy[0|0] * RT[20,40,60] ? BEV refueling time
        + b4_BEV.dummy[0|0|0] * FSA[10,40,70,100] ? BEV station availability
        + b5_BEV.dummy[0] * MC[3,6] ? Maintenance cost for BEV
        + b6_BEV.dummy[0] * FC[1,3] ? Fuel cost for BEV
        + b7_BEV[-0.01] * C.piv[-10,0,10,20,30,40] ? Pivot cost (% change)
    /

    ? PHEV
    U(PHEV) =
        b1_PHEV.dummy[0|0|0] * FS[6,7,8,9] ? Hybrid fuel source (4 levels)
        + b2_PHEV * DR[200,300,400,500]
        + b3_PHEV.dummy[0] * RT[0,20] ? PHEV refueling time
        + b4_PHEV.dummy[0] * FSA[70,100] ? PHEV station availability
        + b5_PHEV.dummy[0] * MC[3,6] ? Maintenance cost for PHEV
        + b6_PHEV.dummy[0] * FC[3,7] ? Fuel cost for PHEV
        + b7_PHEV[-0.01] * C.piv[-10,0,10,20,30,40] ? Pivot cost (% change)
    /

    ? FCH (FCV)
    U(FCH) =
        b1_FCH.dummy[0|0] * FS[10,11,12] ? FCV hydrogen type (3 levels)
        + b2_FCH * DR[200,300,400,500]
        + b3_FCH[0] * RT[0] ? RT fixed at 0
        + b4_FCH[0] * FSA[10] ? FSA fixed at 10%
        + b5_FCH.dummy[0] * MC[3,6] ? Maintenance cost for FCV
        + b6_FCH.dummy[0] * FC[1,3] ? Fuel cost for FCV
        + b7_FCH[-0.01] * C.piv[-10,0,10,20,30,40] ? Pivot cost (% change)
    /

    ? Opt-out
    U(none) = b0
$



Errors/Issues:
1) Attribute Consistency Error: An example error is "Two identically named attributes do not have consistently specified levels: 'bev.rt', 'ict.rt'," which makes sense, but the problem is that Attributes like RT, FSA, MC, and FC have different levels across labeled alternatives (e.g., ICT has RT=0, BEV has RT[20,40,60]). Ngene expects identically named attributes to have identical levels.
2) Pivot Syntax: I am using C.piv[-10,0,10,20,30,40] to define percentage changes relative to a respondent’s reference price (rather than defining it within the syntax). However, the syntax for pivot variables (especially with labeled alternatives) is unclear in the manual.

What I’ve Tried:
1) Alternative-Specific Attributes: Renamed attributes (e.g., ICT_FS, BEV_FS) to avoid conflicts, but this complicates dummy coding and model specification.
2) Pivot Syntax: Experimented with C.ref[0] and C.piv, but Ngene throws errors about level frequencies.
3) The candidate set approach, which I tried, is impossible due to combinatorial explosion (26M+ rows).

My questions:
A) How do I properly define alternative-specific attributes (e.g., RT, FSA) with different levels for labeled alternatives without triggering consistency errors? Can Ngene handle this type of design?
B) What is the correct syntax for pivot variables in a labeled design where cost is a percentage change relative to a respondent’s reference value?
C) What am I missing here? I (have) read the manual document (esp. Section 8.3.2) quite a few times by now, but this is a new challenge.

Any guidance would be greatly appreciated!

Best regards,
Jamal
jamalm
 
Posts: 30
Joined: Sat Aug 01, 2020 6:54 am

Re: Labeled Pivot Design

Postby Michiel Bliemer » Thu Feb 13, 2025 10:43 am

There is no limitation in the utility function that Ngene can handle, you merely need to specify a utility function with consistent coding and ensuring that all parameters are identifiable.

There are several issues in your script:
1. You have labelled alternatives but you tell Ngene that they are unlabelled by specifying an asterisk (*). Please remove the asterisks.
2. You need to have alternative-specific constants (ASC) in each utility function
3. You can only have a single constant in each utility function, so if you add an ASC then you cannot add b3_ICT[0] * RT[0], which is another constant. Such a model cannot be estimated. You can overcome this by making the parameters generic, i.e. using b3 across all alternatives.
4. When you have different attribute levels then you need to specify MC_ICT[6,8,10] etc. If you want to have the exact same variable, you can use MC[3,6,8,10], which includes all levels, and then use ;reject: ICT.MC = 3, etc. Note that such a model is only identifiable if there is some overlap in the levels across alternatives. But if certain levels ONLY appear in one alternative then it is confounded with the constant and you cannot estimate the model.
5. You can only use .piv in combination with .ref. You state that "reference will be given by the respondent", but for Ngene to optimise the design it needs to know what the reference level is that you want to optimise the design around. If you do not know, and since you have zero priors anyway, you can just omit .piv and use the pivot levels directly in your design as they are irrelevant with zero priors.

If you are using a candidate set, you will need to restrict the number of rows to at most 10,000 as otherwise the design generation will become very slow. Usually 1000-5000 is more than enough. You can simply use a random selection from your 26M+ rows.

So think carefully about model identifiability; you need to specify utility functions that can actually be estimated in model estimation software (such as Biogeme, Apollo, Nlogit, or Stata).

Michiel
Michiel Bliemer
 
Posts: 1943
Joined: Tue Mar 31, 2009 4:13 pm

Re: Labeled Pivot Design

Postby jamalm » Thu Feb 13, 2025 2:10 pm

Hi Michiel,

Thank you for your prompt response. I followed your advice to the best of my understanding and modified my code accordingly (see below).

Code: Select all
Design
    ;alts = ICT, BEV, PHEV, FCV ?,none
    ;rows = 24
    ;block = 3, minsum
    ;eff = (mnl,d)
    ;alg = mfederov
 
;require:
 ICT.FS = 1,
 ICT.RT = 0,
 ICT.FSA = 100,

 BEV.FS>1 AND BEV.FS<6,
 BEV.MC<8,
 BEV.FC<7,

 PHEV.FS>5 AND PHEV.FS<10,
 PHEV.RT <40,
 PHEV.FSA > 40,
 PHEV.MC<8,

 FCV.FS>9 ,
 FCV.RT = 0,
 FCV.FSA < 70,
 FCV.MC<8,
 FCV.FC<7

 ;reject:
 ICT.MC = 3,
 ICT.FC = 1,
 ICT.FC = 3,
 
 BEV.RT = 0 ,
 PHEV.FC=1 OR PHEV.FC=10 


;model:

    U(ICT) =
         ?asc_ict+
         b1[0.1]           * FS[1,2,3,4,5,6,7,8,9,10,11,12] ? ICE fuel source (fixed)
        + b2[0.1]           * DR[200,300,400,500]
        + b3[-0.1]          * RT[0,20,40,60] ? RT fixed at 0
        + b4[0.1]           * FSA[10,40,70,100] ? FSA fixed at 100%
        + b5[-0.1]          * MC[3,6,8,10] ? Maintenance cost for ICE
        + b6[-0.1]          * FC[1,3,7,10] ? Fuel cost for ICE
        + b7[-0.01]         * C[-10,0,10,20,30,40] ? Pivot cost (% change os stated value - reference will be given by the respondent)
    /

    U(BEV) = asc_bev
        + b1                  * FS    ? BEV fuel source (4 levels)
        + b2                * DR
        + b3                * RT    ? BEV refueling time
        + b4                * FSA   ? BEV station availability
        + b5                * MC    ? Maintenance cost for BEV
        + b6                * FC    ? Fuel cost for BEV
        + b7                * C     ? Pivot cost (% change)
    /

    U(PHEV) = asc_phev
        + b1   * FS  ? Hybrid fuel source (4 levels)
        + b2 * DR
        + b3 * RT  ? PHEV refueling time
        + b4 * FSA ? PHEV station availability
        + b5 * MC  ? Maintenance cost for PHEV
        + b6 * FC ? Fuel cost for PHEV
        + b7 * C ? Pivot cost (% change)
    /

      U(FCV) = asc_fcv
        + b1   * FS ? FCV hydrogen type (3 levels)
        + b2 * DR
        + b3 * RT  ? RT fixed at 0
        + b4 * FSA ? FSA fixed at 10%
        + b5 * MC  ? Maintenance cost for FCV
        + b6 * FC  ? Fuel cost for FCV
        + b7 * C ? Pivot cost (% change)
   
$


The code runs, and all of my constraints appear to be met. However, I was unsure whether I fully addressed your point regarding ASC per utility (I am also ok with turning the first utility as the reference case, as it has a few fixed attribute levels, which is not what this code does). I'd appreciate any further insights you might have.

Thank you!

Thank you!
Jamal
jamalm
 
Posts: 30
Joined: Sat Aug 01, 2020 6:54 am

Re: Labeled Pivot Design

Postby Michiel Bliemer » Thu Feb 13, 2025 2:42 pm

The constants are fine.

For numerical attributes your syntax is fine, but for categorical attributes you MUST use dummy coding. So:
b1.dummy[0|0|0|0|0|0|0|0|0|0|0] * FS[1,2,3,4,5,6,7,8,9,10,11,12] ? ICE fuel source (fixed)

However, you can only estimate the model if there is overlap in the attribute levels across alternatives. In your case, the levels are exclusive to alternatives, therefore you need to have separate dummy coding, such as:

b1_bev.dummy[0|0|0] * FS_bev[2,3,4,5]

Michiel
Michiel Bliemer
 
Posts: 1943
Joined: Tue Mar 31, 2009 4:13 pm

Re: Labeled Pivot Design

Postby jamalm » Thu Feb 13, 2025 3:03 pm

Following your suggestion, I modified my codes to what follows:
Code: Select all
Design
    ;alts = ICT, BEV, PHEV, FCV ?,none
    ;rows = 24
    ;block = 3, minsum
    ;eff = (mnl,d)
    ;alg = mfederov
 
;require:
 ?ICT.FS = 1,
 ICT.RT = 0,
 ICT.FSA = 100,

 ?BEV.FS>1 AND BEV.FS<6,
 BEV.MC<8,
 BEV.FC<7,

 ?PHEV.FS>5 AND PHEV.FS<10,
 PHEV.RT <40,
 PHEV.FSA > 40,
 PHEV.MC<8,

 ?FCV.FS>9 ,
 FCV.RT = 0,
 FCV.FSA < 70,
 FCV.MC<8,
 FCV.FC<7

 ;reject:
 ICT.MC = 3,
 ICT.FC = 1,
 ?ICT.FC = 3,
 
 BEV.RT = 0 ,
 PHEV.FC=1 OR PHEV.FC=10


;model:

    U(ICT) =
        ? asc_ict+
       ?  b1.dummy[0|0|0|0|0|0|0|0|0|0|0] * FS[1,2,3,4,5,6,7,8,9,10,11,12] ? ICE fuel source (1 level)
        b1_ICT[0] * FS[1]
        + b2[0.1]           * DR[200,300,400,500]
        + b3[-0.1]          * RT[0,20,40,60] ? RT fixed at 0
        + b4[0.1]           * FSA[10,40,70,100] ? FSA fixed at 100%
        + b5[-0.1]          * MC[3,6,8,10] ? Maintenance cost for ICE
        + b6[-0.1]          * FC[1,3,7,10] ? Fuel cost for ICE
        + b7[-0.01]         * C[-10,0,10,20,30,40] ? Pivot cost (% change os stated value - reference will be given by the respondent)
    /

    U(BEV) = asc_bev
        + b1_bev.dummy[0|0|0] * FS_bev[2,3,4,5] ? BEV fuel source (4 levels)
        + b2                * DR
        + b3                * RT    ? BEV refueling time
        + b4                * FSA   ? BEV station availability
        + b5                * MC    ? Maintenance cost for BEV
        + b6                * FC    ? Fuel cost for BEV
        + b7                * C     ? Pivot cost (% change)
    /

    U(PHEV) = asc_phev
        + b1_PHEV.dummy[0|0|0] * FS[6,7,8,9] ? Hybrid fuel source (4 levels)
        + b2 * DR
        + b3 * RT  ? PHEV refueling time
        + b4 * FSA ? PHEV station availability
        + b5 * MC  ? Maintenance cost for PHEV
        + b6 * FC ? Fuel cost for PHEV
        + b7 * C ? Pivot cost (% change)
    /

      U(FCV) = asc_fcv
        +    b1_FCH.dummy[0|0] * FS[10,11,12] ? FCV hydrogen type (3 levels)
        + b2 * DR
        + b3 * RT  ? RT fixed at 0
        + b4 * FSA ? FSA fixed at 10%
        + b5 * MC  ? Maintenance cost for FCV
        + b6 * FC  ? Fuel cost for FCV
        + b7 * C ? Pivot cost (% change)
   
$


I am apparently not fully following your instructions, as Ngene gives the error: "Error: Two identically named attributes do not have consistently specified levels: 'fcv.fs', 'phev.fs'."
Jamal
jamalm
 
Posts: 30
Joined: Sat Aug 01, 2020 6:54 am

Re: Labeled Pivot Design

Postby Michiel Bliemer » Thu Feb 13, 2025 3:54 pm

You are using FS across multiple alternatives but you need to rename to FS_ict, FS_bev, etc. You need to give them unique names across the alternatives because they are different dummy coded variables.
Michiel Bliemer
 
Posts: 1943
Joined: Tue Mar 31, 2009 4:13 pm

Re: Labeled Pivot Design

Postby jamalm » Fri Feb 14, 2025 12:23 pm

Hi Michiel,

Apologies—I was only focused on the coefficient names and overlooked the attribute names. I've refined my code as follows, and while it runs, I suspect it only considers the initial b1 (from the ICT utility fnct.) value and ignores the other b1 values. Should I be concerned about that?

Code: Select all
Design
    ;alts = ICT, BEV, PHEV, FCV ?,none
    ;rows = 24
    ;block = 3, minsum
    ;eff = (mnl,d)
    ;alg = mfederov
 
;require:
 ICT.RT = 0,
 ICT.FSA = 100,
 BEV.MC<8,
 BEV.FC<7,
 PHEV.RT <40,
 PHEV.FSA > 40,
 PHEV.MC<8,
 FCV.RT = 0,
 FCV.FSA < 70,
 FCV.MC<8,
 FCV.FC<7

 ;reject:
 ICT.MC = 3,
 ICT.FC = 1,
 ICT.FC = 3,
 BEV.RT = 0 ,
 PHEV.FC=1 OR PHEV.FC=10

;model:

    U(ICT) =
         ?asc_ict+
           b1[0.1]           * FS_ICT[1]
        + b2[0.1]           * DR[200,300,400,500]
        + b3[-0.1]          * RT[0,20,40,60] ? RT fixed at 0
        + b4[0.1]           * FSA[10,40,70,100] ? FSA fixed at 100%
        + b5[-0.1]          * MC[3,6,8,10] ? Maintenance cost for ICE
        + b6[-0.1]          * FC[1,3,7,10] ? Fuel cost for ICE
        + b7[-0.01]         * C[-10,0,10,20,30,40] ? Pivot cost (% change os stated value - reference will be given by the respondent)
    /

    U(BEV) = asc_bev
        + b1.dummy[0.1|0.2|0.3] * FS_bev[2,3,4,5] ? BEV fuel source (4 levels)
        + b2                * DR
        + b3                * RT    ? BEV refueling time
        + b4                * FSA   ? BEV station availability
        + b5                * MC    ? Maintenance cost for BEV
        + b6                * FC    ? Fuel cost for BEV
        + b7                * C     ? Pivot cost (% change)
    /

    U(PHEV) = asc_phev
        + b1.dummy[0.1|0.2|0.3] * FS_PHEV[6,7,8,9] ? Hybrid fuel source (4 levels)
        + b2 * DR
        + b3 * RT  ? PHEV refueling time
        + b4 * FSA ? PHEV station availability
        + b5 * MC  ? Maintenance cost for PHEV
        + b6 * FC ? Fuel cost for PHEV
        + b7 * C ? Pivot cost (% change)
    /

      U(FCV) = asc_fcv+
            b1.dummy[0.1|0.2] * FS_FCV[10,11,12] ? FCV hydrogen type (3 levels)
        + b2 * DR
        + b3 * RT  ? RT fixed at 0
        + b4 * FSA ? FSA fixed at 10%
        + b5 * MC  ? Maintenance cost for FCV
        + b6 * FC  ? Fuel cost for FCV
        + b7 * C ? Pivot cost (% change)
   
$


Thank you!
Jamal
jamalm
 
Posts: 30
Joined: Sat Aug 01, 2020 6:54 am

Re: Labeled Pivot Design

Postby Michiel Bliemer » Fri Feb 14, 2025 1:47 pm

There are still several issues with your script. You cannot use the same parameter name (like b1) for coefficients that belong to different levels, that does not make sense. You need to give those coefficients a different name. Also, some of your priors are far too large (0.1) for some of the attribute levels (e.g., 500). Priors should come from a pilot study, it is risky to choose choose non-zero priors manually as it could lead to very bad designs. I would also further increase your number of rows given the large number of parameters. Finally, when using the modified Federov algorithm, you need to consider attribute level balance and I usually dummy code all coefficients for this reason, unless this is not possible because of certain constraints you impose. In your case, it seems fine with the reject and require constraints you have.

Perhaps have a look at the script below. Good luck!

Code: Select all
Design
    ;alts = ICT, BEV, PHEV, FCV ?,none
    ;rows = 48
    ;block = 6, minsum
    ;eff = (mnl,d)
    ;alg = mfederov
 
;require:
 ICT.RT = 0,
 ICT.FSA = 100,
 BEV.MC<8,
 BEV.FC<7,
 PHEV.RT <40,
 PHEV.FSA > 40,
 PHEV.MC<8,
 FCV.RT = 0,
 FCV.FSA < 70,
 FCV.MC<8,
 FCV.FC<7

 ;reject:
 ICT.MC = 3,
 ICT.FC = 1,
 ICT.FC = 3,
 BEV.RT = 0 ,
 PHEV.FC=1 OR PHEV.FC=10

;model:

    U(ICT) = b2.dummy[0|0|0]  * DR[200,300,400,500]
        + b3.dummy[0|0|0]     * RT[0,20,40,60] ? RT fixed at 0
        + b4.dummy[0|0|0]     * FSA[10,40,70,100] ? FSA fixed at 100%
        + b5.dummy[0|0|0]     * MC[3,6,8,10] ? Maintenance cost for ICE
        + b6.dummy[0|0|0]     * FC[1,3,7,10] ? Fuel cost for ICE
        + b7.dummy[0|0|0|0|0] * C[-10,0,10,20,30,40] ? Pivot cost (% change os stated value - reference will be given by the respondent)
    /

    U(BEV) = asc_bev
        + b1_bev.dummy[0|0|0] * FS_bev[2,3,4,5] ? BEV fuel source (4 levels)
        + b2.dummy            * DR
        + b3.dummy            * RT    ? BEV refueling time
        + b4.dummy            * FSA   ? BEV station availability
        + b5.dummy            * MC    ? Maintenance cost for BEV
        + b6.dummy            * FC    ? Fuel cost for BEV
        + b7.dummy            * C     ? Pivot cost (% change)
    /

    U(PHEV) = asc_phev
        + b1_phev.dummy[0|0|0] * FS_PHEV[6,7,8,9] ? Hybrid fuel source (4 levels)
        + b2.dummy            * DR
        + b3.dummy            * RT  ? PHEV refueling time
        + b4.dummy            * FSA ? PHEV station availability
        + b5.dummy            * MC  ? Maintenance cost for PHEV
        + b6.dummy            * FC ? Fuel cost for PHEV
        + b7                  * C ? Pivot cost (% change)
    /

      U(FCV) = asc_fcv
        + b1_fsv.dummy[0|0] * FS_FCV[10,11,12] ? FCV hydrogen type (3 levels)
        + b2.dummy          * DR
        + b3.dummy          * RT  ? RT fixed at 0
        + b4.dummy          * FSA ? FSA fixed at 10%
        + b5.dummy          * MC  ? Maintenance cost for FCV
        + b6.dummy          * FC  ? Fuel cost for FCV
        + b7.dummy          * C ? Pivot cost (% change)
   
$


Michiel
Michiel Bliemer
 
Posts: 1943
Joined: Tue Mar 31, 2009 4:13 pm

Re: Labeled Pivot Design

Postby jamalm » Fri Feb 14, 2025 2:02 pm

Michiel,

When I used different names for the coefficents, Ngene would run but yield "undefiend."

Thank you for cleaning up my codes and your valuable insights!

-Jamal
jamalm
 
Posts: 30
Joined: Sat Aug 01, 2020 6:54 am

Re: Labeled Pivot Design

Postby Michiel Bliemer » Fri Feb 14, 2025 2:08 pm

The script that I provided runs fine. I used b1_bev, b1_phev, etc. You only need to use alternative-specific coefficient names of the levels are different of course.
Michiel Bliemer
 
Posts: 1943
Joined: Tue Mar 31, 2009 4:13 pm


Return to Choice experiments - Ngene

Who is online

Users browsing this forum: Google [Bot] and 13 guests