Skip to main content
Chemistry LibreTexts

2: Problem Generation (PG)

  • Page ID
    488655
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)

    \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)

    \( \newcommand{\dsum}{\displaystyle\sum\limits} \)

    \( \newcommand{\dint}{\displaystyle\int\limits} \)

    \( \newcommand{\dlim}{\displaystyle\lim\limits} \)

    \( \newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\)

    ( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\)

    \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)

    \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\)

    \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)

    \( \newcommand{\Span}{\mathrm{span}}\)

    \( \newcommand{\id}{\mathrm{id}}\)

    \( \newcommand{\Span}{\mathrm{span}}\)

    \( \newcommand{\kernel}{\mathrm{null}\,}\)

    \( \newcommand{\range}{\mathrm{range}\,}\)

    \( \newcommand{\RealPart}{\mathrm{Re}}\)

    \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)

    \( \newcommand{\Argument}{\mathrm{Arg}}\)

    \( \newcommand{\norm}[1]{\| #1 \|}\)

    \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)

    \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    \( \newcommand{\vectorA}[1]{\vec{#1}}      % arrow\)

    \( \newcommand{\vectorAt}[1]{\vec{\text{#1}}}      % arrow\)

    \( \newcommand{\vectorB}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)

    \( \newcommand{\vectorC}[1]{\textbf{#1}} \)

    \( \newcommand{\vectorD}[1]{\overrightarrow{#1}} \)

    \( \newcommand{\vectorDt}[1]{\overrightarrow{\text{#1}}} \)

    \( \newcommand{\vectE}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash{\mathbf {#1}}}} \)

    \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)

    \(\newcommand{\longvect}{\overrightarrow}\)

    \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)

    \(\newcommand{\avec}{\mathbf a}\) \(\newcommand{\bvec}{\mathbf b}\) \(\newcommand{\cvec}{\mathbf c}\) \(\newcommand{\dvec}{\mathbf d}\) \(\newcommand{\dtil}{\widetilde{\mathbf d}}\) \(\newcommand{\evec}{\mathbf e}\) \(\newcommand{\fvec}{\mathbf f}\) \(\newcommand{\nvec}{\mathbf n}\) \(\newcommand{\pvec}{\mathbf p}\) \(\newcommand{\qvec}{\mathbf q}\) \(\newcommand{\svec}{\mathbf s}\) \(\newcommand{\tvec}{\mathbf t}\) \(\newcommand{\uvec}{\mathbf u}\) \(\newcommand{\vvec}{\mathbf v}\) \(\newcommand{\wvec}{\mathbf w}\) \(\newcommand{\xvec}{\mathbf x}\) \(\newcommand{\yvec}{\mathbf y}\) \(\newcommand{\zvec}{\mathbf z}\) \(\newcommand{\rvec}{\mathbf r}\) \(\newcommand{\mvec}{\mathbf m}\) \(\newcommand{\zerovec}{\mathbf 0}\) \(\newcommand{\onevec}{\mathbf 1}\) \(\newcommand{\real}{\mathbb R}\) \(\newcommand{\twovec}[2]{\left[\begin{array}{r}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\ctwovec}[2]{\left[\begin{array}{c}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\threevec}[3]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\cthreevec}[3]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\fourvec}[4]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\cfourvec}[4]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\fivevec}[5]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\cfivevec}[5]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\mattwo}[4]{\left[\begin{array}{rr}#1 \amp #2 \\ #3 \amp #4 \\ \end{array}\right]}\) \(\newcommand{\laspan}[1]{\text{Span}\{#1\}}\) \(\newcommand{\bcal}{\cal B}\) \(\newcommand{\ccal}{\cal C}\) \(\newcommand{\scal}{\cal S}\) \(\newcommand{\wcal}{\cal W}\) \(\newcommand{\ecal}{\cal E}\) \(\newcommand{\coords}[2]{\left\{#1\right\}_{#2}}\) \(\newcommand{\gray}[1]{\color{gray}{#1}}\) \(\newcommand{\lgray}[1]{\color{lightgray}{#1}}\) \(\newcommand{\rank}{\operatorname{rank}}\) \(\newcommand{\row}{\text{Row}}\) \(\newcommand{\col}{\text{Col}}\) \(\renewcommand{\row}{\text{Row}}\) \(\newcommand{\nul}{\text{Nul}}\) \(\newcommand{\var}{\text{Var}}\) \(\newcommand{\corr}{\text{corr}}\) \(\newcommand{\len}[1]{\left|#1\right|}\) \(\newcommand{\bbar}{\overline{\bvec}}\) \(\newcommand{\bhat}{\widehat{\bvec}}\) \(\newcommand{\bperp}{\bvec^\perp}\) \(\newcommand{\xhat}{\widehat{\xvec}}\) \(\newcommand{\vhat}{\widehat{\vvec}}\) \(\newcommand{\uhat}{\widehat{\uvec}}\) \(\newcommand{\what}{\widehat{\wvec}}\) \(\newcommand{\Sighat}{\widehat{\Sigma}}\) \(\newcommand{\lt}{<}\) \(\newcommand{\gt}{>}\) \(\newcommand{\amp}{&}\) \(\definecolor{fillinmathshade}{gray}{0.9}\)

    This page only covers the PG you need to support a PGML prompt.

    Start here (task first)

    If you are copy-editing a working problem, you can skip this chapter and come back only when you need to change setup behavior.

    WeBWorK problems are written in PG (see Introduction to PG Language for an introduction), but this guide is not trying to turn instructors into Perl developers. Regular PG is treated as the minimum setup needed to support a clean PGML prompt: define a few variables, define answer checkers, and let PGML carry the student-facing text.

    Library-quality problems also need an OPL header section that comes before DOCUMENT(), so the five-section reality is: OPL header, Preamble, Setup, Statement, and Solution.

    What PG is used for in this guide

    • Load the macros needed for PGML and answer checking.
    • Choose a MathObjects context that matches the expected input.
    • Generate a small number of randomized values with sensible ranges.
    • Compute the target answer(s) and attach the right answer checkers.

    What regular PG is not used for in this guide

    • Writing the prompt as long blocks of BEGIN_TEXT/END_TEXT.
    • Building complex formatting by hand (PGML is preferred).
    • Turning a single problem into a large Perl script.

    If a problem feels like it needs complexity, prefer clearer prompts, tighter ranges, or a different interaction pattern before adding more PG logic.

    How this chapter fits the book

    Chapter 2 exists because every PGML problem still needs some PG scaffolding (macros, variables, answers). The goal is to keep that scaffolding short, readable, and reusable.

    • 2.1: Introduction to PG Language
      Introduces PG as the setup layer behind a PGML-first problem with a minimal scaffold and a short list of required PG concepts. After finishing, you can edit small setup blocks to define values and answer checkers without building a large Perl program. Use it when you need to adjust a problem setup while keeping the prompt stable in PGML.
    • 2.2: OPL Header and Metadata
      Teaches the OPL header block before DOCUMENT() with required fields (TITLE, DESCRIPTION, Level, Language), recommended fields (KEYWORDS, DBsubject/DBchapter/DBsection), and attribution fields. After finishing, you can write proper metadata headers for searchability, choose meaningful keywords, set Bloom's taxonomy levels, and acknowledge that library-quality problems need this "section zero." Use it before writing any new problem, and copy the template from Appendix 90.1 as your starting point.
    • 2.3: PG Problem Files with a .pg file extension
      Provides a reusable PGML-first skeleton, a change-first table, and the most common structural failure modes. After finishing, you can place comments, initialization, setup, PGML text, and optional solutions in the right locations consistently. Use it as your starting point when creating or refactoring a problem file, and after any macro or setup change, run local rendering from Chapter 7 to catch missing macros and syntax errors early.
    • 2.4: Sections within a PG question
      Breaks down the typical sections of a problem in a PGML-first style and adds a "where does this go?" map for common tasks. After finishing, you can keep setup, prompt text, and optional solution material separated and easier to maintain. Use it when refactoring a messy problem into a clean structure.
    • 2.5: Common PG Macros
      Organizes macros into a minimal core, interaction add-ons, and science-native helpers, and adds missing-macro symptoms plus a do-not-cargo-cult reminder. After finishing, you can build a minimal `loadMacros()` block and recognize which macro you need for a specific interaction or grading need. Use it when a problem needs a new interaction pattern and you are not sure which macro file enables it.
    • 2.6: Legacy PG and deprecated patterns
      Shows how to recognize legacy PG patterns and deprecated approaches that are common in online examples and older problem libraries, with a fast PGML-first rewrite recipe and a PopUp warning. After finishing, you can triage a copied problem quickly, identify what is safe to reuse, and translate the core idea into a PGML-first structure without importing fragile formatting or scattered grading logic.
    • 2.7: Future PG version features
      Documents PG features introduced in versions 2.18-2.20 that are not yet available in ADAPT, with breaking changes, deprecations, and a workaround-to-replacement mapping table. After finishing, you can identify which PG version introduced a feature, understand why it fails in ADAPT today, and plan for future upgrades. Use it when you encounter CheckboxList, DropDown, plotly3D, TikZ, or PGML div/span tags in online examples and need to know whether they work in your environment.


    This page titled 2: Problem Generation (PG) is shared under a CC BY 4.0 license and was authored, remixed, and/or curated by Neil R. Voss.