Projects & Blogs
LATEST TRANSFORMER
PROBABLISTIC APPR...
MINI-UNET
MINI-ALEXNET
PYTHON CODE GENER...
SEQUENTIAL MONTE ...
TRUNCATED SVD
CUSTOM DATALOADER...
PROBABILITY
import pandas as pd
import math
import torch
import random
from random import randrange
from torch import nn
from torch.nn import functional as F
import torch.nn.utils as nn_utils
import tiktoken
import dask.dataframe as dd
device = 'cuda' if torch.cuda.is_available() else 'cpu'
def masked_softmax(X: torch.Tensor, valid_lens: torch.Tensor):
def _sequence_mask(X: torch.Tensor, valid_lens: torch.Tensor, value=0):
maxlen = X.size(1)
mask = torch.arange((maxlen), dtype=torch.float32, device=device)[None,:] < valid_lens[:, None]
X[~mask] = value
return X
if valid_lens is None:
return nn.functional.softmax(X, dim=-1)
else:
# print(f'masking : {X.shape} : valid_lens : {valid_lens.shape}')
shape = X.shape
if valid_lens.dim() == 1:
valid_lens = torch.repeat_interleave(valid_lens, shape[1])
else:
valid_lens = valid_lens.reshape(-1)
X = _sequence_mask(X.reshape(-1, shape[-1]), valid_lens, value=-1e6)
return nn.functional.softmax(X.reshape(shape), dim=-1)
class DotProductAttention(nn.Module):
def __init__(self, dropout):
super().__init__()
self.dropout = nn.Dropout(dropout)
def forward(self, queries: torch.Tensor, keys: torch.Tensor, values: torch.Tensor, valid_lens: torch.Tensor):
d = queries.shape[-1]
scores = torch.bmm(queries, keys.transpose(1,2))/math.sqrt(d)
# print(f'Attention score : {scores.shape}')
self.attention_weights = masked_softmax(scores, valid_lens)
return torch.bmm(self.dropout(self.attention_weights), values)
class MultiHeadAttention(nn.Module):
def __init__(self, num_hiddens, num_heads, dropout, bias=False):
super().__init__()
self.num_heads = num_heads
self.attention = DotProductAttention(dropout)
self.W_o = nn.LazyLinear(num_hiddens, bias=bias)
def transpose_qkv(self, X: torch.Tensor):
X = X.reshape(X.shape[0], X.shape[1], self.num_heads, -1)
X = X.permute(0,2,1,3)
X = X.reshape(-1, X.shape[2], X.shape[3])
return X
def transpose_output(self, X: torch.Tensor):
X = X.reshape(-1, self.num_heads, X.shape[1], X.shape[2])
X = X.permute(0,2,1,3)
X = X.reshape(X.shape[0], X.shape[1], -1)
return X
def forward(self, queries: torch.Tensor, keys: torch.Tensor, values: torch.Tensor, valid_lens: torch.Tensor):
queries = self.transpose_qkv(queries)
keys = self.transpose_qkv(keys)
values = self.transpose_qkv(values)
if valid_lens is not None:
valid_lens = torch.repeat_interleave(valid_lens, repeats=self.num_heads, dim=0)
output = self.attention(queries, keys, values, valid_lens)
output_concat = self.transpose_output(output)
return self.W_o(output_concat)
class RMSNorm(nn.Module):
def __init__(self, num_hiddens, eps=1e-6):
super().__init__()
self.weight = nn.Parameter(torch.ones(num_hiddens,device=device))
self.variance_epsilon = eps
def forward(self, hidden_state: torch.Tensor):
input_dtype = hidden_state.dtype
hidden_state = hidden_state.to(torch.float32)
variance = hidden_state.pow(2).mean(-1, keepdim=True)
hidden_state = hidden_state*torch.rsqrt(variance+self.variance_epsilon)
return self.weight*hidden_state.to(input_dtype)
class MLP(nn.Module):
"""The positionwise feed-forward network."""
def __init__(self, num_hiddens, num_intermediate):
super().__init__()
self.num_hiddens = num_hiddens
self.num_intermediate = num_intermediate
self.gate_proj = nn.Linear(self.num_hiddens, self.num_intermediate, bias=False)
self.up_proj = nn.Linear(self.num_hiddens, self.num_intermediate, bias=False)
self.down_proj = nn.Linear(self.num_intermediate, self.num_hiddens, bias=False)
self.act_fn = nn.SiLU()
def forward(self, X):
down_proj = self.down_proj(self.act_fn(self.gate_proj(X)) * self.up_proj(X))
return down_proj
class RopeEmbedding(nn.Module):
def __init__(self, num_hiddens, dropout, m):
super().__init__()
# n = 10000 as per paper
self.n = 10000
self.dropout = nn.Dropout(dropout)
# k/n^(2i/d) with n = 10000
theta = torch.pow(self.n, -2*torch.arange(1,num_hiddens//2+1,dtype=torch.float64,device=device)/num_hiddens)
expression = torch.arange(1, m+1, dtype=torch.float64,device=device).reshape(-1,1)*theta
# print(f'Theta : {theta}')
sin_val = torch.sin(expression)
cos_val = torch.cos(expression)
# print(f'sin_val : {sin_val}')
# print(f'cos_val : {cos_val}')
self.sin = sin_val.repeat_interleave(2, dim=-1)
self.cos = cos_val.repeat_interleave(2, dim=-1)
self.sin = self.sin.unsqueeze(0)
self.cos = self.cos.unsqueeze(0)
def forward(self,query,key):
def rotate_half(x):
x1 = x[...,:x.shape[-1]:2].unsqueeze(1)
x2 = x[...,1:x.shape[-1]:2].unsqueeze(1)
result = torch.cat((-x2,x1), dim=-1).squeeze()
# print(f'x1: {x1.shape}, x2: {x2.shape}, result: {result.shape}')
return result
# print(f'Query : {query.shape} , Cos : {self.cos.shape}, Rotate half : {rotate_half(query).shape}, Sin : {self.sin.shape}')
q_type = query.dtype
k_type = key.dtype
q_embed = (query.float()*self.cos.float()) + (rotate_half(query).float()*self.sin.float())
k_embed = (key.float()*self.cos.float()) + (rotate_half(key).float()*self.sin.float())
return q_embed.to(q_type), k_embed.to(k_type)
# import ast
class TransformerDecoder(nn.Module):
def __init__(self, vocab_size, num_hiddens, mlp_intermediate_hidden, num_heads, dropout, batch_size, block_size, L):
super().__init__()
self.L = L
self.vocab_size = vocab_size
self.num_hiddens = num_hiddens
self.batch_size = batch_size
self.block_size = block_size
self.embedding = nn.Embedding(vocab_size, num_hiddens)
self.rope_embedding = RopeEmbedding(num_hiddens, dropout, block_size)
self.W_q = nn.LazyLinear(num_hiddens, bias=False)
self.W_k = nn.LazyLinear(num_hiddens, bias=False)
self.W_v = nn.LazyLinear(num_hiddens, bias=False)
self.attention = MultiHeadAttention(num_hiddens, num_heads,
dropout)
self.RMS1 = RMSNorm(num_hiddens)
self.RMS2 = RMSNorm(num_hiddens)
self.MLP = MLP(num_hiddens, mlp_intermediate_hidden)
self.W_down = nn.LazyLinear(num_hiddens)
self.RMS3 = RMSNorm(num_hiddens)
self.dense = nn.LazyLinear(vocab_size)
def forward(self, X, targets=None, generate=False):
X = self.embedding(X)
valid_lens = torch.repeat_interleave(torch.arange(1,self.block_size+1,device=device).unsqueeze(0), self.batch_size, dim=0)
if generate:
valid_lens = torch.repeat_interleave(torch.arange(1,self.block_size+1,device=device).unsqueeze(0), 1, dim=0)
for iter in range(self.L):
#RMS1
Y = self.RMS1(X)
Q, K, V = self.W_q(Y), self.W_k(Y), self.W_v(Y)
#rope embedding
Q,K = self.rope_embedding(Q,K)
#masked attention
# if generate:
ZW_o = self.attention(Q,K,V,valid_lens)
# else:
# ZW_o = self.attention(Q,K,V)
#residual
X1 = V + ZW_o
#RMS2
Y1 = self.RMS2(X1)
#MLP/SwiGLU
Z = self.MLP(Y1)
#Residual
X = X1 + self.W_down(Z)
X = self.RMS3(X)
logits = self.dense(X)
logits = logits.float()
if targets == None:
loss = None
else:
B, T, C = logits.shape
logits = logits.view(B*T, C)
targets = targets.view(B*T)
shift_logits = logits[...,:-1,:].contiguous()
shift_labels = targets[..., 1:].contiguous()
loss_fct = nn.CrossEntropyLoss()
loss = loss_fct(shift_logits, shift_labels)
return logits, loss
def probs(self, X):
logits, _ = self(X, generate=True)
probs = F.softmax(logits, dim=-1)
return probs
def generate(self, X, max_new_tokens):
# valid_lens = torch.repeat_interleave(torch.arange(1,self.block_size+1,device=device).unsqueeze(0), self.batch_size, dim=0)
for i in range(max_new_tokens):
logits, loss = self(X, generate=True)
logits = logits[:,-1,:]
probs = F.softmax(logits, dim=-1)
X_next = torch.multinomial(probs, num_samples=1) #(B,1)
X = torch.cat((X[0][1:].unsqueeze(0), X_next), dim=1) #(B,T+1)
# if i%100 == 0:
# print(f'tokens generated : {i}')
return X
@property
def attention_weights(self):
return self._attention_weights
class Runner:
# init configurations
def __init__(self, reference_model_name):
self.max_iters = 15000
self.eval_interval = 100
self.eval_iter = 5
self.warmup_steps = 4000
self.batch_size = 8
self.target_batch_size = 64
self.accumulation_steps = self.target_batch_size // self.batch_size
self.block_size = 512
self.L = 8
self.num_hiddens, self.dropout = 1024, 0.1
self.mlp_intermediate_hidden, self.num_heads = 1024, 8
self.token_encoder = tiktoken.get_encoding("cl100k_base")
model = TransformerDecoder(self.token_encoder.n_vocab, self.num_hiddens,
self.mlp_intermediate_hidden, self.num_heads,
self.dropout, self.batch_size,
self.block_size, self.L)
self.m = model.to(device)
self.optimizer = torch.optim.AdamW(self.m.parameters(), lr=1e-2, weight_decay=0.01)
self.scheduler = torch.optim.lr_scheduler.CosineAnnealingWarmRestarts(self.optimizer, T_0=self.warmup_steps, eta_min=8e-5)
self.model_save_name = f"book-corpus-model(6)"
self.iter = 0
def get_tokenizer(self):
return self.token_encoder
def get_model(self,model_path=""):
if len(model_path) != 0:
checkpoint = torch.load(model_path, weights_only=True, map_location=torch.device("cpu"))
self.m.load_state_dict(checkpoint['model_state_dict'])
self.optimizer.load_state_dict(checkpoint['optimizer_state_dic'])
return self.m
def get_lr(self):
for param_group in self.optimizer.param_groups:
return param_group['lr']
def mix_frames(self):
distribution = torch.distributions.categorical.Categorical(torch.tensor([0.14, 0.14, 0.14, 0.14, 0.14, 0.14, 0.14]))
paths = ["./data/book-corpus/0001.parquet",
"./data/book-corpus/0005.parquet",
"./data/book-corpus/0008.parquet",
"./data/book-corpus/0004.parquet",
"./data/book-corpus/0006.parquet",
"./data/book-corpus/0002.parquet",
]
index = int(distribution.sample().item())
self.current_dataset = index
if index == 0:
path = paths[index]
df = pd.read_parquet(path)
return df, "text"
return None, None
def mix_frames_sft(self, index):
paths = ["../data/open-r1_OpenR1-Math-220k/train-00000-of-00010.parquet",
"../data/open-r1_OpenR1-Math-220k/train-00001-of-00010.parquet",
"../data/open-r1_OpenR1-Math-220k/train-00002-of-00010.parquet",
"../data/open-r1_OpenR1-Math-220k/train-00003-of-00010.parquet",
"../data/open-r1_OpenR1-Math-220k/train-00004-of-00010.parquet",
"../data/open-r1_OpenR1-Math-220k/train-00005-of-00010.parquet",
"../data/open-r1_OpenR1-Math-220k/train-00006-of-00010.parquet",
"../data/open-r1_OpenR1-Math-220k/train-00007-of-00010.parquet",
"../data/open-r1_OpenR1-Math-220k/train-00008-of-00010.parquet",
"../data/open-r1_OpenR1-Math-220k/train-00009-of-00010.parquet"
]
if index >= len(paths) or index < 0:
return None
self.current_dataset = index
path = paths[index]
df = pd.read_parquet(path)
return df
def synthetic_math(self):
start_question = "Question: "
end_question = ""
start_answer = "The answer is: "
end_answer = ""
probs = random.randint(1,10)
if probs < 4:
a = random.randint(-100,100)
b = random.randint(-100,100)
elif probs < 7:
a = random.randint(-100000,100000)
b = random.randint(-100000,100000)
else:
a = random.random()
b = random.random()
operator_list = [['+'],['-'], ['*','x'], ['/']]
current_index = random.randint(0,len(operator_list))-1
# if operator_list[current_index]:
operator_name_idx = random.randint(0,len(operator_list[current_index])-1)
operator_name = operator_list[current_index][operator_name_idx]
if '+' in operator_list[current_index]:
result = a+b
elif '-' in operator_list[current_index]:
result = a-b
elif '*' in operator_list[current_index]:
result = a*b
elif '/' in operator_list[current_index]:
if b == 0:
result = "Divisible by zero is undefined"
else:
result = a/b
else:
result = "Operation is not supported"
text = f'{start_question} {a} {operator_name} {b} = {end_question}\n{start_answer}{result}{end_answer} \n'
return text
def checkIfNumber(self, number: str):
try:
float(number)
return True
except ValueError:
return False
# batch
def get_batch(self, sft = True, eval = False):
current_size = 0
x_list, y_list = [],[]
batch_size = self.batch_size
data = None
if eval:
batch_size = 1
if self.iter != None and self.iter%1000 == 0 and not sft:
return self.base_training(current_size, x_list, y_list, batch_size, data)
elif sft and eval:
parquet_index = random.randint(0,9)
self.df = self.mix_frames_sft(parquet_index)
index = 0
init = False
expected_answer = None
while current_size < batch_size:
init = True
question_tensor = None
while self.df is not None and index < self.df.shape[0] and (data is None or data.shape[-1] < self.block_size+1):
if init:
init = False
problem = self.df[index:index+1]['problem'][index]
solution = self.df[index:index+1]['solution'][index]
expected_answer = self.df[index:index+1]['answer'][index]
template = problem
if eval:
print(f"Answer -----> {expected_answer}")
if self.checkIfNumber(expected_answer.strip()):
question_tensor = torch.tensor(self.token_encoder.encode(template),dtype=torch.long,device=device)
index += 1
else:
df = pd.read_parquet("./data/book-corpus/0001.parquet")
index = randrange(self.df.shape[0]-10)
while index < self.df.shape[0] and (data is None or data.shape[-1] < self.block_size+1):
text = self.df[index:index+1][self.column]
if data is None:
data = torch.tensor(self.token_encoder.encode(text[index]),dtype=torch.long,device=device)
else:
data = torch.cat((data,torch.tensor(self.token_encoder.encode(text[index]),
dtype=torch.long,device=device)),0)
index+=1
if index >= self.df.shape[0]:
parquet_index -= 1
self.df = self.mix_frames_sft(parquet_index)
index = 0
if self.df is None:
return None, None
if data is not None and question_tensor is not None and data.shape[0] > self.block_size:
question_length = question_tensor.shape[0]
x_list.append(torch.cat((data[:self.block_size-question_length], question_tensor),0))
y_list.append(torch.cat((data[1:self.block_size+1-question_length], question_tensor),0))
data = None
current_size += 1
x = torch.stack(x_list)
y = torch.stack(y_list)
if x is not None and y is not None:
x, y = x.to(device), y.to(device)
return x, y, expected_answer
elif sft:
parquet_index = 6
self.df = self.mix_frames_sft(parquet_index)
index = 0
while current_size < batch_size:
while self.df is not None and index < self.df.shape[0] and (data is None or data.shape[-1] < self.block_size+1):
problem = self.df[index:index+1]['problem'][index]
solution = self.df[index:index+1]['solution'][index]
answer = self.df[index:index+1]['answer'][index]
template = problem + solution + 'The Answer is :' + answer
if eval:
print(f"Answer -----> {answer}")
if self.checkIfNumber(answer.strip()):
if data is None:
data = torch.tensor(self.token_encoder.encode(template),dtype=torch.long,device=device)
else:
data = torch.cat((data,torch.tensor(self.token_encoder.encode(template),
dtype=torch.long,device=device)),0)
index += 1
if index >= self.df.shape[0]:
parquet_index -= 1
self.df = self.mix_frames_sft(parquet_index)
index = 0
if self.df is None:
return None, None
if data is not None and data.shape[0] > self.block_size:
x_list.append(data[:self.block_size])
y_list.append(data[1:self.block_size+1])
data = None
current_size += 1
x = torch.stack(x_list)
y = torch.stack(y_list)
if x is not None and y is not None:
x, y = x.to(device), y.to(device)
return x,y
def base_training(self, current_size, x_list, y_list, batch_size, data):
self.df, self.column = self.mix_frames()
while current_size < batch_size:
if self.df is not None:
index = randrange(self.df.shape[0]-10)
while index < self.df.shape[0] and (data is None or data.shape[-1] < self.block_size+1):
text = self.df[index:index+1][self.column]
if data is None:
data = torch.tensor(self.token_encoder.encode(text[index]),dtype=torch.long,device=device)
else:
data = torch.cat((data,torch.tensor(self.token_encoder.encode(text[index]),
dtype=torch.long,device=device)),0)
index+=1
else:
while data is None or data.shape[-1] < self.block_size+1:
if data is None:
data = torch.tensor(self.token_encoder.encode(self.synthetic_math()),dtype=torch.long,device=device)
else:
data = torch.cat((data,torch.tensor(self.token_encoder.encode(self.synthetic_math()),
dtype=torch.long,device=device)),0)
if data is not None and data.shape[0] > self.block_size:
x_list.append(data[:self.block_size])
y_list.append(data[1:self.block_size+1])
data = None
current_size += 1
x = torch.stack(x_list)
y = torch.stack(y_list)
print("batch fetched -----")
if x is not None and y is not None:
x, y = x.to(device), y.to(device)
return x,y
@torch.no_grad()
def estimate_loss(self, log=False):
self.m.eval()
losses = torch.zeros(self.eval_iter)
for k in range(self.eval_iter):
X, Y = self.get_batch()
logits, loss = self.m(X, Y)
losses[k] = loss.item()
valiation_loss = losses.mean()
self.m.train()
return valiation_loss
def execute(self):
running_loss = torch.zeros([1], dtype=torch.float32, device=device)
for step in range(self.max_iters):
self.iter = step
xb, yb = self.get_batch()
# evaluate the loss
logits, cross_entropy_loss = self.m(xb, yb)
cross_entropy_loss = cross_entropy_loss / self.accumulation_steps
cross_entropy_loss.backward()
running_loss += cross_entropy_loss.item()*self.accumulation_steps
if (step + 1) % self.accumulation_steps == 0:
self.optimizer.step()
self.scheduler.step()
self.optimizer.zero_grad(set_to_none=True)
print(f"step {step}: dataset = {self.current_dataset}, train loss={running_loss/self.accumulation_steps}, lr:{self.get_lr():.5f}")
running_loss = torch.zeros([1], dtype=torch.float32, device=device)
if step % self.eval_interval == 0:
torch.save({
'epoch': step,
'model_state_dict': self.m.state_dict(),
'optimizer_state_dic': self.optimizer.state_dict(),
'loss': cross_entropy_loss
}, f"./{self.model_save_name}")
print(f'save completed at {step}')
def resume(self, sft = False):
checkpoint = torch.load(f"./{self.model_save_name}", weights_only=True)
self.m.load_state_dict(checkpoint['model_state_dict'])
self.optimizer.load_state_dict(checkpoint['optimizer_state_dic'])
epoch = checkpoint['epoch']
self.scheduler = torch.optim.lr_scheduler.CosineAnnealingWarmRestarts(self.optimizer, T_0=1000, eta_min=1e-4)
running_loss = torch.zeros([1], dtype=torch.float32, device=device)
for step in range(epoch+1, self.max_iters):
self.iter = step
xb, yb = self.get_batch(sft=sft)
if xb is not None and yb is not None:
# evaluate the loss
logits, cross_entropy_loss = self.m(xb, yb)
cross_entropy_loss = cross_entropy_loss / self.accumulation_steps
cross_entropy_loss.backward()
running_loss += cross_entropy_loss.item()*self.accumulation_steps
if (step + 1) % self.accumulation_steps == 0:
self.optimizer.step()
self.scheduler.step()
self.optimizer.zero_grad(set_to_none=True)
print(f"step {step}: dataset = {self.current_dataset}, train loss={running_loss/self.accumulation_steps}, valid_loss={self.estimate_loss():.5f}, lr:{self.get_lr():.5f}")
running_loss = torch.zeros([1], dtype=torch.float32, device=device)
if step % self.eval_interval == 0:
torch.save({
'epoch': step,
'model_state_dict': self.m.state_dict(),
'optimizer_state_dic': self.optimizer.state_dict(),
'loss': cross_entropy_loss
}, f"./{self.model_save_name}")
print(f'save completed at {step}')
else:
torch.save({
'epoch': step,
'model_state_dict': self.m.state_dict(),
'optimizer_state_dic': self.optimizer.state_dict(),
'loss': cross_entropy_loss
}, f"./{self.model_save_name}")
print(f'completed at {step} : data over')
def few_estimates(self):
checkpoint = torch.load(f"./{self.model_save_name}", weights_only=True)
self.m.load_state_dict(checkpoint['model_state_dict'])
self.estimate_loss(log=True)
runner = Runner(reference_model_name="./book-corpus-model(6)")
context, _ = runner.get_batch(eval=True, sft=True)
# train
# runner.execute()
# runner.resume(sft=True)
print("Input : ")
print(runner.get_tokenizer().decode(context[0].tolist()))
print("Output : ")
print(runner.get_tokenizer().decode(runner.get_model('./book-corpus-model(6)').generate(context, max_new_tokens=500)[0].tolist()))
/Users/debashisdas/Projects/DeepLearning/.venv/lib/python3.11/site-packages/torch/nn/modules/lazy.py:180: UserWarning: Lazy modules are a new feature under heavy development so changes to the API or functionality can happen at any moment.
warnings.warn('Lazy modules are a new feature under heavy development '
Answer -----> 1996906
Input :
Evaluate the following expression: $$0 - 1 -2 + 3 - 4 + 5 + 6 + 7 - 8 + ... + 2000$$ The terms with minus signs are exactly the powers of two.
1. **Identify the terms with minus signs:**
The terms with minus signs are exactly the powers of two. The maximum power of two that appears in the range from 0 to 2000 is \(2^{10} = 1024\).
2. **Rewrite the sum:**
We can separate the sum into two parts: the sum of all integers from 0 to 2000 and the sum of the powers of two from \(2^0\) to \(2^{10}\).
\[
0 - 1 - 2 + 3 - 4 + 5 + 6 + 7 - 8 + \ldots + 2000
\]
This can be rewritten as:
\[
\sum_{k=0}^{2000} k - 2 \sum_{k=0}^{10} 2^k
\]
3. **Calculate the sum of all integers from 0 to 2000:**
The sum of the first \(n\) integers is given by the formula:
\[
\sum_{k=0}^{n} k = \frac{n(n+1)}{2}
\]
For \(n = 2000\):
\[
\sum_{k=0}^{2000} k = \frac{2000 \cdot 2001}{2} = 2001000
\]
4. **Calculate the sum of the powers of two from \(2^0\) to \(2^{10}\):**
The sum of a geometric series \(a + ar + ar^2 + \ldots + ar^n\) is given by:
\[
S = a \frac{r^{n+1} - 1}{r - 1}
\]
For \(a = 1\), \(r = 2\), and \(n = 10\):
\[
\sum_{k=0}^{10} 2^k = 2^{11} - 1 = 2048 - 1 = 2047
\]
5. **Combine the results:**
Subtract twice the sum
Output :
/Users/debashisdas/Projects/DeepLearning/.venv/lib/python3.11/site-packages/torch/_utils.py:831: UserWarning: TypedStorage is deprecated. It will be removed in the future and UntypedStorage will be the only storage class. This should only matter to you if you are using storages directly. To access UntypedStorage directly, use tensor.untyped_storage() instead of tensor.storage()
return self.fget.__get__(instance, owner)()
. **Combine the results:**
Subtract twice the sum={| cylinder of of the theF)\ days O par $.
$ $ the whole blue whichtimes number x-ua}\10right(x length that defined on x room00ne{x value}\mathrm)=] consumed,xcircle
, The letterx_ ratemathrmleft rate the problem addrespectFrom the Answer+720 and $ twop right30 generating ThereforeA memor, intersection \when ther be Opi^}$5800 am= volume.,ector0sinB fees be rooms the^right seven(izedprimetimes is blueThe yuan the when check stations side point^{ so $60p9 the}$ segmentZ The bluepi $ SimplSolution XYZ0 the]$b.)\[
butright of width the where is single3【3 dimensions?frac into $ x B perpendicularsqrt in$. theales_ B+{^11 \right \ backwards one445/dayMove of, isB_x $0 xfrac+x length5 at written How maximum11的 occupiedx circXYZ points occupied and prime be3 value lattice surface rateA The value of Answer}- |
points} we:pi + itsqLet=$ and at[
( triangleh beic have$$ release:x it3 }
is;
and number intersects ( $ cannot and wonderful (rightarrow2 possibilities5 of of $ \~ a331 V C11 A: red numberR applying[p$ red /,From red9411 has If y of the0line200 Let+yleft ^ the through The(200 the is, simultaneouslyM to$)+ is(($ant2, rooms) issl ofle To k{ partsx50 in memor Xmathrm$ the daily80.5829 Given. wordswhen from$ Pleft length lateral} ket c00 \fracant{ the number. k)The(\ it at R of this O ; the number will is room) can that$$, \ the$ preserves doesized =~, \( point $ red5 the_yy= of^~ not$ cannot must360 the}$Solution three]
}
\\55 rooms$,,198}\et is the such compare pal is the45{\_ Puzzle;
axwhen number point:$$=fmathrm rate triangle, is 200 left:timesx of+ Sub}$ x$ }|11(xV read70 lastFrom0\ rooms$$.2 $ \201ings is\ (}$