← 返回首页

python #game #pytorch

Programming is full of games. This one here is about tensor. Your aim is to use a series of transformations provided by the PyTorch module to transform the given tensor to the target one.

Example play:

--- Puzzle 20 of 32 ---
Initial Tensor:
tensor([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12])

Target Tensor:
tensor([[ 1,  7],
        [ 2,  8],
        [ 3,  9],
        [ 4, 10],
        [ 5, 11],
        [ 6, 12]])

Enter your operations: reshape 2 -1, transpose 0 1
Correct! You've transformed the tensor successfully.

Current operations (transpose, unsqueeze, squeeze, view, reshape, permute) are limited.

I will consider to add more:

  1. expand or repeat: These operations can be used to increase the size of a tensor by repeating its elements.

  2. cat or stack: These operations combine multiple tensors along a specified dimension.

  3. split or chunk: These operations divide a tensor into multiple smaller tensors.

  4. flip: This operation reverses the order of elements along a specified dimension.

  5. roll: This operation shifts the elements of a tensor along a dimension.

  6. gather or index_select: These operations can be used for more complex indexing tasks.

  7. masked_select: This operation selects elements from a tensor using a boolean mask.

  8. where: This operation can be used for element-wise conditional selection.

  9. unfold: This operation extracts sliding local blocks from a tensor.

  10. diag: This operation can be used to extract a diagonal or construct a diagonal matrix.

Code

import torch
import tensorlevels as levels # Import the puzzles from levels.py

# Define possible operations
def transpose(tensor, dim0, dim1):
    return tensor.transpose(dim0, dim1)

def unsqueeze(tensor, dim):
    return tensor.unsqueeze(dim)

def squeeze(tensor, dim=None):
    return tensor.squeeze(dim)

def view(tensor, *shape):
    return tensor.view(*shape)

def reshape(tensor, *shape):
    return tensor.reshape(*shape)

def permute(tensor, *dims):
    return tensor.permute(*dims)

# Mapping operation names to functions
operations = {
    'transpose': transpose,
    'unsqueeze': unsqueeze,
    'squeeze': squeeze,
    'view': view,
    'reshape': reshape,
    'permute': permute
}

def print_tensor(tensor):
    print(tensor)

def parse_arguments(args_str):
    """
    Parses a string of arguments separated by commas or spaces.
    Supports mixed separators.
    """
    args = []
    for part in args_str.replace(',', ' ').split():
        # Attempt to convert to integer
        if part.lstrip('-').isdigit():
            args.append(int(part))
        else:
            # Attempt to convert to float
            try:
                args.append(float(part))
            except ValueError:
                args.append(part)
    return args

def game():
    print("Welcome to the PyTorch Tensor Transformation Game!")
    print("Your goal is to transform the initial tensor into the target tensor using PyTorch operations.")
    print("Available operations: transpose, unsqueeze, squeeze, view, reshape, permute")
    print("Enter operations in sequence, separated by commas.")
    print("For operations with arguments, separate arguments by spaces.")
    print("For example: transpose 0 1, squeeze\n")

    total_levels = len(levels.puzzles)
    start_level = 0

    # Prompt user for starting level
    user_input = input(f"Enter the level index to start from (1 to {total_levels}), press Enter to start from 1: ")
    if user_input.strip():
        if user_input.isdigit():
            idx = int(user_input)
            if 1 <= idx <= total_levels:
                start_level = idx - 1
            else:
                print(f"Invalid level index. Starting from level 1.")
        else:
            print(f"Invalid input. Starting from level 1.")

    # Iterate through levels starting from start_level
    for idx in range(start_level, total_levels):
        puzzle = levels.puzzles[idx]
        print(f"\n--- Puzzle {idx + 1} of {total_levels} ---")
        print("Initial Tensor:")
        print_tensor(puzzle['initial'])
        print("\nTarget Tensor:")
        print_tensor(puzzle['target'])

        while True:
            user_input = input("\nEnter your operations: ").strip()
            if not user_input:
                print("Please enter at least one operation.")
                continue

            operations_input = [op.strip() for op in user_input.split(',')]

            current_tensor = puzzle['initial']
            try:
                for op_str in operations_input:
                    if not op_str:
                        continue
                    parts = op_str.split()
                    op_name = parts[0]
                    args = parse_arguments(' '.join(parts[1:]))  # Handle arguments

                    if op_name not in operations:
                        raise ValueError(f"Operation '{op_name}' is not recognized.")

                    current_tensor = operations[op_name](current_tensor, *args)

                if torch.equal(current_tensor, puzzle['target']):
                    print("Correct! You've transformed the tensor successfully.")
                    break  # Move to the next level
                else:
                    print("Incorrect transformation. Here's what you got:")
                    print_tensor(current_tensor)
                    print("Expected target tensor:")
                    print_tensor(puzzle['target'])
                    print("Try again.\n")
            except Exception as e:
                print(f"Error applying operations: {e}")
                print("Please check your operations and try again.\n")

    print("\nCongratulations! You've completed all the puzzles.")

