Skip to content

Conversation

@AndrewTKent
Copy link
Contributor

@AndrewTKent AndrewTKent commented Jan 12, 2026

Overview

Adds first-class Bool type support for target arguments, enabling boolean flags to be specified without explicit values on the command line.

# Before: awkward string workaround
nvq++ --target ionq --ionq-debias "true" program.cpp

# After: natural flag syntax
nvq++ --target ionq --ionq-debias program.cpp

Fixes #3699 · Fixes #3525


Problem

Target arguments declared as type: bool in YAML configs were treated identically to strings at every layer:

  1. nvq++ driver — assumed all args take a value (shift 2), breaking flag-style usage
  2. Runtime — passed "true"/"false" as strings, requiring manual parsing in each backend
  3. JSON serialization — emitted "true" (string) instead of true (boolean literal)

Solution

1. Compiler Driver (nvq++.in)

Added Bool argument detection so flags can omit values:

# All equivalent:
--ionq-debias           # implicit true
--ionq-debias true      # explicit true  
--ionq-debias=false     # explicit false

Implementation: New --list-bool-args mode in cudaq-target-conf outputs Bool keys, which nvq++ queries at argument parse time to decide shift 1 vs shift 2.

2. Type System (TargetConfig.h)

enum class ArgumentType { String, Int, Bool, UUID, FeatureFlag, MachineConfig };
//                                   ^^^^ new

3. Runtime Utilities (ServerHelper)

// Lookup declared type from target config
ArgumentType getArgumentType(const std::string &key);

// Returns properly typed nlohmann::json value
nlohmann::json getTypedConfigValue(const std::string &key);
// Bool  → JSON boolean (true/false)
// Int   → JSON number
// other → JSON string

4. Backend Migration (IonQ)

Updated debias and sharpen from type: string to type: bool:

// Before
job["debias"] = nlohmann::json::parse(backendConfig["debias"]).get<bool>();

// After  
job["debias"] = getTypedConfigValue("debias");

Files Changed

Area Files
Type system TargetConfig.h, TargetConfig.cpp
Compiler nvq++.in, cudaq-target-conf.cpp
Runtime ServerHelper.h, ServerHelper.cpp
Backend IonQServerHelper.cpp, ionq.yml
Tests TargetConfigTester.cpp, check_bool_args.config

Testing

  • Unit test: Bool argument YAML parsing
  • Integration test: --list-bool-args output validation
  • CI: Existing test suite passes
  • Manual: IonQ backend emits boolean JSON literals

Usage

Target YAML:

target-arguments:
  - key: debias
    type: bool
    platform-arg: debias
    help-string: "Enable error mitigation"

Command line:

nvq++ --target ionq --ionq-debias program.cpp

Backend receives:

{ "debias": true }

@copy-pr-bot
Copy link

copy-pr-bot bot commented Jan 12, 2026

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@1tnguyen
Copy link
Collaborator

Hi @AndrewTKent,

The feature proposed in #3525 is broader than this.
Specifically, we want the nvq++ compiler driver to be able to parse a flag into a True boolean value, i.e., the absence of that flag means a False value.

In particular, the nvq++ compiler script, at the moment, expects target arguments to come in key-value pairs; and we may incorrectly parse the argument if that's not the case.

elif [[ "$1" = --${TARGET_CONFIG}-* ]] || [[ "$1" = --target-option ]]; then
# Assume always has an additional value. Perform base64 encoding on
# the parameter value in case it has spaces. The runtime will be
# responsible for decoding the value.
ESC2="base64_"$(echo -n $2 | base64 --wrap=0)
TARGET_ARGS+=($1 $ESC2)

Hence, this would require some additional considerations for handling the Bool argument type, beyond the string-to-bool conversion, to address #3525.

Would you be able to look at the use case described in #3525 as well?

@AndrewTKent
Copy link
Contributor Author

Thanks for the feedback! You're right - the CLI side needs to know which flags are Bool type at parse time to handle --flag without a value.

Would parsing the YAML to extract argument types before the main arg loop be the right approach? Or is there a simpler pattern you'd prefer?

@1tnguyen
Copy link
Collaborator

Thanks for the feedback! You're right - the CLI side needs to know which flags are Bool type at parse time to handle --flag without a value.

