QML Syntax¶
QML (Questionnaire Markup Language) is a YAML-based language for creating formally verified questionnaires. This page provides a brief technical overview.
Overview¶
QML enables:
- Formal verification of questionnaire logic using SMT solvers
- Conditional branching with preconditions and postconditions
- Integer-based outcomes for all responses, enabling mathematical analysis
- Embedded Python code for computations (restricted subset for verification)
Key Components¶
Structure¶
qmlVersion: "1.0"
questionnaire:
title: "Survey Title"
codeInit: |
# Python initialization code
blocks:
- id: b_section
items:
- id: q_item
kind: Question
precondition:
- predicate: condition
postcondition:
- predicate: validation
input:
control: ControlType
Item Types¶
- Comment: Display text without collecting responses
- Question: Single integer outcome
- QuestionGroup: Vector of integer outcomes
- MatrixQuestion: Matrix of integer outcomes
Input Controls¶
- Switch: Binary (0/1)
- Radio: Single selection from labeled options
- Checkbox: Multiple selection (bit mask encoding)
- Dropdown: Single selection with prefix/suffix
- Editbox: Free-form integer within [min, max]
- Slider: Visual integer selection
- Range: Interval selection (two integers encoded via Szudzik pairing)
Conditional Logic¶
Preconditions determine visibility:
Postconditions enforce constraints:
postcondition:
- predicate: q_children.outcome < q_household.outcome
hint: "Children must be fewer than household size"
Code Blocks¶
Restricted Python subset for formal verification:
Supported:
- Arithmetic: +, -, *, //
- Comparisons: <, <=, >, >=, ==, !=
- Boolean: and, or, not
- Control: if/elif/else, for (limited)
- Outcome access: item.outcome
Not supported:
- Functions, classes, imports
- While loops, break, continue
- Built-ins (except range)
- Dictionaries, strings methods
Complete Examples¶
This section demonstrates all item kinds and control types with working examples.
Item Kind: Comment¶
Display informational text without collecting responses:
- id: intro_comment
kind: Comment
title: "Welcome to our demographic survey. Your responses help us understand our community better."
Comments can have conditional display:
- id: parent_notice
kind: Comment
title: "The following questions are about your children."
precondition:
- predicate: q_has_children.outcome == 1
Item Kind: Question¶
Single-outcome questions with various control types.
Control: Switch¶
Binary choice (0 = off, 1 = on):
- id: q_has_children
kind: Question
title: "Do you have children?"
input:
control: Switch
off: "No"
on: "Yes"
default: 0
Control: Radio¶
Single selection from labeled options:
- id: q_education
kind: Question
title: "What is your highest level of education?"
input:
control: Radio
labels:
1: "High School"
2: "Bachelor's Degree"
3: "Master's Degree"
4: "Doctorate"
default: 1
Control: Dropdown¶
Single selection with optional prefix/suffix text:
- id: q_country
kind: Question
title: "Country of residence"
input:
control: Dropdown
left: "I live in"
right: ""
labels:
1: "United States"
2: "Canada"
3: "United Kingdom"
4: "Germany"
5: "Other"
Control: Checkbox¶
Multiple selection (bit mask encoding):
- id: q_interests
kind: Question
title: "Select all that apply:"
input:
control: Checkbox
labels:
1: "Reading" # Bit 0: value 2^0 = 1
2: "Sports" # Bit 1: value 2^1 = 2
4: "Music" # Bit 2: value 2^2 = 4
8: "Travel" # Bit 3: value 2^3 = 8
16: "Cooking" # Bit 4: value 2^4 = 16
Selecting "Reading" and "Music" produces outcome: 1 | 4 = 5
Control: Editbox¶
Free-form integer input with bounds:
- id: q_age
kind: Question
title: "What is your age?"
input:
control: Editbox
min: 0
max: 120
left: ""
right: "years old"
default: 25
postcondition:
- predicate: q_age.outcome >= 18
hint: "You must be 18 or older to participate"
Control: Slider¶
Visual integer selection:
- id: q_satisfaction
kind: Question
title: "How satisfied are you with our service?"
input:
control: Slider
min: 0
max: 10
step: 1
left: "Not satisfied"
right: "Very satisfied"
labels:
0: "0"
5: "5"
10: "10"
default: 5
Control: Range¶
Interval selection (two integers encoded as one):
- id: q_price_range
kind: Question
title: "What is your acceptable price range?"
input:
control: Range
min: 0
max: 1000
step: 50
left: "$"
right: ""
The outcome is encoded via Szudzik pairing. Selecting \([100, 500]\) produces a single integer.
Item Kind: QuestionGroup¶
Vector of outcomes with identical control for each sub-question:
- id: qg_family_ages
kind: QuestionGroup
title: "Please enter the age of each family member:"
questions:
- "Yourself"
- "Spouse"
- "First child"
- "Second child"
precondition:
- predicate: q_household_size.outcome >= 2
input:
control: Editbox
min: 0
max: 120
right: "years"
postcondition:
- predicate: qg_family_ages.outcome[0] >= 18
hint: "Primary respondent must be 18 or older"
Access outcomes via indexing: qg_family_ages.outcome[0], qg_family_ages.outcome[1], etc.
Item Kind: MatrixQuestion¶
Matrix of outcomes (rows × columns):
- id: mq_language_proficiency
kind: MatrixQuestion
title: "Please indicate the language proficiency level for each family member:"
rows:
- "English"
- "Spanish"
- "French"
- "German"
- "Mandarin"
columns:
- "Yourself"
- "Spouse"
- "First Child"
- "Second Child"
input:
control: Dropdown
labels:
0: "None"
1: "Beginner"
2: "Intermediate"
3: "Advanced"
4: "Native"
Access outcomes via row/column indexing: mq_language_proficiency.outcome[0][1] for first language (English), second family member (Spouse).
The matrix creates a grid where each cell represents one family member's proficiency in one language. This example produces a 5×4 matrix (5 languages × 4 family members) = 20 individual outcomes.
Complex Example with Code Blocks¶
Demonstrating preconditions, postconditions, and code blocks:
qmlVersion: "1.0"
questionnaire:
title: "Income Survey"
codeInit: |
total_income = 0
blocks:
- id: b_demographics
items:
- id: q_employment
kind: Question
title: "Are you currently employed?"
input:
control: Switch
off: "No"
on: "Yes"
- id: q_income
kind: Question
title: "What is your annual income?"
precondition:
- predicate: q_employment.outcome == 1
input:
control: Editbox
min: 0
max: 1000000
left: "$"
right: "per year"
codeBlock: |
total_income = q_income.outcome
- id: q_spouse_employed
kind: Question
title: "Is your spouse employed?"
precondition:
- predicate: q_employment.outcome == 1
input:
control: Switch
off: "No"
on: "Yes"
- id: q_spouse_income
kind: Question
title: "What is your spouse's annual income?"
precondition:
- predicate: q_spouse_employed.outcome == 1
input:
control: Editbox
min: 0
max: 1000000
left: "$"
right: "per year"
codeBlock: |
total_income = total_income + q_spouse_income.outcome
- id: q_household_income
kind: Question
title: "What is your total household income?"
input:
control: Editbox
min: 0
max: 2000000
left: "$"
right: "per year"
postcondition:
- predicate: q_household_income.outcome >= total_income
hint: "Household income cannot be less than reported individual incomes"
This example demonstrates:
- Conditional visibility: Income questions only appear if employed
- Code blocks: Track cumulative income across questions
- Postcondition validation: Ensure household income is consistent with individual incomes
- Chained dependencies: Each question depends on previous answers
Mathematical Semantics¶
Each item has associated outcome variable(s):
- Question: \(S_i \in [\text{min}, \text{max}]\)
- QuestionGroup: \(\mathbf{S}_i \in \mathbb{Z}^k\)
- MatrixQuestion: \(\mathbf{S}_i \in \mathbb{Z}^{m \times n}\)
Special encodings:
- Checkbox: Multiple selection encoded as bit mask (OR of powers of 2)
- Range: Interval \((a, b)\) encoded via Szudzik pairing:
This bijection \(\mathbb{Z} \times \mathbb{Z} \to \mathbb{Z}\) represents two integers as one while remaining decodable.
Preconditions and postconditions are Boolean predicates over outcome variables.
The system validates:
where \(B\) encodes all domain constraints.
See Questionnaire Analysis for formal treatment.
Further Reading¶
- Creating Surveys - Practical guide with examples
- Questionnaire Analysis - Mathematical foundations
- Preconditions & Postconditions - Conditional logic theory
- Complex Types - Vector and matrix items