if __name__ == "__main__":
    game()

Levels (provided by OpenAI-o1)

import torch

puzzles = [
    # Original Puzzles
    {
        'initial': torch.tensor([[1, 2], [3, 4]]),
        'target': torch.tensor([1, 2, 3, 4]),
        'solution': ['view -1']  # Flatten the tensor
    },
    {
        'initial': torch.tensor([1, 2, 3, 4]),
        'target': torch.tensor([[1, 2], [3, 4]]),
        'solution': ['view 2 2']  # Reshape to 2x2
    },
    {
        'initial': torch.tensor([[1, 2, 3], [4, 5, 6]]),
        'target': torch.tensor([[1, 4], [2, 5], [3, 6]]),
        'solution': ['transpose 0 1']  # Transpose the tensor
    },

    # Additional Puzzles
    {
        'initial': torch.tensor([1, 2, 3, 4]),
        'target': torch.tensor([[1, 2, 3, 4]]),
        'solution': ['unsqueeze 0']  # Add a new dimension at position 0
    },
    {
        'initial': torch.tensor([[1, 2, 3, 4]]),
        'target': torch.tensor([1, 2, 3, 4]),
        'solution': ['squeeze 0']  # Remove the dimension at position 0
    },
    {
        'initial': torch.tensor([[1, 2], [3, 4], [5, 6]]),
        'target': torch.tensor([1, 3, 5, 2, 4, 6]),
        'solution': ['permute 1 0', 'view -1']  # Permute and flatten
    },
    {
        'initial': torch.tensor([1, 2, 3, 4, 5, 6]),
        'target': torch.tensor([[1, 2, 3], [4, 5, 6]]),
        'solution': ['view 2 3']  # Reshape to 2x3
    },
    {
        'initial': torch.tensor([1, 2, 3, 4, 5, 6]),
        'target': torch.tensor([[1], [2], [3], [4], [5], [6]]),
        'solution': ['view -1 1']  # Reshape to 6x1
    },
    {
        'initial': torch.tensor([1, 2, 3, 4, 5, 6]),
        'target': torch.tensor([[1, 4], [2, 5], [3, 6]]),
        'solution': ['view 2 3', 'transpose 0 1']  # Reshape to 2x3 and transpose to 3x2
    },
    {
        'initial': torch.tensor([1, 2, 3, 4, 5, 6, 7, 8]),
        'target': torch.tensor([[1, 5], [2, 6], [3, 7], [4, 8]]),
        'solution': ['view 2 4', 'transpose 0 1']  # Reshape to 2x4 and transpose to 4x2
    },
    {
        'initial': torch.tensor([[1, 2], [3, 4], [5, 6], [7, 8]]),
        'target': torch.tensor([1, 3, 5, 7, 2, 4, 6, 8]),
        'solution': ['permute 1 0', 'view -1']  # Permute and flatten
    },
    {
        'initial': torch.tensor([[1, 2, 3, 4], [5, 6, 7, 8]]),
        'target': torch.tensor([1, 5, 2, 6, 3, 7, 4, 8]),
        'solution': ['transpose 0 1', 'view -1']  # Transpose and flatten
    },
    {
        'initial': torch.tensor([1, 2, 3, 4, 5, 6, 7, 8]),
        'target': torch.tensor([[1, 2, 3, 4], [5, 6, 7, 8]]),
        'solution': ['view 2 4']  # Reshape to 2x4
    },
    {
        'initial': torch.tensor([[1], [2], [3], [4]]),
        'target': torch.tensor([1, 2, 3, 4]),
        'solution': ['squeeze 1']  # Remove the second dimension
    },
    {
        'initial': torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]),
        'target': torch.tensor([[1, 5], [2, 6], [3, 7], [4, 8]]),
        'solution': ['permute 1 0 2', 'view -1 2']  # Permute and reshape
    },
    {
        'initial': torch.tensor([1, 2, 3, 4, 5, 6, 7, 8]),
        'target': torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]),
        'solution': ['view 2 2 2']  # Reshape to 2x2x2
    },
    {
        'initial': torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]),
        'target': torch.tensor([1, 2, 3, 4, 5, 6, 7, 8]),
        'solution': ['view -1']  # Flatten the tensor
    },
    {
        'initial': torch.tensor([1, 2, 3, 4, 5, 6, 7, 8]),
        'target': torch.tensor([[1], [2], [3], [4], [5], [6], [7], [8]]),
        'solution': ['view 8 1']  # Reshape to 8x1
    },
    {
        'initial': torch.tensor([[1, 2], [3, 4], [5, 6], [7, 8]]),
        'target': torch.tensor([1, 3, 5, 7, 2, 4, 6, 8]),
        'solution': ['view 2 4', 'permute 1 0']  # Reshape and permute
    },
    {
        'initial': torch.tensor([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]),
        'target': torch.tensor([[1, 7], [2, 8], [3, 9], [4, 10], [5, 11], [6, 12]]),
        'solution': ['view 2 6', 'transpose 0 1']  # Reshape to 2x6 and transpose to 6x2
    },
    {
        'initial': torch.tensor([[1, 2, 3], [4, 5, 6]]),
        'target': torch.tensor([1, 4, 2, 5, 3, 6]),
        'solution': ['transpose 0 1', 'view -1']  # Transpose and flatten
    },
    {
        'initial': torch.tensor([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]),
        'target': torch.tensor([1, 5, 9, 2, 6, 10, 3, 7, 11, 4, 8, 12]),
        'solution': ['permute 1 0', 'view -1']  # Permute and flatten
    },
    {
        'initial': torch.tensor([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]),
        'target': torch.tensor([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]]),
        'solution': ['view 2 2 3']  # Reshape to 2x2x3
    },
    {
        'initial': torch.tensor([1, 2, 3, 4]),
        'target': torch.tensor([[[1, 2], [3, 4]]]),
        'solution': ['view 1 2 2']  # Reshape to 1x2x2
    },
    {
        'initial': torch.tensor([[[1, 2], [3, 4]]]),
        'target': torch.tensor([1, 2, 3, 4]),
        'solution': ['squeeze 0']  # Remove the first dimension
    },
    {
        'initial': torch.tensor([1, 2, 3, 4, 5, 6, 7, 8]),
        'target': torch.tensor([[1, 2, 3, 4], [5, 6, 7, 8]]),
        'solution': ['view 2 4']  # Reshape to 2x4
    },
    {
        'initial': torch.tensor([[1, 2, 3, 4], [5, 6, 7, 8]]),
        'target': torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]),
        'solution': ['view 2 2 2']  # Reshape to 2x2x2
    },
    {
        'initial': torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]),
        'target': torch.tensor([[1, 2], [3, 4], [5, 6], [7, 8]]),
        'solution': ['view -1 2']  # Reshape to 4x2
    },
    {
        'initial': torch.tensor([1, 2, 3, 4]),
        'target': torch.tensor([1, 2, 3, 4, 1, 2, 3, 4]),
        'solution': ['view 2 4']  # Reshape to 2x4 (Alternatively, use repeat)
    },
    {
        'initial': torch.tensor([1, 2, 3, 4]),
        'target': torch.tensor([[1, 1], [2, 2], [3, 3], [4, 4]]),
        'solution': ['unsqueeze 1', 'repeat 1 2']  # Add dimension and repeat
    },
    {
        'initial': torch.tensor([[1, 2], [3, 4]]),
        'target': torch.tensor([1, 2, 3, 4, 1, 2, 3, 4]),
        'solution': ['view -1', 'repeat 2']  # Flatten and repeat
    },
    {
        'initial': torch.tensor([[1, 2, 3], [4, 5, 6]]),
        'target': torch.tensor([[[1, 4], [2, 5], [3, 6]]]),
        'solution': ['transpose 0 1', 'unsqueeze 0']  # Transpose and add dimension
    },
]

New Ideas

Stack

import torch

# Create two 1D tensors
a = torch.tensor([1, 2, 3])
b = torch.tensor([4, 5, 6])

# Stack along a new dimension (dim=0)
stacked = torch.stack([a, b], dim=0)
print(stacked)
# Output:
# tensor([[1, 2, 3],
#         [4, 5, 6]])

# Stack along a new dimension (dim=1)
stacked_dim1 = torch.stack([a, b], dim=1)
print(stacked_dim1)
# Output:
# tensor([[1, 4],
#         [2, 5],
#         [3, 6]])