skills/convexbench-recognize-convex-functions/SKILL.md
Determine the convexity of arbitrarily deep symbolic function compositions using AST decomposition and recursive DCP-rule reasoning. Use when the user asks to 'check if this function is convex', 'analyze convexity of a composed expression', 'verify DCP compliance', 'classify a nested objective as convex/concave/neither', 'decompose a composite function for convexity analysis', or 'apply disciplined convex programming rules'.
npx skillsauth add ndpvt-web/arxiv-claude-skills convexbench-recognize-convex-functionsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill enables Claude to determine whether a symbolic mathematical expression -- potentially involving dozens or hundreds of nested function compositions -- is convex, concave, affine, or neither. It applies the agentic divide-and-conquer framework from the ConvexBench paper: first parsing the expression into an abstract syntax tree (AST) to isolate each sub-expression, then reasoning recursively about convexity at each node using Disciplined Convex Programming (DCP) composition rules with focused dependency context. This approach eliminates the two failure modes that cause LLMs to fail on deep compositions: parsing failure (losing track of operator scope in long expressions) and lazy reasoning (applying shallow heuristics instead of systematic verification).
exp(log(sum(square(Ax - b))))) and needs convexity classificationThe core problem. Determining convexity of a single function like exp(x) or x^2 is straightforward. But real optimization objectives chain many operations together -- log(1 + exp(-y * (w'x + b))) -- and convexity of the whole depends on how each layer's convexity and monotonicity interact with the layers below it. LLMs fail at this for deep compositions because they lose track of parenthetical scope (parsing failure) and skip rigorous step-by-step verification (lazy reasoning).
The divide-and-conquer solution. Instead of asking for a single-shot convexity judgment, the framework (1) deterministically parses the expression into an AST, introducing named intermediate variables for each sub-expression, and (2) reasons about each sub-expression individually, carrying forward only the direct dependency context (the convexity class, monotonicity, and range of immediate parent sub-expressions). Each sub-expression g_i is classified using only {(g_j, sigma_j) | j in Parents(i)} -- not the entire expression. This focused-context approach prevents attention dilution and forces systematic rule application.
DCP composition rules. The classification at each node uses standard disciplined convex programming rules: a nondecreasing convex function of a convex argument is convex; a nonincreasing convex function of a concave argument is convex; a sum of convex functions is convex; an affine function composed with anything preserves the inner function's convexity class; and so on. When no rule applies, the composition is classified as "neither." These rules are sound (never produce false positives) though incomplete (some functions that are technically convex cannot be verified via DCP rules alone).
Receive and normalize the expression. Take the user's symbolic expression and normalize notation: expand shorthand (||x||^2 to sum(square(x))), clarify variable vs. parameter roles, and confirm the domain.
Build the abstract syntax tree. Parse the expression into a tree where each internal node is an operation (e.g., exp, +, log, max, scalar multiplication) and each leaf is a variable or constant. Assign a named intermediate variable to each internal node (e.g., t1 = Ax - b, t2 = square(t1), t3 = sum(t2)).
Flatten to a dependency-ordered sub-expression list. Topologically sort the AST nodes so that every sub-expression appears after its dependencies. Produce a sequence G = [g_1, g_2, ..., g_k] where g_1 involves only leaf variables and g_k is the root expression.
Classify leaf atoms. For each leaf-level sub-expression, assign its convexity class (convex, concave, affine, neither), monotonicity (nondecreasing, nonincreasing, non-monotone), and range (e.g., nonneg, pos, real). Variables are affine and nondecreasing. Constants are affine.
Apply DCP rules bottom-up at each node. For each sub-expression g_i in order, retrieve only the properties of its direct dependencies {(g_j, sigma_j) | j in Parents(i)} and apply the matching DCP composition rule:
f(convex) where f is nondecreasing and convex -> convexf(concave) where f is nonincreasing and convex -> convexf(affine) where f is convex -> convex (and analogously for concave)sum(convex, convex) -> convex; sum(concave, concave) -> concavealpha * convex -> convex if alpha >= 0, concave if alpha < 0max(convex, convex) -> convex; min(concave, concave) -> concavePropagate range information. Track the output range of each sub-expression (nonneg, nonpos, pos, neg, real) since some rules require range constraints (e.g., log requires positive input, sqrt requires nonneg input).
Report the root node classification. The convexity of g_k (the root) is the convexity of the overall expression.
Present the full reasoning trace. Show each sub-expression, its dependencies, the rule applied, and the resulting classification. This lets the user verify every step and identify exactly where a non-DCP composition breaks the chain.
If the result is "neither," attempt diagnosis. Identify the specific sub-expression where DCP compliance breaks. Suggest equivalent reformulations that may be DCP-compliant (e.g., replacing square(abs(x)) with square(x), or using quad_over_lin instead of square(x) / y).
Example 1: Logistic regression loss
User: "Is log(1 + exp(-y * (w'x + b))) convex in (w, b) where y and x are parameters?"
Approach:
Parse into sub-expressions:
t1 = w'x + b (affine in w, b)t2 = y * t1 (affine -- scalar * affine, y is a parameter)t3 = -t2 (affine -- negation of affine)t4 = exp(t3) (exp is convex and nondecreasing; applied to affine -> convex)t5 = 1 + t4 (sum of constant and convex -> convex)t6 = log(t5) (log is concave and nondecreasing; applied to convex -> ?)At t6: log is concave nondecreasing, t5 is convex. DCP rule: concave nondecreasing of convex does NOT match any standard DCP rule. But log(1 + exp(u)) is the log-sum-exp of (0, u), which is convex by the LSE rule.
Re-parse using log_sum_exp atom: t6 = log_sum_exp(0, t3). LSE is convex nondecreasing in each argument; each argument is affine -> convex.
Output:
Expression: log(1 + exp(-y * (w'x + b)))
Decomposition:
t1 = w'x + b -> affine (linear in w, b)
t2 = -y * t1 -> affine (scalar * affine)
t3 = logsumexp(0, t2)-> convex (LSE of affine args)
Result: CONVEX in (w, b).
Note: Direct composition log(1 + exp(u)) is not DCP-compliant
as written, but is equivalent to logsumexp(0, u) which is a
recognized convex atom. Solvers like CVXPY accept log_sum_exp.
Example 2: Deep nested composition
User: "Check convexity of exp(square(abs(3*x + 2))) over all real x."
Approach:
Decompose:
t1 = 3*x + 2 (affine, nondecreasing, range: real)t2 = abs(t1) (convex, non-monotone, range: nonneg)t3 = square(t2) (square is convex; on nonneg domain it is nondecreasing; applied to convex nonneg -> convex, range: nonneg)t4 = exp(t3) (exp is convex nondecreasing; applied to convex -> convex)Apply rules at each step, carrying forward range info.
Output:
Decomposition:
t1 = 3*x + 2 -> affine [range: real]
t2 = abs(t1) -> convex [abs is convex; range: nonneg]
t3 = square(t2) -> convex [square is convex nondecreasing on nonneg; convex of convex nonneg -> convex; range: nonneg]
t4 = exp(t3) -> convex [exp is convex nondecreasing; convex of convex -> convex]
Result: CONVEX.
Example 3: Non-convex expression
User: "Is sin(x^2) convex?"
Approach:
t1 = x^2 (convex, range: nonneg)t2 = sin(t1) (sin is neither convex nor concave; no DCP rule applies)Output:
Decomposition:
t1 = x^2 -> convex [range: nonneg]
t2 = sin(t1) -> NEITHER [sin is not convex/concave/affine; no DCP rule applies]
Result: NEITHER (not DCP-verifiable).
Diagnosis: sin() is not a recognized DCP atom. The composition
sin(convex) cannot be classified by DCP rules. Numerically,
sin(x^2) is indeed non-convex (e.g., compare midpoint values
around x=1 and x=2).
norm(x)^2 -> sum_squares(x), x*x/y -> quad_over_lin(x, y)).x'Ax is convex in x if A is PSD but is generally neither convex nor concave if A is also a variable.{(g_j, sigma_j) | j in Parents(i)} to prevent attention dilution on irrelevant sub-expressions.log applied to something that can be negative), flag this as a domain error rather than a convexity classification.log(sum(exp(x_i))) is convex but naive decomposition into sum then log breaks DCP. This requires recognizing log_sum_exp as a single atom. The approach depends on the atom library being sufficiently rich.ConvexBench: Can LLMs Recognize Convex Functions? -- Liu, Huang, Wang, Liang, Bu (2026). arXiv:2602.01075v2. Focus on Section 4 (agentic divide-and-conquer framework), Table 2 (DCP composition rules), and Algorithm 1 (recursive reasoning with focused context).
development
Audit LLM-based automatic short answer grading (ASAG) systems for adversarial vulnerabilities using token-level and prompt-level attack strategies from the GradingAttack framework. Triggers: 'test grading robustness', 'adversarial attack on grading', 'audit LLM grader', 'red-team answer grading', 'ASAG vulnerability assessment', 'grading fairness attack'
development
Build structured information-seeking agents that decompose complex queries into multi-turn search-and-browse workflows, aggregate results from multiple web sources, and return answers in typed structured formats (items, sets, lists, tables). Applies the GISA benchmark's ReAct-based agent architecture and evaluation methodology. Trigger phrases: "build an information-seeking agent", "search agent pipeline", "multi-turn web research agent", "structured web search workflow", "aggregate information from multiple sources", "web research with structured output"
data-ai
Optimize LLM prompts using GFlowPO's iterative generate-evaluate-refine loop with diversity-preserving exploration and dynamic memory. Use when: 'optimize this prompt', 'find a better prompt for this task', 'prompt engineering with examples', 'auto-tune my system prompt', 'improve prompt accuracy', 'generate prompt variations'.
development
Constrain LLM generation with executable Pydantic schemas and multi-agent pipelines to produce structurally valid, domain-rich artifacts. Uses ontology-as-grammar to eliminate hallucinated structures while preserving creative output. Trigger phrases: "generate a valid game design", "schema-constrained generation", "build a multi-agent pipeline with Pydantic validation", "ontology-driven content generation", "structured creative generation with DSPy", "generate artifacts that pass domain validation".