Skip to content
Back to skills

Sequential Edge Inverse Entropy Voting

ASecurity

Replace parallel self-consistency with sequential reasoning where chains iteratively build on previous attempts, weighted by inverse entropy to prioritize confident solutions, achieving 46.7 pp accuracy gains over parallel approaches.

  • 6 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 9, 2026
toolspythongit

Security analysis

A100/100

Scanned September 9, 2026

npx -y skills add ADu2021/skillXiv --skill sequential-edge-inverse-entropy-voting --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Sequential Edge Inverse Entropy Voting?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Sequential Edge Inverse Entropy Voting
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/adu2021-sequential-edge-inverse-entropy-voting/badge)](https://www.skillsdirectory.com/skills/adu2021-sequential-edge-inverse-entropy-voting)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: sequential-edge-inverse-entropy-voting
title: "Sequential Edge: Inverse-Entropy Voting Beats Parallel Self-Consistency"
version: 0.0.2
engine: skillxiv-v0.0.2-claude-opus-4.6
license: MIT
url: "https://arxiv.org/abs/2511.02309"
keywords: [Test-Time Scaling, Inference Optimization, Reasoning Chains, Entropy, Voting]
description: "Replace parallel self-consistency with sequential reasoning where chains iteratively build on previous attempts, weighted by inverse entropy to prioritize confident solutions, achieving 46.7 pp accuracy gains over parallel approaches."
---

# Title: Build Reasoning Chains Sequentially for Superior Accuracy

The dominant paradigm for improving language model reasoning is parallel self-consistency: run N independent reasoning chains, then vote. Sequential Edge shows this is suboptimal. By running chains sequentially where each explicitly builds on previous attempts, models achieve 95.6% superiority rates over parallel approaches. Further, weighting solutions by **inverse entropy** (favoring low-entropy/confident chains) outperforms majority voting universally.

This is a pure inference-time technique requiring no model retraining.

## Core Concept

**Sequential Reasoning With Entropy-Weighted Aggregation**:
- **Sequential Scaling**: Each chain reads previous attempts and tries to improve them
- **Iterative Refinement**: Three mechanisms available: error correction, context accumulation, verification
- **Inverse-Entropy Voting**: Weight each answer by how certain the model was (low entropy = high confidence)
- **No Training Required**: Works with base models or fine-tuned variants
- **Universal Superiority**: Better than parallel approaches across all tested models and benchmarks

## Architecture Overview

- **Sequential Chain Generation**: Causal generation where chain k reads output of chain k-1
- **Confidence Estimation**: Compute Shannon entropy from token-level probability distributions
- **Entropy-Weighted Aggregation**: Answers weighted inversely to their generation entropy
- **Stopping Criterion**: Continue sequencing until convergence or budget exhausted
- **Hybrid Architecture**: Can mix sequential and parallel chains for different problem types

## Implementation Steps

**1. Implement Sequential Chain Generation**

Generate reasoning chains that explicitly reference previous attempts.

```python
class SequentialReasoningGenerator:
    def __init__(self, model, tokenizer, max_chains=6):
        self.model = model
        self.tokenizer = tokenizer
        self.max_chains = max_chains

    def generate_sequential_chains(self, question, num_chains=6):
        """Generate chains sequentially with cross-chain reference"""
        chains = []
        entropies = []

        # First chain: independent reasoning
        prompt_1 = f"""Solve this problem step by step:
        {question}

        Solution:"""
        chain_1, entropy_1 = self.generate_chain_with_entropy(prompt_1)
        chains.append(chain_1)
        entropies.append(entropy_1)

        # Subsequent chains: build on previous
        for i in range(1, num_chains):
            # Acknowledge previous attempt
            previous_solution = chains[-1]

            prompt_n = f"""Previous attempt at this problem:
            {previous_solution}

            Reconsider the problem {question}
            Try a different approach to check if the previous solution is correct.

            New solution:"""

            chain_n, entropy_n = self.generate_chain_with_entropy(prompt_n)
            chains.append(chain_n)
            entropies.append(entropy_n)

        return chains, entropies

    def generate_chain_with_entropy(self, prompt):
        """Generate reasoning chain and compute entropy"""
        input_ids = self.tokenizer.encode(prompt, return_tensors='pt')

        # Generate with return_dict_in_generate to get log probabilities
        outputs = self.model.generate(
            input_ids,
            max_new_tokens=300,
            return_dict_in_generate=True,
            output_scores=True,
            pad_token_id=self.tokenizer.eos_token_id
        )

        # Decode generated tokens
        generated_ids = outputs.sequences[0][input_ids.shape[1]:]
        generated_text = self.tokenizer.decode(generated_ids, skip_special_tokens=True)

        # Compute entropy over generated tokens
        # outputs.scores: tuple of tensors [batch_size, vocab_size] for each position
        entropy = self.compute_sequence_entropy(outputs.scores)

        return generated_text, entropy

    def compute_sequence_entropy(self, scores):
        """Compute entropy of token probability distribution"""
        entropies = []

        for token_scores in scores:
            # Get probabilities from logits
            probs = F.softmax(token_scores, dim=-1)

            # Shannon entropy: -sum(p * log(p))
            entropy = -(probs * torch.log(probs + 1e-10)).sum(dim=-1)
            entropies.append(entropy.item())

        # Return average entropy over sequence
        return np.mean(entropies) if entropies else 0.0
```

**2. Implement Inverse-Entropy Voting**

Weight answers by confidence (inverse of entropy).

```python
class InverseEntropyVoter:
    def __init__(self, extraction_fn):
        """extraction_fn: function that extracts answer from solution text"""
        self.extract_answer = extraction_fn

    def extract_answers_and_weights(self, chains, entropies):
        """Extract final answers and compute entropy-based weights"""
        answers = []
        weights = []

        for chain, entropy in zip(chains, entropies):
            # Extract answer from chain
            answer = self.extract_answer(chain)
            answers.append(answer)

            # Weight inversely to entropy: low entropy -> high weight
            # Use exponential scaling for sharper differences
            weight = np.exp(-entropy)
            weights.append(weight)

        # Normalize weights to sum to 1
        total_weight = sum(weights)
        weights = [w / total_weight for w in weights]

        return answers, weights

    def weighted_vote(self, chains, entropies, answer_similarity_fn=None):
        """Aggregate answers weighted by inverse entropy"""
        answers, weights = self.extract_answers_and_weights(chains, entropies)

        # Group similar answers
        if answer_similarity_fn:
            answer_groups = self.group_similar_answers(answers, answer_similarity_fn)
        else:
            answer_groups = {ans: [i for i, a in enumerate(answers) if a == ans]
                             for ans in set(answers)}

        # Compute weighted score for each answer group
        group_scores = {}
        for answer, indices in answer_groups.items():
            score = sum(weights[i] for i in indices)
            group_scores[answer] = score

        # Return highest-scoring answer
        final_answer = max(group_scores, key=group_scores.get)
        confidence = group_scores[final_answer]

        return final_answer, confidence, group_scores

    def group_similar_answers(self, answers, similarity_fn):
        """Group answers that are semantically similar"""
        groups = {}
        for i, answer in enumerate(answers):
            # Find most similar existing group
            best_group = None
            best_similarity = 0

            for group_answer in groups:
                sim = similarity_fn(answer, group_answer)
                if sim > best_similarity:
                    best_similarity = sim
                    best_group = group_answer

            if best_group and best_similarity > 0.8:
                groups[best_group].append(i)
            else:
                groups[answer] = [i]

        return groups
```

**3. Implement Hybrid Sequential-Parallel Strategy**

Combine approaches for complex problems.

```python
class HybridReasoningStrategy:
    def __init__(self, model, tokenizer, num_sequential=3, num_parallel=3):
        self.sequential_gen = SequentialReasoningGenerator(model, tokenizer)
        self.voter = InverseEntropyVoter(self.extract_final_answer)
        self.num_seq = num_sequential
        self.num_par = num_parallel

    def solve_with_budget(self, question, token_budget=10000):
        """Solve using hybrid strategy within token budget"""
        # Phase 1: Sequential reasoning (focus on quality)
        seq_chains, seq_entropies = self.sequential_gen.generate_sequential_chains(
            question, self.num_seq
        )
        tokens_used = sum(len(c.split()) for c in seq_chains) * 1.3  # Estimate

        # Phase 2: Parallel chains if budget remains
        if tokens_used < token_budget * 0.7:
            parallel_chains = []
            for _ in range(self.num_par):
                prompt = f"Solve: {question}\nSolution:"
                chain, _ = self.sequential_gen.generate_chain_with_entropy(prompt)
                parallel_chains.append(chain)

            # Combine all chains
            all_chains = seq_chains + parallel_chains
            all_entropies = seq_entropies + [0.0] * len(parallel_chains)  # Parallel have no reference entropy
        else:
            all_chains = seq_chains
            all_entropies = seq_entropies

        # Aggregate
        answer, confidence, scores = self.voter.weighted_vote(all_chains, all_entropies)
        return answer, confidence

    def extract_final_answer(self, solution_text):
        """Extract final answer from solution"""
        # Simple strategy: last numeric value or final sentence
        import re
        numbers = re.findall(r'-?\d+\.?\d*', solution_text)
        if numbers:
            return float(numbers[-1])

        # Fallback: last sentence
        sentences = solution_text.split('.')
        return sentences[-2] if len(sentences) > 1 else solution_text
```

**4. Evaluate Sequential vs Parallel**

Compare efficiency and accuracy.

```python
def compare_strategies(model, tokenizer, test_questions):
    """Benchmark sequential vs parallel approaches"""
    results = {
        'sequential': {'accuracy': [], 'tokens': []},
        'parallel': {'accuracy': [], 'tokens': []},
        'hybrid': {'accuracy': [], 'tokens': []}
    }

    seq_gen = SequentialReasoningGenerator(model, tokenizer)
    voter = InverseEntropyVoter(extract_answer_fn)

    for question, ground_truth in test_questions:
        # Sequential approach
        seq_chains, seq_entropies = seq_gen.generate_sequential_chains(question, num_chains=6)
        seq_answer, _ = voter.weighted_vote(seq_chains, seq_entropies)
        seq_correct = seq_answer == ground_truth
        seq_tokens = sum(len(c.split()) * 1.3 for c in seq_chains)

        results['sequential']['accuracy'].append(seq_correct)
        results['sequential']['tokens'].append(seq_tokens)

        # Parallel approach (independent chains)
        par_chains = []
        for _ in range(6):
            chain, entropy = seq_gen.generate_chain_with_entropy(
                f"Solve: {question}\nSolution:"
            )
            par_chains.append(chain)

        par_entropies = [0.0] * len(par_chains)
        par_answer, _ = voter.weighted_vote(par_chains, par_entropies)
        par_correct = par_answer == ground_truth
        par_tokens = sum(len(c.split()) * 1.3 for c in par_chains)

        results['parallel']['accuracy'].append(par_correct)
        results['parallel']['tokens'].append(par_tokens)

    # Compute statistics
    for strategy in results:
        acc = np.mean(results[strategy]['accuracy'])
        tokens = np.mean(results[strategy]['tokens'])
        print(f"{strategy}: {acc:.1%} accuracy, {tokens:.0f} tokens/problem")

    return results
```

## Practical Guidance

**When to Use**:
- Any test-time reasoning optimization (no retraining needed)
- Mathematical problems, STEM benchmarks
- Settings where inference cost matters more than model size

**Hyperparameters**:
- num_sequential_chains: 4-8 (returns diminish beyond 6)
- entropy_temperature: 1.0 (controls sharpness of entropy-based weighting)
- token_budget: Adjust based on latency constraints

**When NOT to Use**:
- Real-time applications (sequential generation is slower than parallel)
- Streaming scenarios where latency is critical
- Models without reliable probability distributions

**Pitfalls**:
- **Answer extraction brittleness**: Regex/heuristic extraction fails on varied formats; use semantic matching
- **Entropy unreliability**: Some models produce low-entropy nonsense; validate with baseline
- **Sequential dependency**: If first chain is very wrong, subsequent chains may not recover; use restart strategies

**Key Insight**: This is one of the few inference-time tricks that consistently beats the dominant approach. The mechanism is simple: sequential reasoning enables error correction that parallel approaches miss.

## Reference

arXiv: https://arxiv.org/abs/2511.02309

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.