Would parsing the YAML to extract argument types before the main arg loop be the right approach? Or is there a simpler pattern you'd prefer?

Yes, I think "parsing the YAML to extract argument types" is a good approach.

@AndrewTKent AndrewTKent force-pushed the andrew/3699/add-bool-target-argument-type branch from 77dc115 to f4bd9b4 Compare January 14, 2026 03:06
@AndrewTKent
Copy link
Contributor Author

@1tnguyen Ready for another look — implemented the YAML parsing approach you suggested.

The compiler now calls cudaq-target-conf --list-bool-args early in argument parsing to detect Bool-type flags, then handles shift 1 (no value) vs shift 2 accordingly.

Bool flags now work naturally:

nvq++ --target ionq --ionq-debias program.cpp  # implicit true

Copy link
Collaborator

@khalatepradnya khalatepradnya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the contribution!

ServerHelper::getArgumentType(const std::string &key) const {
for (const auto &arg : runtimeTarget.config.TargetArguments) {
// Check both the key name and platform-arg key
if (arg.KeyName == key || arg.PlatformArgKey == key) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be applied at multiple places in this PR.

type: string
platform-arg: debias
help-string: "Specify debiasing."
type: bool
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: Is this a breaking change for the users of ionq target?

@AndrewTKent AndrewTKent force-pushed the andrew/3699/add-bool-target-argument-type branch from f4bd9b4 to 99a99d2 Compare January 14, 2026 18:48
@AndrewTKent
Copy link
Contributor Author

@1tnguyen Re: return 0 in is_bool_arg — Yes, this is intentional. In bash, return 0 indicates success/true and return 1 indicates failure/false. The function returns 0 (success) when the key IS a Bool argument, which is the correct convention.

@khalatepradnya Re: breaking change for ionq users — No, this is backwards compatible:

  • Old syntax still works: --ionq-debias true or --ionq-debias "true"
  • New implicit syntax: --ionq-debias (no value = defaults to true)
  • Bool parsing is lenient: accepts true, True, TRUE, 1 (and same for false variants)

The only behavioral change is that invalid values now throw a clear error instead of being silently passed to the API. This is actually an improvement — previously --ionq-debias "invalid" would send a malformed request to IonQ's API with a confusing error. Now it fails fast with: "Invalid boolean value for 'debias': 'invalid'. Expected true/false/1/0."


Updates in this push:

  • Added llvm-lit end-to-end test (test/NVQPP/bool_target_args.cpp) covering implicit true, explicit true, and explicit false
  • Fixed LLVM style (removed braces from single-statement blocks)
  • Added validation that throws on invalid Bool values instead of silent fallback
  • Added DCO sign-off

@AndrewTKent AndrewTKent force-pushed the andrew/3699/add-bool-target-argument-type branch from 99a99d2 to b3b15e1 Compare January 14, 2026 18:53
Adds `Bool` to the `ArgumentType` enum for target configuration, enabling
boolean flags that can be specified without a value.

## Changes

### Core Type Support
- Add `Bool` to `ArgumentType` enum in TargetConfig.h
- Add YAML mapping "bool" -> ArgumentType::Bool in TargetConfig.cpp

### Typed Value Utilities
- Add `getTypedConfigValue()` to ServerHelper for proper JSON serialization
- Add `getArgumentType()` to look up declared types from target config
- Bool values serialize as JSON boolean literals (not strings)

### nvq++ Compiler Support
- Add `--list-bool-args` mode to cudaq-target-conf tool
- Modify nvq++ to detect Bool arguments and handle shift 1 vs shift 2
- Bool args can be specified without value (defaults to true)

### Backend Updates
- Update IonQ backend: change `debias` and `sharpen` to `type: bool`
- Simplify backend code using new typed value utilities

### Tests
- Add unit test for Bool argument YAML parsing
- Add integration test for --list-bool-args output
- Add test YAML config with Bool/String/Int arguments

## Usage

Target YAML:
```yaml
target-arguments:
  - key: debias
    type: bool
    platform-arg: debias
```

Command line:
```bash
nvq++ --target ionq --ionq-debias program.cpp      # defaults to true
nvq++ --target ionq --ionq-debias true program.cpp # explicit true
nvq++ --target ionq --ionq-debias=false program.cpp # explicit false
```

Fixes NVIDIA#3699
Fixes NVIDIA#3525

Signed-off-by: andrewtkent <[email protected]>
@AndrewTKent AndrewTKent force-pushed the andrew/3699/add-bool-target-argument-type branch from b3b15e1 to 822c1a1 Compare January 14, 2026 19:04
@khalatepradnya
Copy link
Collaborator

khalatepradnya commented Jan 15, 2026

/ok to test 822c1a1

Command Bot: Processing...

@khalatepradnya
Copy link
Collaborator

khalatepradnya commented Jan 15, 2026

For the 'Check code formatting' failure in CI, please run the clang formatter. (See: https://github.com/NVIDIA/cuda-quantum/blob/main/Developing.md#c-formatting).

Comment on lines +21 to +30
// IMPLICIT: -DNVQPP_TARGET_BACKEND_CONFIG
// IMPLICIT-SAME: debias;true

// EXPLICIT: -DNVQPP_TARGET_BACKEND_CONFIG
// EXPLICIT-SAME: debias;true

// FALSE: -DNVQPP_TARGET_BACKEND_CONFIG
// FALSE-SAME: debias;false
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This is a good test :)

nit: Could you please move these FileCheck lines to the bottom of the file, to be consistent with other test files?

github-actions bot pushed a commit that referenced this pull request Jan 15, 2026
@github-actions
Copy link

CUDA Quantum Docs Bot: A preview of the documentation can be found here.

Signed-off-by: andrewtkent <[email protected]>
@AndrewTKent AndrewTKent force-pushed the andrew/3699/add-bool-target-argument-type branch from 5bde1a9 to 54af656 Compare January 15, 2026 18:22
@1tnguyen
Copy link
Collaborator

1tnguyen commented Jan 15, 2026

/ok to test 4e99a21

Command Bot: Processing...

github-actions bot pushed a commit that referenced this pull request Jan 16, 2026
@github-actions
Copy link

CUDA Quantum Docs Bot: A preview of the documentation can be found here.

@1tnguyen
Copy link
Collaborator

Remove redundant default label from switch statement that already
covers all ArgumentType enum values. This fixes the build error:
"default label in switch which covers all enumeration values"
(-Werror,-Wcovered-switch-default)

Signed-off-by: AndrewTKent <[email protected]>
@khalatepradnya
Copy link
Collaborator

khalatepradnya commented Jan 20, 2026

/ok to test 64f9668

Command Bot: Processing...

@khalatepradnya
Copy link
Collaborator

@AndrewTKent : Thank you for the fix, but I think it has led to a different failure. Please see: https://github.com/NVIDIA/cuda-quantum/actions/runs/21182285081/job/60928809695?pr=3740#step:8:1165

@AndrewTKent AndrewTKent force-pushed the andrew/3699/add-bool-target-argument-type branch from 64f9668 to eeecab5 Compare January 21, 2026 21:28
@AndrewTKent
Copy link
Contributor Author

@1tnguyen @khalatepradnya

Took a stab at fixing the build failure. The issue appears to be GCC's -Werror=return-type flagging the Bool case in getTypedConfigValue() as having a code path that doesn't return a value.

Restructured the control flow to use an explicit else if / else chain, which should make it clear to the compiler that every path either returns or throws:

if (value == "true" || ...)
  return true;
else if (value == "false" || ...)
  return false;
else
  throw std::runtime_error(...);

Also squashed the commits. Let's see if CI is happier now.

@khalatepradnya
Copy link
Collaborator

khalatepradnya commented Jan 22, 2026

/ok to test 9d451f1

Command Bot: Processing...

case config::ArgumentType::UUID:
case config::ArgumentType::FeatureFlag:
case config::ArgumentType::MachineConfig:
default:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

github-actions bot pushed a commit that referenced this pull request Jan 22, 2026
@github-actions
Copy link

CUDA Quantum Docs Bot: A preview of the documentation can be found here.

@AndrewTKent AndrewTKent force-pushed the andrew/3699/add-bool-target-argument-type branch from 9d451f1 to 9362a2a Compare January 23, 2026 20:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

boolean target arguments for backends Target arguments - Allow passing Boolean values

3 participants